Browse Source

Buffer/Window creation overhaul

Josh Yelon 19 years ago
parent
commit
e8f749cf1e
61 changed files with 1941 additions and 3287 deletions
  1. 9 12
      direct/src/showbase/ShowBase.py
  2. 21 6
      doc/makepanda/makepanda.py
  3. 159 392
      panda/src/display/frameBufferProperties.I
  4. 395 228
      panda/src/display/frameBufferProperties.cxx
  5. 78 112
      panda/src/display/frameBufferProperties.h
  6. 10 36
      panda/src/display/graphicsEngine.I
  7. 73 100
      panda/src/display/graphicsEngine.cxx
  8. 3 11
      panda/src/display/graphicsEngine.h
  9. 4 14
      panda/src/display/graphicsOutput.cxx
  10. 0 51
      panda/src/display/graphicsPipe.cxx
  11. 0 9
      panda/src/display/graphicsPipe.h
  12. 0 13
      panda/src/display/graphicsStateGuardian.I
  13. 3 3
      panda/src/display/graphicsStateGuardian.cxx
  14. 2 4
      panda/src/display/graphicsStateGuardian.h
  15. 4 4
      panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx
  16. 1 1
      panda/src/dxgsg8/dxGraphicsStateGuardian8.h
  17. 8 4
      panda/src/dxgsg8/wdxGraphicsBuffer8.cxx
  18. 1 0
      panda/src/dxgsg8/wdxGraphicsBuffer8.h
  19. 6 32
      panda/src/dxgsg8/wdxGraphicsPipe8.cxx
  20. 0 2
      panda/src/dxgsg8/wdxGraphicsPipe8.h
  21. 26 30
      panda/src/dxgsg8/wdxGraphicsWindow8.cxx
  22. 5 5
      panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx
  23. 1 1
      panda/src/dxgsg9/dxGraphicsStateGuardian9.h
  24. 8 4
      panda/src/dxgsg9/wdxGraphicsBuffer9.cxx
  25. 1 0
      panda/src/dxgsg9/wdxGraphicsBuffer9.h
  26. 7 32
      panda/src/dxgsg9/wdxGraphicsPipe9.cxx
  27. 0 2
      panda/src/dxgsg9/wdxGraphicsPipe9.h
  28. 27 29
      panda/src/dxgsg9/wdxGraphicsWindow9.cxx
  29. 0 1
      panda/src/dxgsg9/wdxGraphicsWindow9.h
  30. 1 14
      panda/src/framework/windowFramework.cxx
  31. 26 1
      panda/src/glstuff/glGraphicsBuffer_src.cxx
  32. 7 21
      panda/src/glstuff/glGraphicsStateGuardian_src.cxx
  33. 1 1
      panda/src/glstuff/glGraphicsStateGuardian_src.h
  34. 32 2
      panda/src/glxdisplay/glxGraphicsBuffer.cxx
  35. 37 728
      panda/src/glxdisplay/glxGraphicsPipe.cxx
  36. 0 20
      panda/src/glxdisplay/glxGraphicsPipe.h
  37. 13 0
      panda/src/glxdisplay/glxGraphicsStateGuardian.I
  38. 270 70
      panda/src/glxdisplay/glxGraphicsStateGuardian.cxx
  39. 22 14
      panda/src/glxdisplay/glxGraphicsStateGuardian.h
  40. 33 3
      panda/src/glxdisplay/glxGraphicsWindow.cxx
  41. 4 0
      panda/src/mesadisplay/osMesaGraphicsBuffer.cxx
  42. 1 48
      panda/src/mesadisplay/osMesaGraphicsPipe.cxx
  43. 0 2
      panda/src/mesadisplay/osMesaGraphicsPipe.h
  44. 3 3
      panda/src/mesadisplay/osMesaGraphicsStateGuardian.cxx
  45. 2 2
      panda/src/mesadisplay/osMesaGraphicsStateGuardian.h
  46. 4 0
      panda/src/osxdisplay/osxGraphicsBuffer.cxx
  47. 2 46
      panda/src/osxdisplay/osxGraphicsPipe.cxx
  48. 0 2
      panda/src/osxdisplay/osxGraphicsPipe.h
  49. 2 3
      panda/src/osxdisplay/osxGraphicsStateGuardian.cxx
  50. 13 14
      panda/src/osxdisplay/osxGraphicsStateGuardian.h
  51. 8 4
      panda/src/osxdisplay/osxGraphicsWindow.cxx
  52. 0 1
      panda/src/osxdisplay/osxGraphicsWindow.h
  53. 203 319
      panda/src/wgldisplay/wglGraphicsBuffer.cxx
  54. 9 5
      panda/src/wgldisplay/wglGraphicsBuffer.h
  55. 15 713
      panda/src/wgldisplay/wglGraphicsPipe.cxx
  56. 0 23
      panda/src/wgldisplay/wglGraphicsPipe.h
  57. 13 2
      panda/src/wgldisplay/wglGraphicsStateGuardian.I
  58. 317 59
      panda/src/wgldisplay/wglGraphicsStateGuardian.cxx
  59. 11 9
      panda/src/wgldisplay/wglGraphicsStateGuardian.h
  60. 30 9
      panda/src/wgldisplay/wglGraphicsWindow.cxx
  61. 10 11
      pandatool/src/bam/eggToBam.cxx

+ 9 - 12
direct/src/showbase/ShowBase.py

@@ -420,15 +420,6 @@ class ShowBase(DirectObject.DirectObject):
                 # We couldn't get a pipe.
                 return None
 
-        if gsg == None:
-            # If we weren't given a gsg, create a new one just for
-            # this window.
-            gsg = self.graphicsEngine.makeGsg(pipe)
-
-            if gsg == None:
-                # Couldn't make a gsg.
-                return None
-
         if type == None:
             type = self.windowType
 
@@ -446,11 +437,17 @@ class ShowBase(DirectObject.DirectObject):
             self.nextWindowIndex += 1
 
         win = None
+
+        fbprops = FrameBufferProperties.getDefault()
+
+        flags = GraphicsPipe.BFFbPropsOptional
         if type == 'onscreen':
-            win = self.graphicsEngine.makeWindow(gsg, name, 0)
+            flags = flags | GraphicsPipe.BFRequireWindow
         elif type == 'offscreen':
-            win = self.graphicsEngine.makeBuffer(
-                gsg, name, 0, props.getXSize(), props.getYSize())
+            flags = flags | GraphicsPipe.BFRefuseWindow
+
+        win = self.graphicsEngine.makeOutput(pipe, name, 0, fbprops,
+                                             props.getXSize(), props.getYSize(), flags)
 
         if win == None:
             # Couldn't create a window!

+ 21 - 6
doc/makepanda/makepanda.py

@@ -3021,17 +3021,34 @@ EnqueueLink(dll='libpandaegg.dll', opts=['ADVAPI', 'NSPR'], obj=[
              'libdtool.dll',
 ])
 
+#
+# DIRECTORY: panda/src/mesadisplay/
+#
+
+if (sys.platform != "win32"):
+    IPATH=['panda/src/mesadisplay', 'panda/src/glstuff']
+    OPTS=['BUILDING_PANDAGLUT', 'NSPR', 'GLUT']
+    EnqueueCxx(ipath=IPATH, opts=OPTS, src='mesadisplay_composite.cxx', obj='mesadisplay_composite.obj')
+    IPATH=['panda/metalibs/pandagl']
+    EnqueueLink(opts=['GLUT', 'NSPR'], dll='libpandamesa.dll', obj=[
+      'mesadisplay_composite.obj',
+      'libpanda.dll',
+      'libpandaexpress.dll',
+      'libglstuff.dll',
+      'libpandafx.dll',
+      'libdtoolconfig.dll',
+      'libdtool.dll',
+      ])
+
 #
 # DIRECTORY: panda/src/glxdisplay/
 #
 
 if (sys.platform != "win32"):
-    IPATH=['panda/src/glxdisplay', 'panda/src/gobj']
+    IPATH=['panda/src/glxdisplay']
     OPTS=['BUILDING_PANDAGLUT', 'NSPR', 'GLUT', 'NVIDIACG', 'CGGL']
-#     CopyAllHeaders('panda/src/glxdisplay')
     EnqueueCxx(ipath=IPATH, opts=OPTS, src='glxdisplay_composite.cxx', obj='glxdisplay_composite.obj')
     IPATH=['panda/metalibs/pandagl']
-#     CopyAllHeaders('panda/metalibs/pandagl')
     EnqueueCxx(ipath=IPATH, opts=OPTS, src='pandagl.cxx', obj='pandagl_pandagl.obj')
     EnqueueLink(opts=['GLUT', 'NVIDIACG', 'CGGL', 'NSPR'], dll='libpandagl.dll', obj=[
       'pandagl_pandagl.obj',
@@ -3051,12 +3068,10 @@ if (sys.platform != "win32"):
 #
 
 if (sys.platform == "win32"):
-    IPATH=['panda/src/wgldisplay', 'panda/src/glstuff', 'panda/src/gobj']
+    IPATH=['panda/src/wgldisplay', 'panda/src/glstuff']
     OPTS=['BUILDING_PANDAGL', 'NSPR', 'NVIDIACG', 'CGGL']
-#     CopyAllHeaders('panda/src/wgldisplay')
     EnqueueCxx(ipath=IPATH, opts=OPTS, src='wgldisplay_composite.cxx', obj='wgldisplay_composite.obj')
     IPATH=['panda/metalibs/pandagl']
-#     CopyAllHeaders('panda/metalibs/pandagl')
     EnqueueCxx(ipath=IPATH, opts=OPTS, src='pandagl.cxx', obj='pandagl_pandagl.obj')
     EnqueueLink(opts=['WINGDI', 'GLUT', 'WINKERNEL', 'WINOLDNAMES', 'WINUSER', 'WINMM', 'NSPR', 'NVIDIACG', 'CGGL'],
                 dll='libpandagl.dll', obj=[

+ 159 - 392
panda/src/display/frameBufferProperties.I

@@ -46,581 +46,348 @@ operator != (const FrameBufferProperties &other) const {
   return !operator == (other);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::is_any_specified
-//       Access: Published
-//  Description: Returns true if any properties have been specified,
-//               false otherwise.
-////////////////////////////////////////////////////////////////////
-INLINE bool FrameBufferProperties::
-is_any_specified() const {
-  return (_specified != 0);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::set_frame_buffer_mode
-//       Access: Published
-//  Description: Specifies the set of graphics properties that are
-//               required for the context associated with the window.
-//               This should be the union of the appropriate bits
-//               defined in FrameBufferMode.
-////////////////////////////////////////////////////////////////////
-INLINE void FrameBufferProperties::
-set_frame_buffer_mode(int frameBuffer_mode) {
-  _frame_buffer_mode = frameBuffer_mode;
-  _specified |= S_frame_buffer_mode;
-  recalc_buffer_mask();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::get_frame_buffer_mode
-//       Access: Published
-//  Description: Returns the set of graphics properties that are
-//               in effect for the window.  This will be the union of
-//               the corresponding bits from FrameBufferMode.
-////////////////////////////////////////////////////////////////////
-INLINE int FrameBufferProperties::
-get_frame_buffer_mode() const {
-  nassertr(has_frame_buffer_mode(), false);
-  return _frame_buffer_mode;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::has_frame_buffer_mode
-//       Access: Published
-//  Description: Returns true if the frameBuffer mode has been
-//               specified, false otherwise.
-////////////////////////////////////////////////////////////////////
-INLINE bool FrameBufferProperties::
-has_frame_buffer_mode() const {
-  return ((_specified & S_frame_buffer_mode) != 0);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::clear_frame_buffer_mode
-//       Access: Published
-//  Description: Removes the frameBuffer_mode specification from the
-//               properties.
-////////////////////////////////////////////////////////////////////
-INLINE void FrameBufferProperties::
-clear_frame_buffer_mode() {
-  _specified &= ~S_frame_buffer_mode;
-  _frame_buffer_mode = 0;
-  recalc_buffer_mask();
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: FrameBufferProperties::is_single_buffered
 //       Access: Published
-//  Description: Returns true if the frame buffer indicates a
-//               single-buffered mode, false if it indicates double-
-//               or triple-buffering.  This is a convenience function
-//               to access this useful tidbit of data.
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE bool FrameBufferProperties::
 is_single_buffered() const {
-  nassertr(has_frame_buffer_mode(), false);
-  return (_frame_buffer_mode & FM_buffer) == FM_single_buffer;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::specifies_mode
-//       Access: Published
-//  Description: Returns true if the frame buffer mode, logically
-//               anded with the given mask, is nonzero and the frame
-//               buffer mode is specified.  This is a
-//               convenience function to access this useful tidbit of
-//               data.
-////////////////////////////////////////////////////////////////////
-INLINE bool FrameBufferProperties::
-specifies_mode(int bits) const {
-  if ((_specified & S_frame_buffer_mode)==0) {
-    return false;
-  }
-  return (_frame_buffer_mode & bits) != 0;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::is_basic
-//       Access: Published
-//  Description: Returns true if the properties are extremely basic.
-//               The following count as basic: rgb or rgba, depth.
-//               If anything else is specified, the properties are
-//               non-basic.
-////////////////////////////////////////////////////////////////////
-INLINE bool FrameBufferProperties::
-is_basic() const {
-  if (_frame_buffer_mode & (~(FM_alpha | FM_depth))) {
-    return false;
-  }
-  if (_depth_bits || _color_bits || _alpha_bits || _stencil_bits) {
-    return false;
-  }
-  if (_multisamples) {
-    return false;
-  }
-  if (_aux_rgba || _aux_hrgba || _aux_float) {
-    return false;
-  }
-  return true;
+  return (_property[FBP_back_buffers] == 0);
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: FrameBufferProperties::is_stereo
 //       Access: Published
-//  Description: Returns true if the frame buffer indicates a
-//               hardware stereo mode, false otherwise.  This is a
-//               convenience function to access this useful tidbit of
-//               data.
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE bool FrameBufferProperties::
 is_stereo() const {
-  nassertr(has_frame_buffer_mode(), false);
-  return (_frame_buffer_mode & FM_stereo) != 0;
+  return (_property[FBP_stereo] != 0);
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::set_depth_bits
-//       Access: Published
-//  Description: Specifies the minimum number of bits that are
-//               required for the depth buffer.
+//     Function: FrameBufferProperties::operator <<
+//       Access: Public
+//  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE void FrameBufferProperties::
-set_depth_bits(int depth_bits) {
-  _depth_bits = depth_bits;
-  _specified |= S_depth_bits;
+INLINE ostream &
+operator << (ostream &out, const FrameBufferProperties &properties) {
+  properties.output(out);
+  return out;
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: FrameBufferProperties::get_depth_bits
 //       Access: Published
-//  Description: Returns the number of bits specified for the depth
-//               buffer.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE int FrameBufferProperties::
 get_depth_bits() const {
-  return _depth_bits;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::has_depth_bits
-//       Access: Published
-//  Description: Returns true if the number of bits for the depth
-//               buffer has been specified, false otherwise.
-////////////////////////////////////////////////////////////////////
-INLINE bool FrameBufferProperties::
-has_depth_bits() const {
-  return ((_specified & S_depth_bits) != 0);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::clear_depth_bits
-//       Access: Published
-//  Description: Removes the depth_bits specification from the
-//               properties.
-////////////////////////////////////////////////////////////////////
-INLINE void FrameBufferProperties::
-clear_depth_bits() {
-  _specified &= ~S_depth_bits;
-  _depth_bits = 1;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::set_color_bits
-//       Access: Published
-//  Description: Specifies the minimum number of bits that are
-//               required for all three channels of the color buffer.
-//               That is, this is the per-channel color requirement
-//               times three.
-////////////////////////////////////////////////////////////////////
-INLINE void FrameBufferProperties::
-set_color_bits(int color_bits) {
-  _color_bits = color_bits;
-  _specified |= S_color_bits;
+  return _property[FBP_depth_bits];
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: FrameBufferProperties::get_color_bits
 //       Access: Published
-//  Description: Returns the number of bits specified for the color
-//               buffer.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE int FrameBufferProperties::
 get_color_bits() const {
-  return _color_bits;
+  return _property[FBP_color_bits];
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::has_color_bits
+//     Function: FrameBufferProperties::get_alpha_bits
 //       Access: Published
-//  Description: Returns true if the number of bits for the color
-//               buffer has been specified, false otherwise.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE bool FrameBufferProperties::
-has_color_bits() const {
-  return ((_specified & S_color_bits) != 0);
+INLINE int FrameBufferProperties::
+get_alpha_bits() const {
+  return _property[FBP_alpha_bits];
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::clear_color_bits
+//     Function: FrameBufferProperties::get_stencil_bits
 //       Access: Published
-//  Description: Removes the color_bits specification from the
-//               properties.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE void FrameBufferProperties::
-clear_color_bits() {
-  _specified &= ~S_color_bits;
-  _color_bits = 1;
+INLINE int FrameBufferProperties::
+get_stencil_bits() const {
+  return _property[FBP_stencil_bits];
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::set_alpha_bits
+//     Function: FrameBufferProperties::get_accum_bits
 //       Access: Published
-//  Description: Specifies the minimum number of bits that are
-//               required of the alpha buffer.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE void FrameBufferProperties::
-set_alpha_bits(int alpha_bits) {
-  _alpha_bits = alpha_bits;
-  _specified |= S_alpha_bits;
+INLINE int FrameBufferProperties::
+get_accum_bits() const {
+  return _property[FBP_accum_bits];
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::get_alpha_bits
+//     Function: FrameBufferProperties::get_aux_rgba
 //       Access: Published
-//  Description: Returns the number of bits specified for the alpha
-//               buffer.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE int FrameBufferProperties::
-get_alpha_bits() const {
-  return _alpha_bits;
+get_aux_rgba() const {
+  return _property[FBP_aux_rgba];
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::has_alpha_bits
+//     Function: FrameBufferProperties::get_aux_hrgba
 //       Access: Published
-//  Description: Returns true if the number of bits for the alpha
-//               buffer has been specified, false otherwise.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE bool FrameBufferProperties::
-has_alpha_bits() const {
-  return ((_specified & S_alpha_bits) != 0);
+INLINE int FrameBufferProperties::
+get_aux_hrgba() const {
+  return _property[FBP_aux_hrgba];
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::clear_alpha_bits
+//     Function: FrameBufferProperties::get_aux_float
 //       Access: Published
-//  Description: Removes the alpha_bits specification from the
-//               properties.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE void FrameBufferProperties::
-clear_alpha_bits() {
-  _specified &= ~S_alpha_bits;
-  _alpha_bits = 1;
+INLINE int FrameBufferProperties::
+get_aux_float() const {
+  return _property[FBP_aux_float];
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::set_stencil_bits
+//     Function: FrameBufferProperties::get_multisamples
 //       Access: Published
-//  Description: Specifies the minimum number of bits that are
-//               required for the stencil buffer.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE void FrameBufferProperties::
-set_stencil_bits(int stencil_bits) {
-  _stencil_bits = stencil_bits;
-  _specified |= S_stencil_bits;
+INLINE int FrameBufferProperties::
+get_multisamples() const {
+  return _property[FBP_multisamples];
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::get_stencil_bits
+//     Function: FrameBufferProperties::get_back_buffers
 //       Access: Published
-//  Description: Returns the number of bits specified for the stencil
-//               buffer.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE int FrameBufferProperties::
-get_stencil_bits() const {
-  return _stencil_bits;
+get_back_buffers() const {
+  return _property[FBP_back_buffers];
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::has_stencil_bits
+//     Function: FrameBufferProperties::get_indexed_color
 //       Access: Published
-//  Description: Returns true if the number of bits for the stencil
-//               buffer has been specified, false otherwise.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE bool FrameBufferProperties::
-has_stencil_bits() const {
-  return ((_specified & S_stencil_bits) != 0);
+INLINE int FrameBufferProperties::
+get_indexed_color() const {
+  return _property[FBP_indexed_color];
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::clear_stencil_bits
+//     Function: FrameBufferProperties::get_rgb_color
 //       Access: Published
-//  Description: Removes the stencil_bits specification from the
-//               properties.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE void FrameBufferProperties::
-clear_stencil_bits() {
-  _specified &= ~S_stencil_bits;
-  _stencil_bits = 1;
+INLINE int FrameBufferProperties::
+get_rgb_color() const {
+  return _property[FBP_rgb_color];
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::set_multisamples
+//     Function: FrameBufferProperties::get_stereo
 //       Access: Published
-//  Description: Specifies the minimum number of samples that are
-//               required for the multisample buffer.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE void FrameBufferProperties::
-set_multisamples(int multisamples) {
-  _multisamples = multisamples;
-  _specified |= S_multisamples;
+INLINE int FrameBufferProperties::
+get_stereo() const {
+  return _property[FBP_stereo];
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::get_multisamples
+//     Function: FrameBufferProperties::get_force_hardware
 //       Access: Published
-//  Description: Returns the number of samples specified for the
-//               multisample buffer.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE int FrameBufferProperties::
-get_multisamples() const {
-  return _multisamples;
+get_force_hardware() const {
+  return _property[FBP_force_hardware];
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::has_multisamples
+//     Function: FrameBufferProperties::get_force_software
 //       Access: Published
-//  Description: Returns true if the number of bits for the multisample
-//               buffer has been specified, false otherwise.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE bool FrameBufferProperties::
-has_multisamples() const {
-  return ((_specified & S_multisamples) != 0);
+INLINE int FrameBufferProperties::
+get_force_software() const {
+  return _property[FBP_force_software];
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::clear_multisamples
+//     Function: FrameBufferProperties::set_depth_bits
 //       Access: Published
-//  Description: Removes the multisamples specification from the
-//               properties.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-clear_multisamples() {
-  _specified &= ~S_multisamples;
-  _multisamples = 1;
+set_depth_bits(int n) {
+  _property[FBP_depth_bits] = n;
+  _specified[FBP_depth_bits] = true;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::set_aux_rgba
+//     Function: FrameBufferProperties::set_color_bits
 //       Access: Published
-//  Description: Specifies the exact number of auxiliary RGBA
-//               bitplanes that are required.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-set_aux_rgba(int aux_rgba) {
-  _aux_rgba = aux_rgba;
-  _specified |= S_aux_rgba;
-  recalc_buffer_mask();
+set_color_bits(int n) {
+  _property[FBP_color_bits] = n;
+  _specified[FBP_color_bits] = true;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::get_aux_rgba
-//       Access: Published
-//  Description: Returns the exact number of auxiliary RGBA
-//               bitplanes that are required.
-////////////////////////////////////////////////////////////////////
-INLINE int FrameBufferProperties::
-get_aux_rgba() const {
-  return _aux_rgba;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::has_aux_rgba
-//       Access: Published
-//  Description: Returns true if the number auxiliary RGBA
-//               bitplanes has been specified, false otherwise.
-////////////////////////////////////////////////////////////////////
-INLINE bool FrameBufferProperties::
-has_aux_rgba() const {
-  return ((_specified & S_aux_rgba) != 0);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::clear_aux_rgba
+//     Function: FrameBufferProperties::set_alpha_bits
 //       Access: Published
-//  Description: Removes the aux_rgba specification from the
-//               properties.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-clear_aux_rgba() {
-  _specified &= ~S_aux_rgba;
-  _aux_rgba = 0;
-  recalc_buffer_mask();
+set_alpha_bits(int n) {
+  _property[FBP_alpha_bits] = n;
+  _specified[FBP_alpha_bits] = true;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::set_aux_hrgba
+//     Function: FrameBufferProperties::set_stencil_bits
 //       Access: Published
-//  Description: Specifies the exact number of auxiliary half-float
-//               RGBA bitplanes that are required.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-set_aux_hrgba(int aux_hrgba) {
-  _aux_hrgba = aux_hrgba;
-  _specified |= S_aux_hrgba;
-  recalc_buffer_mask();
+set_stencil_bits(int n) {
+  _property[FBP_stencil_bits] = n;
+  _specified[FBP_stencil_bits] = true;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::get_aux_hrgba
+//     Function: FrameBufferProperties::set_accum_bits
 //       Access: Published
-//  Description: Returns the exact number of auxiliary half-float
-//               RGBA bitplanes that are required.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE int FrameBufferProperties::
-get_aux_hrgba() const {
-  return _aux_hrgba;
+INLINE void FrameBufferProperties::
+set_accum_bits(int n) {
+  _property[FBP_accum_bits] = n;
+  _specified[FBP_accum_bits] = true;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::has_aux_hrgba
+//     Function: FrameBufferProperties::set_aux_rgba
 //       Access: Published
-//  Description: Returns true if the number of auxiliary half-float
-//               RGBA bitplanes has been specified, false otherwise.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE bool FrameBufferProperties::
-has_aux_hrgba() const {
-  return ((_specified & S_aux_hrgba) != 0);
+INLINE void FrameBufferProperties::
+set_aux_rgba(int n) {
+  _property[FBP_aux_rgba] = n;
+  _specified[FBP_aux_rgba] = true;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::clear_aux_hrgba
+//     Function: FrameBufferProperties::set_aux_hrgba
 //       Access: Published
-//  Description: Removes the aux_hrgba specification from the
-//               properties.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-clear_aux_hrgba() {
-  _specified &= ~S_aux_hrgba;
-  _aux_hrgba = 0;
-  recalc_buffer_mask();
+set_aux_hrgba(int n) {
+  _property[FBP_aux_hrgba] = n;
+  _specified[FBP_aux_hrgba] = true;
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: FrameBufferProperties::set_aux_float
 //       Access: Published
-//  Description: Specifies the exact number of auxiliary float
-//               single-channel bitplanes that are required.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-set_aux_float(int aux_float) {
-  _aux_float = aux_float;
-  _specified |= S_aux_float;
-  recalc_buffer_mask();
+set_aux_float(int n) {
+  _property[FBP_aux_float] = n;
+  _specified[FBP_aux_float] = true;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::get_aux_float
+//     Function: FrameBufferProperties::set_multisamples
 //       Access: Published
-//  Description: Returns the exact number of auxiliary float
-//               single-channel bitplanes that are required.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE int FrameBufferProperties::
-get_aux_float() const {
-  return _aux_float;
+INLINE void FrameBufferProperties::
+set_multisamples(int n) {
+  _property[FBP_multisamples] = n;
+  _specified[FBP_multisamples] = true;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::has_aux_float
+//     Function: FrameBufferProperties::set_back_buffers
 //       Access: Published
-//  Description: Returns true if the number of auxiliary float
-//               single-channel bitplanes has been specified, false
-//               otherwise.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE bool FrameBufferProperties::
-has_aux_float() const {
-  return ((_specified & S_aux_float) != 0);
+INLINE void FrameBufferProperties::
+set_back_buffers(int n) {
+  _property[FBP_back_buffers] = n;
+  _specified[FBP_back_buffers] = true;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::clear_aux_float
+//     Function: FrameBufferProperties::set_indexed_color
 //       Access: Published
-//  Description: Removes the aux_float specification from the
-//               properties.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-clear_aux_float() {
-  _specified &= ~S_aux_float;
-  _aux_float = 0;
-  recalc_buffer_mask();
+set_indexed_color(int n) {
+  _property[FBP_indexed_color] = n;
+  _specified[FBP_indexed_color] = true;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::set_specified
+//     Function: FrameBufferProperties::set_rgb_color
 //       Access: Published
-//  Description: Sets all the specified bits.  Effectively, this
-//               causes the default values to be specified for all
-//               not-yet-specified fields.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-set_specified() {
-  _specified = S_ALL_SPECIFIED;
-  recalc_buffer_mask();
+set_rgb_color(int n) {
+  _property[FBP_rgb_color] = n;
+  _specified[FBP_rgb_color] = true;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::get_specified
-//       Access: Public
-//  Description: Returns the specified flags.
-////////////////////////////////////////////////////////////////////
-INLINE int FrameBufferProperties::
-get_specified() const {
-  return _specified;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::get_buffer_mask
-//       Access: Public
-//  Description: Returns the buffer mask for the bitplanes
-//               in the frame buffer.
+//     Function: FrameBufferProperties::set_stereo
+//       Access: Published
+//  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE int FrameBufferProperties::
-get_buffer_mask() const {
-  return _buffer_mask;
+INLINE void FrameBufferProperties::
+set_stereo(int n) {
+  _property[FBP_stereo] = n;
+  _specified[FBP_stereo] = true;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::buffer_mask_remove
-//       Access: Public
-//  Description: Removes one or more bits from the buffer mask.
-//               This is generally called by the gsg when one of the
-//               bitplanes is failing for some implementation-
-//               dependent reason.  Changing the properties will
-//               cause the _buffer_mask information to be lost.
+//     Function: FrameBufferProperties::set_force_hardware
+//       Access: Published
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-buffer_mask_remove(int bits) {
-  _buffer_mask &= (~bits);
+set_force_hardware(int n) {
+  _property[FBP_force_hardware] = n;
+  _specified[FBP_force_hardware] = true;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::buffer_mask_add
-//       Access: Public
-//  Description: Adds one or more bits to the buffer mask.
-//               This is generally called by the gsg when the
-//               implementation supplies a bitplane that was not
-//               specifically requested (say, a freebie stencil
-//               buffer). Changing the properties will
-//               cause the _buffer_mask information to be lost.
+//     Function: FrameBufferProperties::set_force_software
+//       Access: Published
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-buffer_mask_add(int bits) {
-  _buffer_mask |= bits;
-}
-
-INLINE ostream &
-operator << (ostream &out, const FrameBufferProperties &properties) {
-  properties.output(out);
-  return out;
+set_force_software(int n) {
+  _property[FBP_force_software] = n;
+  _specified[FBP_force_software] = true;
 }

+ 395 - 228
panda/src/display/frameBufferProperties.cxx

@@ -38,18 +38,10 @@ FrameBufferProperties() {
 ////////////////////////////////////////////////////////////////////
 void FrameBufferProperties::
 operator = (const FrameBufferProperties &copy) {
-  _specified = copy._specified;
-  _flags = copy._flags;
-  _frame_buffer_mode = copy._frame_buffer_mode;
-  _depth_bits = copy._depth_bits;
-  _color_bits = copy._color_bits;
-  _alpha_bits = copy._alpha_bits;
-  _stencil_bits = copy._stencil_bits;
-  _multisamples = copy._multisamples;
-  _aux_rgba = copy._aux_rgba;
-  _aux_hrgba = copy._aux_hrgba;
-  _aux_float = copy._aux_float;
-  _buffer_mask = copy._buffer_mask;
+  for (int i=0; i<FBP_COUNT; i++) {
+    _specified[i] = copy._specified[i];
+    _property[i]  = copy._property[i];
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -61,52 +53,8 @@ operator = (const FrameBufferProperties &copy) {
 ////////////////////////////////////////////////////////////////////
 bool FrameBufferProperties::
 subsumes(const FrameBufferProperties &other) const {
-  if (other._specified & S_depth_bits) {
-    if (((_specified & S_depth_bits)==0) || (other._depth_bits > _depth_bits)) {
-      return false;
-    }
-  }
-  if (other._specified & S_color_bits) {
-    if (((_specified & S_color_bits)==0) || (other._color_bits > _color_bits)) {
-      return false;
-    }
-  }
-  if (other._specified & S_alpha_bits) {
-    if (((_specified & S_alpha_bits)==0) || (other._alpha_bits > _alpha_bits)) {
-      return false;
-    }
-  }
-  if (other._specified & S_stencil_bits) {
-    if (((_specified & S_stencil_bits)==0) || (other._stencil_bits > _stencil_bits)) {
-      return false;
-    }
-  }
-  if ((other._specified & S_multisamples) && (other._multisamples > 1)) {
-    // Multisample spec of 1 is ignored - 1 multisample is tautologous.
-    if (((_specified & S_multisamples)==0) || (other._multisamples > _multisamples)) {
-      return false;
-    }
-  }
-  if (other._specified & S_aux_rgba) {
-    if (((_specified & S_aux_rgba)==0) || (other._aux_rgba > _aux_rgba)) {
-      return false;
-    }
-  }
-  if (other._specified & S_aux_hrgba) {
-    if (((_specified & S_aux_hrgba)==0) || (other._aux_hrgba > _aux_hrgba)) {
-      return false;
-    }
-  }
-  if (other._specified & S_aux_float) {
-    if (((_specified & S_aux_float)==0) || (other._aux_float > _aux_float)) {
-      return false;
-    }
-  }
-  if (other._specified & S_frame_buffer_mode) {
-    if ((_specified & S_frame_buffer_mode)==0) {
-      return false;
-    }
-    if (other._frame_buffer_mode & (~_frame_buffer_mode)) {
+  for (int i=0; i<FBP_COUNT; i++) {
+    if (other._property[i] > _property[i]) {
       return false;
     }
   }
@@ -120,59 +68,70 @@ subsumes(const FrameBufferProperties &other) const {
 //               the default values filled in according to the user's
 //               config file.
 ////////////////////////////////////////////////////////////////////
-FrameBufferProperties FrameBufferProperties::
+const FrameBufferProperties &FrameBufferProperties::
 get_default() {
+  static bool                  default_ready = false;
+  static FrameBufferProperties default_props;
 
-  FrameBufferProperties props;
+  if (default_ready) {
+    return default_props;
+  }
 
-  int mode = 0;
+  default_props._property[FBP_rgb_color] = 1;
+  
   int num_words = framebuffer_mode.get_num_words();
   for (int i = 0; i < num_words; i++) {
     string word = framebuffer_mode.get_word(i);
     if (cmp_nocase_uh(word, "rgb") == 0) {
-      mode |= FM_rgb;
+      default_props._property[FBP_indexed_color] = 0;
+      default_props._property[FBP_rgb_color] = 1;
 
     } else if (cmp_nocase_uh(word, "index") == 0) {
-      mode |= FM_index;
+      default_props._property[FBP_indexed_color] = 1;
+      default_props._property[FBP_rgb_color] = 0;
 
     } else if (cmp_nocase_uh(word, "single") == 0 ||
                cmp_nocase_uh(word, "single-buffer") == 0) {
-      mode = (mode & ~FM_buffer) | FM_single_buffer;
+      default_props._property[FBP_back_buffers] = 0;
 
     } else if (cmp_nocase_uh(word, "double") == 0 ||
                cmp_nocase_uh(word, "double-buffer") == 0) {
-      mode = (mode & ~FM_buffer) | FM_double_buffer;
+      default_props._property[FBP_back_buffers] = 1;
 
     } else if (cmp_nocase_uh(word, "triple") == 0 ||
                cmp_nocase_uh(word, "triple-buffer") == 0) {
-      mode = (mode & ~FM_buffer) | FM_triple_buffer;
+      default_props._property[FBP_back_buffers] = 2;
 
     } else if (cmp_nocase_uh(word, "accum") == 0) {
-      mode |= FM_accum;
+      default_props._property[FBP_accum_bits] = 1;
 
     } else if (cmp_nocase_uh(word, "alpha") == 0) {
-      mode |= FM_alpha;
-
+      default_props._property[FBP_indexed_color] = 0;
+      default_props._property[FBP_rgb_color] = 1;
+      default_props._property[FBP_alpha_bits] = 1;
+      
     } else if (cmp_nocase_uh(word, "rgba") == 0) {
-      mode |= FM_rgba;
-
+      default_props._property[FBP_indexed_color] = 0;
+      default_props._property[FBP_rgb_color] = 1;
+      default_props._property[FBP_alpha_bits] = 1;
+      
     } else if (cmp_nocase_uh(word, "depth") == 0) {
-      mode |= FM_depth;
+      default_props._property[FBP_depth_bits] = 1;
 
     } else if (cmp_nocase_uh(word, "stencil") == 0) {
-      mode |= FM_stencil;
+      default_props._property[FBP_stencil_bits] = 1;
 
     } else if (cmp_nocase_uh(word, "multisample") == 0) {
-      mode |= FM_multisample;
+      default_props._property[FBP_multisamples] = 1;
 
     } else if (cmp_nocase_uh(word, "stereo") == 0) {
-      mode |= FM_stereo;
+      default_props._property[FBP_stereo] = 1;
 
     } else if (cmp_nocase_uh(word, "software") == 0) {
-      mode |= FM_software;
+      default_props._property[FBP_force_software] = 1;
 
     } else if (cmp_nocase_uh(word, "hardware") == 0) {
-      mode |= FM_hardware;
+      default_props._property[FBP_force_hardware] = 1;
 
     } else {
       display_cat.warning()
@@ -180,38 +139,14 @@ get_default() {
     }
   }
 
-  if (framebuffer_hardware) {
-    mode |= FM_hardware;
-  }
-  if (framebuffer_software) {
-    mode |= FM_software;
-  }
-  if (framebuffer_multisample) {
-    mode |= FM_multisample;
-  }
-  if (framebuffer_depth) {
-    mode |= FM_depth;
-  }
-  if (framebuffer_alpha) {
-    mode |= FM_alpha;
-  }
-  if (framebuffer_stereo) {
-    mode |= FM_stereo;
-  }
-  if ((mode & FM_hardware) && (mode & FM_software)) {
-    mode = mode & ~(FM_hardware | FM_software);
+  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;
   }
 
-  props.set_frame_buffer_mode(mode);
-  props.set_depth_bits(depth_bits);
-  props.set_color_bits(color_bits);
-  props.set_alpha_bits(alpha_bits);
-  props.set_stencil_bits(stencil_bits);
-  props.set_multisamples(multisamples);
-
-  props.recalc_buffer_mask();
-
-  return props;
+  default_ready = true;
+  return default_props;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -221,18 +156,15 @@ get_default() {
 ////////////////////////////////////////////////////////////////////
 bool FrameBufferProperties::
 operator == (const FrameBufferProperties &other) const {
-  return (_specified == other._specified &&
-          _flags == other._flags &&
-          _frame_buffer_mode == other._frame_buffer_mode &&
-          _depth_bits == other._depth_bits &&
-          _color_bits == other._color_bits &&
-          _alpha_bits == other._alpha_bits &&
-          _stencil_bits == other._stencil_bits &&
-          _multisamples == other._multisamples &&
-          _aux_rgba == other._aux_rgba &&
-          _aux_hrgba == other._aux_hrgba &&
-          _aux_float == other._aux_float &&
-          _buffer_mask == other._buffer_mask);
+  for (int i=0; i<FBP_COUNT; i++) {
+    if (_specified[i] != other._specified[i]) {
+      return false;
+    }
+    if (_property[i] != other._property[i]) {
+      return false;
+    }
+  }
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -244,18 +176,10 @@ operator == (const FrameBufferProperties &other) const {
 ////////////////////////////////////////////////////////////////////
 void FrameBufferProperties::
 clear() {
-  _specified = 0;
-  _flags = 0;
-  _frame_buffer_mode = 0;
-  _depth_bits = 1;
-  _color_bits = 1;
-  _alpha_bits = 1;
-  _stencil_bits = 1;
-  _multisamples = 1;
-  _aux_rgba = 0;
-  _aux_hrgba = 0;
-  _aux_float = 0;
-  recalc_buffer_mask();
+  for (int i=0; i<FBP_COUNT; i++) {
+    _specified[i] = 0;
+    _property[i] = 0;
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -267,139 +191,382 @@ clear() {
 ////////////////////////////////////////////////////////////////////
 void FrameBufferProperties::
 add_properties(const FrameBufferProperties &other) {
-  if (other.has_frame_buffer_mode()) {
-    set_frame_buffer_mode(other.get_frame_buffer_mode());
+  for (int i=0; i<FBP_COUNT; i++) {
+    if (other._specified[i]) {
+      _property[i] = other._property[i];
+      _specified[i] = true;
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::output
+//       Access: Published
+//  Description: Sets any properties that are explicitly specified in
+//               other on this object.  Leaves other properties
+//               unchanged.
+////////////////////////////////////////////////////////////////////
+void FrameBufferProperties::
+output(ostream &out) const {
+  if (_property[FBP_depth_bits] > 0) {
+    out << "depth_bits=" << _property[FBP_depth_bits] << " ";
+  }
+  if (_property[FBP_color_bits] > 0) {
+    out << "color_bits=" << _property[FBP_color_bits] << " ";
+  }
+  if (_property[FBP_alpha_bits] > 0) {
+    out << "alpha_bits=" << _property[FBP_alpha_bits] << " ";
+  }
+  if (_property[FBP_stencil_bits] > 0) {
+    out << "stencil_bits=" << _property[FBP_stencil_bits] << " ";
+  }
+  if (_property[FBP_accum_bits] > 0) {
+    out << "accum_bits=" << _property[FBP_accum_bits] << " ";
   }
-  if (other.has_depth_bits()) {
-    set_depth_bits(other.get_depth_bits());
+  if (_property[FBP_aux_rgba] > 0) {
+    out << "aux_rgba=" << _property[FBP_aux_rgba] << " ";
   }
-  if (other.has_color_bits()) {
-    set_color_bits(other.get_color_bits());
+  if (_property[FBP_aux_hrgba] > 0) {
+    out << "aux_hrgba=" << _property[FBP_aux_hrgba] << " ";
   }
-  if (other.has_alpha_bits()) {
-    set_alpha_bits(other.get_alpha_bits());
+  if (_property[FBP_aux_float] > 0) {
+    out << "aux_float=" << _property[FBP_aux_float] << " ";
   }
-  if (other.has_stencil_bits()) {
-    set_stencil_bits(other.get_stencil_bits());
+  if (_property[FBP_multisamples] > 0) {
+    out << "multisamples=" << _property[FBP_multisamples] << " ";
   }
-  if (other.has_multisamples()) {
-    set_multisamples(other.get_multisamples());
+  if (_property[FBP_back_buffers] > 0) {
+    out << "back_buffers=" << _property[FBP_back_buffers] << " ";
   }
-  if (other.has_aux_rgba()) {
-    set_aux_rgba(other.get_aux_rgba());
+  if (_property[FBP_indexed_color] > 0) {
+    out << "indexed_color=" << _property[FBP_indexed_color] << " ";
   }
-  if (other.has_aux_hrgba()) {
-    set_aux_hrgba(other.get_aux_hrgba());
+  if (_property[FBP_stereo] > 0) {
+    out << "stereo=" << _property[FBP_stereo] << " ";
   }
-  if (other.has_aux_float()) {
-    set_aux_float(other.get_aux_float());
+  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] << " ";
   }
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::output
+//     Function: FrameBufferProperties::get_buffer_mask
+//       Access: Private
+//  Description: Converts the framebuffer properties into 
+//               a RenderBuffer::Type.
+////////////////////////////////////////////////////////////////////
+int FrameBufferProperties::
+get_buffer_mask() const {
+  int mask = 0;
+  
+  if (_property[FBP_back_buffers] > 0) {
+    mask = RenderBuffer::T_front | RenderBuffer::T_back;
+  } else {
+    mask = RenderBuffer::T_front;
+  }
+  if (_property[FBP_depth_bits] > 0) {
+    mask |= RenderBuffer::T_depth;
+  }
+  if (_property[FBP_stencil_bits] > 0) {
+    mask |= RenderBuffer::T_stencil;
+  }
+  for (int aux_rgba=0; aux_rgba < _property[FBP_aux_rgba]; ++aux_rgba) {
+    mask |= (RenderBuffer::T_aux_rgba_0 << aux_rgba);
+  }
+  for (int aux_hrgba=0; aux_hrgba < _property[FBP_aux_hrgba]; ++aux_hrgba) {
+    mask |= (RenderBuffer::T_aux_hrgba_0 << aux_hrgba);
+  }
+  for (int aux_float=0; aux_float < _property[FBP_aux_float]; ++aux_float) {
+    mask |= (RenderBuffer::T_aux_float_0 << aux_float);
+  }
+  
+  return mask;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::is_any_specified
 //       Access: Published
-//  Description: Sets any properties that are explicitly specified in
-//               other on this object.  Leaves other properties
-//               unchanged.
+//  Description: Returns true if any properties have been specified,
+//               false otherwise.
 ////////////////////////////////////////////////////////////////////
-void FrameBufferProperties::
-output(ostream &out) const {
-  if (has_frame_buffer_mode()) {
-    out << "frameBuffer_mode=";
-    int frameBuffer_mode = get_frame_buffer_mode();
-    if ((frameBuffer_mode & FM_index) != 0) {
-      out << "FM_index";
-    } else {
-      out << "FM_rgb";
+bool FrameBufferProperties::
+is_any_specified() const {
+  for (int i=0; i<FBP_COUNT; i++) {
+    if (_specified[i]) {
+      return true;
     }
+  }
+  return false;
+}
 
-    if ((frameBuffer_mode & FM_triple_buffer) != 0) {
-      out << "|FM_triple_buffer";
-    } else if ((frameBuffer_mode & FM_double_buffer) != 0) {
-      out << "|FM_double_buffer";
-    } else {
-      out << "|FM_single_buffer";
-    }
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::set_all_specified
+//       Access: Published
+//  Description: sets all the specified bits.
+////////////////////////////////////////////////////////////////////
+void FrameBufferProperties::
+set_all_specified() {
+  for (int i=0; i<FBP_COUNT; i++) {
+    _specified[i] = true;
+  }
+}
 
-    if ((frameBuffer_mode & FM_accum) != 0) {
-      out << "|FM_accum";
-    }
-    if ((frameBuffer_mode & FM_alpha) != 0) {
-      out << "|FM_alpha";
-    }
-    if ((frameBuffer_mode & FM_depth) != 0) {
-      out << "|FM_depth";
-    }
-    if ((frameBuffer_mode & FM_stencil) != 0) {
-      out << "|FM_stencil";
-    }
-    if ((frameBuffer_mode & FM_multisample) != 0) {
-      out << "|FM_multisample";
-    }
-    if ((frameBuffer_mode & FM_stereo) != 0) {
-      out << "|FM_stereo";
-    }
-    if ((frameBuffer_mode & FM_software) != 0) {
-      out << "|FM_software";
-    }
-    if ((frameBuffer_mode & FM_hardware) != 0) {
-      out << "|FM_hardware";
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::get_property_set
+//       Access: Published
+//  Description: returns a summary of which properties are nonzero.
+////////////////////////////////////////////////////////////////////
+int FrameBufferProperties::
+get_property_set() const {
+  int result = 0;
+  for (int i=0; i<FBP_COUNT; i++) {
+    if (_property[i]) {
+      result |= (1<<i);
     }
-    out << " ";
   }
-  if (has_depth_bits()) {
-    out << "depth_bits=" << get_depth_bits() << " ";
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::is_basic
+//       Access: Published
+//  Description: Returns true if the properties are extremely basic.
+//               The following count as basic: rgb or rgba, depth.
+//               If anything else is specified, the properties are
+//               non-basic.
+////////////////////////////////////////////////////////////////////
+bool FrameBufferProperties::
+is_basic() const {
+  if (_property[FBP_depth_bits] > 1) {
+    return false;
+  }
+  if (_property[FBP_color_bits] > 1) {
+    return false;
+  }
+  if (_property[FBP_alpha_bits] > 1) {
+    return false;
+  }
+  if (_property[FBP_stencil_bits] > 0) {
+    return false;
+  }
+  if (_property[FBP_aux_rgba] > 0) {
+    return false;
   }
-  if (has_color_bits()) {
-    out << "color_bits=" << get_color_bits() << " ";
+  if (_property[FBP_aux_hrgba] > 0) {
+    return false;
   }
-  if (has_alpha_bits()) {
-    out << "alpha_bits=" << get_alpha_bits() << " ";
+  if (_property[FBP_aux_float] > 0) {
+    return false;
   }
-  if (has_stencil_bits()) {
-    out << "stencil_bits=" << get_stencil_bits() << " ";
+  if (_property[FBP_multisamples] > 1) {
+    return false;
   }
-  if (has_multisamples()) {
-    out << "multisamples=" << get_multisamples() << " ";
+  if (_property[FBP_back_buffers] > 0) {
+    return false;
   }
-  if (has_aux_rgba()) {
-    out << "aux_rgba=" << get_aux_rgba() << " ";
+  if (_property[FBP_indexed_color] > 0) {
+    return false;
   }
-  if (has_aux_hrgba()) {
-    out << "aux_hrgba=" << get_aux_hrgba() << " ";
+  if (_property[FBP_force_hardware] > 0) {
+    return false;
   }
-  if (has_aux_float()) {
-    out << "aux_float=" << get_aux_float() << " ";
+  if (_property[FBP_force_software] > 0) {
+    return false;
   }
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: FrameBufferProperties::recalc_buffer_mask
-//       Access: Private
-//  Description: Calculates the buffer mask based on the mode
-//               and aux bitplanes.
+//     Function: FrameBufferProperties::set_one_bit_per_channel
+//       Access: Published
+//  Description: If any of the depth, color, alpha, accum, or
+//               stencil properties is set to more than one,
+//               then they are reduced to one.
 ////////////////////////////////////////////////////////////////////
 void FrameBufferProperties::
-recalc_buffer_mask() {
-  if ((_frame_buffer_mode & FM_buffer) == FM_single_buffer) {
-    _buffer_mask = RenderBuffer::T_front;
-  } else {
-    _buffer_mask = RenderBuffer::T_front | RenderBuffer::T_back;
+set_one_bit_per_channel() {
+  for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; ++prop) {
+    if (_property[prop] > 1) {
+      _property[prop] = 1;
+    }
   }
-  if (_frame_buffer_mode & FM_depth) {
-    _buffer_mask |= RenderBuffer::T_depth;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::get_quality
+//       Access: Published
+//  Description: Assumes that these properties are a description of
+//               a window.
+//
+//               Measures how well this window satisfies a specified
+//               set of requirements.  A higher quality number means
+//               that more requirements were satisfied.  A quality of
+//               zero means that the window is unsuitable.
+//
+//               The routine deducts a lot if the window fails to
+//               provide a requested feature.  It deducts less
+//               if the window provides a feature, but at a degraded
+//               level of functionality (ie, the user asks for rgba8,
+//               color, but the window only provides rgba4).  The
+//               routine also deducts a small amount for unnecessary
+//               features.  For example, if the window has an
+//               accumulation buffer when one is not requested will
+//               reduce quality slightly.  Maximum quality is obtained
+//               when the window exactly matches the request.
+//
+//               If you want to know whether the window satisfies
+//               all of the requirements, use the "subsumes" function.
+////////////////////////////////////////////////////////////////////
+int FrameBufferProperties::
+get_quality(const FrameBufferProperties &reqs) const {
+
+  if ((_property[FBP_indexed_color]==0) && (_property[FBP_rgb_color]==0)) {
+    // Nonfunctioning window.
+    return 0;
+  }
+  
+  if ((reqs._property[FBP_rgb_color]      > _property[FBP_rgb_color])||
+      (reqs._property[FBP_indexed_color]  > _property[FBP_indexed_color])) {
+    // These properties are nonnegotiable.
+    return 0;
+  }
+
+  int quality = 100000000;
+
+  // 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])) {
+    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)) {
+      quality -= 1000000;
+    }
+  }
+
+  // Deduct for missing aux bitplanes.
+  // Cost: 100,000
+
+  for (int prop=FBP_aux_rgba; prop<=FBP_aux_float; prop++) {
+    if (reqs._property[prop] > _property[prop]) {
+      quality -= 100000;
+    }
+  }
+
+  // Deduct for stereo not enabled.
+  // Cost: 100,000
+
+  if (reqs._property[FBP_stereo] > _property[FBP_stereo]) {
+    quality -= 100000;
+  }
+
+  // Deduct for insufficient back-buffers.
+  // Cost: 100,000
+  
+  if (reqs._property[FBP_back_buffers] > _property[FBP_back_buffers]) {
+    quality -= 100000;
+  }
+
+  // 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++) {
+    if (reqs._property[prop] > _property[prop]) {
+      quality -= 10000;
+    }
   }
-  if (_frame_buffer_mode & FM_stencil) {
-    _buffer_mask |= RenderBuffer::T_stencil;
+
+  // deduct for insufficient multisamples.
+  // Cost: 1,000
+
+  if (reqs._property[FBP_multisamples] > _property[FBP_multisamples]) {
+    quality -= 1000;
   }
-  for (int aux_rgba=0; aux_rgba < _aux_rgba; ++aux_rgba) {
-    _buffer_mask |= (RenderBuffer::T_aux_rgba_0 << aux_rgba);
+
+  // Deduct for unrequested bitplanes.
+  // Cost: 10
+  
+  for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; prop++) {
+    if ((_property[prop]) && (reqs._property[prop] == 0)) {
+      quality -= 10;
+    }
   }
-  for (int aux_hrgba=0; aux_hrgba < _aux_hrgba; ++aux_hrgba) {
-    _buffer_mask |= (RenderBuffer::T_aux_hrgba_0 << aux_hrgba);
+  for (int prop=FBP_aux_rgba; prop<=FBP_aux_float; prop++) {
+    int extra = _property[prop] > reqs._property[prop];
+    if (extra > 0) {
+      if (extra > 3) {
+        quality -= 30;
+      } else {
+        quality -= extra*10;
+      }
+    }
   }
-  for (int aux_float=0; aux_float < _aux_float; ++aux_float) {
-    _buffer_mask |= (RenderBuffer::T_aux_float_0 << aux_float);
+  
+  // Deduct for excessive resolution in any bitplane.
+  // Cost: 10
+  
+  for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; prop++) {
+    if (reqs._property[prop] <= 8) {
+      if (_property[prop] > 8) {
+        quality -= 10;
+      }
+    }
+    if (reqs._property[prop] <= 32) {
+      if (_property[prop] > 32) {
+        quality -= 10;
+      }
+    }
   }
+  
+  return quality;
+};
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::verify_hardware_software
+//       Access: Public
+//  Description: Validates that the properties represent the desired
+//               kind of renderer (hardware or software).  If not,
+//               prints out an error message and returns false.
+////////////////////////////////////////////////////////////////////
+bool FrameBufferProperties::
+verify_hardware_software(const FrameBufferProperties &props, const string &renderer) const {
+
+  if (get_force_hardware() < props.get_force_hardware()) {
+    display_cat.error()
+      << "The application requested harware acceleration, but your OpenGL\n";
+    display_cat.error()
+      << "driver, " << renderer << ", only supports software rendering.\n";
+    display_cat.error()
+      << "You need to install a hardware-accelerated OpenGL driver, or,\n";
+    display_cat.error()
+      << "if you actually *want* to use a software renderer, then\n";
+    display_cat.error()
+      << "change the word 'hardware' to 'software' in the Config.prc file.\n";
+    return false;
+  }
+
+  if (get_force_software() < props.get_force_software()) {
+    display_cat.error()
+      << "The application requested a software renderer, but your OpenGL\n";
+    display_cat.error()
+      << "driver, " << renderer << ", is probably hardware-accelerated.\n";
+    display_cat.error()
+      << "If you want to allow hardware acceleration, then change the word\n";
+    display_cat.error()
+      << "'software' to 'hardware' in the Config.prc file.\n";
+    return false;
+  }
+  
+  return true;
 }
+
+

+ 78 - 112
panda/src/display/frameBufferProperties.h

@@ -29,132 +29,98 @@
 //               create a GSG.
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA FrameBufferProperties {
-PUBLISHED:
-  FrameBufferProperties();
-  INLINE FrameBufferProperties(const FrameBufferProperties &copy);
-  void operator = (const FrameBufferProperties &copy);
-  INLINE ~FrameBufferProperties();
-
-  static FrameBufferProperties get_default();
-
-  bool operator == (const FrameBufferProperties &other) const;
-  INLINE bool operator != (const FrameBufferProperties &other) const;
-
-  enum FrameBufferMode {
-    FM_rgb            = 0x0000,
-    FM_index          = 0x0001,
-    FM_single_buffer  = 0x0000,
-    FM_double_buffer  = 0x0002,
-    FM_triple_buffer  = 0x0006,
-    FM_buffer         = 0x0006,  // == (FM_single_buffer | FM_double_buffer | FM_triple_buffer)
-    FM_accum          = 0x0008,
-    FM_alpha          = 0x0010,
-    FM_rgba           = 0x0010,  // == (FM_rgb | FM_alpha)
-    FM_depth          = 0x0020,
-    FM_stencil        = 0x0040,
-    FM_multisample    = 0x0080,
-    FM_stereo         = 0x0100,
-    FM_software       = 0x0200,
-    FM_hardware       = 0x0400,
-  };
 
-  // This bitmask indicates which of the parameters in the properties
-  // structure have been filled in by the user, and which remain
-  // unspecified.
-  enum Specified {
-    S_frame_buffer_mode = 0x0001,
-    S_depth_bits        = 0x0002,
-    S_color_bits        = 0x0004,
-    S_alpha_bits        = 0x0008,
-    S_stencil_bits      = 0x0010,
-    S_multisamples      = 0x0020,
-    S_aux_rgba          = 0x0040,
-    S_aux_hrgba         = 0x0080,
-    S_aux_float         = 0x0100,
-    S_ALL_SPECIFIED     = 0x01FF,
+private:
+  enum FrameBufferProperty {
+    // This section has to start with "depth" and end with "accum"
+    FBP_depth_bits,
+    FBP_color_bits,
+    FBP_alpha_bits,
+    FBP_stencil_bits,
+    FBP_accum_bits,
+
+    // This section has to start with "rgba" and end with "float"
+    FBP_aux_rgba,
+    FBP_aux_hrgba,
+    FBP_aux_float,
+
+    // This section can be in any order.
+    FBP_multisamples,
+    FBP_back_buffers,
+    FBP_indexed_color,
+    FBP_rgb_color,
+    FBP_stereo,
+    FBP_force_hardware,
+    FBP_force_software,
+    
+    // This is a sentinel value.
+    FBP_COUNT
   };
   
-  void clear();
-  INLINE void set_specified();
-  INLINE int get_specified() const;
-  INLINE int get_buffer_mask() const;
-  INLINE bool is_any_specified() const;
-  INLINE bool specifies_mode(int bit) const;
-  INLINE bool is_single_buffered() const;
-  INLINE bool is_stereo() const;
-  INLINE bool is_basic() const;
-  
-  bool subsumes(const FrameBufferProperties &prop) const;
-  
-  INLINE void set_frame_buffer_mode(int frameBuffer_mode);
-  INLINE int get_frame_buffer_mode() const;
-  INLINE bool has_frame_buffer_mode() const;
-  INLINE void clear_frame_buffer_mode();
+  int _property[FBP_COUNT];
+  int _specified[FBP_COUNT];
 
-  INLINE void set_depth_bits(int depth_bits);
-  INLINE int get_depth_bits() const;
-  INLINE bool has_depth_bits() const;
-  INLINE void clear_depth_bits();
+PUBLISHED:
 
-  INLINE void set_color_bits(int color_bits);
+  // Individual queries.
+  INLINE int get_depth_bits() const;
   INLINE int get_color_bits() const;
-  INLINE bool has_color_bits() const;
-  INLINE void clear_color_bits();
-
-  INLINE void set_alpha_bits(int alpha_bits);
   INLINE int get_alpha_bits() const;
-  INLINE bool has_alpha_bits() const;
-  INLINE void clear_alpha_bits();
-
-  INLINE void set_stencil_bits(int stencil_bits);
   INLINE int get_stencil_bits() const;
-  INLINE bool has_stencil_bits() const;
-  INLINE void clear_stencil_bits();
-
-  INLINE void set_multisamples(int multisamples);
-  INLINE int get_multisamples() const;
-  INLINE bool has_multisamples() const;
-  INLINE void clear_multisamples();
-
-  INLINE void set_aux_rgba(int naux);
+  INLINE int get_accum_bits() const;
   INLINE int get_aux_rgba() const;
-  INLINE bool has_aux_rgba() const;
-  INLINE void clear_aux_rgba();
-  
-  INLINE void set_aux_hrgba(int naux);
   INLINE int get_aux_hrgba() const;
-  INLINE bool has_aux_hrgba() const;
-  INLINE void clear_aux_hrgba();
-
-  INLINE void set_aux_float(int naux);
   INLINE int get_aux_float() const;
-  INLINE bool has_aux_float() const;
-  INLINE void clear_aux_float();
+  INLINE int get_multisamples() 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;
+
+  // Individual assigners.
+  INLINE void set_depth_bits(int n);
+  INLINE void set_color_bits(int n);
+  INLINE void set_alpha_bits(int n);
+  INLINE void set_stencil_bits(int n);
+  INLINE void set_accum_bits(int n);
+  INLINE void set_aux_rgba(int n);
+  INLINE void set_aux_hrgba(int n);
+  INLINE void set_aux_float(int n);
+  INLINE void set_multisamples(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);
+
+  // Other.
+
+  FrameBufferProperties();
+  INLINE FrameBufferProperties(const FrameBufferProperties &copy);
+  INLINE ~FrameBufferProperties();
+  void operator = (const FrameBufferProperties &copy);
+  static const FrameBufferProperties &get_default();
+  bool operator == (const FrameBufferProperties &other) const;
+  INLINE bool operator != (const FrameBufferProperties &other) const;
 
+  void clear();
+  void set_all_specified();
+  bool subsumes(const FrameBufferProperties &other) const;
   void add_properties(const FrameBufferProperties &other);
   void output(ostream &out) const;
-
-public:
-  INLINE void buffer_mask_add(int bits);
-  INLINE void buffer_mask_remove(int bits);
-
-private:
-  void recalc_buffer_mask();
-
-private:
-
-  int _specified;
-  int _flags;
-  int _frame_buffer_mode;
-  int _depth_bits;
-  int _color_bits;
-  int _alpha_bits;
-  int _stencil_bits;
-  int _multisamples;
-  int _aux_rgba;
-  int _aux_hrgba;
-  int _aux_float;
-  int _buffer_mask;
+  void set_one_bit_per_channel();
+  
+  bool is_stereo() const;
+  bool is_single_buffered() const;
+  int get_quality(const FrameBufferProperties &reqs) const;
+  bool is_any_specified() const;
+  bool is_basic() const;
+  int get_buffer_mask() const;
+  int get_property_set() const;
+  bool verify_hardware_software(const FrameBufferProperties &props, const string &renderer) const;
 };
 
 INLINE ostream &operator << (ostream &out, const FrameBufferProperties &properties);

+ 10 - 36
panda/src/display/graphicsEngine.I

@@ -91,31 +91,6 @@ close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) {
   pipe->close_gsg(gsg);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsEngine::make_gsg
-//       Access: Published
-//  Description: Creates a new gsg using the indicated GraphicsPipe
-//               and returns it.  The GraphicsEngine does not
-//               officially own the pointer to the gsg; but if any
-//               windows are created using this GSG, the
-//               GraphicsEngine will own the pointers to these
-//               windows, which in turn will own the pointer to the
-//               GSG.
-//
-//               There is no explicit way to release a GSG, but it
-//               will be destructed when all windows that reference it
-//               are destructed, and the draw thread that owns the GSG
-//               runs one more time.
-//
-//               This flavor of make_gsg() uses the default
-//               frame buffer properties, specified via
-//               set_frame_buffer_properties().
-////////////////////////////////////////////////////////////////////
-INLINE PT(GraphicsStateGuardian) GraphicsEngine::
-make_gsg(GraphicsPipe *pipe) {
-  return make_gsg(pipe, get_frame_buffer_properties(), NULL);
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::make_window
 //       Access: Published
@@ -124,8 +99,9 @@ make_gsg(GraphicsPipe *pipe) {
 INLINE GraphicsWindow *GraphicsEngine::
 make_window(GraphicsStateGuardian *gsg, const string &name, int sort) {
   // The hardwired size here is never used.
+  FrameBufferProperties fbprops = FrameBufferProperties::get_default();
   GraphicsOutput *result = make_output(gsg->get_pipe(), name, sort,
-                                       gsg->get_default_properties(), 50, 50,
+                                       fbprops, 50, 50,
                                        GraphicsPipe::BF_require_window |
                                        GraphicsPipe::BF_fb_props_optional,
                                        gsg, NULL);
@@ -140,17 +116,15 @@ make_window(GraphicsStateGuardian *gsg, const string &name, int sort) {
 INLINE GraphicsOutput *GraphicsEngine::
 make_buffer(GraphicsStateGuardian *gsg, const string &name,
             int sort, int x_size, int y_size) {
-  FrameBufferProperties props = gsg->get_default_properties();
-  int clear =
-        FrameBufferProperties::FM_buffer |
-        FrameBufferProperties::FM_stereo |
-        FrameBufferProperties::FM_accum |
-        FrameBufferProperties::FM_multisample |
-        FrameBufferProperties::FM_hardware |
-        FrameBufferProperties::FM_software;
-  props.set_frame_buffer_mode(props.get_frame_buffer_mode() & (~clear));
+  FrameBufferProperties props = FrameBufferProperties::get_default();
+  props.set_back_buffers(0);
+  props.set_stereo(0);
+  props.set_accum_bits(0);
+  props.set_multisamples(0);
+  props.set_force_hardware(0);
+  props.set_force_software(0);
   GraphicsOutput *result = make_output(gsg->get_pipe(), name, sort,
-                                       gsg->get_default_properties(), x_size, y_size,
+                                       props, x_size, y_size,
                                        GraphicsPipe::BF_refuse_window |
                                        GraphicsPipe::BF_fb_props_optional,
                                        gsg, NULL);

+ 73 - 100
panda/src/display/graphicsEngine.cxx

@@ -113,9 +113,6 @@ GraphicsEngine(Pipeline *pipeline) :
   _windows_sorted = true;
   _window_sort_index = 0;
   
-  // Default frame buffer properties.
-  _frame_buffer_properties = FrameBufferProperties::get_default();
-
   set_threading_model(GraphicsThreadingModel(threading_model));
   if (!_threading_model.is_default()) {
     display_cat.info()
@@ -143,35 +140,6 @@ GraphicsEngine::
   remove_all_windows();
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsEngine::set_frame_buffer_properties
-//       Access: Published
-//  Description: Specifies the default frame buffer properties for
-//               future gsg's created using the one-parameter
-//               make_gsg() method.
-////////////////////////////////////////////////////////////////////
-void GraphicsEngine::
-set_frame_buffer_properties(const FrameBufferProperties &properties) {
-  MutexHolder holder(_lock);
-  _frame_buffer_properties = properties;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsEngine::get_frame_buffer_properties
-//       Access: Published
-//  Description: Returns the frame buffer properties for future gsg's.
-//               See set_frame_buffer_properties().
-////////////////////////////////////////////////////////////////////
-FrameBufferProperties GraphicsEngine::
-get_frame_buffer_properties() const {
-  FrameBufferProperties result;
-  {
-    MutexHolder holder(_lock);
-    result = _frame_buffer_properties;
-  }
-  return result;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::set_threading_model
 //       Access: Published
@@ -215,40 +183,10 @@ get_threading_model() const {
   return result;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsEngine::make_gsg
-//       Access: Published
-//  Description: Creates a new gsg using the indicated GraphicsPipe
-//               and returns it.  The GraphicsEngine does not
-//               officially own the pointer to the gsg; but if any
-//               windows are created using this GSG, the
-//               GraphicsEngine will own the pointers to these
-//               windows, which in turn will own the pointer to the
-//               GSG.
-//
-//               There is no explicit way to release a GSG, but it
-//               will be destructed when all windows that reference it
-//               are destructed, and the draw thread that owns the GSG
-//               runs one more time.
-////////////////////////////////////////////////////////////////////
-PT(GraphicsStateGuardian) GraphicsEngine::
-make_gsg(GraphicsPipe *pipe, const FrameBufferProperties &properties,
-         GraphicsStateGuardian *share_with) {
-  // TODO: ask the draw thread to make the GSG.
-  PT(GraphicsStateGuardian) gsg = pipe->make_gsg(properties, share_with);
-  if (gsg != (GraphicsStateGuardian *)NULL) {
-    gsg->_threading_model = get_threading_model();
-    gsg->_pipe = pipe;
-    gsg->_engine = this;
+// THIS IS THE OLD CODE FOR make_gsg
+//  PT(GraphicsStateGuardian) gsg = pipe->make_gsg(properties, share_with);
 
-    // If there was no global GSG previously, this becomes the one.
-    if (GraphicsStateGuardian::get_global_gsg() == NULL) {
-      gsg->make_global_gsg();
-    }
-  }
 
-  return gsg;
-}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::make_output
@@ -315,43 +253,48 @@ make_output(GraphicsPipe *pipe,
     host = host->get_host();
   }
 
-  // Sanity check everything.
-
-  GraphicsThreadingModel threading_model = get_threading_model();
-  nassertr(pipe != (GraphicsPipe *)NULL, NULL);
-  if (gsg != (GraphicsStateGuardian *)NULL) {
-    nassertr(pipe == gsg->get_pipe(), NULL);
-    nassertr(this == gsg->get_engine(), NULL);
-    nassertr(threading_model.get_draw_name() ==
-             gsg->get_threading_model().get_draw_name(), NULL);
-  }
-  if (host != (GraphicsOutput *)NULL) {
-    nassertr(gsg == host->get_gsg(), NULL);
-  }
-  
-  // If the gsg is null, then create one.
-  
-  if (gsg == (GraphicsStateGuardian *)NULL) {
-    gsg = make_gsg(pipe, prop);
-  }
-  
-  // If there is a host window, and it is not yet initialized,
-  // then call open_windows to get the host ready.  If that 
-  // fails, give up on using the host window.
+  // If a gsg or host was supplied, and either is not yet initialized,
+  // then call open_windows to get both ready.  If that fails,
+  // give up on using the supplied gsg and host.
 
-  if (host != (GraphicsOutput *)NULL) {
-    if ((!host->is_valid())||
+  if (host == (GraphicsOutput *)NULL) {
+    if (gsg != (GraphicsStateGuardian*)NULL) {
+      if ((!gsg->is_valid())||(gsg->needs_reset())) {
+        open_windows();
+      }
+      if ((!gsg->is_valid())||(gsg->needs_reset())) {
+        gsg = NULL;
+      }
+    }
+  } else {
+    if ((host->get_gsg()==0)||
+        (!host->is_valid())||
         (!host->get_gsg()->is_valid())||
         (host->get_gsg()->needs_reset())) {
       open_windows();
     }
-    if ((!host->is_valid())||
+    if ((host->get_gsg()==0)||
+        (!host->is_valid())||
         (!host->get_gsg()->is_valid())||
         (host->get_gsg()->needs_reset())) {
       host = NULL;
+      gsg = NULL;
+    } else {
+      gsg = host->get_gsg();
     }
   }
 
+  // Sanity check everything.
+
+  GraphicsThreadingModel threading_model = get_threading_model();
+  nassertr(pipe != (GraphicsPipe *)NULL, NULL);
+  if (gsg != (GraphicsStateGuardian *)NULL) {
+    nassertr(pipe == gsg->get_pipe(), NULL);
+    nassertr(this == gsg->get_engine(), NULL);
+    nassertr(threading_model.get_draw_name() ==
+             gsg->get_threading_model().get_draw_name(), NULL);
+  }
+  
   // Determine if a parasite buffer meets the user's specs.
 
   bool can_use_parasite = false;
@@ -379,7 +322,8 @@ make_output(GraphicsPipe *pipe,
       (host->get_fb_properties().subsumes(prop))) {
     ParasiteBuffer *buffer = new ParasiteBuffer(host, name, x_size, y_size, flags);
     buffer->_sort = sort;
-    do_add_window(buffer, gsg, threading_model);
+    do_add_window(buffer, threading_model);
+    do_add_gsg(host->get_gsg(), pipe, threading_model);
     return buffer;
   }
 
@@ -391,12 +335,15 @@ make_output(GraphicsPipe *pipe,
       pipe->make_output(name, prop, x_size, y_size, flags, gsg, host, retry, precertify);
     if (window != (GraphicsOutput *)NULL) {
       window->_sort = sort;
-      do_add_window(window, gsg, threading_model);
-      if (precertify) {
+      if ((precertify) && (gsg != 0) && (window->get_gsg()==gsg)) {
+        do_add_window(window, threading_model);
+        do_add_gsg(window->get_gsg(), pipe, threading_model);
         return window;
       }
+      do_add_window(window, threading_model);
       open_windows();
       if (window->is_valid()) {
+        do_add_gsg(window->get_gsg(), pipe, threading_model);
         if (window->get_fb_properties().subsumes(prop)) {
           return window;
         } else {
@@ -428,7 +375,8 @@ make_output(GraphicsPipe *pipe,
     }
     ParasiteBuffer *buffer = new ParasiteBuffer(host, name, x_size, y_size, flags);
     buffer->_sort = sort;
-    do_add_window(buffer, gsg, threading_model);
+    do_add_window(buffer, threading_model);
+    do_add_gsg(host->get_gsg(), pipe, threading_model);
     return buffer;
   }
 
@@ -1590,7 +1538,7 @@ do_draw(CullResult *cull_result, SceneSetup *scene_setup,
 //               opened.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
-do_add_window(GraphicsOutput *window, GraphicsStateGuardian *gsg,
+do_add_window(GraphicsOutput *window,
               const GraphicsThreadingModel &threading_model) {
   MutexHolder holder(_lock);
 
@@ -1602,14 +1550,13 @@ do_add_window(GraphicsOutput *window, GraphicsStateGuardian *gsg,
 
   _windows_sorted = false;
   _windows.push_back(window);
-  
+
   WindowRenderer *cull = 
     get_window_renderer(threading_model.get_cull_name(),
                         threading_model.get_cull_stage());
   WindowRenderer *draw = 
     get_window_renderer(threading_model.get_draw_name(),
                         threading_model.get_draw_stage());
-  draw->add_gsg(gsg);
   
   if (threading_model.get_cull_sorting()) {
     cull->add_window(cull->_cull, window);
@@ -1625,16 +1572,42 @@ do_add_window(GraphicsOutput *window, GraphicsStateGuardian *gsg,
   // pipes might prefer this to be done in draw, for instance.  For
   // now, we assume this is the app thread.
   _app.add_window(_app._window, window);
-  
+
   if (display_cat.is_debug()) {
     display_cat.debug()
       << "Created " << window->get_type() << " " << (void *)window << "\n";
   }
-  
-  // By default, try to open each window as it is added.
+
   window->request_open();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::do_add_gsg
+//       Access: Private
+//  Description: An internal function called by make_output to add
+//               the newly-created gsg object to the engine's
+//               list of gsg's.
+////////////////////////////////////////////////////////////////////
+void GraphicsEngine::
+do_add_gsg(GraphicsStateGuardian *gsg, GraphicsPipe *pipe,
+           const GraphicsThreadingModel &threading_model) {
+  MutexHolder holder(_lock);
+
+  gsg->_threading_model = get_threading_model();
+  gsg->_pipe = pipe;
+  gsg->_engine = this;
+
+  // If there was no global GSG previously, this becomes the one.
+  if (GraphicsStateGuardian::get_global_gsg() == NULL) {
+    gsg->make_global_gsg();
+  }
+
+  WindowRenderer *draw = 
+    get_window_renderer(threading_model.get_draw_name(),
+                        threading_model.get_draw_stage());
+
+  draw->add_gsg(gsg);
+}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::do_remove_window

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

@@ -60,9 +60,6 @@ PUBLISHED:
   GraphicsEngine(Pipeline *pipeline = NULL);
   ~GraphicsEngine();
 
-  void set_frame_buffer_properties(const FrameBufferProperties &properties);
-  FrameBufferProperties get_frame_buffer_properties() const; 
-
   void set_threading_model(const GraphicsThreadingModel &threading_model);
   GraphicsThreadingModel get_threading_model() const;
 
@@ -72,12 +69,6 @@ PUBLISHED:
   INLINE void set_portal_cull(bool value);
   INLINE bool get_portal_cull() const;
 
-
-  INLINE PT(GraphicsStateGuardian) make_gsg(GraphicsPipe *pipe);
-  PT(GraphicsStateGuardian) make_gsg(GraphicsPipe *pipe,
-                                     const FrameBufferProperties &properties,
-                                     GraphicsStateGuardian *share_with = NULL);
-  
   GraphicsOutput *make_output(GraphicsPipe *pipe,
                               const string &name, int sort,
                               const FrameBufferProperties &prop,
@@ -175,8 +166,10 @@ private:
   void do_draw(CullResult *cull_result, SceneSetup *scene_setup,
                GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread);
 
-  void do_add_window(GraphicsOutput *window, GraphicsStateGuardian *gsg,
+  void do_add_window(GraphicsOutput *window,
                      const GraphicsThreadingModel &threading_model);
+  void do_add_gsg(GraphicsStateGuardian *gsg, GraphicsPipe *pipe,
+                  const GraphicsThreadingModel &threading_model);
   void do_remove_window(GraphicsOutput *window, Thread *current_thread);
   void do_resort_windows();
   void terminate_threads(Thread *current_thread);
@@ -328,7 +321,6 @@ private:
   WindowRenderer _app;
   typedef pmap<string, PT(RenderThread) > Threads;
   Threads _threads;
-  FrameBufferProperties _frame_buffer_properties;
   GraphicsThreadingModel _threading_model;
   bool _auto_flip;
   bool _portal_enabled; //toggle to portal culling on/off

+ 4 - 14
panda/src/display/graphicsOutput.cxx

@@ -731,20 +731,10 @@ get_texture_card() {
 GraphicsOutput *GraphicsOutput::
 make_texture_buffer(const string &name, int x_size, int y_size,
                     Texture *tex, bool to_ram) {
-  FrameBufferProperties props = get_gsg()->get_default_properties();
-  int clear =
-    FrameBufferProperties::FM_buffer |
-    FrameBufferProperties::FM_stereo |
-    FrameBufferProperties::FM_accum |
-
-// DO NOT USE STENCIL FOR NOW FOR TEXTURE BUFFERS
-    FrameBufferProperties::FM_stencil |
-
-    FrameBufferProperties::FM_multisample |
-    FrameBufferProperties::FM_hardware |
-    FrameBufferProperties::FM_software;
-  props.set_frame_buffer_mode(props.get_frame_buffer_mode() & (~clear));
-
+  FrameBufferProperties props;
+  props.set_rgb_color(1);
+  props.set_depth_bits(1);
+  
   GraphicsOutput *buffer = get_gsg()->get_engine()->
     make_output(get_gsg()->get_pipe(),
                 name, get_sort()-1,

+ 0 - 51
panda/src/display/graphicsPipe.cxx

@@ -24,42 +24,6 @@
 
 TypeHandle GraphicsPipe::_type_handle;
 
-// This array keeps the bitmasks of options that we pull out of the
-// requested frame_buffer_mode, in order.  This is used by derived
-// classes to find a suitable pixel format (or fbconfig, or whatever
-// the backend calls it) that comes as close as possible to the
-// requested configuration.
-
-const int GraphicsPipe::strip_properties[] = {
-  // One esoteric option removed.
-  FrameBufferProperties::FM_multisample,
-  FrameBufferProperties::FM_stencil,
-  FrameBufferProperties::FM_accum,
-  FrameBufferProperties::FM_alpha,
-  FrameBufferProperties::FM_stereo,
-  
-  // Two esoteric options removed.
-  FrameBufferProperties::FM_stencil | FrameBufferProperties::FM_multisample,
-  FrameBufferProperties::FM_accum | FrameBufferProperties::FM_multisample,
-  FrameBufferProperties::FM_alpha | FrameBufferProperties::FM_multisample,
-  FrameBufferProperties::FM_stereo | FrameBufferProperties::FM_multisample,
-  FrameBufferProperties::FM_stencil | FrameBufferProperties::FM_accum,
-  FrameBufferProperties::FM_alpha | FrameBufferProperties::FM_stereo,
-  FrameBufferProperties::FM_stencil | FrameBufferProperties::FM_accum | FrameBufferProperties::FM_multisample,
-  FrameBufferProperties::FM_alpha | FrameBufferProperties::FM_stereo | FrameBufferProperties::FM_multisample,
-  
-  // All esoteric options removed.
-  FrameBufferProperties::FM_stencil | FrameBufferProperties::FM_accum | FrameBufferProperties::FM_alpha | FrameBufferProperties::FM_stereo | FrameBufferProperties::FM_multisample,
-  
-  // All esoteric options, plus some we'd really really prefer,
-  // removed.
-  FrameBufferProperties::FM_stencil | FrameBufferProperties::FM_accum | FrameBufferProperties::FM_alpha | FrameBufferProperties::FM_stereo | FrameBufferProperties::FM_multisample | FrameBufferProperties::FM_double_buffer,
-  
-  // A zero marks the end of the array.
-  0
-};
-
-
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsPipe::Constructor
 //       Access: Protected
@@ -154,21 +118,6 @@ make_device(void *scrn) {
   return NULL;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsPipe::make_gsg
-//       Access: Protected, Virtual
-//  Description: Creates a new GSG to use the pipe (but no windows
-//               have been created yet for the GSG).  This method will
-//               be called in the draw thread for the GSG.
-////////////////////////////////////////////////////////////////////
-PT(GraphicsStateGuardian) GraphicsPipe::
-make_gsg(const FrameBufferProperties &properties, 
-         GraphicsStateGuardian *share_with) {
-  display_cat.error()
-    << "make_gsg() unimplemented by " << get_type() << "\n";
-  return NULL;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsPipe::close_gsg
 //       Access: Protected, Virtual

+ 0 - 9
panda/src/display/graphicsPipe.h

@@ -80,10 +80,6 @@ PUBLISHED:
     BF_refuse_window       = 0x0004,
     BF_require_window      = 0x0008,
 
-    // Flags that control gsg creation.
-    BF_share_gsg           = 0x0010, // New window must use the old gsg.
-    BF_share_textures      = 0x0020, // New window must share textures with old gsg.
-
     // Miscellaneous control flags.
     BF_can_bind_color      = 0x0040, // Need capability: bind the color bitplane to a tex.
     BF_can_bind_every      = 0x0080, // Need capability: bind all bitplanes to a tex.
@@ -110,11 +106,6 @@ public:
   virtual PT(GraphicsDevice) make_device(void *scrn = NULL);
 
 protected:
-  // The make_output() and make_gsg() interfaces on GraphicsPipe are
-  // protected; don't try to call them directly.  Instead, use
-  // the interface on GraphicsEngine to make a new window or buffer.
-  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
-                                             GraphicsStateGuardian *share_with);
   virtual void close_gsg(GraphicsStateGuardian *gsg);
   
   virtual PT(GraphicsOutput) make_output(const string &name,

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

@@ -132,19 +132,6 @@ is_valid() const {
   return _is_valid;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsStateGuardian::get_properties
-//       Access: Published
-//  Description: Returns the default frame buffer properties for
-//               this GSG.  All windows created for this GSG will be
-//               created with these properties, unless explicitly
-//               overridden.
-////////////////////////////////////////////////////////////////////
-INLINE const FrameBufferProperties &GraphicsStateGuardian::
-get_default_properties() const {
-  return _default_properties;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_pipe
 //       Access: Published

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

@@ -78,10 +78,10 @@ TypeHandle GraphicsStateGuardian::_type_handle;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 GraphicsStateGuardian::
-GraphicsStateGuardian(const FrameBufferProperties &properties,
-                      CoordinateSystem internal_coordinate_system) :
+GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
+                      GraphicsPipe *pipe) :
   _internal_coordinate_system(internal_coordinate_system),
-  _default_properties(properties)
+  _pipe(pipe)
 {
   _coordinate_system = CS_invalid;
   _internal_transform = TransformState::make_identity();

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

@@ -67,8 +67,8 @@ class EXPCL_PANDA GraphicsStateGuardian : public GraphicsStateGuardianBase {
   // Interfaces all GSGs should have
   //
 public:
-  GraphicsStateGuardian(const FrameBufferProperties &properties,
-                        CoordinateSystem internal_coordinate_system);
+  GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
+                        GraphicsPipe *pipe);
   virtual ~GraphicsStateGuardian();
 
 PUBLISHED:
@@ -83,7 +83,6 @@ PUBLISHED:
   INLINE bool is_valid() const;
   INLINE bool needs_reset() const;
 
-  INLINE const FrameBufferProperties &get_default_properties() const;
   INLINE GraphicsPipe *get_pipe() const;
   INLINE GraphicsEngine *get_engine() const;
   INLINE const GraphicsThreadingModel &get_threading_model() const;
@@ -427,7 +426,6 @@ private:
   pvector<ClipPlaneInfo> _clip_plane_info;
   bool _clip_planes_enabled_this_frame;
 
-  FrameBufferProperties _default_properties;
   PT(GraphicsPipe) _pipe;
   GraphicsEngine *_engine;
   GraphicsThreadingModel _threading_model;

+ 4 - 4
panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx

@@ -81,8 +81,8 @@ unsigned char *DXGraphicsStateGuardian8::_safe_buffer_start = NULL;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 DXGraphicsStateGuardian8::
-DXGraphicsStateGuardian8(const FrameBufferProperties &properties) :
-  GraphicsStateGuardian(properties, CS_yup_left)
+DXGraphicsStateGuardian8(GraphicsPipe *pipe) :
+  GraphicsStateGuardian(CS_yup_left, pipe)
 {
   _screen = NULL;
   _d3d_device = NULL;
@@ -531,7 +531,7 @@ do_clear(const RenderBuffer &buffer) {
           if (FAILED(hr2)) {
             dxgsg8_cat.error()
               << "Unable to clear depth buffer; removing.\n";
-            _current_properties->buffer_mask_remove(RenderBuffer::T_depth);
+            _current_properties->set_depth_bits(0);
           }
         }
         if (buffer_type & RenderBuffer::T_stencil) {
@@ -541,7 +541,7 @@ do_clear(const RenderBuffer &buffer) {
           if (FAILED(hr2)) {
             dxgsg8_cat.error()
               << "Unable to clear stencil buffer; removing.\n";
-            _current_properties->buffer_mask_remove(RenderBuffer::T_stencil);
+            _current_properties->set_stencil_bits(0);
           }
         }
       }

+ 1 - 1
panda/src/dxgsg8/dxGraphicsStateGuardian8.h

@@ -45,7 +45,7 @@ class DXIndexBufferContext8;
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDADX DXGraphicsStateGuardian8 : public GraphicsStateGuardian {
 public:
-  DXGraphicsStateGuardian8(const FrameBufferProperties &properties);
+  DXGraphicsStateGuardian8(GraphicsPipe *pipe);
   ~DXGraphicsStateGuardian8();
 
   virtual TextureContext *prepare_texture(Texture *tex);

+ 8 - 4
panda/src/dxgsg8/wdxGraphicsBuffer8.cxx

@@ -393,8 +393,12 @@ close_buffer() {
 bool wdxGraphicsBuffer8::
 open_buffer() {
   bool state;
-  DXGraphicsStateGuardian8 *dxgsg;
-  DCAST_INTO_R(dxgsg, _gsg, false);
+
+  // GSG creation/initialization.
+  if (_gsg == 0) {
+    _dxgsg = new DXGraphicsStateGuardian8(_pipe);
+    _gsg = _dxgsg;
+  }
 
   // create texture
   int tex_index;
@@ -418,7 +422,7 @@ open_buffer() {
     _dx_texture_context8 = DCAST (DXTextureContext8, tc);
 
     // create a depth stencil buffer if needed
-    hr = dxgsg -> _d3d_device -> GetDepthStencilSurface (&_depth_stencil_surface);
+    hr = _dxgsg -> _d3d_device -> GetDepthStencilSurface (&_depth_stencil_surface);
     if (SUCCEEDED  (hr))
     {
       D3DSURFACE_DESC surface_description;
@@ -444,7 +448,7 @@ open_buffer() {
 //          multisample_quality = surface_description.MultiSampleQuality;
           discard = false;
 
-          hr = dxgsg -> _d3d_device -> CreateDepthStencilSurface (
+          hr = _dxgsg -> _d3d_device -> CreateDepthStencilSurface (
             width, height, format, multisample_type, /* multisample_quality,
             discard, */ &this -> _new_z_stencil_surface);
           if (SUCCEEDED  (hr)) {

+ 1 - 0
panda/src/dxgsg8/wdxGraphicsBuffer8.h

@@ -61,6 +61,7 @@ private:
   static void process_1_event();
 
   int _cube_map_index;
+  DXGraphicsStateGuardian8 *_dxgsg;
   IDirect3DSurface8 *_back_buffer;
   IDirect3DSurface8 *_z_stencil_buffer;
   IDirect3DSurface8 *_direct_3d_surface;

+ 6 - 32
panda/src/dxgsg8/wdxGraphicsPipe8.cxx

@@ -98,9 +98,10 @@ make_output(const string &name,
     return NULL;
   }
 
-  DXGraphicsStateGuardian8 *wdxgsg;
-  DCAST_INTO_R(wdxgsg, gsg, NULL);
-
+  DXGraphicsStateGuardian8 *wdxgsg = 0;
+  if (gsg != 0) {
+    DCAST_INTO_R(wdxgsg, gsg, NULL);
+  }
   
   // First thing to try: a visible window.
 
@@ -110,8 +111,7 @@ make_output(const string &name,
         ((flags&BF_size_track_host)!=0)||
         ((flags&BF_rtt_cumulative)!=0)||
         ((flags&BF_can_bind_color)!=0)||
-        ((flags&BF_can_bind_every)!=0)||
-        (properties != gsg->get_default_properties())) {
+        ((flags&BF_can_bind_every)!=0)) {
       return NULL;
     }
     return new wdxGraphicsWindow8(this, name, properties,
@@ -126,8 +126,7 @@ make_output(const string &name,
         ((flags&BF_require_window)!=0)||
         ((flags&BF_size_track_host)!=0)||
         ((flags&BF_rtt_cumulative)!=0)||
-        ((flags&BF_can_bind_every)!=0)||
-        (properties != gsg->get_default_properties())) {
+        ((flags&BF_can_bind_every)!=0)) {
       return NULL;
     }
     if ((gsg != 0)&&
@@ -795,31 +794,6 @@ make_device(void *scrn) {
   return device.p();
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: wdxGraphicsPipew8::make_gsg
-//       Access: Public, Virtual
-//  Description: Creates a new empty GSG.  Can do no real initialization
-//               until window is opened, and we know the full device requirements
-////////////////////////////////////////////////////////////////////
-
-PT(GraphicsStateGuardian) wdxGraphicsPipe8::
-make_gsg(const FrameBufferProperties &properties,
-         GraphicsStateGuardian *share_with) {
-  if (share_with != (GraphicsStateGuardian *)NULL) {
-    wdxdisplay8_cat.error()
-      << "wdxGraphicsPipe8 does not presently support sharing texture contexts.\n";
-    return NULL;
-  }
-
-  // DX never supports stereo.  We should also remove other properties
-  // we don't have, but we don't know enough right now.
-  FrameBufferProperties new_properties = properties;
-  new_properties.set_frame_buffer_mode(properties.get_frame_buffer_mode() & ~FrameBufferProperties::FM_stereo);
-
-  PT(DXGraphicsStateGuardian8) gsg = new DXGraphicsStateGuardian8(new_properties);
-  return gsg.p();
-}
-
 pmap<D3DFORMAT_FLAG, D3DFORMAT> g_D3DFORMATmap;
 
 void Init_D3DFORMAT_map() {

+ 0 - 2
panda/src/dxgsg8/wdxGraphicsPipe8.h

@@ -38,8 +38,6 @@ public:
   virtual string get_interface_name() const;
   static PT(GraphicsPipe) pipe_constructor();
 
-  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
-                                             GraphicsStateGuardian *share_with);
   virtual PT(GraphicsDevice) make_device(void *scrn);
 
   bool find_best_depth_format(DXScreenData &Display, D3DDISPLAYMODE &Test_display_mode,

+ 26 - 30
panda/src/dxgsg8/wdxGraphicsWindow8.cxx

@@ -141,15 +141,13 @@ void wdxGraphicsWindow8::
 make_current() {
   PStatTimer timer(_make_current_pcollector);
 
-  DXGraphicsStateGuardian8 *dxgsg;
-  DCAST_INTO_V(dxgsg, _gsg);
-  dxgsg->set_context(&_wcontext);
+  _dxgsg->set_context(&_wcontext);
 
   // Now that we have made the context current to a window, we can
   // reset the GSG state if this is the first time it has been used.
   // (We can't just call reset() when we construct the GSG, because
   // reset() requires having a current context.)
-  dxgsg->reset_if_new();
+  _dxgsg->reset_if_new();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -270,11 +268,15 @@ close_window() {
 bool wdxGraphicsWindow8::
 open_window() {
   PT(DXGraphicsDevice8) dxdev;
-  DXGraphicsStateGuardian8 *dxgsg;
-  DCAST_INTO_R(dxgsg, _gsg, false);
   WindowProperties props;
   bool discard_device = false;
 
+  // GSG creation/initialization.
+  if (_gsg == 0) {
+    _dxgsg = new DXGraphicsStateGuardian8(_pipe);
+    _gsg = _dxgsg;
+  }
+  
   if (!choose_device()) {
     return false;
   }
@@ -292,12 +294,12 @@ open_window() {
   // In that case just create an additional swapchain for this window
 
   while (true) {
-    if (dxgsg->get_pipe()->get_device() == NULL || discard_device) {
+    if (_dxgsg->get_pipe()->get_device() == NULL || discard_device) {
       wdxdisplay8_cat.debug() << "device is null or fullscreen\n";
 
       // If device exists, free it
-      if (dxgsg->get_pipe()->get_device()) {
-        dxgsg->dx_cleanup();
+      if (_dxgsg->get_pipe()->get_device()) {
+        _dxgsg->dx_cleanup();
       }
 
       wdxdisplay8_cat.debug() << "device width " << _wcontext._display_mode.Width << "\n";
@@ -306,9 +308,9 @@ open_window() {
         wdxdisplay8_cat.error() << "fatal: must be trying to create two fullscreen windows: not supported\n";
         return false;
       }
-      dxgsg->get_pipe()->make_device((void*)(&_wcontext));
-      dxgsg->copy_pres_reset(&_wcontext);
-      dxgsg->create_swap_chain(&_wcontext);
+      _dxgsg->get_pipe()->make_device((void*)(&_wcontext));
+      _dxgsg->copy_pres_reset(&_wcontext);
+      _dxgsg->create_swap_chain(&_wcontext);
       break;
 
     } else {
@@ -316,7 +318,7 @@ open_window() {
       // reference to _window.
       wdxdisplay8_cat.debug() << "device is not null\n";
 
-      dxdev = (DXGraphicsDevice8*)dxgsg->get_pipe()->get_device();
+      dxdev = (DXGraphicsDevice8*)(_dxgsg->get_pipe()->get_device());
       props = get_properties();
       memcpy(&_wcontext, &dxdev->_Scrn, sizeof(DXScreenData));
 
@@ -326,7 +328,7 @@ open_window() {
       _wcontext._presentation_params.BackBufferHeight = _wcontext._display_mode.Height = props.get_y_size();
 
       wdxdisplay8_cat.debug() << "device width " << _wcontext._presentation_params.BackBufferWidth << "\n";
-      if (!dxgsg->create_swap_chain(&_wcontext)) {
+      if (!_dxgsg->create_swap_chain(&_wcontext)) {
         discard_device = true;
         continue; // try again
       }
@@ -349,17 +351,15 @@ open_window() {
 ////////////////////////////////////////////////////////////////////
 void wdxGraphicsWindow8::
 reset_window(bool swapchain) {
-  DXGraphicsStateGuardian8 *dxgsg;
-  DCAST_INTO_V(dxgsg, _gsg);
   if (swapchain) {
     if (_wcontext._swap_chain) {
-      dxgsg->create_swap_chain(&_wcontext);
+      _dxgsg->create_swap_chain(&_wcontext);
       wdxdisplay8_cat.debug() << "created swapchain " << _wcontext._swap_chain << "\n";
     }
   }
   else {
     if (_wcontext._swap_chain) {
-      dxgsg->release_swap_chain(&_wcontext);
+      _dxgsg->release_swap_chain(&_wcontext);
       wdxdisplay8_cat.debug() << "released swapchain " << _wcontext._swap_chain << "\n";
     }
   }
@@ -528,10 +528,7 @@ create_screen_buffers_and_device(DXScreenData &display, bool force_16bpp_zbuffer
 
   wdxdisplay8_cat.debug() << "Display Width " << dwRenderWidth << " and PresParam Width " << _wcontext._presentation_params.BackBufferWidth << "\n";
 
-  // BUGBUG: need to change panda to put frame buffer properties with GraphicsWindow, not GSG!!
-  // Update: Did I fix the bug? - Josh
-  int frame_buffer_mode = _fb_properties.get_frame_buffer_mode();
-  bool bWantStencil = ((frame_buffer_mode & FrameBufferProperties::FM_stencil) != 0);
+  bool bWantStencil = (_fb_properties.get_stencil_bits() > 0);
 
   PRINT_REFCNT(wdxdisplay8, _d3d8);
 
@@ -710,15 +707,15 @@ create_screen_buffers_and_device(DXScreenData &display, bool force_16bpp_zbuffer
   PRINT_REFCNT(wdxdisplay8, _wcontext._d3d_device);
 
   if (presentation_params->EnableAutoDepthStencil) {
-    _fb_properties.buffer_mask_add(RenderBuffer::T_depth);
+    _fb_properties.set_depth_bits(1);
     if (IS_STENCIL_FORMAT(presentation_params->AutoDepthStencilFormat)) {
-      _fb_properties.buffer_mask_add(RenderBuffer::T_stencil);
+      _fb_properties.set_stencil_bits(1);
     } else {
-      _fb_properties.buffer_mask_remove(RenderBuffer::T_stencil);
+      _fb_properties.set_stencil_bits(0);
     }
   } else {
-    _fb_properties.buffer_mask_remove(RenderBuffer::T_depth);
-    _fb_properties.buffer_mask_remove(RenderBuffer::T_stencil);
+    _fb_properties.set_depth_bits(0);
+    _fb_properties.set_stencil_bits(0);
   }
 
   init_resized_window();
@@ -882,8 +879,7 @@ search_for_device(wdxGraphicsPipe8 *dxpipe, DXDeviceInfo *device_info) {
   _wcontext._is_dx8_1 = dxpipe->__is_dx8_1;
   _wcontext._card_id = device_info->cardID;  // could this change by end?
 
-  int frame_buffer_mode = _fb_properties.get_frame_buffer_mode();
-  bool bWantStencil = ((frame_buffer_mode & FrameBufferProperties::FM_stencil) != 0);
+  bool bWantStencil = (_fb_properties.get_stencil_bits() > 0);
 
   hr = _d3d8->GetAdapterIdentifier(device_info->cardID, D3DENUM_NO_WHQL_LEVEL,
                                    &_wcontext._dx_device_id);
@@ -964,7 +960,7 @@ search_for_device(wdxGraphicsPipe8 *dxpipe, DXDeviceInfo *device_info) {
 
   bool bNeedZBuffer =
     ((!(_d3dcaps.RasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )) &&
-     ((frame_buffer_mode & FrameBufferProperties::FM_depth) != 0));
+     (_fb_properties.get_depth_bits() > 0));
 
   _wcontext._presentation_params.EnableAutoDepthStencil = bNeedZBuffer;
 

+ 5 - 5
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -89,8 +89,8 @@ unsigned char *DXGraphicsStateGuardian9::_safe_buffer_start = NULL;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 DXGraphicsStateGuardian9::
-DXGraphicsStateGuardian9(const FrameBufferProperties &properties) :
-  GraphicsStateGuardian(properties, CS_yup_left)
+DXGraphicsStateGuardian9(GraphicsPipe *pipe) :
+  GraphicsStateGuardian(CS_yup_left, pipe)
 {
   _screen = NULL;
   _d3d_device = NULL;
@@ -751,7 +751,7 @@ do_clear(const RenderBuffer &buffer) {
           if (FAILED(hr2)) {
             dxgsg9_cat.error()
               << "Unable to clear depth buffer; removing.\n";
-            _current_properties->buffer_mask_remove(RenderBuffer::T_depth);
+            _current_properties->set_depth_bits(0);
           }
         }
         if (buffer_type & RenderBuffer::T_stencil) {
@@ -761,7 +761,7 @@ do_clear(const RenderBuffer &buffer) {
           if (FAILED(hr2)) {
             dxgsg9_cat.error()
               << "Unable to clear stencil buffer; removing.\n";
-            _current_properties->buffer_mask_remove(RenderBuffer::T_stencil);
+            _current_properties->set_stencil_bits(0);
           }
         }
       }
@@ -5198,4 +5198,4 @@ do_issue_stencil() {
     stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_front_enable, 0);
     stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_back_enable, 0);
   }
-}
+}

+ 1 - 1
panda/src/dxgsg9/dxGraphicsStateGuardian9.h

@@ -78,7 +78,7 @@ class DXIndexBufferContext9;
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDADX DXGraphicsStateGuardian9 : public GraphicsStateGuardian {
 public:
-  DXGraphicsStateGuardian9(const FrameBufferProperties &properties);
+  DXGraphicsStateGuardian9(GraphicsPipe *pipe);
   ~DXGraphicsStateGuardian9();
 
   virtual TextureContext *prepare_texture(Texture *tex);

+ 8 - 4
panda/src/dxgsg9/wdxGraphicsBuffer9.cxx

@@ -429,8 +429,12 @@ close_buffer() {
 bool wdxGraphicsBuffer9::
 open_buffer() {
   bool state;
-  DXGraphicsStateGuardian9 *dxgsg;
-  DCAST_INTO_R(dxgsg, _gsg, false);
+
+  // GSG creation/initialization.
+  if (_gsg == 0) {
+    _dxgsg = new DXGraphicsStateGuardian9(_pipe);
+    _gsg = _dxgsg;
+  }
 
   // create texture
   int tex_index;
@@ -454,7 +458,7 @@ open_buffer() {
     _dx_texture_context9 = DCAST (DXTextureContext9, tc);
 
     // create a depth stencil buffer if needed
-    hr = dxgsg -> _d3d_device -> GetDepthStencilSurface (&_depth_stencil_surface);
+    hr = _dxgsg -> _d3d_device -> GetDepthStencilSurface (&_depth_stencil_surface);
     if (SUCCEEDED  (hr))
     {
       D3DSURFACE_DESC surface_description;
@@ -480,7 +484,7 @@ open_buffer() {
           multisample_quality = surface_description.MultiSampleQuality;
           discard = false;
 
-          hr = dxgsg -> _d3d_device -> CreateDepthStencilSurface (
+          hr = _dxgsg -> _d3d_device -> CreateDepthStencilSurface (
             width, height, format, multisample_type, multisample_quality,
             discard, &this -> _new_z_stencil_surface, NULL);
           if (SUCCEEDED  (hr)) {

+ 1 - 0
panda/src/dxgsg9/wdxGraphicsBuffer9.h

@@ -60,6 +60,7 @@ private:
   static void process_1_event();
 
   int _cube_map_index;
+  DXGraphicsStateGuardian9 *_dxgsg;
   IDirect3DSurface9 *_back_buffer;
   IDirect3DSurface9 *_z_stencil_buffer;
   IDirect3DSurface9 *_direct_3d_surface;

+ 7 - 32
panda/src/dxgsg9/wdxGraphicsPipe9.cxx

@@ -98,9 +98,11 @@ make_output(const string &name,
     return NULL;
   }
 
-  DXGraphicsStateGuardian9 *wdxgsg;
-  DCAST_INTO_R(wdxgsg, gsg, NULL);
-
+  DXGraphicsStateGuardian9 *wdxgsg = 0;
+  if (gsg != 0) {
+    DCAST_INTO_R(wdxgsg, gsg, NULL);
+  }
+  
   // First thing to try: a visible window.
 
   if (retry == 0) {
@@ -109,8 +111,7 @@ make_output(const string &name,
         ((flags&BF_size_track_host)!=0)||
         ((flags&BF_rtt_cumulative)!=0)||
         ((flags&BF_can_bind_color)!=0)||
-        ((flags&BF_can_bind_every)!=0)||
-        (prop != gsg->get_default_properties())) {
+        ((flags&BF_can_bind_every)!=0)) {
       return NULL;
     }
     return new wdxGraphicsWindow9(this, name, prop,
@@ -125,8 +126,7 @@ make_output(const string &name,
         ((flags&BF_require_window)!=0)||
         ((flags&BF_size_track_host)!=0)||
         ((flags&BF_rtt_cumulative)!=0)||
-        ((flags&BF_can_bind_every)!=0)||
-        (prop != gsg->get_default_properties())) {
+        ((flags&BF_can_bind_every)!=0)) {
       return NULL;
     }
     if ((gsg != 0)&&
@@ -821,31 +821,6 @@ make_device(void *scrn) {
   return device.p();
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: wdxGraphicsPipew9::make_gsg
-//       Access: Public, Virtual
-//  Description: Creates a new empty GSG.  Can do no real initialization
-//               until window is opened, and we know the full device requirements
-////////////////////////////////////////////////////////////////////
-
-PT(GraphicsStateGuardian) wdxGraphicsPipe9::
-make_gsg(const FrameBufferProperties &properties,
-         GraphicsStateGuardian *share_with) {
-  if (share_with != (GraphicsStateGuardian *)NULL) {
-    wdxdisplay9_cat.error()
-      << "wdxGraphicsPipe9 does not presently support sharing texture contexts.\n";
-    return NULL;
-  }
-
-  // DX never supports stereo.  We should also remove other properties
-  // we don't have, but we don't know enough right now.
-  FrameBufferProperties new_properties = properties;
-  new_properties.set_frame_buffer_mode(properties.get_frame_buffer_mode() & ~FrameBufferProperties::FM_stereo);
-
-  PT(DXGraphicsStateGuardian9) gsg = new DXGraphicsStateGuardian9(new_properties);
-  return gsg.p();
-}
-
 pmap<D3DFORMAT_FLAG, D3DFORMAT> g_D3DFORMATmap;
 
 void Init_D3DFORMAT_map() {

+ 0 - 2
panda/src/dxgsg9/wdxGraphicsPipe9.h

@@ -38,8 +38,6 @@ public:
   virtual string get_interface_name() const;
   static PT(GraphicsPipe) pipe_constructor();
 
-  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
-                                             GraphicsStateGuardian *share_with);
   virtual PT(GraphicsDevice) make_device(void *scrn);
 
   bool find_best_depth_format(DXScreenData &Display, D3DDISPLAYMODE &Test_display_mode,

+ 27 - 29
panda/src/dxgsg9/wdxGraphicsWindow9.cxx

@@ -75,15 +75,13 @@ void wdxGraphicsWindow9::
 make_current() {
   PStatTimer timer(_make_current_pcollector);
 
-  DXGraphicsStateGuardian9 *dxgsg;
-  DCAST_INTO_V(dxgsg, _gsg);
-  dxgsg->set_context(&_wcontext);
+  _dxgsg->set_context(&_wcontext);
 
   // Now that we have made the context current to a window, we can
   // reset the GSG state if this is the first time it has been used.
   // (We can't just call reset() when we construct the GSG, because
   // reset() requires having a current context.)
-  dxgsg->reset_if_new();
+  _dxgsg->reset_if_new();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -271,11 +269,15 @@ close_window() {
 bool wdxGraphicsWindow9::
 open_window() {
   PT(DXGraphicsDevice9) dxdev;
-  DXGraphicsStateGuardian9 *dxgsg;
-  DCAST_INTO_R(dxgsg, _gsg, false);
   WindowProperties props;
   bool discard_device = false;
 
+  // GSG creation/initialization.
+  if (_gsg == 0) {
+    _dxgsg = new DXGraphicsStateGuardian9(_pipe);
+    _gsg = _dxgsg;
+  }
+  
   if (!choose_device()) {
     return false;
   }
@@ -293,12 +295,12 @@ open_window() {
   // In that case just create an additional swapchain for this window
 
   while (true) {
-    if (dxgsg->get_pipe()->get_device() == NULL || discard_device) {
+    if (_dxgsg->get_pipe()->get_device() == NULL || discard_device) {
       wdxdisplay9_cat.debug() << "device is null or fullscreen\n";
 
       // If device exists, free it
-      if (dxgsg->get_pipe()->get_device()) {
-        dxgsg->dx_cleanup();
+      if (_dxgsg->get_pipe()->get_device()) {
+        _dxgsg->dx_cleanup();
       }
 
       wdxdisplay9_cat.debug() << "device width " << _wcontext._display_mode.Width << "\n";
@@ -307,9 +309,9 @@ open_window() {
         wdxdisplay9_cat.error() << "fatal: must be trying to create two fullscreen windows: not supported\n";
         return false;
       }
-      dxgsg->get_pipe()->make_device((void*)(&_wcontext));
-      dxgsg->copy_pres_reset(&_wcontext);
-      dxgsg->create_swap_chain(&_wcontext);
+      _dxgsg->get_pipe()->make_device((void*)(&_wcontext));
+      _dxgsg->copy_pres_reset(&_wcontext);
+      _dxgsg->create_swap_chain(&_wcontext);
       break;
 
     } else {
@@ -317,7 +319,7 @@ open_window() {
       // reference to _window.
       wdxdisplay9_cat.debug() << "device is not null\n";
 
-      dxdev = (DXGraphicsDevice9*)dxgsg->get_pipe()->get_device();
+      dxdev = (DXGraphicsDevice9*)_dxgsg->get_pipe()->get_device();
       props = get_properties();
       memcpy(&_wcontext, &dxdev->_Scrn, sizeof(DXScreenData));
 
@@ -327,7 +329,7 @@ open_window() {
       _wcontext._presentation_params.BackBufferHeight = _wcontext._display_mode.Height = props.get_y_size();
 
       wdxdisplay9_cat.debug() << "device width " << _wcontext._presentation_params.BackBufferWidth << "\n";
-      if (!dxgsg->create_swap_chain(&_wcontext)) {
+      if (!_dxgsg->create_swap_chain(&_wcontext)) {
         discard_device = true;
         continue; // try again
       }
@@ -350,17 +352,15 @@ open_window() {
 ////////////////////////////////////////////////////////////////////
 void wdxGraphicsWindow9::
 reset_window(bool swapchain) {
-  DXGraphicsStateGuardian9 *dxgsg;
-  DCAST_INTO_V(dxgsg, _gsg);
   if (swapchain) {
     if (_wcontext._swap_chain) {
-      dxgsg->create_swap_chain(&_wcontext);
+      _dxgsg->create_swap_chain(&_wcontext);
       wdxdisplay9_cat.debug() << "created swapchain " << _wcontext._swap_chain << "\n";
     }
   }
   else {
     if (_wcontext._swap_chain) {
-      dxgsg->release_swap_chain(&_wcontext);
+      _dxgsg->release_swap_chain(&_wcontext);
       wdxdisplay9_cat.debug() << "released swapchain " << _wcontext._swap_chain << "\n";
     }
   }
@@ -530,9 +530,8 @@ create_screen_buffers_and_device(DXScreenData &display, bool force_16bpp_zbuffer
 
   // BUGBUG: need to change panda to put frame buffer properties with GraphicsWindow, not GSG!!
   // Update: Did I fix the bug? - Josh
-  int frame_buffer_mode = _fb_properties.get_frame_buffer_mode();
-  bool bWantStencil = ((frame_buffer_mode & FrameBufferProperties::FM_stencil) != 0);
-  bool bWantAlpha = ((frame_buffer_mode & FrameBufferProperties::FM_rgba) != 0);
+  bool bWantStencil = (_fb_properties.get_stencil_bits() > 0);
+  bool bWantAlpha = (_fb_properties.get_alpha_bits() > 0);
 
   PRINT_REFCNT(wdxdisplay9, _d3d9);
 
@@ -746,15 +745,15 @@ create_screen_buffers_and_device(DXScreenData &display, bool force_16bpp_zbuffer
   PRINT_REFCNT(wdxdisplay9, _wcontext._d3d_device);
 
   if (presentation_params->EnableAutoDepthStencil) {
-    _fb_properties.buffer_mask_add(RenderBuffer::T_depth);
+    _fb_properties.set_depth_bits(1);
     if (IS_STENCIL_FORMAT(presentation_params->AutoDepthStencilFormat)) {
-      _fb_properties.buffer_mask_add(RenderBuffer::T_stencil);
+      _fb_properties.set_stencil_bits(1);
     } else {
-      _fb_properties.buffer_mask_remove(RenderBuffer::T_stencil);
+      _fb_properties.set_stencil_bits(0);
     }
   } else {
-    _fb_properties.buffer_mask_remove(RenderBuffer::T_depth);
-    _fb_properties.buffer_mask_remove(RenderBuffer::T_stencil);
+    _fb_properties.set_depth_bits(0);
+    _fb_properties.set_stencil_bits(0);
   }
 
   init_resized_window();
@@ -918,8 +917,7 @@ search_for_device(wdxGraphicsPipe9 *dxpipe, DXDeviceInfo *device_info) {
   _wcontext._is_dx9_1 = dxpipe->__is_dx9_1;
   _wcontext._card_id = device_info->cardID;  // could this change by end?
 
-  int frame_buffer_mode = _fb_properties.get_frame_buffer_mode();
-  bool bWantStencil = ((frame_buffer_mode & FrameBufferProperties::FM_stencil) != 0);
+  bool bWantStencil = (_fb_properties.get_stencil_bits() > 0);
 
   hr = _d3d9->GetAdapterIdentifier(device_info->cardID, 0,
                                    &_wcontext._dx_device_id);
@@ -1000,7 +998,7 @@ search_for_device(wdxGraphicsPipe9 *dxpipe, DXDeviceInfo *device_info) {
 
   bool bNeedZBuffer =
     ((!(_d3dcaps.RasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )) &&
-     ((frame_buffer_mode & FrameBufferProperties::FM_depth) != 0));
+     (_fb_properties.get_depth_bits() > 0));
 
   _wcontext._presentation_params.EnableAutoDepthStencil = bNeedZBuffer;
 

+ 0 - 1
panda/src/dxgsg9/wdxGraphicsWindow9.h

@@ -83,7 +83,6 @@ private:
   DXGraphicsStateGuardian9 *_dxgsg;
   DXScreenData _wcontext;
 
-  int _buffer_mask;
   int _depth_buffer_bpp;
   bool _awaiting_restore;
 

+ 1 - 14
panda/src/framework/windowFramework.cxx

@@ -151,26 +151,13 @@ open_window(const WindowProperties &props, GraphicsEngine *engine,
             GraphicsPipe *pipe, GraphicsStateGuardian *gsg) {
   nassertr(_window == (GraphicsWindow *)NULL, _window);
 
-  PT(GraphicsStateGuardian) ptgsg = gsg;
-
-  // If we were not given a gsg in the arguments, create a new one
-  // just for this window.
-  if (ptgsg == (GraphicsStateGuardian *)NULL) {
-    ptgsg = engine->make_gsg(pipe);
-    if (ptgsg == (GraphicsStateGuardian *)NULL) {
-      // No GSG, no window.
-      framework_cat.fatal() << "open_window: failed to create gsg object!\n";
-      return NULL;
-    }
-  }
-
   static int next_window_index = 1;
   ostringstream stream;
   stream << "window" << next_window_index;
   next_window_index++;
   string name = stream.str();
 
-  _window = engine->make_window(ptgsg, name, 0);
+  _window = engine->make_window(gsg, name, 0);
   if (_window != (GraphicsWindow *)NULL) {
     _window->request_properties(props);
 

+ 26 - 1
panda/src/glstuff/glGraphicsBuffer_src.cxx

@@ -439,6 +439,9 @@ select_cube_map(int cube_map_index) {
 bool CLP(GraphicsBuffer)::
 open_buffer() {
 
+  // Double check that we have a host
+  nassertr(_host != 0, false);
+
   // Check for support of relevant extensions.
   CLP(GraphicsStateGuardian) *glgsg;
   DCAST_INTO_R(glgsg, _gsg, false);
@@ -446,7 +449,29 @@ open_buffer() {
       (glgsg->_glDrawBuffers == 0)) {
     return false;
   }
-
+  
+  // Describe the framebuffer properties of the FBO.  
+  // 
+  // The rule is that the properties should be as close
+  // as possible to those requested, subject to the limits
+  // of the implementation.  This particular implementation
+  // is fairly limited.  But that's okay, we just have to
+  // tell the truth about what we actually provide by setting
+  // the _fb_properties accurately.
+
+  _fb_properties.set_depth_bits(1);
+  _fb_properties.set_color_bits(1);
+  _fb_properties.set_alpha_bits(1);
+  _fb_properties.set_stencil_bits(0);
+  _fb_properties.set_accum_bits(0);
+  _fb_properties.set_multisamples(0);
+  _fb_properties.set_back_buffers(0);
+  _fb_properties.set_indexed_color(0);
+  _fb_properties.set_rgb_color(1);
+  _fb_properties.set_stereo(0);
+  _fb_properties.set_force_hardware(_host->get_fb_properties().get_force_hardware());
+  _fb_properties.set_force_software(_host->get_fb_properties().get_force_software());
+  
   _is_valid = true;
   return true;
 }

+ 7 - 21
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -259,8 +259,8 @@ fix_component_ordering(CPTA_uchar orig_image, GLenum external_format,
 //  Description:
 ////////////////////////////////////////////////////////////////////
 CLP(GraphicsStateGuardian)::
-CLP(GraphicsStateGuardian)(const FrameBufferProperties &properties) :
-  GraphicsStateGuardian(properties, CS_yup_right)
+CLP(GraphicsStateGuardian)(GraphicsPipe *pipe) :
+  GraphicsStateGuardian(CS_yup_right, pipe)
 {
   _error_count = 0;
 }
@@ -973,17 +973,6 @@ reset() {
 
   _auto_rescale_normal = false;
 
-  // If we don't have double-buffering, don't attempt to write to the
-  // back buffer.
-  // Update: this code has been disabled.  Instead, the code that
-  // creates the window needs to make sure it created a back buffer
-  // in those cases where a back buffer was requested. - Josh
-  // GLboolean has_back;
-  // GLP(GetBooleanv)(GL_DOUBLEBUFFER, &has_back);
-  // if (!has_back) {
-  //   _buffer_mask &= ~RenderBuffer::T_back;
-  // }
-
   // Ensure the initial state is what we say it should be (in some
   // cases, we don't want the GL default settings; in others, we have
   // to force the point with some drivers that aren't strictly
@@ -3026,7 +3015,6 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
 
   // Match framebuffer format if necessary.
   if (tex->get_match_framebuffer_format()) {
-    int mode = _current_properties->get_frame_buffer_mode();
 
     switch (tex->get_format()) {
     case Texture::F_depth_component:
@@ -3036,7 +3024,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
       break;
 
     default:
-      if (mode & FrameBufferProperties::FM_alpha) {
+      if (_current_properties->get_alpha_bits()) {
         tex->set_format(Texture::F_rgba);
       } else {
         tex->set_format(Texture::F_rgb);
@@ -3092,12 +3080,10 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr,
   int xo, yo, w, h;
   dr->get_region_pixels(xo, yo, w, h);
 
-  int mode = _current_properties->get_frame_buffer_mode();
-
-  Texture::Format format = tex->get_format();
   Texture::ComponentType component_type = tex->get_component_type();
   bool color_mode = false;
 
+  Texture::Format format = tex->get_format();
   switch (format) {
   case Texture::F_depth_component:
     if (_current_properties->get_depth_bits() <= 8) {
@@ -3117,7 +3103,7 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr,
 
   default:
     color_mode = true;
-    if (mode & FrameBufferProperties::FM_alpha) {
+    if (_current_properties->get_alpha_bits()) {
       format = Texture::F_rgba;
     } else {
       format = Texture::F_rgb;
@@ -4369,13 +4355,13 @@ set_read_buffer(const RenderBuffer &rb) {
       }
       index += 1;
     }
-    for (int i=0; i<_current_properties->get_aux_rgba(); i++) {
+    for (int i=0; i<_current_properties->get_aux_hrgba(); i++) {
       if (rb._buffer_type & (RenderBuffer::T_aux_hrgba_0 << i)) {
         buffer = GL_COLOR_ATTACHMENT0_EXT + index;
       }
       index += 1;
     }
-    for (int i=0; i<_current_properties->get_aux_rgba(); i++) {
+    for (int i=0; i<_current_properties->get_aux_float(); i++) {
       if (rb._buffer_type & (RenderBuffer::T_aux_float_0 << i)) {
         buffer = GL_COLOR_ATTACHMENT0_EXT + index;
       }

+ 1 - 1
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -89,7 +89,7 @@ typedef void (APIENTRY * PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);
 ////////////////////////////////////////////////////////////////////
 class EXPCL_GL CLP(GraphicsStateGuardian) : public GraphicsStateGuardian {
 public:
-  CLP(GraphicsStateGuardian)(const FrameBufferProperties &properties);
+  CLP(GraphicsStateGuardian)(GraphicsPipe *pipe);
   virtual ~CLP(GraphicsStateGuardian)();
 
   virtual void reset();

+ 32 - 2
panda/src/glxdisplay/glxGraphicsBuffer.cxx

@@ -161,11 +161,28 @@ close_buffer() {
 ////////////////////////////////////////////////////////////////////
 bool glxGraphicsBuffer::
 open_buffer() {
+
   glxGraphicsPipe *glx_pipe;
   DCAST_INTO_R(glx_pipe, _pipe, false);
-  glxGraphicsStateGuardian *glxgsg;
-  DCAST_INTO_R(glxgsg, _gsg, false);
 
+  // GSG Creation/Initialization
+  glxGraphicsStateGuardian *glxgsg;
+  if (_gsg == 0) {
+    // There is no old gsg.  Create a new one.
+    glxgsg = new glxGraphicsStateGuardian(_pipe, NULL);
+    glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), true);
+    _gsg = glxgsg;
+  } else {
+    // If the old gsg has the wrong pixel format, create a
+    // new one that shares with the old gsg.
+    DCAST_INTO_R(glxgsg, _gsg, false);
+    if (!glxgsg->get_fb_properties().subsumes(_fb_properties)) {
+      glxgsg = new glxGraphicsStateGuardian(_pipe, glxgsg);
+      glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), true);
+      _gsg = glxgsg;
+    }
+  }
+  
   if (glxgsg->_fbconfig == None) {
     // If we didn't use an fbconfig to create the GSG, we can't create
     // a PBuffer.
@@ -203,6 +220,19 @@ open_buffer() {
     return false;
   }
 
+  glXMakeCurrent(_display, _pbuffer, glxgsg->_context);
+  glxgsg->reset_if_new();
+  if (!glxgsg->is_valid()) {
+    close_buffer();
+    return false;
+  }
+  if (!glxgsg->get_fb_properties().verify_hardware_software
+      (_fb_properties, glxgsg->get_gl_renderer())) {
+    close_buffer();
+    return false;
+  }
+  _fb_properties = glxgsg->get_fb_properties();
+  
   _is_valid = true;
   return true;
 }

+ 37 - 728
panda/src/glxdisplay/glxGraphicsPipe.cxx

@@ -167,109 +167,6 @@ pipe_constructor() {
   return new glxGraphicsPipe;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: glxGraphicsPipe::make_gsg
-//       Access: Protected, Virtual
-//  Description: Creates a new GSG to use the pipe (but no windows
-//               have been created yet for the GSG).  This method will
-//               be called in the draw thread for the GSG.
-////////////////////////////////////////////////////////////////////
-PT(GraphicsStateGuardian) glxGraphicsPipe::
-make_gsg(const FrameBufferProperties &properties,
-         GraphicsStateGuardian *share_with) {
-  if (!_is_valid) {
-    return NULL;
-  }
-
-  glxGraphicsStateGuardian *share_gsg = NULL;
-  GLXContext share_context = NULL;
-
-  if (share_with != (GraphicsStateGuardian *)NULL) {
-    if (!share_with->is_exact_type(glxGraphicsStateGuardian::get_class_type())) {
-      glxdisplay_cat.error()
-        << "Cannot share context between glxGraphicsStateGuardian and "
-        << share_with->get_type() << "\n";
-      return NULL;
-    }
-
-    DCAST_INTO_R(share_gsg, share_with, NULL);
-    share_context = share_gsg->_context;
-  }
-
-  // There's no interface in GLX to query whether we have a software
-  // or a hardware rendering context.  Fortunately, there seems to be
-  // only one likely software GLX context, and that's Mesa; we will
-  // assume that any Mesa GLX context is software-based, and any other
-  // context is hardware-based.
-
-  // Unforunately, to determine whether we are using Mesa, we need to
-  // create a GL context, bind it to a window, and then examine the
-  // GL_RENDERER string to see if it contains "Mesa".  So we must
-  // create the GSG and its window first, and wait until the GSG has
-  // been reset, before we can ask this question.  Therefore we don't
-  // deal with hardware/software at this point, but rather in
-  // glxGraphicsStateGuardian::reset().
-
-  // We do, however, need to determine ahead of time whether the user
-  // would prefer a hardware or software context.
-  int frame_buffer_mode = properties.get_frame_buffer_mode();
-  int want_hardware = (frame_buffer_mode & (FrameBufferProperties::FM_hardware | 
-                                            FrameBufferProperties::FM_software));
-
-  FrameBufferProperties new_properties = properties;
-  GLXContext context = NULL;
-  XVisualInfo *visual = NULL;
-
-#ifdef HAVE_GLXFBCONFIG
-  GLXFBConfig fbconfig = choose_fbconfig(new_properties);
-  if (fbconfig != None) {
-    context = 
-      glXCreateNewContext(_display, fbconfig, GLX_RGBA_TYPE, share_context,
-                          GL_TRUE);
-    if (context == NULL) {
-      fbconfig = None;
-    }
-  }
-#endif  // HAVE_GLXFBCONFIG
-
-  if (context == NULL) {
-    // If we couldn't create a context with the fbconfig interface,
-    // try falling back to the older XVisual interface.
-    visual = choose_visual(new_properties);
-
-    if (visual != (XVisualInfo *)NULL) {
-      context = glXCreateContext(_display, visual, None, GL_TRUE);
-    }
-  }
-
-  if (context == NULL) {
-    glxdisplay_cat.error()
-      << "Could not create GL context.\n";
-    return NULL;
-  }
-
-#ifdef HAVE_GLXFBCONFIG
-  if (visual == (XVisualInfo *)NULL) {
-    // If we used the fbconfig to open the context, we still need to
-    // get the associated XVisual.
-    nassertr(fbconfig != None, NULL);
-    visual = glXGetVisualFromFBConfig(_display, fbconfig);
-  }
-
-  // Now we can make a GSG.
-  PT(glxGraphicsStateGuardian) gsg = 
-    new glxGraphicsStateGuardian(new_properties, share_gsg, want_hardware,
-                                 context, visual, _display, _screen, fbconfig);
-
-#else
-  PT(glxGraphicsStateGuardian) gsg = 
-    new glxGraphicsStateGuardian(new_properties, share_gsg, want_hardware,
-                                 context, visual, _display, _screen);
-#endif  // HAVE_GLXFBCONFIG
-
-  return gsg.p();
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: glxGraphicsPipe::make_output
 //       Access: Protected, Virtual
@@ -288,14 +185,11 @@ make_output(const string &name,
     return NULL;
   }
 
-  // This pipe is not yet capable of creating nonhomogeneous windows.
-  if (properties != gsg->get_default_properties()) {
-    return NULL;
+  glxGraphicsStateGuardian *glxgsg = 0;
+  if (gsg != 0) {
+    DCAST_INTO_R(glxgsg, gsg, NULL);
   }
-
-  glxGraphicsStateGuardian *glxgsg;
-  DCAST_INTO_R(glxgsg, gsg, NULL);
-
+  
   // First thing to try: a glxGraphicsWindow
 
   if (retry == 0) {
@@ -311,22 +205,39 @@ make_output(const string &name,
                                  x_size, y_size, flags, gsg, host);
   }
   
-  //  // Second thing to try: a glGraphicsBuffer
-  //  
-  //  if (retry == 1) {
-  //    if ((!support_render_texture)||
-  //        ((flags&BF_require_parasite)!=0)||
-  //        ((flags&BF_require_window)!=0)) {
-  //      return NULL;
-  //    }
-  //    if (precertify) {
-  //      if (!glxgsg->_supports_framebuffer_object) {
-  //        return NULL;
-  //      }
-  //    }
-  //    return new glGraphicsBuffer(this, name, properties,
-  //                                x_size, y_size, flags, gsg, host);
-  //  }
+  // Second thing to try: a GLGraphicsBuffer
+
+  if (retry == 1) {
+    if ((!support_render_texture)||
+	//        (!gl_support_fbo)||
+        (host==0)||
+        ((flags&BF_require_parasite)!=0)||
+        ((flags&BF_require_window)!=0)) {
+      return NULL;
+    }
+    // Early failure - if we are sure that this buffer WONT
+    // meet specs, we can bail out early.
+    if ((flags & BF_fb_props_optional)==0) {
+      if ((properties.get_indexed_color() > 0)||
+          (properties.get_back_buffers() > 0)||
+          (properties.get_accum_bits() > 0)||
+          (properties.get_multisamples() > 0)) {
+        return NULL;
+      }
+    }
+    // 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)&&
+        (properties.is_basic())) {
+      precertify = true;
+    }
+    return new GLGraphicsBuffer(this, name, properties,
+                                x_size, y_size, flags, gsg, host);
+  }
   
 #ifdef HAVE_GLXFBCONFIG
   // Third thing to try: a glxGraphicsBuffer
@@ -349,608 +260,6 @@ make_output(const string &name,
   return NULL;
 }
 
-
-#ifdef HAVE_GLXFBCONFIG
-////////////////////////////////////////////////////////////////////
-//     Function: glxGraphicsPipe::choose_fbconfig
-//       Access: Private
-//  Description: Selects an appropriate GLXFBConfig for the given
-//               frame buffer properties.  Returns the selected
-//               fbconfig if successful, or None otherwise.
-//
-//               If successful, this may modify properties to reflect
-//               the actual visual chosen.
-////////////////////////////////////////////////////////////////////
-GLXFBConfig glxGraphicsPipe::
-choose_fbconfig(FrameBufferProperties &properties) const {
-  int frame_buffer_mode = 0;
-  if (properties.has_frame_buffer_mode()) {
-    frame_buffer_mode = properties.get_frame_buffer_mode();
-  }
-
-  int want_depth_bits = properties.get_depth_bits();
-  int want_color_bits = properties.get_color_bits();
-  int want_alpha_bits = properties.get_alpha_bits();
-  int want_stencil_bits = properties.get_stencil_bits();
-  int want_multisamples = properties.get_multisamples();
-
-  GLXFBConfig fbconfig = 
-    try_for_fbconfig(frame_buffer_mode, want_depth_bits, want_color_bits,
-                     want_alpha_bits, want_stencil_bits, want_multisamples);
-
-  if (fbconfig == None) {
-    glxdisplay_cat.info()
-      << "glxGraphicsPipe::choose_fbconfig() - fbconfig with requested "
-      << "capabilities not found; trying for lesser fbconfig.\n";
-
-    bool special_size_request =
-      (want_depth_bits != 1 || want_color_bits != 1);
-
-    // We try to be smart about choosing a close match for the fbconfig.
-    // First, we'll eliminate some of the more esoteric options one at
-    // a time, then two at a time, and finally we'll try just the bare
-    // minimum.
-
-    if (special_size_request) {
-      // Actually, first we'll eliminate all of the minimum sizes, to
-      // try to open a window with all of the requested options, but
-      // maybe not as many bits in some options as we'd like.
-      fbconfig = try_for_fbconfig(frame_buffer_mode);
-    }
-
-    if (fbconfig == None) {
-      // Ok, not good enough.  Now try to eliminate options, but keep
-      // as many bits as we asked for.
-
-      pset<int> tried_masks;
-      tried_masks.insert(frame_buffer_mode);
-
-      int i;
-      for (i = 0; fbconfig == None && strip_properties[i] != 0; i++) {
-        int new_frame_buffer_mode = frame_buffer_mode & ~strip_properties[i];
-        if (tried_masks.insert(new_frame_buffer_mode).second) {
-          fbconfig = try_for_fbconfig(new_frame_buffer_mode, want_depth_bits,
-                                      want_color_bits, want_alpha_bits, 
-                                      want_stencil_bits, want_multisamples);
-
-        }
-      }
-
-      if (special_size_request) {
-        tried_masks.clear();
-        tried_masks.insert(frame_buffer_mode);
-
-        if (fbconfig == None) {
-          // Try once more, this time eliminating all of the size
-          // requests.
-          for (i = 0; fbconfig == None && strip_properties[i] != 0; i++) {
-            int new_frame_buffer_mode = frame_buffer_mode & ~strip_properties[i];
-            if (tried_masks.insert(new_frame_buffer_mode).second) {
-              fbconfig = try_for_fbconfig(new_frame_buffer_mode);
-            }
-          }
-        }
-      }
-
-      if (fbconfig == None) {
-        // Here's our last-ditch desparation attempt: give us any GLX
-        // fbconfig at all!
-        fbconfig = try_for_fbconfig(0);
-      }
-
-      if (fbconfig == None) {
-        // This is only an info message, because we can still fall
-        // back to the XVisual interface.
-        glxdisplay_cat.info()
-          << "Could not get any GLX fbconfig.\n";
-        return None;
-      }
-    }
-  }
-
-  glxdisplay_cat.info()
-    << "Selected suitable GLX fbconfig.\n";
-
-  // Now update our framebuffer_mode and bit depth appropriately.
-  int render_mode, double_buffer, stereo, red_size, green_size, blue_size,
-    alpha_size, ared_size, agreen_size, ablue_size, aalpha_size,
-    depth_size, stencil_size, samples;
-  
-  glXGetFBConfigAttrib(_display, fbconfig, GLX_RGBA, &render_mode);
-  glXGetFBConfigAttrib(_display, fbconfig, GLX_DOUBLEBUFFER, &double_buffer);
-  glXGetFBConfigAttrib(_display, fbconfig, GLX_STEREO, &stereo);
-  glXGetFBConfigAttrib(_display, fbconfig, GLX_RED_SIZE, &red_size);
-  glXGetFBConfigAttrib(_display, fbconfig, GLX_GREEN_SIZE, &green_size);
-  glXGetFBConfigAttrib(_display, fbconfig, GLX_BLUE_SIZE, &blue_size);
-  glXGetFBConfigAttrib(_display, fbconfig, GLX_ALPHA_SIZE, &alpha_size);
-  glXGetFBConfigAttrib(_display, fbconfig, GLX_ACCUM_RED_SIZE, &ared_size);
-  glXGetFBConfigAttrib(_display, fbconfig, GLX_ACCUM_GREEN_SIZE, &agreen_size);
-  glXGetFBConfigAttrib(_display, fbconfig, GLX_ACCUM_BLUE_SIZE, &ablue_size);
-  glXGetFBConfigAttrib(_display, fbconfig, GLX_ACCUM_ALPHA_SIZE, &aalpha_size);
-  glXGetFBConfigAttrib(_display, fbconfig, GLX_DEPTH_SIZE, &depth_size);
-  glXGetFBConfigAttrib(_display, fbconfig, GLX_STENCIL_SIZE, &stencil_size);
-  glXGetFBConfigAttrib(_display, fbconfig, GLX_SAMPLES, &samples);
-
-  frame_buffer_mode = 0;
-  if (double_buffer) {
-    frame_buffer_mode |= FrameBufferProperties::FM_double_buffer;
-  }
-  if (stereo) {
-    frame_buffer_mode |= FrameBufferProperties::FM_stereo;
-  }
-  if (!render_mode) {
-    frame_buffer_mode |= FrameBufferProperties::FM_index;
-  }
-  if (stencil_size != 0) {
-    frame_buffer_mode |= FrameBufferProperties::FM_stencil;
-  }
-  if (depth_size != 0) {
-    frame_buffer_mode |= FrameBufferProperties::FM_depth;
-  }
-  if (alpha_size != 0) {
-    frame_buffer_mode |= FrameBufferProperties::FM_alpha;
-  }
-  if (ared_size + agreen_size + ablue_size != 0) {
-    frame_buffer_mode |= FrameBufferProperties::FM_accum;
-  }
-  if (samples != 0) {
-    frame_buffer_mode |= FrameBufferProperties::FM_multisample;
-  }
-
-  properties.set_frame_buffer_mode(frame_buffer_mode);
-  properties.set_color_bits(red_size + green_size + blue_size);
-  properties.set_alpha_bits(alpha_size);
-  properties.set_depth_bits(depth_size);
-  properties.set_stencil_bits(stencil_size);
-  properties.set_multisamples(samples);
-
-  if (glxdisplay_cat.is_debug()) {
-    glxdisplay_cat.debug()
-      << "GLX Fbconfig Info (# bits of each):" << endl
-      << " RGBA: " << red_size << " " << green_size << " " << blue_size
-      << " " << alpha_size << endl
-      << " Accum RGBA: " << ared_size << " " << agreen_size << " "
-      << ablue_size << " " << aalpha_size << endl
-      << " Depth: " << depth_size << endl
-      << " Stencil: " << stencil_size << endl
-      << " Samples: " << samples << endl
-      << " DoubleBuffer? " << double_buffer << endl
-      << " Stereo? " << stereo << endl;
-  }
-
-  return fbconfig;
-}
-#endif  // HAVE_GLXFBCONFIG
-
-#ifdef HAVE_GLXFBCONFIG
-////////////////////////////////////////////////////////////////////
-//     Function: glxGraphicsPipe::try_for_fbconfig
-//       Access: Private
-//  Description: Attempt to get the requested fbconfig, if it is
-//               available.  It's just a wrapper around
-//               glXChooseFBConfig().  It returns the fbconfig
-//               information if possible, or None if it is not.
-////////////////////////////////////////////////////////////////////
-GLXFBConfig glxGraphicsPipe::
-try_for_fbconfig(int framebuffer_mode,
-                 int want_depth_bits, int want_color_bits,
-                 int want_alpha_bits, int want_stencil_bits,
-                 int want_multisamples) const {
-  static const int max_attrib_list = 32;
-  int attrib_list[max_attrib_list];
-  int n=0;
-
-  if (glxdisplay_cat.is_debug()) {
-    glxdisplay_cat.debug()
-      << "Trying for fbconfig with: RGB(" << want_color_bits << ")";
-  }
-
-  int want_color_component_bits = max(want_color_bits / 3, 1);
-
-  attrib_list[n++] = GLX_RED_SIZE;
-  attrib_list[n++] = want_color_component_bits;
-  attrib_list[n++] = GLX_GREEN_SIZE;
-  attrib_list[n++] = want_color_component_bits;
-  attrib_list[n++] = GLX_BLUE_SIZE;
-  attrib_list[n++] = want_color_component_bits;
-
-  if (framebuffer_mode & FrameBufferProperties::FM_alpha) {
-    if (glxdisplay_cat.is_debug()) {
-      glxdisplay_cat.debug(false) << " ALPHA(" << want_alpha_bits << ")";
-    }
-    attrib_list[n++] = GLX_ALPHA_SIZE;
-    attrib_list[n++] = want_alpha_bits;
-  }
-
-  switch (framebuffer_mode & FrameBufferProperties::FM_buffer) {
-  case FrameBufferProperties::FM_single_buffer:
-    if (glxdisplay_cat.is_debug()) {
-      glxdisplay_cat.debug(false) << " SINGLEBUFFER";
-    }
-    attrib_list[n++] = GLX_DOUBLEBUFFER;
-    attrib_list[n++] = false;
-    break;
-
-  case FrameBufferProperties::FM_double_buffer:
-  case FrameBufferProperties::FM_triple_buffer:
-    if (glxdisplay_cat.is_debug()) {
-      glxdisplay_cat.debug(false) << " DOUBLEBUFFER";
-    }
-    attrib_list[n++] = GLX_DOUBLEBUFFER;
-    attrib_list[n++] = true;
-    break;
-  }
-
-  if (framebuffer_mode & FrameBufferProperties::FM_stereo) {
-    if (glxdisplay_cat.is_debug()) {
-      glxdisplay_cat.debug(false) << " STEREO";
-    }
-    attrib_list[n++] = GLX_STEREO;
-    attrib_list[n++] = true;
-  } else {
-    attrib_list[n++] = GLX_STEREO;
-    attrib_list[n++] = false;
-  }
-
-  if (framebuffer_mode & FrameBufferProperties::FM_depth) {
-    if (glxdisplay_cat.is_debug()) {
-      glxdisplay_cat.debug(false) << " DEPTH(" << want_depth_bits << ")";
-    }
-    attrib_list[n++] = GLX_DEPTH_SIZE;
-    attrib_list[n++] = want_depth_bits;
-  }
-
-  if (framebuffer_mode & FrameBufferProperties::FM_stencil) {
-    if (glxdisplay_cat.is_debug()) {
-      glxdisplay_cat.debug(false) << " STENCIL(" << want_stencil_bits << ")";
-    }
-    attrib_list[n++] = GLX_STENCIL_SIZE;
-    attrib_list[n++] = want_stencil_bits;
-  }
-
-  if (framebuffer_mode & FrameBufferProperties::FM_accum) {
-    if (glxdisplay_cat.is_debug()) {
-      glxdisplay_cat.debug(false) << " ACCUM";
-    }
-    attrib_list[n++] = GLX_ACCUM_RED_SIZE;
-    attrib_list[n++] = want_color_component_bits;
-    attrib_list[n++] = GLX_ACCUM_GREEN_SIZE;
-    attrib_list[n++] = want_color_component_bits;
-    attrib_list[n++] = GLX_ACCUM_BLUE_SIZE;
-    attrib_list[n++] = want_color_component_bits;
-    if (framebuffer_mode & FrameBufferProperties::FM_alpha) {
-      attrib_list[n++] = GLX_ACCUM_ALPHA_SIZE;
-      attrib_list[n++] = want_alpha_bits;
-    }
-  }
-
-  if (framebuffer_mode & FrameBufferProperties::FM_multisample) {
-    if (glxdisplay_cat.is_debug()) {
-      glxdisplay_cat.debug(false) << " MULTISAMPLE(" << want_multisamples << ")";
-    }
-    attrib_list[n++] = GLX_SAMPLE_BUFFERS;
-    attrib_list[n++] = 1;
-    attrib_list[n++] = GLX_SAMPLES;
-    attrib_list[n++] = want_multisamples;
-  }
-
-  // Terminate the list
-  nassertr(n < max_attrib_list, None);
-  attrib_list[n] = (int)None;
-
-  int num_configs = 0;
-  GLXFBConfig *configs =
-    glXChooseFBConfig(_display, _screen, attrib_list, &num_configs);
-
-  if (glxdisplay_cat.is_debug()) {
-    if (configs != NULL) {
-      glxdisplay_cat.debug(false) 
-        << ", " << num_configs << " matches found!\n";
-    } else {
-      glxdisplay_cat.debug(false) << ", no match.\n";
-    }
-  }
-
-  if (configs == NULL || num_configs == 0) {
-    return None;
-  }
-
-  // Pick the first matching fbconfig; this will be the "best" one
-  // according to the GLX specifics.
-  GLXFBConfig fbconfig = configs[0];
-  XFree(configs);
-
-  return fbconfig;
-}
-#endif  // HAVE_GLXFBCONFIG
-
-////////////////////////////////////////////////////////////////////
-//     Function: glxGraphicsPipe::choose visual
-//       Access: Private
-//  Description: Selects an appropriate X visual for the given frame
-//               buffer properties.  Returns the visual pointer if
-//               successful, or NULL otherwise.
-//
-//               If successful, this may modify properties to reflect
-//               the actual visual chosen.
-//
-//               This is an older GLX interface, replaced by the new
-//               fbconfig interface.  However, some implementations of
-//               GLX may not support fbconfig, so we have to have this
-//               code as a fallback.
-////////////////////////////////////////////////////////////////////
-XVisualInfo *glxGraphicsPipe::
-choose_visual(FrameBufferProperties &properties) const {
-  int frame_buffer_mode = 0;
-
-  if (properties.has_frame_buffer_mode()) {
-    frame_buffer_mode = properties.get_frame_buffer_mode();
-  }
-
-  int want_depth_bits = properties.get_depth_bits();
-  int want_color_bits = properties.get_color_bits();
-  int want_alpha_bits = properties.get_alpha_bits();
-  int want_stencil_bits = properties.get_stencil_bits();
-  int want_multisamples = properties.get_multisamples();
-
-  XVisualInfo *visual = 
-    try_for_visual(frame_buffer_mode, want_depth_bits, want_color_bits,
-                   want_alpha_bits, want_stencil_bits, want_multisamples);
-
-  if (visual == NULL) {
-    glxdisplay_cat.info()
-      << "glxGraphicsPipe::choose_visual() - visual with requested "
-      << " capabilities not found; trying for lesser visual.\n";
-
-    bool special_size_request =
-      (want_depth_bits != 1 || want_color_bits != 1);
-
-    // We try to be smart about choosing a close match for the visual.
-    // First, we'll eliminate some of the more esoteric options one at
-    // a time, then two at a time, and finally we'll try just the bare
-    // minimum.
-
-    if (special_size_request) {
-      // Actually, first we'll eliminate all of the minimum sizes, to
-      // try to open a window with all of the requested options, but
-      // maybe not as many bits in some options as we'd like.
-      visual = try_for_visual(frame_buffer_mode);
-    }
-
-    if (visual == NULL) {
-      // Ok, not good enough.  Now try to eliminate options, but keep
-      // as many bits as we asked for.
-
-      // This array keeps the bitmasks of options that we pull out of
-      // the requested frame_buffer_mode, in order.
-
-      pset<int> tried_masks;
-      tried_masks.insert(frame_buffer_mode);
-
-      int i;
-      for (i = 0; visual == NULL && strip_properties[i] != 0; i++) {
-        int new_frame_buffer_mode = frame_buffer_mode & ~strip_properties[i];
-        if (tried_masks.insert(new_frame_buffer_mode).second) {
-          visual = try_for_visual(new_frame_buffer_mode, want_depth_bits,
-                                  want_color_bits, want_alpha_bits, 
-                                  want_stencil_bits, want_multisamples);
-
-        }
-      }
-
-      if (special_size_request) {
-        tried_masks.clear();
-        tried_masks.insert(frame_buffer_mode);
-
-        if (visual == NULL) {
-          // Try once more, this time eliminating all of the size
-          // requests.
-          for (i = 0; visual == NULL && strip_properties[i] != 0; i++) {
-            int new_frame_buffer_mode = frame_buffer_mode & ~strip_properties[i];
-            if (tried_masks.insert(new_frame_buffer_mode).second) {
-              visual = try_for_visual(new_frame_buffer_mode);
-            }
-          }
-        }
-      }
-
-      if (visual == NULL) {
-        // Here's our last-ditch desparation attempt: give us any GLX
-        // visual at all!
-        visual = try_for_visual(0);
-      }
-
-      if (visual == NULL) {
-        glxdisplay_cat.error()
-          << "Could not get any GLX visual.\n";
-        return NULL;
-      }
-    }
-  }
-
-  glxdisplay_cat.info()
-    << "Got visual 0x" << hex << (int)visual->visualid << dec << ".\n";
-
-  // Now update our framebuffer_mode and bit depth appropriately.
-  int render_mode, double_buffer, stereo, red_size, green_size, blue_size,
-    alpha_size, ared_size, agreen_size, ablue_size, aalpha_size,
-    depth_size, stencil_size, samples;
-  
-  glXGetConfig(_display, visual, GLX_RGBA, &render_mode);
-  glXGetConfig(_display, visual, GLX_DOUBLEBUFFER, &double_buffer);
-  glXGetConfig(_display, visual, GLX_STEREO, &stereo);
-  glXGetConfig(_display, visual, GLX_RED_SIZE, &red_size);
-  glXGetConfig(_display, visual, GLX_GREEN_SIZE, &green_size);
-  glXGetConfig(_display, visual, GLX_BLUE_SIZE, &blue_size);
-  glXGetConfig(_display, visual, GLX_ALPHA_SIZE, &alpha_size);
-  glXGetConfig(_display, visual, GLX_ACCUM_RED_SIZE, &ared_size);
-  glXGetConfig(_display, visual, GLX_ACCUM_GREEN_SIZE, &agreen_size);
-  glXGetConfig(_display, visual, GLX_ACCUM_BLUE_SIZE, &ablue_size);
-  glXGetConfig(_display, visual, GLX_ACCUM_ALPHA_SIZE, &aalpha_size);
-  glXGetConfig(_display, visual, GLX_DEPTH_SIZE, &depth_size);
-  glXGetConfig(_display, visual, GLX_STENCIL_SIZE, &stencil_size);
-  glXGetConfig(_display, visual, GLX_STENCIL_SIZE, &samples);
-
-  frame_buffer_mode = 0;
-  if (double_buffer) {
-    frame_buffer_mode |= FrameBufferProperties::FM_double_buffer;
-  }
-  if (stereo) {
-    frame_buffer_mode |= FrameBufferProperties::FM_stereo;
-  }
-  if (!render_mode) {
-    frame_buffer_mode |= FrameBufferProperties::FM_index;
-  }
-  if (stencil_size != 0) {
-    frame_buffer_mode |= FrameBufferProperties::FM_stencil;
-  }
-  if (depth_size != 0) {
-    frame_buffer_mode |= FrameBufferProperties::FM_depth;
-  }
-  if (alpha_size != 0) {
-    frame_buffer_mode |= FrameBufferProperties::FM_alpha;
-  }
-  if (ared_size + agreen_size + ablue_size != 0) {
-    frame_buffer_mode |= FrameBufferProperties::FM_accum;
-  }
-  if (samples != 0) {
-    frame_buffer_mode |= FrameBufferProperties::FM_multisample;
-  }
-
-  properties.set_frame_buffer_mode(frame_buffer_mode);
-  properties.set_color_bits(red_size + green_size + blue_size);
-  properties.set_alpha_bits(alpha_size);
-  properties.set_depth_bits(depth_size);
-  properties.set_stencil_bits(stencil_size);
-  properties.set_multisamples(samples);
-
-  if (glxdisplay_cat.is_debug()) {
-    glxdisplay_cat.debug()
-      << "GLX Visual Info (# bits of each):" << endl
-      << " RGBA: " << red_size << " " << green_size << " " << blue_size
-      << " " << alpha_size << endl
-      << " Accum RGBA: " << ared_size << " " << agreen_size << " "
-      << ablue_size << " " << aalpha_size << endl
-      << " Depth: " << depth_size << endl
-      << " Stencil: " << stencil_size << endl
-      << " Samples: " << samples << endl
-      << " DoubleBuffer? " << double_buffer << endl
-      << " Stereo? " << stereo << endl;
-  }
-
-  return visual;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: glxGraphicsPipe::try_for_visual
-//       Access: Private
-//  Description: Attempt to get the requested visual, if it is
-//               available.  It's just a wrapper around
-//               glXChooseVisual().  It returns the visual information
-//               if possible, or NULL if it is not.
-//
-//               This is an older GLX interface, replaced by the new
-//               fbconfig interface.  However, some implementations of
-//               GLX may not support fbconfig, so we have to have this
-//               code as a fallback.
-////////////////////////////////////////////////////////////////////
-XVisualInfo *glxGraphicsPipe::
-try_for_visual(int framebuffer_mode,
-               int want_depth_bits, int want_color_bits,
-               int want_alpha_bits, int want_stencil_bits,
-               int want_multisamples) const {
-  static const int max_attrib_list = 32;
-  int attrib_list[max_attrib_list];
-  int n=0;
-
-  if (glxdisplay_cat.is_debug()) {
-    glxdisplay_cat.debug()
-      << "Trying for visual with: RGB(" << want_color_bits << ")";
-  }
-
-  int want_color_component_bits = max(want_color_bits / 3, 1);
-
-  attrib_list[n++] = GLX_RGBA;
-  attrib_list[n++] = GLX_RED_SIZE;
-  attrib_list[n++] = want_color_component_bits;
-  attrib_list[n++] = GLX_GREEN_SIZE;
-  attrib_list[n++] = want_color_component_bits;
-  attrib_list[n++] = GLX_BLUE_SIZE;
-  attrib_list[n++] = want_color_component_bits;
-
-  if (framebuffer_mode & FrameBufferProperties::FM_alpha) {
-    if (glxdisplay_cat.is_debug()) {
-      glxdisplay_cat.debug(false) << " ALPHA(" << want_alpha_bits << ")";
-    }
-    attrib_list[n++] = GLX_ALPHA_SIZE;
-    attrib_list[n++] = want_alpha_bits;
-  }
-  if (framebuffer_mode & FrameBufferProperties::FM_double_buffer) {
-    if (glxdisplay_cat.is_debug()) {
-      glxdisplay_cat.debug(false) << " DOUBLEBUFFER";
-    }
-    attrib_list[n++] = GLX_DOUBLEBUFFER;
-  }
-  if (framebuffer_mode & FrameBufferProperties::FM_stereo) {
-    if (glxdisplay_cat.is_debug()) {
-      glxdisplay_cat.debug(false) << " STEREO";
-    }
-    attrib_list[n++] = GLX_STEREO;
-  }
-  if (framebuffer_mode & FrameBufferProperties::FM_depth) {
-    if (glxdisplay_cat.is_debug()) {
-      glxdisplay_cat.debug(false) << " DEPTH(" << want_depth_bits << ")";
-    }
-    attrib_list[n++] = GLX_DEPTH_SIZE;
-    attrib_list[n++] = want_depth_bits;
-  }
-  if (framebuffer_mode & FrameBufferProperties::FM_stencil) {
-    if (glxdisplay_cat.is_debug()) {
-      glxdisplay_cat.debug(false) << " STENCIL(" << want_stencil_bits << ")";
-    }
-    attrib_list[n++] = GLX_STENCIL_SIZE;
-    attrib_list[n++] = want_stencil_bits;
-  }
-  if (framebuffer_mode & FrameBufferProperties::FM_accum) {
-    if (glxdisplay_cat.is_debug()) {
-      glxdisplay_cat.debug(false) << " ACCUM";
-    }
-    attrib_list[n++] = GLX_ACCUM_RED_SIZE;
-    attrib_list[n++] = want_color_component_bits;
-    attrib_list[n++] = GLX_ACCUM_GREEN_SIZE;
-    attrib_list[n++] = want_color_component_bits;
-    attrib_list[n++] = GLX_ACCUM_BLUE_SIZE;
-    attrib_list[n++] = want_color_component_bits;
-    if (framebuffer_mode & FrameBufferProperties::FM_alpha) {
-      attrib_list[n++] = GLX_ACCUM_ALPHA_SIZE;
-      attrib_list[n++] = want_alpha_bits;
-    }
-  }
-  if (framebuffer_mode & FrameBufferProperties::FM_multisample) {
-    if (glxdisplay_cat.is_debug()) {
-      glxdisplay_cat.debug(false) << " MULTISAMPLE(" << want_multisamples << ")";
-    }
-    attrib_list[n++] = GLX_SAMPLES;
-    attrib_list[n++] = want_multisamples;
-  }
-
-  // Terminate the list
-  nassertr(n < max_attrib_list, NULL);
-  attrib_list[n] = (int)None;
-
-  XVisualInfo *vinfo = glXChooseVisual(_display, _screen, attrib_list);
-
-  if (glxdisplay_cat.is_debug()) {
-    if (vinfo != NULL) {
-      glxdisplay_cat.debug(false) << ", match found!\n";
-    } else {
-      glxdisplay_cat.debug(false) << ", no match.\n";
-    }
-  }
-
-  return vinfo;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: glxGraphicsPipe::make_hidden_cursor
 //       Access: Private

+ 0 - 20
panda/src/glxdisplay/glxGraphicsPipe.h

@@ -112,8 +112,6 @@ public:
   Atom _net_wm_window_type_fullscreen;
 
 protected:
-  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
-                                             GraphicsStateGuardian *share_with);
   virtual PT(GraphicsOutput) make_output(const string &name,
                                          const FrameBufferProperties &properties,
                                          int x_size, int y_size, int flags,
@@ -123,24 +121,6 @@ protected:
                                          bool &precertify);
 
 private:
-#ifdef HAVE_GLXFBCONFIG
-  GLXFBConfig choose_fbconfig(FrameBufferProperties &properties) const;
-  GLXFBConfig try_for_fbconfig(int framebuffer_mode,
-                               int want_depth_bits = 1, 
-                               int want_color_bits = 1,
-                               int want_alpha_bits = 1, 
-                               int want_stencil_bits = 1,
-                               int want_multisamples = 1) const;
-#endif
-
-  XVisualInfo *choose_visual(FrameBufferProperties &properties) const;
-  XVisualInfo *try_for_visual(int framebuffer_mode,
-                              int want_depth_bits = 1, 
-                              int want_color_bits = 1,
-                              int want_alpha_bits = 1, 
-                              int want_stencil_bits = 1,
-                              int want_multisamples = 1) const;
-
   void make_hidden_cursor();
   void release_hidden_cursor();
 

+ 13 - 0
panda/src/glxdisplay/glxGraphicsStateGuardian.I

@@ -15,3 +15,16 @@
 // [email protected] .
 //
 ////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsStateGuardian::get_fb_properties
+//       Access: Private
+//  Description: Gets the FrameBufferProperties for all windows and
+//               buffers that use this GSG.
+////////////////////////////////////////////////////////////////////
+INLINE const FrameBufferProperties &glxGraphicsStateGuardian::
+get_fb_properties() const {
+  return _fbprops;
+}
+
+

+ 270 - 70
panda/src/glxdisplay/glxGraphicsStateGuardian.cxx

@@ -31,27 +31,21 @@ TypeHandle glxGraphicsStateGuardian::_type_handle;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 glxGraphicsStateGuardian::
-glxGraphicsStateGuardian(const FrameBufferProperties &properties,
-                         glxGraphicsStateGuardian *share_with,
-                         int want_hardware,
-                         GLXContext context, XVisualInfo *visual, 
-                         Display *display, int screen
-#ifdef HAVE_GLXFBCONFIG
-                         , GLXFBConfig fbconfig
-#endif  // HAVE_GLXFBCONFIG
-                         ) :
-  GLGraphicsStateGuardian(properties),
-  _want_hardware(want_hardware),
-  _context(context),
-  _visual(visual),
-  _display(display),
-  _screen(screen)
-#ifdef HAVE_GLXFBCONFIG
-  , _fbconfig(fbconfig)
-#endif  // HAVE_GLXFBCONFIG
+glxGraphicsStateGuardian(GraphicsPipe *pipe,
+			 glxGraphicsStateGuardian *share_with) :
+  GLGraphicsStateGuardian(pipe)
 {
+  _share_context=0;
+  _context=0;
+  _display=0;
+  _screen=0;
+  _visual=0;
+  _visuals=0;
+  _fbconfig=0;
+  
   if (share_with != (glxGraphicsStateGuardian *)NULL) {
     _prepared_objects = share_with->get_prepared_objects();
+    _share_context = share_with->_context;
   }
   
   _libgl_handle = NULL;
@@ -66,8 +60,8 @@ glxGraphicsStateGuardian(const FrameBufferProperties &properties,
 ////////////////////////////////////////////////////////////////////
 glxGraphicsStateGuardian::
 ~glxGraphicsStateGuardian() {
-  if (_visual != (XVisualInfo *)NULL) {
-    XFree(_visual);
+  if (_visuals != (XVisualInfo *)NULL) {
+    XFree(_visuals);
   }
   if (_context != (GLXContext)NULL) {
     glXDestroyContext(_display, _context);
@@ -78,6 +72,258 @@ glxGraphicsStateGuardian::
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsStateGuardian::get_properties
+//       Access: Private
+//  Description: Gets the FrameBufferProperties to match the
+//               indicated visual.
+////////////////////////////////////////////////////////////////////
+void glxGraphicsStateGuardian::
+get_properties(FrameBufferProperties &properties, XVisualInfo *visual) {
+
+  int use_gl, render_mode, double_buffer, stereo,
+    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);
+  glXGetConfig(_display, visual, GLX_STEREO, &stereo);
+  glXGetConfig(_display, visual, GLX_RED_SIZE, &red_size);
+  glXGetConfig(_display, visual, GLX_GREEN_SIZE, &green_size);
+  glXGetConfig(_display, visual, GLX_BLUE_SIZE, &blue_size);
+  glXGetConfig(_display, visual, GLX_ALPHA_SIZE, &alpha_size);
+  glXGetConfig(_display, visual, GLX_ACCUM_RED_SIZE, &ared_size);
+  glXGetConfig(_display, visual, GLX_ACCUM_GREEN_SIZE, &agreen_size);
+  glXGetConfig(_display, visual, GLX_ACCUM_BLUE_SIZE, &ablue_size);
+  glXGetConfig(_display, visual, GLX_ACCUM_ALPHA_SIZE, &aalpha_size);
+  glXGetConfig(_display, visual, GLX_DEPTH_SIZE, &depth_size);
+  glXGetConfig(_display, visual, GLX_STENCIL_SIZE, &stencil_size);
+
+  properties.clear();
+
+  if (use_gl == 0) {
+    // If we return a set of properties without setting either
+    // rgb_color or indexed_color, then this indicates a visual
+    // that's no good for any kind of rendering.
+    return;
+  }
+
+  if (double_buffer) {
+    properties.set_back_buffers(1);
+  }
+  if (stereo) {
+    properties.set_stereo(1);
+  }
+  if (render_mode) {
+    properties.set_rgb_color(1);
+  } else {
+    properties.set_indexed_color(1);
+  }
+  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);
+  
+  // Set both hardware and software bits, indicating not-yet-known.
+  properties.set_force_software(1);
+  properties.set_force_hardware(1);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsStateGuardian::get_properties_advanced
+//       Access: Private
+//  Description: Gets the FrameBufferProperties to match the
+//               indicated GLXFBConfig
+////////////////////////////////////////////////////////////////////
+void glxGraphicsStateGuardian::
+get_properties_advanced(FrameBufferProperties &properties, 
+			bool &pbuffer_supported, bool &slow,
+                        fbconfig config) {
+
+  properties.clear();
+
+#ifdef HAVE_GLXFBCONFIG
+  // Now update our framebuffer_mode and bit depth appropriately.
+  int render_mode, 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;
+  
+  glXGetFBConfigAttrib(_display, config, GLX_RGBA, &render_mode);
+  glXGetFBConfigAttrib(_display, config, GLX_DOUBLEBUFFER, &double_buffer);
+  glXGetFBConfigAttrib(_display, config, GLX_STEREO, &stereo);
+  glXGetFBConfigAttrib(_display, config, GLX_RED_SIZE, &red_size);
+  glXGetFBConfigAttrib(_display, config, GLX_GREEN_SIZE, &green_size);
+  glXGetFBConfigAttrib(_display, config, GLX_BLUE_SIZE, &blue_size);
+  glXGetFBConfigAttrib(_display, config, GLX_ALPHA_SIZE, &alpha_size);
+  glXGetFBConfigAttrib(_display, config, GLX_ACCUM_RED_SIZE, &ared_size);
+  glXGetFBConfigAttrib(_display, config, GLX_ACCUM_GREEN_SIZE, &agreen_size);
+  glXGetFBConfigAttrib(_display, config, GLX_ACCUM_BLUE_SIZE, &ablue_size);
+  glXGetFBConfigAttrib(_display, config, GLX_ACCUM_ALPHA_SIZE, &aalpha_size);
+  glXGetFBConfigAttrib(_display, config, GLX_DEPTH_SIZE, &depth_size);
+  glXGetFBConfigAttrib(_display, config, GLX_STENCIL_SIZE, &stencil_size);
+  glXGetFBConfigAttrib(_display, config, GLX_SAMPLES, &samples);
+  glXGetFBConfigAttrib(_display, config, GLX_DRAWABLE_TYPE, &drawable_type);
+  glXGetFBConfigAttrib(_display, config, GLX_CONFIG_CAVEAT, &caveat);
+
+  if ((drawable_type & GLX_WINDOW_BIT)==0) {
+    // If we return a set of properties without setting either
+    // rgb_color or indexed_color, then this indicates a visual
+    // that's no good for any kind of rendering.
+    return;
+  }
+  pbuffer_supported = false;
+  if ((drawable_type & GLX_PBUFFER_BIT)!=0) {
+    pbuffer_supported = true;
+  }
+  
+  if (caveat & GLX_SLOW_CONFIG) {
+    slow = true;
+  } else {
+    slow = false;
+  }
+  
+  if (double_buffer) {
+    properties.set_back_buffers(1);
+  }
+  if (stereo) {
+    properties.set_stereo(1);
+  }
+  if (render_mode) {
+    properties.set_rgb_color(1);
+  } else {
+    properties.set_indexed_color(1);
+  }
+  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);
+#endif // HAVE_GLXFBCONFIG
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsStateGuardian::choose_pixel_format
+//       Access: Private
+//  Description: Selects a visual or fbconfig for all the windows
+//               and buffers that use this gsg.  Also creates the GL
+//               context and obtains the visual.
+////////////////////////////////////////////////////////////////////
+void glxGraphicsStateGuardian::
+choose_pixel_format(const FrameBufferProperties &properties,
+		    Display *display,
+		    int screen,
+                    bool need_pbuffer) {
+
+  _display = display;
+  _screen = screen;
+  _context = 0;
+  _fbconfig = 0;
+  _visual = 0;
+  _visuals = 0;
+  _fbprops.clear();
+
+#ifdef HAVE_GLXFBCONFIG  
+  //// Choose best format available using GLXFBConfig
+
+  static const int max_attrib_list = 32;
+  int attrib_list[max_attrib_list];
+  int n = 0;
+  attrib_list[n++] = GLX_STEREO;
+  attrib_list[n++] = GLX_DONT_CARE;
+  attrib_list[n++] = GLX_RENDER_TYPE;
+  attrib_list[n++] = GLX_DONT_CARE;
+  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);
+
+  int best_quality = 0;
+  int best_result = 0;
+  FrameBufferProperties best_props;
+
+  if (configs != 0) {
+    for (int i=0; i<num_configs; i++) {
+      FrameBufferProperties fbprops;
+      bool pbuffer_supported, slow;
+      get_properties_advanced(fbprops, pbuffer_supported, slow, configs[i]);
+      int quality = fbprops.get_quality(properties);
+      if ((quality > 0)&&(slow)) quality -= 10000000;
+      if ((need_pbuffer==0)||(pbuffer_supported)) {
+	if (quality > best_quality) {
+	  best_quality = quality;
+	  best_result = i;
+	  best_props = fbprops;
+	}
+      }
+    }
+  }
+  
+  if (best_quality > 0) {
+    _fbconfig = configs[best_result];
+    _context = 
+      glXCreateNewContext(_display, _fbconfig, GLX_RGBA_TYPE, _share_context,
+                          GL_TRUE);
+    if (_context) {
+      _visuals = glXGetVisualFromFBConfig(_display, _fbconfig);
+      _visual = _visuals;
+      if (_visual) {
+	_fbprops = best_props;
+	return;
+      }
+    }
+    // This really shouldn't happen, so I'm not too careful about cleanup.
+    _fbconfig = 0;
+    _context = 0;
+    _visual = 0;
+    _visuals = 0;
+  }
+#endif // HAVE_GLXFBCONFIG
+  
+  if (need_pbuffer) {
+    // The xvisual interface cannot create pbuffers.
+    return;
+  }
+
+  // Scan available visuals.
+  int nvisuals=0;
+  _visuals = XGetVisualInfo(_display, 0, 0, &nvisuals);
+  if (_visuals != 0) {
+    for (int i=0; i<nvisuals; i++) {
+      FrameBufferProperties fbprops;
+      get_properties(fbprops, _visuals+i);
+      int quality = fbprops.get_quality(properties);
+      if (quality > best_quality) {
+	best_quality = quality;
+	best_result = i;
+	best_props = fbprops;
+      }
+    }
+  }
+  
+  if (best_quality > 0) {
+    _visual = _visuals+best_result;
+    _context = glXCreateContext(_display, _visual, None, GL_TRUE);    
+    if (_context) {
+      _fbprops = best_props;
+      return;
+    }
+  }
+
+  glxdisplay_cat.error() <<
+    "Could not find a usable pixel format.\n";
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: glxGraphicsStateGuardian::reset
 //       Access: Public, Virtual
@@ -106,64 +352,18 @@ reset() {
     _glXSwapIntervalSGI(sync_video ? 1 : 0);
   }
 
-  // Finally, check that the context is the right kind of context:
-  // hardware or software.  This really means examining the
-  // _gl_renderer string for "Mesa" (see the comment in
-  // glxGraphicsPipe).
-
-  bool hardware = ((_want_hardware & FrameBufferProperties::FM_hardware) != 0);
-  bool software = ((_want_hardware & FrameBufferProperties::FM_software) != 0);
-  // If the user specified neither hardware nor software frame buffer,
-  // he gets either one.
-  if (!hardware && !software) {
-    hardware = true;
-    software = true;
-  }
-
-  // FIXME: should these properties be taken from the window?
-  FrameBufferProperties properties = get_default_properties();
-  int frame_buffer_mode = properties.get_frame_buffer_mode();
-
   // 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.
-    if (!software) {
-      glxdisplay_cat.error()
-        << "The application requested harware acceleration, but your OpenGL\n";
-      glxdisplay_cat.error()
-        << "driver, " << _gl_renderer << ", only supports software rendering.\n";
-      glxdisplay_cat.error()
-        << "You need to install a hardware-accelerated OpenGL driver, or,\n";
-      glxdisplay_cat.error()
-        << "if you actually *want* to use a software renderer, then\n";
-      glxdisplay_cat.error()
-        << "change the word 'hardware' to 'software' in the Config.prc file.\n";
-      _is_valid = false;
-    }
-    frame_buffer_mode = (frame_buffer_mode | FrameBufferProperties::FM_software) & ~FrameBufferProperties::FM_hardware;
-
+    _fbprops.set_force_software(1);
+    _fbprops.set_force_hardware(0);
   } else {
-    // It's some other renderer, therefore probably a hardware context.
-    if (!hardware) {
-      glxdisplay_cat.error()
-        << "Using GL renderer " << _gl_renderer << "; it is probably hardware-accelerated.\n";
-      glxdisplay_cat.error()
-        << "To allow use of this display add FM_hardware to your frame buffer mode.\n";
-      _is_valid = false;
-    }
-    frame_buffer_mode = (frame_buffer_mode | FrameBufferProperties::FM_hardware) & ~FrameBufferProperties::FM_software;
+    _fbprops.set_force_hardware(1);
+    _fbprops.set_force_software(0);
   }
-
-  // FIXME: we need a place to store this now.
-  /*
-  // Update the GSG's record to indicate whether we believe it is a
-  // hardware or software renderer.
-  properties.set_frame_buffer_mode(frame_buffer_mode);
-  set_properties(properties);
-  */
 }
 
 ////////////////////////////////////////////////////////////////////

+ 22 - 14
panda/src/glxdisplay/glxGraphicsStateGuardian.h

@@ -73,15 +73,24 @@ typedef int (* PFNGLXSWAPINTERVALSGIPROC) (int interval);
 ////////////////////////////////////////////////////////////////////
 class glxGraphicsStateGuardian : public GLGraphicsStateGuardian {
 public:
-  glxGraphicsStateGuardian(const FrameBufferProperties &properties,
-                           glxGraphicsStateGuardian *share_with,
-                           int want_hardware,
-                           GLXContext context, XVisualInfo *visual,
-                           Display *display, int screen
 #ifdef HAVE_GLXFBCONFIG
-                           , GLXFBConfig fbconfig
-#endif  // HAVE_GLXFBCONFIG
-                           );
+  typedef GLXFBConfig fbconfig;
+#else
+  typedef int         fbconfig;
+#endif
+
+  INLINE const FrameBufferProperties &get_fb_properties() const;
+  void get_properties(FrameBufferProperties &properties, XVisualInfo *visual);
+  void get_properties_advanced(FrameBufferProperties &properties,
+			       bool &supports_pbuffer, bool &slow,
+			       fbconfig config);
+  void choose_pixel_format(const FrameBufferProperties &properties, 
+			   Display *_display,
+			   int _screen,
+			   bool need_pbuffer);
+  
+  glxGraphicsStateGuardian(GraphicsPipe *pipe,
+			   glxGraphicsStateGuardian *share_with);
 
   virtual ~glxGraphicsStateGuardian();
 
@@ -89,15 +98,14 @@ public:
 
   bool glx_is_at_least_version(int major_version, int minor_version) const;
 
-  int _want_hardware;
+  GLXContext _share_context;
   GLXContext _context;
-  XVisualInfo *_visual;
   Display *_display;
   int _screen;
-
-#ifdef HAVE_GLXFBCONFIG
-  GLXFBConfig _fbconfig;
-#endif  // HAVE_GLXFBCONFIG
+  XVisualInfo *_visual;
+  XVisualInfo *_visuals;
+  fbconfig _fbconfig;
+  FrameBufferProperties _fbprops;
 
 public:
   bool _supports_swap_control;

+ 33 - 3
panda/src/glxdisplay/glxGraphicsWindow.cxx

@@ -519,14 +519,31 @@ bool glxGraphicsWindow::
 open_window() {
   glxGraphicsPipe *glx_pipe;
   DCAST_INTO_R(glx_pipe, _pipe, false);
-  glxGraphicsStateGuardian *glxgsg;
-  DCAST_INTO_R(glxgsg, _gsg, false);
 
+  // GSG Creation/Initialization
+  glxGraphicsStateGuardian *glxgsg;
+  if (_gsg == 0) {
+    // There is no old gsg.  Create a new one.
+    glxgsg = new glxGraphicsStateGuardian(_pipe, NULL);
+    glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), false);
+    _gsg = glxgsg;
+  } else {
+    // If the old gsg has the wrong pixel format, create a
+    // new one that shares with the old gsg.
+    DCAST_INTO_R(glxgsg, _gsg, false);
+    if (!glxgsg->get_fb_properties().subsumes(_fb_properties)) {
+      glxgsg = new glxGraphicsStateGuardian(_pipe, glxgsg);
+      glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), false);
+      _gsg = glxgsg;
+    }
+  }
+  
+  
   XVisualInfo *visual_info = glxgsg->_visual;
   if (visual_info == NULL) {
     // No X visual for this fbconfig; how can we open the window?
     glxdisplay_cat.error()
-      << "Cannot open window without an X visual.\n";
+      << "Cannot open window.\n";
     return false;
   }
   Visual *visual = visual_info->visual;
@@ -600,6 +617,19 @@ open_window() {
     XDefineCursor(_display, _xwindow, glx_pipe->get_hidden_cursor());
   }
 
+  glXMakeCurrent(_display, _xwindow, glxgsg->_context);
+  glxgsg->reset_if_new();
+  if (!glxgsg->is_valid()) {
+    close_window();
+    return false;
+  }
+  if (!glxgsg->get_fb_properties().verify_hardware_software
+      (_fb_properties, glxgsg->get_gl_renderer())) {
+    close_window();
+    return false;
+  }
+  _fb_properties = glxgsg->get_fb_properties();
+  
   XMapWindow(_display, _xwindow);
 
   return true;

+ 4 - 0
panda/src/mesadisplay/osMesaGraphicsBuffer.cxx

@@ -129,6 +129,10 @@ close_buffer() {
 ////////////////////////////////////////////////////////////////////
 bool OsMesaGraphicsBuffer::
 open_buffer() {
+  if (_gsg == 0) {
+    _gsg = new OSMesaGraphicsStateGuardian(_pipe, NULL);
+  }
+  
   _image = PTA_uchar::empty_array(_x_size * _y_size * 4);
   _is_valid = true;
   return true;

+ 1 - 48
panda/src/mesadisplay/osMesaGraphicsPipe.cxx

@@ -72,52 +72,6 @@ pipe_constructor() {
   return new OsMesaGraphicsPipe;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: OsMesaGraphicsPipe::make_gsg
-//       Access: Protected, Virtual
-//  Description: Creates a new GSG to use the pipe (but no windows
-//               have been created yet for the GSG).  This method will
-//               be called in the draw thread for the GSG.
-////////////////////////////////////////////////////////////////////
-PT(GraphicsStateGuardian) OsMesaGraphicsPipe::
-make_gsg(const FrameBufferProperties &properties, 
-         GraphicsStateGuardian *share_with) {
-
-  OSMesaGraphicsStateGuardian *share_gsg = NULL;
-
-  if (share_with != (GraphicsStateGuardian *)NULL) {
-    if (!share_with->is_exact_type(OSMesaGraphicsStateGuardian::get_class_type())) {
-      mesadisplay_cat.error()
-        << "Cannot share context between OSMesaGraphicsStateGuardian and "
-        << share_with->get_type() << "\n";
-      return NULL;
-    }
-
-    DCAST_INTO_R(share_gsg, share_with, NULL);
-  }
-
-  // We ignore the requested properties; OSMesa contexts are all the
-  // same.
-
-  FrameBufferProperties mesa_props;
-
-  int frame_buffer_mode = 
-    FrameBufferProperties::FM_rgba | 
-    FrameBufferProperties::FM_single_buffer | 
-    FrameBufferProperties::FM_accum | 
-    FrameBufferProperties::FM_depth | 
-    FrameBufferProperties::FM_stencil | 
-    FrameBufferProperties::FM_software;
-
-  mesa_props.set_frame_buffer_mode(frame_buffer_mode);
-  mesa_props.set_color_bits(24);
-  mesa_props.set_alpha_bits(8);
-  mesa_props.set_stencil_bits(8);
-  mesa_props.set_depth_bits(8);
-
-  return new OSMesaGraphicsStateGuardian(mesa_props, share_gsg);
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: OsMesaGraphicsPipe::make_output
 //       Access: Protected, Virtual
@@ -144,8 +98,7 @@ make_output(const string &name,
         ((flags&BF_require_window)!=0)||
         ((flags&BF_size_track_host)!=0)||
         ((flags&BF_can_bind_every)!=0)||
-        ((flags&BF_rtt_cumulative)!=0)||
-        (properties != gsg->get_default_properties())) {
+        ((flags&BF_rtt_cumulative)!=0)) {
       return NULL;
     }
     return new OsMesaGraphicsBuffer(this, name, properties,

+ 0 - 2
panda/src/mesadisplay/osMesaGraphicsPipe.h

@@ -46,8 +46,6 @@ public:
   static PT(GraphicsPipe) pipe_constructor();
 
 protected:
-  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
-                                             GraphicsStateGuardian *share_with);  
   virtual PT(GraphicsOutput) make_output(const string &name,
                                          const FrameBufferProperties &properties,
                                          int x_size, int y_size, int flags,

+ 3 - 3
panda/src/mesadisplay/osMesaGraphicsStateGuardian.cxx

@@ -26,9 +26,9 @@ TypeHandle OSMesaGraphicsStateGuardian::_type_handle;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 OSMesaGraphicsStateGuardian::
-OSMesaGraphicsStateGuardian(const FrameBufferProperties &properties,
-                            OSMesaGraphicsStateGuardian *share_with) : 
-  MesaGraphicsStateGuardian(properties)
+OSMesaGraphicsStateGuardian(GraphicsPipe *pipe,
+			    OSMesaGraphicsStateGuardian *share_with) : 
+  MesaGraphicsStateGuardian(pipe)
 {
   OSMesaContext share_context = NULL;
   if (share_with != (OSMesaGraphicsStateGuardian *)NULL) {

+ 2 - 2
panda/src/mesadisplay/osMesaGraphicsStateGuardian.h

@@ -29,8 +29,8 @@
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDAMESA OSMesaGraphicsStateGuardian : public MesaGraphicsStateGuardian {
 public:
-  OSMesaGraphicsStateGuardian(const FrameBufferProperties &properties,
-                              OSMesaGraphicsStateGuardian *share_with);
+  OSMesaGraphicsStateGuardian(GraphicsPipe *pipe,
+			      OSMesaGraphicsStateGuardian *share_with);
   virtual ~OSMesaGraphicsStateGuardian();
 
   OSMesaContext _context;

+ 4 - 0
panda/src/osxdisplay/osxGraphicsBuffer.cxx

@@ -141,6 +141,10 @@ close_buffer() {
 bool osxGraphicsBuffer::
 open_buffer() {
 
+  if (_gsg == 0) {
+    _gsg = new osxGraphicsStateGuardian(_pipe, NULL);
+  }
+  
   return false;
 }
 

+ 2 - 46
panda/src/osxdisplay/osxGraphicsPipe.cxx

@@ -67,47 +67,6 @@ pipe_constructor() {
   return new osxGraphicsPipe;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: osxGraphicsPipe::make_gsg
-//       Access: Protected, Virtual
-//  Description: Creates a new GSG to use the pipe (but no windows
-//               have been created yet for the GSG).  This method will
-//               be called in the draw thread for the GSG.
-////////////////////////////////////////////////////////////////////
-PT(GraphicsStateGuardian) osxGraphicsPipe::
-make_gsg(const FrameBufferProperties &properties, 
-         GraphicsStateGuardian *share_with) {
-		 
-		 
-  if (!_is_valid) {
-    return NULL;
-  }
-
-  osxGraphicsStateGuardian *share_gsg = NULL;
-
-  if (share_with != (GraphicsStateGuardian *)NULL) {
-    if (!share_with->is_exact_type(osxGraphicsStateGuardian::get_class_type())) 
-	{
-      osxdisplay_cat.error()
-        << "Cannot share context between osxGraphicsStateGuardian and "
-        << share_with->get_type() << "\n";
-      return NULL;
-    }
-
-    DCAST_INTO_R(share_gsg, share_with, NULL);
-  }
-
-  int frame_buffer_mode = 0;
-  if (properties.has_frame_buffer_mode()) {
-    frame_buffer_mode = properties.get_frame_buffer_mode();
-  }
-
-
-	PT(osxGraphicsStateGuardian) gsg1 = new osxGraphicsStateGuardian(properties,(osxGraphicsStateGuardian *)  share_with, 1);
-                          
-    return gsg1.p();
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: osxGraphicsPipe::make_output
 //       Access: Protected, Virtual
@@ -136,9 +95,7 @@ make_output(const string &name,
         ((flags&BF_refuse_window)!=0)||
         ((flags&BF_size_track_host)!=0)||
         ((flags&BF_can_bind_color)!=0)||
-        ((flags&BF_can_bind_every)!=0)
- //       ||(properties != gsg->get_default_properties())
-		) {
+        ((flags&BF_can_bind_every)!=0)) {
       return NULL;
     }
     return new osxGraphicsWindow(this, name, properties,
@@ -168,8 +125,7 @@ make_output(const string &name,
         ((flags&BF_require_parasite)!=0)||
         ((flags&BF_require_window)!=0)||
         ((flags&BF_size_track_host)!=0)||
-        ((flags&BF_can_bind_every)!=0)||
-        (properties != gsg->get_default_properties())) {
+        ((flags&BF_can_bind_every)!=0)) {
       return NULL;
     }
     return new osxGraphicsBuffer(this, name, properties,

+ 0 - 2
panda/src/osxdisplay/osxGraphicsPipe.h

@@ -36,8 +36,6 @@ public:
   static PT(GraphicsPipe) pipe_constructor();
 
 protected:
-  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
-                                             GraphicsStateGuardian *share_with);
   virtual PT(GraphicsOutput) make_output(const string &name,
                                          const FrameBufferProperties &properties,
                                          int x_size, int y_size, int flags,

+ 2 - 3
panda/src/osxdisplay/osxGraphicsStateGuardian.cxx

@@ -57,9 +57,8 @@ void *osxGraphicsStateGuardian::get_extension_func(const char *prefix, const cha
 //  Description:
 ////////////////////////////////////////////////////////////////////
 osxGraphicsStateGuardian::
-osxGraphicsStateGuardian(const FrameBufferProperties &properties,
-                         osxGraphicsStateGuardian *share_with,
-                         int pfnum) : 
+osxGraphicsStateGuardian(GraphicsPipe *pipe,
+                         osxGraphicsStateGuardian *share_with) :
   GLGraphicsStateGuardian(properties),
   _share_with(share_with),
   _aglPixFmt(NULL),

+ 13 - 14
panda/src/osxdisplay/osxGraphicsStateGuardian.h

@@ -36,31 +36,30 @@ class osxGraphicsWindow;
 ////////////////////////////////////////////////////////////////////
 class osxGraphicsStateGuardian : public GLGraphicsStateGuardian {
 public:
-  osxGraphicsStateGuardian(const FrameBufferProperties &properties, 
-                           osxGraphicsStateGuardian *share_with,
-                           int pfnum);
-   virtual ~osxGraphicsStateGuardian();
-   virtual void reset();
+  osxGraphicsStateGuardian(GraphicsPipe *pipe,
+                           osxGraphicsStateGuardian *share_with);
+  virtual ~osxGraphicsStateGuardian();
+  virtual void reset();
 	
 protected:
   virtual void *get_extension_func(const char *prefix, const char *name);
   
 public:
-	OSStatus buildGL (osxGraphicsWindow  &window);
-	AGLContext  get_context(void) { return _aglcontext; };
+  OSStatus buildGL (osxGraphicsWindow  &window);
+  AGLContext  get_context(void) { return _aglcontext; };
 
   // We have to save a pointer to the GSG we intend to share texture
   // context with, since we don't create our own context in the
   // constructor.
-    PT(osxGraphicsStateGuardian) _share_with;
-  	AGLPixelFormat	_aglPixFmt;
-	AGLContext		_aglcontext;
-
-
-	const AGLPixelFormat  getAGlPixelFormat() const { return _aglPixFmt; };
+  PT(osxGraphicsStateGuardian) _share_with;
+  AGLPixelFormat	_aglPixFmt;
+  AGLContext		_aglcontext;
+  
+  const AGLPixelFormat  getAGlPixelFormat() const { return _aglPixFmt; };
 
 public:
-	GLint   SharedBuffer;
+  GLint   SharedBuffer;
+
 public:
   static TypeHandle get_class_type() {
     return _type_handle;

+ 8 - 4
panda/src/osxdisplay/osxGraphicsWindow.cxx

@@ -735,10 +735,14 @@ extern OSErr CPSSetFrontProcess( struct CPSProcessSerNum *psn);
 ////////////////////////////////////////////////////////////////////
 bool osxGraphicsWindow::open_window()
 {
-	WindowProperties req_properties  = _properties;
-	_properties.clear();
-		
-	return OSOpenWindow(req_properties);
+  WindowProperties req_properties  = _properties;
+  _properties.clear();
+  
+  if (_gsg == 0) {
+    _gsg = new osxGraphicsStateGuardian(_pipe, NULL);
+  }
+  
+  return OSOpenWindow(req_properties);
 }
 
 

+ 0 - 1
panda/src/osxdisplay/osxGraphicsWindow.h

@@ -49,7 +49,6 @@ public:
 
   virtual bool move_pointer(int device, int x, int y);
 
-//  virtual void make_current();
   virtual bool begin_frame(FrameMode mode, Thread *current_thread);
   virtual void end_frame(FrameMode mode, Thread *current_thread);
   virtual void begin_flip();

+ 203 - 319
panda/src/wgldisplay/wglGraphicsBuffer.cxx

@@ -43,7 +43,8 @@ wglGraphicsBuffer(GraphicsPipe *pipe,
 {
   _pbuffer = (HPBUFFERARB)0;
   _pbuffer_dc = (HDC)0;
-
+  release_pbuffer();
+  
   // Since the pbuffer never gets flipped, we get screenshots from the
   // same buffer we draw into.
   _screenshot_buffer_type = _draw_buffer_type;
@@ -78,24 +79,21 @@ begin_frame(FrameMode mode, Thread *current_thread) {
   wglGraphicsStateGuardian *wglgsg;
   DCAST_INTO_R(wglgsg, _gsg, false);
 
-  if (_pbuffer_dc) {
-    int flag = 0;
-    wglgsg->_wglQueryPbufferARB(_pbuffer, WGL_PBUFFER_LOST_ARB, &flag);
-    if (flag != 0) {
-      // The pbuffer was lost, due to a mode change or something
-      // silly like that.  We must therefore recreate the pbuffer.
-      close_buffer();
-      if (!open_buffer()) {
-        return false;
-      }
-    }
+  if (_fb_properties.is_single_buffered()) {
+    wglgsg->_wglReleaseTexImageARB(_pbuffer, WGL_FRONT_LEFT_ARB);
+  } else {
+    wglgsg->_wglReleaseTexImageARB(_pbuffer, WGL_BACK_LEFT_ARB);
   }
 
+  if (!rebuild_bitplanes()) {
+    wglGraphicsPipe::wgl_make_current(0, 0, &_make_current_pcollector);
+    return false;
+  }
+  
   wglGraphicsPipe::wgl_make_current(_pbuffer_dc, wglgsg->get_context(_pbuffer_dc),
                                     &_make_current_pcollector);
   
   if (mode == FM_render) {
-    begin_render_texture();
     clear_cube_map_selection();
   }
 
@@ -116,7 +114,7 @@ end_frame(FrameMode mode, Thread *current_thread) {
   nassertv(_gsg != (GraphicsStateGuardian *)NULL);
 
   if (mode == FM_render) {
-    end_render_texture();
+    bind_texture_to_pbuffer();
     copy_to_textures();
   }
   
@@ -132,42 +130,19 @@ end_frame(FrameMode mode, Thread *current_thread) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: wglGraphicsStateGuardian::begin_render_texture
+//     Function: GraphicsOutput::bind_texture_to_pbuffer
 //       Access: Private
-//  Description: If the GraphicsOutput supports direct render-to-texture,
-//               and if any setup needs to be done during begin_frame,
-//               then the setup code should go here.  Any textures that
-//               can not be rendered to directly should be reflagged
-//               as RTM_copy_texture.
+//  Description: Looks for the appropriate texture,
+//               and binds that texture to the pbuffer.
 ////////////////////////////////////////////////////////////////////
 void wglGraphicsBuffer::
-begin_render_texture() {
-  wglGraphicsStateGuardian *wglgsg;
-  DCAST_INTO_V(wglgsg, _gsg);
-  
-  if (_fb_properties.is_single_buffered()) {
-    wglgsg->_wglReleaseTexImageARB(_pbuffer, WGL_FRONT_LEFT_ARB);
-  } else {
-    wglgsg->_wglReleaseTexImageARB(_pbuffer, WGL_BACK_LEFT_ARB);
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsOutput::end_render_texture
-//       Access: Private
-//  Description: If the GraphicsOutput supports direct render-to-texture,
-//               and if any setup needs to be done during end_frame,
-//               then the setup code should go here.  Any textures that
-//               could not be rendered to directly should be reflagged
-//               as RTM_copy_texture.
-////////////////////////////////////////////////////////////////////
-void wglGraphicsBuffer::
-end_render_texture() {
+bind_texture_to_pbuffer() {
   wglGraphicsStateGuardian *wglgsg;
   DCAST_INTO_V(wglgsg, _gsg);
 
   // Find the color texture, if there is one. That one can be bound to
   // the framebuffer.  All others must be marked RTM_copy_to_texture.
+
   int tex_index = -1;
   for (int i=0; i<count_textures(); i++) {
     if (get_rtm_mode(i) == RTM_bind_or_copy) {
@@ -183,6 +158,25 @@ end_render_texture() {
   
   if (tex_index >= 0) {
     Texture *tex = get_texture(tex_index);
+    if ((_pbuffer_bound != 0)&&(_pbuffer_bound != tex)) {
+      _pbuffer_bound->release(wglgsg->get_prepared_objects());
+      _pbuffer_bound = 0;
+    }
+    int tex_x = _x_size;
+    int tex_y = _y_size;
+    if (!wglgsg->get_supports_tex_non_pow2()) {
+      tex_x = Texture::up_to_power_2(tex_x);
+      tex_y = Texture::up_to_power_2(tex_y);
+    }
+    tex->set_x_size(tex_x);
+    tex->set_y_size(tex_y);
+    if (tex->get_match_framebuffer_format()) {
+      if (_fb_properties.get_alpha_bits()) {
+        tex->set_format(Texture::F_rgba);
+      } else {
+        tex->set_format(Texture::F_rgb);
+      }
+    }
     TextureContext *tc = tex->prepare_now(_gsg->get_prepared_objects(), _gsg);
     nassertv(tc != (TextureContext *)NULL);
     CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
@@ -197,6 +191,12 @@ end_render_texture() {
     } else {
       wglgsg->_wglBindTexImageARB(_pbuffer, WGL_BACK_LEFT_ARB);
     }
+    _pbuffer_bound = tex;
+  } else {
+    if (_pbuffer_bound != 0) {
+      _pbuffer_bound->release(wglgsg->get_prepared_objects());
+      _pbuffer_bound = 0;
+    }
   }
 }
 
@@ -266,20 +266,12 @@ close_buffer() {
     wglGraphicsStateGuardian *wglgsg;
     DCAST_INTO_V(wglgsg, _gsg);
 
-    if (_pbuffer_dc) {
-      wglgsg->_wglReleasePbufferDCARB(_pbuffer, _pbuffer_dc);
-    }
-    if (_pbuffer) {
-      wglgsg->_wglDestroyPbufferARB(_pbuffer);
-    }
-    
     _gsg.clear();
     _active = false;
   }
-
-  _pbuffer_dc = 0;
-  _pbuffer = 0;
-
+  
+  release_pbuffer();
+  
   _is_valid = false;
 }
 
@@ -292,39 +284,59 @@ close_buffer() {
 ////////////////////////////////////////////////////////////////////
 bool wglGraphicsBuffer::
 open_buffer() {
-  wglGraphicsStateGuardian *wglgsg;
-  DCAST_INTO_R(wglgsg, _gsg, false);
 
-  // Make sure a pixel format is chosen, and take its properties.
-  if (wglgsg->get_pfnum() < 0) {
-    wglgsg->choose_pixel_format(_fb_properties);
-  }
-  _fb_properties = wglgsg->get_pfnum_properties();
+  // pbuffers don't seem to work correctly in double-buffered
+  // mode. Besides, the back buffer is a pointless waste of space.  
+  // So always use a single-buffered gsg.
+  
+  _fb_properties.set_back_buffers(0);
+  
+  // GSG creation/initialization.
 
+  wglGraphicsStateGuardian *wglgsg;
+  if (_gsg == 0) {
+    // There is no old gsg.  Create a new one.
+    wglgsg = new wglGraphicsStateGuardian(_pipe, NULL);
+    wglgsg->choose_pixel_format(_fb_properties, true);
+    _gsg = wglgsg;
+  } else {
+    // If the old gsg has the wrong pixel format, create a
+    // new one that shares with the old gsg.
+    DCAST_INTO_R(wglgsg, _gsg, false);
+    if ((!wglgsg->get_fb_properties().subsumes(_fb_properties))||
+        (!wglgsg->get_fb_properties().is_single_buffered())||
+        (!wglgsg->pfnum_supports_pbuffer())) {
+      wglgsg = new wglGraphicsStateGuardian(_pipe, wglgsg);
+      wglgsg->choose_pixel_format(_fb_properties, true);
+      _gsg = wglgsg;
+    }
+  }
+  
+  // Use the temp window to initialize the gsg.
+  
   HDC twindow_dc = wglgsg->get_twindow_dc();
   if (twindow_dc == 0) {
     // If we couldn't make a window, we can't get a GL context.
     return false;
   }
-
   wglGraphicsPipe::wgl_make_current(twindow_dc, wglgsg->get_context(twindow_dc),
                                     &_make_current_pcollector);
   wglgsg->reset_if_new();
-
+  wglgsg->report_my_gl_errors();
+  if (!wglgsg->get_fb_properties().verify_hardware_software
+      (_fb_properties,wglgsg->get_gl_renderer())) {
+    return false;
+  }
+  _fb_properties = wglgsg->get_fb_properties();
+  
   // Now that we have fully made a window and used that window to
   // create a rendering context, we can attempt to create a pbuffer.
   // This might fail if the pbuffer extensions are not supported.
 
-  if (!make_pbuffer(twindow_dc)) {
+  if (!rebuild_bitplanes()) {
     wglGraphicsPipe::wgl_make_current(0, 0, &_make_current_pcollector);
     return false;
   }
-
-  _pbuffer_dc = wglgsg->_wglGetPbufferDCARB(_pbuffer);
-  
-  wglGraphicsPipe::wgl_make_current(_pbuffer_dc, wglgsg->get_context(_pbuffer_dc),
-                                    &_make_current_pcollector);
-  wglgsg->report_my_gl_errors();
   
   _is_valid = true;
 
@@ -332,7 +344,38 @@ open_buffer() {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: wglGraphicsBuffer::make_pbuffer
+//     Function: wglGraphicsBuffer::release_pbuffer
+//       Access: Private
+//  Description: Destroys the pbuffer if it has been created.  The
+//               intent is that this may allow it to be recreated
+//               with different options.
+////////////////////////////////////////////////////////////////////
+void wglGraphicsBuffer::
+release_pbuffer() {
+  wglGraphicsStateGuardian *wglgsg;
+  DCAST_INTO_V(wglgsg, _gsg);
+
+  if (_pbuffer_bound != 0) {
+    _pbuffer_bound->release(wglgsg->get_prepared_objects());
+    _pbuffer_bound = 0;
+  }
+  wglGraphicsPipe::wgl_make_current(0, 0, NULL);
+  if (_pbuffer_dc) {
+    wglgsg->_wglReleasePbufferDCARB(_pbuffer, _pbuffer_dc);
+  }
+  if (_pbuffer) {
+    wglgsg->_wglDestroyPbufferARB(_pbuffer);
+  }
+  _pbuffer = (HPBUFFERARB)0;
+  _pbuffer_dc = (HDC)0;
+  _pbuffer_mipmap = false;
+  _pbuffer_sizex = 0;
+  _pbuffer_sizey = 0;
+  _pbuffer_type = Texture::TT_2d_texture;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: wglGraphicsBuffer::rebuild_bitplanes
 //       Access: Private
 //  Description: Once the GL context has been fully realized, attempts
 //               to create an offscreen pbuffer if the graphics API
@@ -340,7 +383,7 @@ open_buffer() {
 //               failure.
 ////////////////////////////////////////////////////////////////////
 bool wglGraphicsBuffer::
-make_pbuffer(HDC twindow_dc) {
+rebuild_bitplanes() {
   wglGraphicsStateGuardian *wglgsg;
   DCAST_INTO_R(wglgsg, _gsg, false);
 
@@ -350,57 +393,6 @@ make_pbuffer(HDC twindow_dc) {
     return false;
   }
 
-  int pbformat = wglgsg->get_pfnum();
-
-  if (wglgsg->_supports_pixel_format) {
-    bool got_pbuffer_format = false;
-    bool any_binds = false;
-    
-    for (int i=0; i<count_textures(); i++) {
-      if (get_rtm_mode(i) == RTM_bind_or_copy) {
-        any_binds = true;
-      }
-    }
-
-    if (any_binds && wglgsg->_supports_render_texture) {
-      // First, try to get a pbuffer format that supports
-      // render-to-texture.
-      int new_pbformat = choose_pbuffer_format(twindow_dc, true);
-      if (new_pbformat != 0) {
-        pbformat = new_pbformat;
-        got_pbuffer_format = true;
-      }
-    }
-
-    if (!got_pbuffer_format) {
-      // Failing that, just get a matching pbuffer format,
-      // and disable RTM_bind_or_copy.
-      for (int i=0; i<count_textures(); i++) {
-        if (get_rtm_mode(i) == RTM_bind_or_copy) {
-          _textures[i]._rtm_mode = RTM_copy_texture;
-        }
-      }
-      int new_pbformat = choose_pbuffer_format(twindow_dc, false);
-      if (new_pbformat != 0) {
-        pbformat = new_pbformat;
-        got_pbuffer_format = true;
-      }
-    }
-
-    if (wgldisplay_cat.is_debug()) {
-      FrameBufferProperties properties;
-      wglGraphicsPipe::get_properties_advanced(properties, wglgsg, 
-                                               twindow_dc, pbformat);
-      wgldisplay_cat.debug()
-        << "Chose pixfmt #" << pbformat << " for pbuffer = " 
-        << properties << "\n";
-    }
-  }
-
-  static const int max_attrib_list = 64;
-  int iattrib_list[max_attrib_list];
-  int ni = 0;
-
   // Find the texture to bind to the color buffer.
   Texture *bindtexture = NULL;
   for (int i=0; i<count_textures(); i++) {
@@ -411,227 +403,119 @@ make_pbuffer(HDC twindow_dc) {
       break;
     }
   }
-  
-  if (bindtexture != 0) {
-
-    if (_fb_properties.get_frame_buffer_mode() & FrameBufferProperties::FM_alpha) {
-      iattrib_list[ni++] = WGL_TEXTURE_FORMAT_ARB;
-      iattrib_list[ni++] = WGL_TEXTURE_RGBA_ARB;
-    } else {
-      iattrib_list[ni++] = WGL_TEXTURE_FORMAT_ARB;
-      iattrib_list[ni++] = WGL_TEXTURE_RGB_ARB;
-    }
-
-    if (bindtexture->uses_mipmaps()) {
-      iattrib_list[ni++] = WGL_MIPMAP_TEXTURE_ARB;
-      iattrib_list[ni++] = 1;
-    }
-
-    switch (bindtexture->get_texture_type()) {
-    case Texture::TT_cube_map:
-      iattrib_list[ni++] = WGL_TEXTURE_TARGET_ARB;
-      iattrib_list[ni++] = WGL_TEXTURE_CUBE_MAP_ARB;
-      break;
 
-    case Texture::TT_1d_texture:
-      iattrib_list[ni++] = WGL_TEXTURE_TARGET_ARB;
-      iattrib_list[ni++] = WGL_TEXTURE_1D_ARB;
-      break;
+  // If we already have a pbuffer, and if it's lost, then 
+  // force the rebuild.
 
-    default:
-      iattrib_list[ni++] = WGL_TEXTURE_TARGET_ARB;
-      iattrib_list[ni++] = WGL_TEXTURE_2D_ARB;
+  if (_pbuffer_dc) {
+    int flag = 0;
+    wglgsg->_wglQueryPbufferARB(_pbuffer, WGL_PBUFFER_LOST_ARB, &flag);
+    if (flag != 0) {
+      release_pbuffer();
     }
-  }  
-
-  // Terminate the list.
-  nassertr(ni <= max_attrib_list, false);
-  iattrib_list[ni] = 0;
+  }
   
-  _pbuffer = wglgsg->_wglCreatePbufferARB(twindow_dc, pbformat, 
-                                          _x_size, _y_size, iattrib_list);
-
-  if (_pbuffer == 0) {
-    wgldisplay_cat.info()
-      << "Attempt to create pbuffer failed.\n";
-    return false;
+  // Determine what pbuffer attributes are needed
+  // for currently-applicable textures.
+
+  if (_creation_flags & GraphicsPipe::BF_size_track_host) {
+    if ((_host->get_x_size() != _x_size)||
+        (_host->get_y_size() != _y_size)) {
+      set_size_and_recalc(_host->get_x_size(),
+                          _host->get_y_size());
+    }
+  }
+  int desired_x = _x_size;
+  int desired_y = _y_size;
+  if ((bindtexture != 0)&&(!wglgsg->get_supports_tex_non_pow2())) {
+    desired_x = Texture::up_to_power_2(desired_x);
+    desired_y = Texture::up_to_power_2(desired_y);
+  }
+  bool desired_mipmap = false;
+  Texture::TextureType desired_type = Texture::TT_2d_texture;
+  if (bindtexture != 0) {
+    desired_mipmap = bindtexture->uses_mipmaps();
+    desired_type = bindtexture->get_texture_type();
   }
 
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: wglGraphicsBuffer::choose_pbuffer_format
-//       Access: Private
-//  Description: Select a suitable pixel format that matches the GSG's
-//               existing format, and also is appropriate for a pixel
-//               buffer.  Returns the selected pfnum if successful, or
-//               0 on failure.
-////////////////////////////////////////////////////////////////////
-int wglGraphicsBuffer::
-choose_pbuffer_format(HDC twindow_dc, bool draw_to_texture) {
-  if (wgldisplay_cat.is_debug()) {
-    wgldisplay_cat.debug()
-      << "choose_pbuffer_format(twindow_dc, draw_to_texture = " 
-      << draw_to_texture << ")\n";
+  if ((_pbuffer != 0)&&
+      (_pbuffer_sizex == desired_x)&&
+      (_pbuffer_sizey == desired_y)&&
+      (_pbuffer_mipmap == desired_mipmap)&&
+      (_pbuffer_type == desired_type)) {
+    // the pbuffer we already have is fine. Do not rebuild.
+    return true;
   }
 
-  wglGraphicsStateGuardian *wglgsg;
-  DCAST_INTO_R(wglgsg, _gsg, false);
+  // Release the old pbuffer, if there was one.
+  
+  release_pbuffer();
+
+  // Allocate the new pbuffer.
 
-  int pbformat = wglgsg->get_pfnum();
+  int pfnum = wglgsg->get_pfnum();
 
   static const int max_attrib_list = 64;
   int iattrib_list[max_attrib_list];
-  int ivalue_list[max_attrib_list];
   int ni = 0;
   
-  int acceleration_i, pixel_type_i, double_buffer_i, stereo_i,
-    red_bits_i, green_bits_i, blue_bits_i, alpha_bits_i, 
-    accum_red_bits_i, accum_green_bits_i, accum_blue_bits_i,
-    accum_alpha_bits_i, depth_bits_i, 
-    stencil_bits_i, sample_buffers_i, multisamples_i;
-  
-  iattrib_list[acceleration_i = ni++] = WGL_ACCELERATION_ARB;
-  iattrib_list[pixel_type_i = ni++] = WGL_PIXEL_TYPE_ARB;
-  iattrib_list[double_buffer_i = ni++] = WGL_DOUBLE_BUFFER_ARB;
-  iattrib_list[stereo_i = ni++] = WGL_STEREO_ARB;
-  iattrib_list[red_bits_i = ni++] = WGL_RED_BITS_ARB;
-  iattrib_list[green_bits_i = ni++] = WGL_GREEN_BITS_ARB;
-  iattrib_list[blue_bits_i = ni++] = WGL_BLUE_BITS_ARB;
-  iattrib_list[alpha_bits_i = ni++] = WGL_ALPHA_BITS_ARB;
-  iattrib_list[accum_red_bits_i = ni++] = WGL_ACCUM_RED_BITS_ARB;
-  iattrib_list[accum_green_bits_i = ni++] = WGL_ACCUM_GREEN_BITS_ARB;
-  iattrib_list[accum_blue_bits_i = ni++] = WGL_ACCUM_BLUE_BITS_ARB;
-  iattrib_list[accum_alpha_bits_i = ni++] = WGL_ACCUM_ALPHA_BITS_ARB;
-  iattrib_list[depth_bits_i = ni++] = WGL_DEPTH_BITS_ARB;
-  iattrib_list[stencil_bits_i = ni++] = WGL_STENCIL_BITS_ARB;
-  
-  if (wglgsg->_supports_wgl_multisample) {
-    iattrib_list[sample_buffers_i = ni++] = WGL_SAMPLE_BUFFERS_ARB;
-    iattrib_list[multisamples_i = ni++] = WGL_SAMPLES_ARB;
+  if (_fb_properties.get_alpha_bits()) {
+    iattrib_list[ni++] = WGL_TEXTURE_FORMAT_ARB;
+    iattrib_list[ni++] = WGL_TEXTURE_RGBA_ARB;
+  } else {
+    iattrib_list[ni++] = WGL_TEXTURE_FORMAT_ARB;
+    iattrib_list[ni++] = WGL_TEXTURE_RGB_ARB;
   }
-  
-  // Terminate the list.
-  nassertr(ni <= max_attrib_list, false);
-  
-  if (!wglgsg->_wglGetPixelFormatAttribivARB(twindow_dc, pbformat, 0,
-                                             ni, iattrib_list, ivalue_list)) {
-    if (wgldisplay_cat.is_debug()) {
-      wgldisplay_cat.debug()
-        << "Could not query old format " << pbformat << ".\n";
-    }
-    return 0;
+
+  if (desired_mipmap) {
+    iattrib_list[ni++] = WGL_MIPMAP_TEXTURE_ARB;
+    iattrib_list[ni++] = 1;
   }
-  
-  ni = 0;
-  float fattrib_list[max_attrib_list];
-  int nf = 0;
-  
-  // Since we are trying to create a pbuffer, the pixel format we
-  // request (and subsequently use) must be "pbuffer capable".
-  iattrib_list[ni++] = WGL_DRAW_TO_PBUFFER_ARB;
-  iattrib_list[ni++] = true;
-  iattrib_list[ni++] = WGL_SUPPORT_OPENGL_ARB;
-  iattrib_list[ni++] = true;
-
-  if (draw_to_texture) {
-    // If we want to be able to render-to-texture, request that.
-    if (_fb_properties.get_frame_buffer_mode() & FrameBufferProperties::FM_alpha) {
-      iattrib_list[ni++] = WGL_BIND_TO_TEXTURE_RGBA_ARB;
-      iattrib_list[ni++] = true;
-    } else {
-      iattrib_list[ni++] = WGL_BIND_TO_TEXTURE_RGB_ARB;
-      iattrib_list[ni++] = true;
-    }
-  }    
-  
-  // Match up the framebuffer bits.
-  iattrib_list[ni++] = WGL_RED_BITS_ARB;
-  iattrib_list[ni++] = ivalue_list[red_bits_i];
-  iattrib_list[ni++] = WGL_GREEN_BITS_ARB;
-  iattrib_list[ni++] = ivalue_list[green_bits_i];
-  iattrib_list[ni++] = WGL_BLUE_BITS_ARB;
-  iattrib_list[ni++] = ivalue_list[blue_bits_i];
-  iattrib_list[ni++] = WGL_ALPHA_BITS_ARB;
-  iattrib_list[ni++] = ivalue_list[alpha_bits_i];
-  
-  iattrib_list[ni++] = WGL_ACCUM_RED_BITS_ARB;
-  iattrib_list[ni++] = ivalue_list[accum_red_bits_i];
-  iattrib_list[ni++] = WGL_ACCUM_GREEN_BITS_ARB;
-  iattrib_list[ni++] = ivalue_list[accum_green_bits_i];
-  iattrib_list[ni++] = WGL_ACCUM_BLUE_BITS_ARB;
-  iattrib_list[ni++] = ivalue_list[accum_blue_bits_i];
-  iattrib_list[ni++] = WGL_ACCUM_ALPHA_BITS_ARB;
-  iattrib_list[ni++] = ivalue_list[accum_alpha_bits_i];
-  
-  iattrib_list[ni++] = WGL_DEPTH_BITS_ARB;
-  iattrib_list[ni++] = ivalue_list[depth_bits_i];
-  
-  iattrib_list[ni++] = WGL_STENCIL_BITS_ARB;
-  iattrib_list[ni++] = ivalue_list[stencil_bits_i];
-  
-  if (wglgsg->_supports_wgl_multisample) {
-    iattrib_list[ni++] = WGL_SAMPLE_BUFFERS_ARB;
-    iattrib_list[ni++] = ivalue_list[sample_buffers_i];
-    iattrib_list[ni++] = WGL_SAMPLES_ARB;
-    iattrib_list[ni++] = ivalue_list[multisamples_i];
+
+  switch (desired_type) {
+  case Texture::TT_cube_map:
+    iattrib_list[ni++] = WGL_TEXTURE_TARGET_ARB;
+    iattrib_list[ni++] = WGL_TEXTURE_CUBE_MAP_ARB;
+    break;
+    
+  case Texture::TT_1d_texture:
+    iattrib_list[ni++] = WGL_TEXTURE_TARGET_ARB;
+    iattrib_list[ni++] = WGL_TEXTURE_1D_ARB;
+    break;
+    
+  default:
+    iattrib_list[ni++] = WGL_TEXTURE_TARGET_ARB;
+    iattrib_list[ni++] = WGL_TEXTURE_2D_ARB;
   }
   
-  // Match up properties.
-  iattrib_list[ni++] = WGL_DOUBLE_BUFFER_ARB;
-  iattrib_list[ni++] = ivalue_list[double_buffer_i];
-  iattrib_list[ni++] = WGL_STEREO_ARB;
-  iattrib_list[ni++] = ivalue_list[stereo_i];
-  
-  // Terminate the lists.
-  nassertr(ni < max_attrib_list && nf < max_attrib_list, NULL);
+  // Terminate the list.
+  nassertr(ni <= max_attrib_list, false);
   iattrib_list[ni] = 0;
-  fattrib_list[nf] = 0;
-  
-  // Now obtain a list of pixel formats that meet these minimum
-  // requirements.
-  static const unsigned int max_pformats = 32;
-  int pformat[max_pformats];
-  memset(pformat, 0, sizeof(pformat));
-  unsigned int nformats = 0;
-  if (!wglgsg->_wglChoosePixelFormatARB(twindow_dc, iattrib_list, fattrib_list,
-                                        max_pformats, pformat, &nformats)
-      || nformats == 0) {
-    if (wgldisplay_cat.is_debug()) {
-      wgldisplay_cat.debug()
-        << "No formats meet the criteria.\n";
-    }
-    return 0;
-  }
-  
-  nformats = min(nformats, max_pformats);
-  
-  if (wgldisplay_cat.is_debug()) {
-    wgldisplay_cat.debug()
-      << "Found " << nformats << " pbuffer formats: [";
-    for (unsigned int i = 0; i < nformats; i++) {
-      wgldisplay_cat.debug(false)
-        << " " << pformat[i];
-    }
-    wgldisplay_cat.debug(false)
-      << " ]\n";
+
+  HDC twindow_dc = wglgsg->get_twindow_dc();
+  if (twindow_dc == 0) {
+    return false;
   }
   
-  // If one of the options is the original pixfmt, keep it.
-  bool found_pbformat = false;
-  for (unsigned int i = 0; i < nformats && !found_pbformat; i++) {
-    if (pformat[i] == pbformat) {
-      found_pbformat = true;
-    }
-  }
+  wglGraphicsPipe::wgl_make_current(twindow_dc, wglgsg->get_context(twindow_dc),
+                                    &_make_current_pcollector);
+
+  _pbuffer = wglgsg->_wglCreatePbufferARB(twindow_dc, pfnum, 
+                                          desired_x, desired_y, iattrib_list);
   
-  if (!found_pbformat) {
-    // Otherwise, pick any of them.
-    pbformat = pformat[0];
+  if (_pbuffer == 0) {
+    wgldisplay_cat.info()
+      << "Attempt to create pbuffer failed.\n";
+    return false;
   }
 
-  return pbformat;
+  _pbuffer_dc = wglgsg->_wglGetPbufferDCARB(_pbuffer);
+  _pbuffer_mipmap = desired_mipmap;
+  _pbuffer_type = desired_type;
+  _pbuffer_sizex = desired_x;
+  _pbuffer_sizey = desired_y;
+  
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 9 - 5
panda/src/wgldisplay/wglGraphicsBuffer.h

@@ -61,16 +61,20 @@ protected:
   virtual bool open_buffer();
 
 private:
-  void begin_render_texture();
-  void end_render_texture();
-  bool make_pbuffer(HDC window_dc);
-  int choose_pbuffer_format(HDC twindow_dc, bool draw_to_texture);
+  void bind_texture_to_pbuffer();
+  bool rebuild_bitplanes();
+  void release_pbuffer();
 
   static void process_1_event();
 
   HPBUFFERARB _pbuffer;
   HDC _pbuffer_dc;
-
+  bool _pbuffer_mipmap;
+  Texture::TextureType _pbuffer_type;
+  int _pbuffer_sizex;
+  int _pbuffer_sizey;
+  PT(Texture) _pbuffer_bound;
+  
 public:
   static TypeHandle get_class_type() {
     return _type_handle;

+ 15 - 713
panda/src/wgldisplay/wglGraphicsPipe.cxx

@@ -64,11 +64,12 @@ wgl_make_current(HDC hdc, HGLRC hglrc, PStatCollector *collector) {
   _current_valid = true;
   _current_hdc = hdc;
   _current_hglrc = hglrc;
+  BOOL res;
   if (collector) {
     PStatTimer timer(*collector);
-    wglMakeCurrent(hdc, hglrc);
+    res = wglMakeCurrent(hdc, hglrc);
   } else {
-    wglMakeCurrent(hdc, hglrc);
+    res = wglMakeCurrent(hdc, hglrc);
   }    
 }
 
@@ -99,35 +100,6 @@ pipe_constructor() {
   return new wglGraphicsPipe;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: wglGraphicsPipe::make_gsg
-//       Access: Private
-//  Description: Creates a new GSG to use the pipe (but no windows
-//               have been created yet for the GSG).
-////////////////////////////////////////////////////////////////////
-PT(GraphicsStateGuardian) wglGraphicsPipe::
-make_gsg(const FrameBufferProperties &properties,
-         GraphicsStateGuardian *share_with) {
-  if (!_is_valid) {
-    return NULL;
-  }
-
-  wglGraphicsStateGuardian *share_gsg = NULL;
-
-  if (share_with != (GraphicsStateGuardian *)NULL) {
-    if (!share_with->is_exact_type(wglGraphicsStateGuardian::get_class_type())) {
-      wgldisplay_cat.error()
-        << "Cannot share context between wglGraphicsStateGuardian and "
-        << share_with->get_type() << "\n";
-      return NULL;
-    }
-
-    DCAST_INTO_R(share_gsg, share_with, NULL);
-  }
-
-  return new wglGraphicsStateGuardian(properties, share_gsg, -1);
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: wglGraphicsPipe::make_output
 //       Access: Protected, Virtual
@@ -147,8 +119,10 @@ make_output(const string &name,
     return NULL;
   }
 
-  wglGraphicsStateGuardian *wglgsg;
-  DCAST_INTO_R(wglgsg, gsg, NULL);
+  wglGraphicsStateGuardian *wglgsg = 0;
+  if (gsg != 0) {
+    DCAST_INTO_R(wglgsg, gsg, NULL);
+  }
 
   // First thing to try: a wglGraphicsWindow
 
@@ -185,11 +159,10 @@ make_output(const string &name,
     // Early failure - if we are sure that this buffer WONT
     // meet specs, we can bail out early.
     if ((flags & BF_fb_props_optional)==0) {
-      if ((properties.specifies_mode(FrameBufferProperties::FM_index))||
-          (properties.specifies_mode(FrameBufferProperties::FM_buffer))||
-          (properties.specifies_mode(FrameBufferProperties::FM_accum))||
-          (properties.specifies_mode(FrameBufferProperties::FM_stencil))||
-          (properties.specifies_mode(FrameBufferProperties::FM_multisample))) {
+      if ((properties.get_indexed_color() > 0)||
+          (properties.get_back_buffers() > 0)||
+          (properties.get_accum_bits() > 0)||
+          (properties.get_multisamples() > 0)) {
         return NULL;
       }
     }
@@ -213,7 +186,6 @@ make_output(const string &name,
     if ((!support_render_texture)||
         ((flags&BF_require_parasite)!=0)||
         ((flags&BF_require_window)!=0)||
-        ((flags&BF_size_track_host)!=0)||
         ((flags&BF_rtt_cumulative)!=0)||
         ((flags&BF_can_bind_every)!=0)) {
       return NULL;
@@ -222,7 +194,7 @@ make_output(const string &name,
     // meet specs, we can bail out early.
     if ((flags & BF_fb_props_optional) == 0) {
       if ((properties.get_aux_rgba() > 0)||
-          (properties.get_aux_hrgba() > 0)||
+          (properties.get_aux_rgba() > 0)||
           (properties.get_aux_float() > 0)) {
         return NULL;
       }
@@ -232,8 +204,9 @@ make_output(const string &name,
     if ((wglgsg != 0) &&
         (wglgsg->is_valid()) &&
         (!wglgsg->needs_reset()) &&
-        (wglgsg->_supports_pbuffer) &&
-        (properties.is_basic())) {
+        (wglgsg->pfnum_supports_pbuffer()) &&
+        (wglgsg->get_fb_properties().subsumes(properties))&&
+        (wglgsg->get_fb_properties().is_single_buffered())) {
       precertify = true;
     }
     return new wglGraphicsBuffer(this, name, properties,
@@ -245,677 +218,6 @@ make_output(const string &name,
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: wglGraphicsPipe::choose_pfnum
-//       Access: Private, Static
-//  Description: Selects a suitable pixel format number for the given
-//               frame buffer properties.  Returns the selected number
-//               if successful, or 0 otherwise.
-////////////////////////////////////////////////////////////////////
-int wglGraphicsPipe::
-choose_pfnum(const FrameBufferProperties &properties, HDC hdc) {
-  int frame_buffer_mode = 0;
-
-  if (properties.has_frame_buffer_mode()) {
-    frame_buffer_mode = properties.get_frame_buffer_mode();
-  }
-
-  int want_depth_bits = properties.get_depth_bits();
-  int want_color_bits = properties.get_color_bits();
-  int want_alpha_bits = properties.get_alpha_bits();
-  int want_stencil_bits = properties.get_stencil_bits();
-
-  // We decide these up front, and don't modify them--if the user asks
-  // for hardware, we never fail over to software.
-  bool hardware = ((frame_buffer_mode & FrameBufferProperties::FM_hardware) != 0);
-  bool software = ((frame_buffer_mode & FrameBufferProperties::FM_software) != 0);
-  // If the user specified neither hardware nor software frame buffer,
-  // he gets either one.
-  if (!hardware && !software) {
-    hardware = true;
-    software = true;
-  }
-
-  int pfnum = 
-    try_for_pfnum(hdc, hardware, software, frame_buffer_mode, 
-                  want_depth_bits, want_color_bits, want_alpha_bits,
-                  want_stencil_bits);
-  if (pfnum == 0) {
-    wgldisplay_cat.info()
-      << "wglGraphicsPipe::choose_pfnum() - pfnum with requested "
-      << "capabilities not found; trying for lesser pfnum.\n";
-
-    bool special_size_request =
-      (want_depth_bits != 1 || want_color_bits != 1);
-
-    // We try to be smart about choosing a close match for the pfnum.
-    // First, we'll eliminate some of the more esoteric options one at
-    // a time, then two at a time, and finally we'll try just the bare
-    // minimum.
-
-    if (special_size_request) {
-      // Actually, first we'll eliminate all of the minimum sizes, to
-      // try to open a window with all of the requested options, but
-      // maybe not as many bits in some options as we'd like.
-      pfnum = try_for_pfnum(hdc, hardware, software, frame_buffer_mode);
-    }
-
-    if (pfnum == 0) {
-      // Ok, not good enough.  Now try to eliminate options, but keep
-      // as many bits as we asked for.
-
-      pset<int> tried_masks;
-      tried_masks.insert(frame_buffer_mode);
-
-      int i;
-      for (i = 0; pfnum == 0 && strip_properties[i] != 0; i++) {
-        int new_frame_buffer_mode = frame_buffer_mode & ~strip_properties[i];
-        if (tried_masks.insert(new_frame_buffer_mode).second) {
-          pfnum = try_for_pfnum(hdc, hardware, software, new_frame_buffer_mode,
-                                want_depth_bits, want_color_bits, 
-                                want_alpha_bits, want_stencil_bits);
-        }
-      }
-
-      if (special_size_request) {
-        tried_masks.clear();
-        tried_masks.insert(frame_buffer_mode);
-
-        if (pfnum == 0) {
-          // Try once more, this time eliminating all of the size
-          // requests.
-          for (i = 0; pfnum == 0 && strip_properties[i] != 0; i++) {
-            int new_frame_buffer_mode = frame_buffer_mode & ~strip_properties[i];
-            if (tried_masks.insert(new_frame_buffer_mode).second) {
-              pfnum = try_for_pfnum(hdc, hardware, software, 
-                                    new_frame_buffer_mode);
-            }
-          }
-        }
-      }
-
-      if (pfnum == 0) {
-        // Here's our last-ditch desparation attempt: give us any pixel
-        // format at all!
-        pfnum = try_for_pfnum(hdc, hardware, software, 0);
-      }
-
-      if (pfnum == 0) {
-        wgldisplay_cat.error()
-          << "Could not get any OpenGL pixel format.\n";
-        return 0;
-      }
-    }
-  }
-
-  return pfnum;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: wglGraphicsPipe::try_for_pfnum
-//       Access: Private, Static
-//  Description: Attempt to get the requested pixel format, if it is
-//               available, using the standard DescribePixelFormat
-//               call.  It returns the pfnum if one is available, or 0
-//               if no available pixel formats match the requested
-//               options.
-////////////////////////////////////////////////////////////////////
-int wglGraphicsPipe::
-try_for_pfnum(HDC hdc, bool hardware, bool software, int frame_buffer_mode,
-              int want_depth_bits, int want_color_bits,
-              int want_alpha_bits, int want_stencil_bits) {
-  if (wgldisplay_cat.is_debug()) {
-    wgldisplay_cat.debug()
-      << "try_for_pfnum(hdc, hardware = " << hardware
-      << ", software = " << software
-      << ", frame_buffer_mode = 0x" << hex << frame_buffer_mode << dec
-      << ", want_depth_bits = " << want_depth_bits
-      << ", want_color_bits = " << want_color_bits
-      << ", want_alpha_bits = " << want_alpha_bits
-      << ", want_stencil_bits = " << want_stencil_bits
-      << ")\n";
-  }
-
-  PIXELFORMATDESCRIPTOR pfd;
-  ZeroMemory(&pfd,sizeof(PIXELFORMATDESCRIPTOR));
-  pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
-  pfd.nVersion = 1;
-
-  DWORD want_flags = (PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW);
-  DWORD dont_want_flags = 0;
-
-  switch (frame_buffer_mode & FrameBufferProperties::FM_buffer) {
-  case FrameBufferProperties::FM_single_buffer:
-    dont_want_flags |= PFD_DOUBLEBUFFER;
-    break;
-    
-  case FrameBufferProperties::FM_double_buffer:
-  case FrameBufferProperties::FM_triple_buffer:
-    want_flags |= PFD_DOUBLEBUFFER;
-    break;
-  }
-
-  if (frame_buffer_mode & FrameBufferProperties::FM_stereo) {
-    want_flags |= PFD_STEREO;
-  }
-
-  // We have to call DescribePixelFormat() once just to get the
-  // highest pfnum available.  Then we can iterate through all of the
-  // pfnums.
-  int max_pfnum = DescribePixelFormat(hdc, 1, 0, NULL);
-  int pfnum = 0;
-
-  int found_pfnum = 0;
-  int found_colorbits = 0;
-  int found_depthbits = 0;
-  bool found_is_hardware;
-
-  for (pfnum = 1; pfnum <= max_pfnum; pfnum++) {
-    DescribePixelFormat(hdc, pfnum, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
-
-    // skip driver types we are not looking for
-    bool is_hardware = ((pfd.dwFlags & PFD_GENERIC_FORMAT) == 0);
-    if ((is_hardware && !hardware) || (!is_hardware && !software)) {
-      continue;
-    }
-
-    if ((pfd.iPixelType == PFD_TYPE_COLORINDEX) && 
-        (frame_buffer_mode & FrameBufferProperties::FM_index) == 0) {
-      continue;
-    }
-
-    if ((pfd.dwFlags & want_flags) != want_flags) {
-      continue;
-
-    } else if (pfd.cColorBits < want_color_bits) {
-      continue;
-
-    } else if ((frame_buffer_mode & FrameBufferProperties::FM_alpha) != 0 && 
-               (pfd.cAlphaBits < want_alpha_bits)) {
-      continue;
-
-    } else if ((frame_buffer_mode & FrameBufferProperties::FM_depth) != 0 && 
-               (pfd.cDepthBits < want_depth_bits)) {
-      continue;
-
-    } else if ((frame_buffer_mode & FrameBufferProperties::FM_stencil) != 0 && 
-               (pfd.cStencilBits < want_stencil_bits)) {
-      continue;
-    }
-
-    // We've passed all the tests; this is an acceptable format.  Do
-    // we prefer this one over the previously-found acceptable
-    // formats?
-    bool preferred = false;
-
-    if (found_pfnum == 0) {
-      // If this is the first acceptable format we've found, of course
-      // we prefer it.
-      preferred = true;
-
-    } else if (!found_is_hardware && is_hardware) {
-      // We always prefer hardware-supported modes, given a choice.
-      preferred = true;
-
-    } else if ((frame_buffer_mode & FrameBufferProperties::FM_depth) != 0
-               && pfd.cDepthBits > found_depthbits) {
-      // We like having lots of depth bits, to a point.
-      if (pfd.cColorBits < found_colorbits && found_depthbits >= 16) {
-        // We don't like sacrificing color bits if we have at least 16
-        // bits of Z.
-      } else {
-        preferred = true;
-      }
-
-    } else if (pfd.cColorBits > found_colorbits) {
-      // We also like having lots of color bits.
-      preferred = true;
-    }
-
-    if (preferred) {
-      found_pfnum = pfnum;
-      found_colorbits = pfd.cColorBits;
-      found_depthbits = pfd.cDepthBits;
-      found_is_hardware = is_hardware;
-    }
-  }
-
-  if (found_pfnum != 0) {
-    if (wgldisplay_cat.is_debug()) {
-      wgldisplay_cat.debug()
-        << "found pfnum " << found_pfnum << ":\n";
-
-      DescribePixelFormat(hdc, found_pfnum, 
-                          sizeof(PIXELFORMATDESCRIPTOR), &pfd);
-
-      wgldisplay_cat.debug() 
-        << "  color = " << (int)(pfd.cColorBits)
-        << " = R" << (int)(pfd.cRedBits) 
-        << " G" << (int)(pfd.cGreenBits)
-        << " B" << (int)(pfd.cBlueBits)
-        << " A" << (int)(pfd.cAlphaBits) << "\n";
-
-      if ((frame_buffer_mode & FrameBufferProperties::FM_alpha) != 0) {
-        wgldisplay_cat.debug()
-          << "  alpha = " << (int)(pfd.cAlphaBits) << "\n";
-      }
-      if ((frame_buffer_mode & FrameBufferProperties::FM_depth) != 0) {
-        wgldisplay_cat.debug()
-          << "  depth = " << (int)(pfd.cDepthBits) << "\n";
-      }
-      if ((frame_buffer_mode & FrameBufferProperties::FM_stencil) != 0) {
-        wgldisplay_cat.debug()
-          << "  stencil = " << (int)(pfd.cStencilBits) << "\n";
-      }
-      wgldisplay_cat.debug()
-        << "  flags = " << format_pfd_flags(pfd.dwFlags) << " (missing "
-        << format_pfd_flags((~pfd.dwFlags) & want_flags) << ", extra "
-        << format_pfd_flags(pfd.dwFlags & dont_want_flags) << ")\n";
-    }
-  }
-
-  return found_pfnum;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: wglGraphicsPipe::get_properties
-//       Access: Private, Static
-//  Description: Gets the FrameBufferProperties to match the
-//               indicated pixel format descriptor.
-////////////////////////////////////////////////////////////////////
-void wglGraphicsPipe::
-get_properties(FrameBufferProperties &properties, HDC hdc,
-               int pfnum) {
-  PIXELFORMATDESCRIPTOR pfd;
-  ZeroMemory(&pfd,sizeof(PIXELFORMATDESCRIPTOR));
-  pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
-  pfd.nVersion = 1;
-
-  DescribePixelFormat(hdc, pfnum, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
-
-  properties.clear();
-
-  int mode = 0;
-  if (pfd.dwFlags & PFD_DOUBLEBUFFER) {
-    mode |= FrameBufferProperties::FM_double_buffer;
-  }
-  if (pfd.dwFlags & PFD_STEREO) {
-    mode |= FrameBufferProperties::FM_stereo;
-  }
-  if (pfd.dwFlags & PFD_GENERIC_FORMAT) {
-    mode |= FrameBufferProperties::FM_software;
-  } else {
-    mode |= FrameBufferProperties::FM_hardware;
-  }
-  
-  if (pfd.cColorBits != 0) {
-    mode |= FrameBufferProperties::FM_rgb;
-    properties.set_color_bits(pfd.cColorBits);
-  }
-  if (pfd.cAlphaBits != 0) {
-    mode |= FrameBufferProperties::FM_alpha;
-    properties.set_alpha_bits(pfd.cAlphaBits);
-  }
-  if (pfd.cDepthBits != 0) {
-    mode |= FrameBufferProperties::FM_depth;
-    properties.set_depth_bits(pfd.cDepthBits);
-  }
-  if (pfd.cStencilBits != 0) {
-    mode |= FrameBufferProperties::FM_stencil;
-    properties.set_stencil_bits(pfd.cStencilBits);
-  }
-
-  properties.set_frame_buffer_mode(mode);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: wglGraphicsPipe::choose_pfnum_advanced
-//       Access: Private, Static
-//  Description: Uses the WGL extensions, if available, to find a
-//               suitable pfnum.  This requires having created a
-//               temporary context first.  Returns the pixel format
-//               chosen if successful, or the original pixel format
-//               number on failure.
-////////////////////////////////////////////////////////////////////
-int wglGraphicsPipe::
-choose_pfnum_advanced(const FrameBufferProperties &properties, 
-                      const wglGraphicsStateGuardian *wglgsg,
-                      HDC window_dc, int orig_pfnum) {
-  int frame_buffer_mode = 0;
-
-  if (properties.has_frame_buffer_mode()) {
-    frame_buffer_mode = properties.get_frame_buffer_mode();
-  }
-
-  int want_depth_bits = properties.get_depth_bits();
-  int want_color_bits = properties.get_color_bits();
-  int want_alpha_bits = properties.get_alpha_bits();
-  int want_stencil_bits = properties.get_stencil_bits();
-  int want_multisamples = properties.get_multisamples();
-
-  int pfnum = 
-    try_for_pfnum_advanced(orig_pfnum, wglgsg, window_dc, frame_buffer_mode, 
-                           want_depth_bits, want_color_bits, want_alpha_bits,
-                           want_stencil_bits, want_multisamples);
-  if (pfnum == 0) {
-    wgldisplay_cat.info()
-      << "wglGraphicsPipe::choose_pfnum() - pfnum with requested "
-      << "capabilities not found; trying for lesser pfnum.\n";
-
-    bool special_size_request =
-      (want_depth_bits != 1 || want_color_bits != 1);
-
-    // We try to be smart about choosing a close match for the pfnum.
-    // First, we'll eliminate some of the more esoteric options one at
-    // a time, then two at a time, and finally we'll try just the bare
-    // minimum.
-
-    if (special_size_request) {
-      // Actually, first we'll eliminate all of the minimum sizes, to
-      // try to open a window with all of the requested options, but
-      // maybe not as many bits in some options as we'd like.
-      pfnum = try_for_pfnum_advanced(orig_pfnum, wglgsg, window_dc, 
-                                     frame_buffer_mode);
-    }
-
-    if (pfnum == 0) {
-      // Ok, not good enough.  Now try to eliminate options, but keep
-      // as many bits as we asked for.
-
-      pset<int> tried_masks;
-      tried_masks.insert(frame_buffer_mode);
-
-      int i;
-      for (i = 0; pfnum == 0 && strip_properties[i] != 0; i++) {
-        int new_frame_buffer_mode = frame_buffer_mode & ~strip_properties[i];
-        if (tried_masks.insert(new_frame_buffer_mode).second) {
-          pfnum = try_for_pfnum_advanced(orig_pfnum, wglgsg, window_dc, 
-                                         new_frame_buffer_mode, 
-                                         want_depth_bits, want_color_bits, 
-                                         want_alpha_bits, want_stencil_bits,
-                                         want_multisamples);
-        }
-      }
-
-      if (special_size_request) {
-        tried_masks.clear();
-        tried_masks.insert(frame_buffer_mode);
-
-        if (pfnum == 0) {
-          // Try once more, this time eliminating all of the size
-          // requests.
-          for (i = 0; pfnum == 0 && strip_properties[i] != 0; i++) {
-            int new_frame_buffer_mode = frame_buffer_mode & ~strip_properties[i];
-            if (tried_masks.insert(new_frame_buffer_mode).second) {
-              pfnum = try_for_pfnum_advanced(orig_pfnum, wglgsg, window_dc,
-                                             new_frame_buffer_mode);
-            }
-          }
-        }
-      }
-
-      if (pfnum == 0) {
-        // Here's our last-ditch desparation attempt: give us any pixel
-        // format at all!
-        pfnum = try_for_pfnum_advanced(orig_pfnum, wglgsg, window_dc, 0);
-      }
-
-      if (pfnum == 0) {
-        // This is only an info message, because we just return the
-        // original pfnum in this case.
-        wgldisplay_cat.info()
-          << "Could not get any pfnum using wglChoosePixelFormatARB.\n";
-        return orig_pfnum;
-      }
-    }
-  }
-
-  return pfnum;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: wglGraphicsPipe::try_for_pfnum_advanced
-//       Access: Private, Static
-//  Description: Attempt to get the requested pixel format, if it is
-//               available, using the advanced wglChoosePixelFormatARB
-//               call.  It returns the pfnum if one is available, or 0
-//               if no available pixel formats match the requested
-//               options.
-////////////////////////////////////////////////////////////////////
-int wglGraphicsPipe::
-try_for_pfnum_advanced(int orig_pfnum, const wglGraphicsStateGuardian *wglgsg,
-                       HDC window_dc, int frame_buffer_mode,
-                       int want_depth_bits, int want_color_bits,
-                       int want_alpha_bits, int want_stencil_bits,
-                       int want_multisamples) {
-  if (wgldisplay_cat.is_debug()) {
-    wgldisplay_cat.debug()
-      << "try_for_pfnum_advanced(orig_pfnum = " << orig_pfnum 
-      << ", wglgsg, window_dc, frame_buffer_mode = 0x" << hex << frame_buffer_mode << dec
-      << ", want_depth_bits = " << want_depth_bits
-      << ", want_color_bits = " << want_color_bits
-      << ", want_alpha_bits = " << want_alpha_bits
-      << ", want_stencil_bits = " << want_stencil_bits
-      << ", want_multisamples = " << want_multisamples
-      << ")\n";
-  }
-
-  static const int max_attrib_list = 32;
-  int iattrib_list[max_attrib_list];
-  float fattrib_list[max_attrib_list];
-  int ni = 0;
-  int nf = 0;
-
-  iattrib_list[ni++] = WGL_SUPPORT_OPENGL_ARB;
-  iattrib_list[ni++] = true;
-  iattrib_list[ni++] = WGL_PIXEL_TYPE_ARB;
-  iattrib_list[ni++] = WGL_TYPE_RGBA_ARB;
-  iattrib_list[ni++] = WGL_COLOR_BITS_ARB;
-  iattrib_list[ni++] = want_color_bits;
-
-  if (frame_buffer_mode & FrameBufferProperties::FM_alpha) {
-    iattrib_list[ni++] = WGL_ALPHA_BITS_ARB;
-    iattrib_list[ni++] = want_alpha_bits;
-  }
-
-  switch (frame_buffer_mode & FrameBufferProperties::FM_buffer) {
-  case FrameBufferProperties::FM_single_buffer:
-    iattrib_list[ni++] = WGL_DOUBLE_BUFFER_ARB;
-    iattrib_list[ni++] = false;
-    break;
-
-  case FrameBufferProperties::FM_double_buffer:
-  case FrameBufferProperties::FM_triple_buffer:
-    iattrib_list[ni++] = WGL_DOUBLE_BUFFER_ARB;
-    iattrib_list[ni++] = true;
-    break;
-  }
-
-  if (frame_buffer_mode & FrameBufferProperties::FM_stereo) {
-    iattrib_list[ni++] = WGL_STEREO_ARB;
-    iattrib_list[ni++] = true;
-  } else {
-    iattrib_list[ni++] = WGL_STEREO_ARB;
-    iattrib_list[ni++] = false;
-  }
-
-  if (frame_buffer_mode & FrameBufferProperties::FM_depth) {
-    iattrib_list[ni++] = WGL_DEPTH_BITS_ARB;
-    iattrib_list[ni++] = want_depth_bits;
-  }
-
-  if (frame_buffer_mode & FrameBufferProperties::FM_stencil) {
-    iattrib_list[ni++] = WGL_STENCIL_BITS_ARB;
-    iattrib_list[ni++] = want_stencil_bits;
-  }
-
-  if (frame_buffer_mode & FrameBufferProperties::FM_accum) {
-    iattrib_list[ni++] = WGL_ACCUM_BITS_ARB;
-    iattrib_list[ni++] = want_color_bits;
-    if (frame_buffer_mode & FrameBufferProperties::FM_alpha) {
-      iattrib_list[ni++] = WGL_ACCUM_ALPHA_BITS_ARB;
-      iattrib_list[ni++] = want_alpha_bits;
-    }
-  }
-
-  if (frame_buffer_mode & FrameBufferProperties::FM_multisample) {
-    iattrib_list[ni++] = WGL_SAMPLE_BUFFERS_ARB;
-    iattrib_list[ni++] = 1;
-    iattrib_list[ni++] = WGL_SAMPLES_ARB;
-    iattrib_list[ni++] = want_multisamples;
-  }
-
-  // Terminate the lists.
-  nassertr(ni < max_attrib_list && nf < max_attrib_list, NULL);
-  iattrib_list[ni] = 0;
-  fattrib_list[nf] = 0;
-
-  // Now obtain a list of pixel formats that meet these minimum
-  // requirements.
-  static const unsigned int max_pformats = 32;
-  int pformat[max_pformats];
-  memset(pformat, 0, sizeof(pformat));
-  unsigned int nformats = 0;
-  if (!wglgsg->_wglChoosePixelFormatARB(window_dc, iattrib_list, fattrib_list,
-                                        max_pformats, pformat, &nformats) ||
-      nformats == 0) {
-    if (wgldisplay_cat.is_debug()) {
-      wgldisplay_cat.debug()
-        << "No formats meet the criteria.\n";
-    }
-    return 0;
-  }
-  
-  nformats = min(nformats, max_pformats);
-
-  if (wgldisplay_cat.is_debug()) {
-    wgldisplay_cat.debug()
-      << "Found " << nformats << " advanced formats: [";
-    for (unsigned int i = 0; i < nformats; i++) {
-      wgldisplay_cat.debug(false)
-        << " " << pformat[i];
-    }
-    wgldisplay_cat.debug(false)
-      << " ]\n";
-  }
-  
-  // If our original pfnum is on the list, take it.
-  unsigned int i;
-  for (i = 0; i < nformats; i++) {
-    if (pformat[i] == orig_pfnum) {
-      return orig_pfnum;
-    }
-  }
-
-  // Try to find one on the list that corresponds closely with our
-  // original pfnum choice.
-  FrameBufferProperties orig_props;
-  get_properties(orig_props, window_dc, orig_pfnum);
-
-  for (i = 0; i < nformats; i++) {
-    FrameBufferProperties new_props;
-    if (get_properties_advanced(new_props, wglgsg, window_dc, pformat[i])) {
-      if (new_props.get_color_bits() == orig_props.get_color_bits() &&
-          new_props.get_alpha_bits() == orig_props.get_alpha_bits() &&
-          new_props.get_depth_bits() == orig_props.get_depth_bits() &&
-          new_props.get_stencil_bits() == orig_props.get_stencil_bits()) {
-        return pformat[i];
-      }
-    }
-  }
-
-  // Otherwise, just pick the first one on the list, which is the
-  // "best" one according to WGL.
-  return pformat[0];
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: wglGraphicsPipe::get_properties_advanced
-//       Access: Private, Static
-//  Description: Gets the FrameBufferProperties to match the
-//               indicated pixel format descriptor, using the WGL
-//               extensions.
-////////////////////////////////////////////////////////////////////
-bool wglGraphicsPipe::
-get_properties_advanced(FrameBufferProperties &properties, 
-                        const wglGraphicsStateGuardian *wglgsg, 
-                        HDC window_dc, int pfnum) {
-
-  static const int max_attrib_list = 32;
-  int iattrib_list[max_attrib_list];
-  int ivalue_list[max_attrib_list];
-  int ni = 0;
-
-  int acceleration_i, pixel_type_i, double_buffer_i, stereo_i,
-    color_bits_i, alpha_bits_i, accum_bits_i, depth_bits_i, 
-    stencil_bits_i, multisamples_i;
-
-  iattrib_list[acceleration_i = ni++] = WGL_ACCELERATION_ARB;
-  iattrib_list[pixel_type_i = ni++] = WGL_PIXEL_TYPE_ARB;
-  iattrib_list[double_buffer_i = ni++] = WGL_DOUBLE_BUFFER_ARB;
-  iattrib_list[stereo_i = ni++] = WGL_STEREO_ARB;
-  iattrib_list[color_bits_i = ni++] = WGL_COLOR_BITS_ARB;
-  iattrib_list[alpha_bits_i = ni++] = WGL_ALPHA_BITS_ARB;
-  iattrib_list[accum_bits_i = ni++] = WGL_ACCUM_BITS_ARB;
-  iattrib_list[depth_bits_i = ni++] = WGL_DEPTH_BITS_ARB;
-  iattrib_list[stencil_bits_i = ni++] = WGL_STENCIL_BITS_ARB;
-
-  if (wglgsg->_supports_wgl_multisample) {
-    iattrib_list[multisamples_i = ni++] = WGL_SAMPLES_ARB;
-  }
-
-  // Terminate the list.
-  nassertr(ni <= max_attrib_list, false);
-
-  if (!wglgsg->_wglGetPixelFormatAttribivARB(window_dc, pfnum, 0,
-                                             ni, iattrib_list, ivalue_list)) {
-    return false;
-  }
-
-  int frame_buffer_mode = 0;
-  if (ivalue_list[acceleration_i] == WGL_NO_ACCELERATION_ARB) {
-    frame_buffer_mode |= FrameBufferProperties::FM_software;
-  } else {
-    frame_buffer_mode |= FrameBufferProperties::FM_hardware;
-  }
-
-  if (ivalue_list[pixel_type_i] == WGL_TYPE_COLORINDEX_ARB) {
-    frame_buffer_mode |= FrameBufferProperties::FM_index;
-  }
-  if (ivalue_list[double_buffer_i]) {
-    frame_buffer_mode |= FrameBufferProperties::FM_double_buffer;
-  }
-  if (ivalue_list[stereo_i]) {
-    frame_buffer_mode |= FrameBufferProperties::FM_stereo;
-  }
-  if (ivalue_list[alpha_bits_i] != 0) {
-    frame_buffer_mode |= FrameBufferProperties::FM_alpha;
-    properties.set_alpha_bits(ivalue_list[alpha_bits_i]);
-  }
-  if (ivalue_list[accum_bits_i] != 0) {
-    frame_buffer_mode |= FrameBufferProperties::FM_accum;
-  }
-  if (ivalue_list[depth_bits_i] != 0) {
-    frame_buffer_mode |= FrameBufferProperties::FM_depth;
-    properties.set_depth_bits(ivalue_list[depth_bits_i]);
-  }
-  if (ivalue_list[stencil_bits_i] != 0) {
-    frame_buffer_mode |= FrameBufferProperties::FM_stencil;
-    properties.set_stencil_bits(ivalue_list[stencil_bits_i]);
-  }
-  if (wglgsg->_supports_wgl_multisample) {
-    if (ivalue_list[multisamples_i] != 0) {
-      frame_buffer_mode |= FrameBufferProperties::FM_multisample;
-      properties.set_multisamples(ivalue_list[multisamples_i]);
-    }
-  }
-
-  properties.set_frame_buffer_mode(frame_buffer_mode);
-  properties.set_color_bits(ivalue_list[color_bits_i]);
-
-  return true;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: wglGraphicsPipe::format_pfd_flags
 //       Access: Private, Static

+ 0 - 23
panda/src/wgldisplay/wglGraphicsPipe.h

@@ -46,32 +46,9 @@ protected:
                                          GraphicsOutput *host,
                                          int retry,
                                          bool &precertify);
-  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties, 
-                                             GraphicsStateGuardian *share_with);
 
 private:
 
-  static int choose_pfnum(const FrameBufferProperties &properties, HDC hdc);
-  static int try_for_pfnum(HDC hdc, bool hardware, bool software, 
-                           int frame_buffer_mode,
-                           int want_depth_bits = 1, int want_color_bits = 1,
-                           int want_alpha_bits = 1, int want_stencil_bits = 1);
-
-  static void get_properties(FrameBufferProperties &properties, HDC hdc,
-                             int pfnum);
-
-  static int choose_pfnum_advanced(const FrameBufferProperties &properties, 
-                                   const wglGraphicsStateGuardian *wglgsg,
-                                   HDC window_dc, int orig_pfnum);
-  static int try_for_pfnum_advanced(int orig_pfnum, 
-                                    const wglGraphicsStateGuardian *wglgsg,
-                                    HDC window_dc, int frame_buffer_mode,
-                                    int want_depth_bits = 1, int want_color_bits = 1,
-                                    int want_alpha_bits = 1, int want_stencil_bits = 1,
-                                    int want_multisamples = 1);
-  static bool get_properties_advanced(FrameBufferProperties &properties, 
-                                      const wglGraphicsStateGuardian *wglgsg, 
-                                      HDC window_dc, int pfnum);
   static string format_pfd_flags(DWORD pfd_flags);
   static void wgl_make_current(HDC hdc, HGLRC hglrc, PStatCollector *collector);
 

+ 13 - 2
panda/src/wgldisplay/wglGraphicsStateGuardian.I

@@ -33,7 +33,18 @@ get_pfnum() const {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: wglGraphicsStateGuardian::get_pfnum_properties
+//     Function: wglGraphicsStateGuardian::pfnum_supports_pbuffer
+//       Access: Public
+//  Description: Returns true if the gsg's pixel format is capable
+//               of supporting a pbuffer.
+////////////////////////////////////////////////////////////////////
+INLINE bool wglGraphicsStateGuardian::
+pfnum_supports_pbuffer() const {
+  return _pfnum_supports_pbuffer;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: wglGraphicsStateGuardian::get_fb_properties
 //       Access: Public
 //  Description: Returns the properties of the pixel format that
 //               was chosen for this gsg.  In OpenGL under Microsoft
@@ -44,7 +55,7 @@ get_pfnum() const {
 //               context must also share the same pixel format.
 ////////////////////////////////////////////////////////////////////
 INLINE const FrameBufferProperties &wglGraphicsStateGuardian::
-get_pfnum_properties() const {
+get_fb_properties() const {
   return _pfnum_properties;
 }
 

+ 317 - 59
panda/src/wgldisplay/wglGraphicsStateGuardian.cxx

@@ -31,18 +31,20 @@ bool wglGraphicsStateGuardian::_twindow_class_registered = false;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 wglGraphicsStateGuardian::
-wglGraphicsStateGuardian(const FrameBufferProperties &properties,
-                         wglGraphicsStateGuardian *share_with,
-                         int pfnum) : 
-  GLGraphicsStateGuardian(properties),
-  _share_with(share_with),
-  _pfnum(pfnum)
+wglGraphicsStateGuardian(GraphicsPipe *pipe,
+                         wglGraphicsStateGuardian *share_with) : 
+  GLGraphicsStateGuardian(pipe),
+  _share_with(share_with)
 {
   _made_context = false;
   _context = (HGLRC)NULL;
 
   _twindow = (HWND)0;
   _twindow_dc = (HDC)0;
+
+  _pfnum = -1;
+  _pfnum_supports_pbuffer = false;
+  _pfnum_properties.clear();
   
   _supports_pbuffer = false;
   _supports_pixel_format = false;
@@ -64,89 +66,345 @@ wglGraphicsStateGuardian::
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: wglGraphicsStateGuardian::choose_pixel_format
+//     Function: wglGraphicsStateGuardian::get_properties
 //       Access: Private
-//  Description: Selects a pixel format.
+//  Description: Gets the FrameBufferProperties to match the
+//               indicated pixel format descriptor.
+////////////////////////////////////////////////////////////////////
+void wglGraphicsStateGuardian::
+get_properties(FrameBufferProperties &properties, HDC hdc, int pfnum) {
+  
+  PIXELFORMATDESCRIPTOR pfd;
+  ZeroMemory(&pfd,sizeof(PIXELFORMATDESCRIPTOR));
+  pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
+  pfd.nVersion = 1;
+
+  DescribePixelFormat(hdc, pfnum, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
+
+  properties.clear();
+  properties.set_all_specified();
+  
+  if (((pfd.dwFlags & PFD_SUPPORT_OPENGL) == 0)||
+      ((pfd.dwFlags & PFD_DRAW_TO_WINDOW) == 0)) {
+    // Return without setting either RGB or Indexed Color.
+    // This indicates a window that can't do anything at all.
+    return;
+  }
+
+  if (pfd.iPixelType == PFD_TYPE_COLORINDEX) {
+    properties.set_indexed_color(1);
+  } else {
+    properties.set_rgb_color(1);
+  }
+
+  int mode = 0;
+  if (pfd.dwFlags & PFD_DOUBLEBUFFER) {
+    properties.set_back_buffers(1);
+  }
+  if (pfd.dwFlags & PFD_STEREO) {
+    properties.set_stereo(1);
+  }
+  if (pfd.dwFlags & PFD_GENERIC_FORMAT) {
+    properties.set_force_software(1);
+  } else {
+    properties.set_force_hardware(1);
+  }
+  
+  if (pfd.cColorBits != 0) {
+    properties.set_color_bits(pfd.cColorBits);
+  }
+  if (pfd.cAlphaBits != 0) {
+    properties.set_alpha_bits(pfd.cAlphaBits);
+  }
+  if (pfd.cDepthBits != 0) {
+    properties.set_depth_bits(pfd.cDepthBits);
+  }
+  if (pfd.cStencilBits != 0) {
+    properties.set_stencil_bits(pfd.cStencilBits);
+  }
+
+  // The basic API doesn't do accum or multisample.
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: wglGraphicsStateGuardian::get_properties_advanced
+//       Access: Private
+//  Description: Gets the FrameBufferProperties to match the
+//               indicated pixel format descriptor, using the WGL
+//               extensions.
 ////////////////////////////////////////////////////////////////////
 bool wglGraphicsStateGuardian::
-choose_pixel_format(const FrameBufferProperties &properties) {
+get_properties_advanced(FrameBufferProperties &properties, 
+                        HDC window_dc, int pfnum) {
+  
+  static const int max_attrib_list = 32;
+  int iattrib_list[max_attrib_list];
+  int ivalue_list[max_attrib_list];
+  int ni = 0;
+  
+  int acceleration_i, pixel_type_i, double_buffer_i, stereo_i,
+    color_bits_i, alpha_bits_i, accum_bits_i, depth_bits_i, 
+    stencil_bits_i, multisamples_i;
+  
+  iattrib_list[acceleration_i = ni++] = WGL_ACCELERATION_ARB;
+  iattrib_list[pixel_type_i = ni++] = WGL_PIXEL_TYPE_ARB;
+  iattrib_list[double_buffer_i = ni++] = WGL_DOUBLE_BUFFER_ARB;
+  iattrib_list[stereo_i = ni++] = WGL_STEREO_ARB;
+  iattrib_list[color_bits_i = ni++] = WGL_COLOR_BITS_ARB;
+  iattrib_list[alpha_bits_i = ni++] = WGL_ALPHA_BITS_ARB;
+  iattrib_list[accum_bits_i = ni++] = WGL_ACCUM_BITS_ARB;
+  iattrib_list[depth_bits_i = ni++] = WGL_DEPTH_BITS_ARB;
+  iattrib_list[stencil_bits_i = ni++] = WGL_STENCIL_BITS_ARB;
   
+  if (_supports_wgl_multisample) {
+    iattrib_list[multisamples_i = ni++] = WGL_SAMPLES_ARB;
+  }
+  
+  // Terminate the list.
+  nassertr(ni <= max_attrib_list, false);
+  
+  if (!_wglGetPixelFormatAttribivARB(window_dc, pfnum, 0,
+                                     ni, iattrib_list, ivalue_list)) {
+    return false;
+  }
+  
+  properties.clear();
+  properties.set_all_specified();
+
   int frame_buffer_mode = 0;
-  if (properties.has_frame_buffer_mode()) {
-    frame_buffer_mode = properties.get_frame_buffer_mode();
+  if (ivalue_list[acceleration_i] == WGL_NO_ACCELERATION_ARB) {
+    properties.set_force_software(1);
+  } else {
+    properties.set_force_hardware(1);
+  }
+  
+  if (ivalue_list[pixel_type_i] == WGL_TYPE_COLORINDEX_ARB) {
+    properties.set_indexed_color(1);
+  } else {
+    properties.set_rgb_color(1);
+  }
+
+  if (ivalue_list[double_buffer_i]) {
+    properties.set_back_buffers(1);
+  }
+  
+  if (ivalue_list[stereo_i]) {
+    properties.set_stereo(1);
+  }
+  
+  if (ivalue_list[alpha_bits_i] != 0) {
+    properties.set_alpha_bits(ivalue_list[alpha_bits_i]);
   }
 
-  wglGraphicsPipe *pipe;
-  DCAST_INTO_R(pipe, get_pipe(), false);
+  if (ivalue_list[accum_bits_i] != 0) {
+    properties.set_accum_bits(ivalue_list[accum_bits_i]);
+  }
+  
+  if (ivalue_list[depth_bits_i] != 0) {
+    properties.set_depth_bits(ivalue_list[depth_bits_i]);
+  }
 
-  // We need a DC to examine the available pixel formats.  We'll use
-  // the screen DC.
-  HDC hdc = GetDC(NULL);
+  if (ivalue_list[stencil_bits_i] != 0) {
+    properties.set_stencil_bits(ivalue_list[stencil_bits_i]);
+  }
 
-  if (!gl_force_pixfmt.has_value()) {
-    _pfnum = pipe->choose_pfnum(properties, hdc);
-    if (_pfnum == 0) {
-      ReleaseDC(NULL, hdc);
-      return false;
+  if (_supports_wgl_multisample) {
+    if (ivalue_list[multisamples_i] != 0) {
+      properties.set_multisamples(ivalue_list[multisamples_i]);
     }
-  } else {
+  }
+  
+  properties.set_color_bits(ivalue_list[color_bits_i]);
+  
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: wglGraphicsStateGuardian::choose_pixel_format
+//       Access: Private
+//  Description: Selects a pixel format for all the windows and
+//               buffers that use this gsg.
+////////////////////////////////////////////////////////////////////
+void wglGraphicsStateGuardian::
+choose_pixel_format(const FrameBufferProperties &properties,
+                    bool need_pbuffer) {
+
+  //// Choose best format available using DescribePixelFormat.
+  //
+  // In the process, we need a DC to examine the available
+  // pixel formats.  We'll use the screen DC.
+
+  if (gl_force_pixfmt.has_value()) {
     wgldisplay_cat.info()
       << "overriding pixfmt choice with gl-force-pixfmt(" 
       << gl_force_pixfmt << ")\n";
     _pfnum = gl_force_pixfmt;
+    _pfnum_properties = properties;
+    _pfnum_supports_pbuffer = true;
+    return;
   }
+  
+  int  best_pfnum = 0;
+  int  best_quality = 0;
+  FrameBufferProperties best_prop;
+  
+  HDC hdc = GetDC(NULL);
 
-  // Query the properties of the pixel format we chose.
-  pipe->get_properties(_pfnum_properties, hdc, _pfnum);
+  int max_pfnum = DescribePixelFormat(hdc, 1, 0, NULL);
+  
+  for (int pfnum = 0; pfnum<max_pfnum; ++pfnum) {
+    FrameBufferProperties pfprop;
+    get_properties(pfprop, hdc, pfnum);
+    int quality = pfprop.get_quality(properties);
+    if (quality > best_quality) {
+      best_pfnum = pfnum;
+      best_quality = quality;
+      best_prop = pfprop;
+    }
+  }
   
-  // We're done with hdc now.
   ReleaseDC(NULL, hdc);
 
+  _pfnum = best_pfnum;
+  _pfnum_supports_pbuffer = false;
+  _pfnum_properties = best_prop;
+  
+  if (best_quality == 0) {
+    wgldisplay_cat.error()
+      << "Could not find a usable pixel format.\n";
+    return;
+  }
+
   if (wgldisplay_cat.is_debug()) {
     wgldisplay_cat.debug()
       << "Preliminary pixfmt #" << _pfnum << " = " 
       << _pfnum_properties << "\n";
   }
 
-  // We need to create a temporary GSG to query the WGL
-  // extensions, so we can look for more advanced properties like
-  // multisampling.
+  //// See whether or not the wgl extensions are available.
   //
-  // Don't bother with the advanced stuff unless the
-  // requested frame buffer requires multisample, since at the moment
-  // that's the only reason we'd need to use the advanced query.
+  // This routine is called before "reset".  So the extensions
+  // list is empty.  We need to create a twindow, make it current,
+  // fetch the extensions temporarily, get the few extensions
+  // we need, then clear the extensions list again in preparation
+  // for the reset.
+  
+  HDC twindow_dc = get_twindow_dc();
+  if (twindow_dc == 0) {
+    return;
+  }
+
+  HGLRC twindow_ctx = wglCreateContext(twindow_dc);
+  if (twindow_ctx == 0) {
+    return;
+  }
+
+  wglGraphicsPipe::wgl_make_current(twindow_dc, twindow_ctx, NULL);
+
+  _extensions.clear();
+  save_extensions((const char *)GLP(GetString)(GL_EXTENSIONS));
+  get_extra_extensions();
+  _supports_pixel_format = has_extension("WGL_ARB_pixel_format");
+  _supports_wgl_multisample = has_extension("WGL_ARB_multisample");
+  _extensions.clear();
+
+  if (!_supports_pixel_format) {
+    wglDeleteContext(twindow_ctx);
+    return;
+  }
+
+  _wglGetPixelFormatAttribivARB =
+    (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)wglGetProcAddress("wglGetPixelFormatAttribivARB");
+  _wglGetPixelFormatAttribfvARB =
+    (PFNWGLGETPIXELFORMATATTRIBFVARBPROC)wglGetProcAddress("wglGetPixelFormatAttribfvARB");
+  _wglChoosePixelFormatARB =
+    (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
+
+  if (_wglGetPixelFormatAttribivARB == NULL ||
+      _wglGetPixelFormatAttribfvARB == NULL ||
+      _wglChoosePixelFormatARB == NULL) {
+    wgldisplay_cat.error()
+      << "Driver claims to support WGL_ARB_pixel_format extension, but does not define all functions.\n";
+    wglDeleteContext(twindow_ctx);
+    return;
+  }
+
+  //// Use the wgl extensions to find a better format.
   //
-  // Now that this is in the draw thread, it's probably possible
-  // to write this code in a more elegant manner.
-
-  if (frame_buffer_mode & (FrameBufferProperties::FM_multisample)) {
-
-    PT(wglGraphicsStateGuardian) temp_gsg = 
-      new wglGraphicsStateGuardian(_pfnum_properties, _share_with, _pfnum);
-
-    FrameBufferProperties adv_properties = _pfnum_properties;
-
-    HDC twindow_dc = temp_gsg->get_twindow_dc();
-    if (twindow_dc != 0) {
-      pipe->wgl_make_current(twindow_dc, temp_gsg->get_context(twindow_dc),
-                             NULL);
-      temp_gsg->reset_if_new();
-      
-      if (temp_gsg->_supports_pixel_format) {
-        int adv_pfnum = pipe->
-          choose_pfnum_advanced(properties, temp_gsg, twindow_dc, _pfnum);
-        if (pipe->get_properties_advanced
-            (adv_properties, temp_gsg, twindow_dc, adv_pfnum)) {
-          _pfnum_properties = adv_properties;
-          _pfnum = adv_pfnum;
-        } else {
-          wgldisplay_cat.debug()
-            << "Unable to query properties using extension interface.\n";
+  
+  static const int max_attrib_list = 64;
+  int iattrib_list[max_attrib_list];
+  float fattrib_list[max_attrib_list];
+  int ni = 0;
+  int nf = 0;
+  
+  iattrib_list[ni++] = WGL_SUPPORT_OPENGL_ARB;
+  iattrib_list[ni++] = true;
+  iattrib_list[ni++] = WGL_PIXEL_TYPE_ARB;
+  iattrib_list[ni++] = WGL_TYPE_RGBA_ARB;
+
+  if (need_pbuffer) {
+    iattrib_list[ni++] = WGL_DRAW_TO_PBUFFER_ARB;
+    iattrib_list[ni++] = true;
+    if (_pfnum_properties.get_alpha_bits()) {
+      iattrib_list[ni++] = WGL_BIND_TO_TEXTURE_RGBA_ARB;
+      iattrib_list[ni++] = true;
+    } else {
+      iattrib_list[ni++] = WGL_BIND_TO_TEXTURE_RGB_ARB;
+      iattrib_list[ni++] = true;
+    }
+  }
+
+  nassertv(ni < max_attrib_list && nf < max_attrib_list);
+  iattrib_list[ni] = 0;
+  fattrib_list[nf] = 0;
+  
+  static const int max_pformats = 1024;
+  int pformat[max_pformats];
+  memset(pformat, 0, sizeof(pformat));
+  int nformats = 0;
+  
+  if (!_wglChoosePixelFormatARB(twindow_dc, iattrib_list, fattrib_list,
+                                max_pformats, pformat, (unsigned int *)&nformats)) {
+    nformats = 0;
+  }
+  nformats = min(nformats, max_pformats);
+  
+  if (wgldisplay_cat.is_debug()) {
+    wgldisplay_cat.debug()
+      << "Found " << nformats << " advanced formats: [";
+    for (int i = 0; i < nformats; i++) {
+      wgldisplay_cat.debug(false)
+        << " " << pformat[i];
+    }
+    wgldisplay_cat.debug(false)
+      << " ]\n";
+  }
+  
+  if (nformats > 0) {
+    if (need_pbuffer) {
+      best_quality = 0;
+    }
+
+    for (int i = 0; i < nformats; i++) {
+      FrameBufferProperties pfprop;
+      if (get_properties_advanced(pfprop, twindow_dc, pformat[i])) {
+        int quality = pfprop.get_quality(properties);
+        if (quality > best_quality) {
+          best_pfnum = pformat[i];
+          best_quality = quality;
+          best_prop = pfprop;
         }
       }
     }
+    
+    _pfnum = best_pfnum;
+    _pfnum_supports_pbuffer = need_pbuffer;
+    _pfnum_properties = best_prop;
   }
-  return true;
+  
+  wglDeleteContext(twindow_ctx);
+  release_twindow();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -446,7 +704,7 @@ release_twindow() {
     _twindow = 0;
   }
 }
-  
+
 ////////////////////////////////////////////////////////////////////
 //     Function: wglGraphicsStateGuardian::register_twindow_class
 //       Access: Private, Static

+ 11 - 9
panda/src/wgldisplay/wglGraphicsStateGuardian.h

@@ -34,16 +34,18 @@
 ////////////////////////////////////////////////////////////////////
 class wglGraphicsStateGuardian : public GLGraphicsStateGuardian {
 public:
-  wglGraphicsStateGuardian(const FrameBufferProperties &properties, 
-                           wglGraphicsStateGuardian *share_with,
-                           int pfnum);
+  wglGraphicsStateGuardian(GraphicsPipe *pipe,
+                           wglGraphicsStateGuardian *share_with);
   virtual ~wglGraphicsStateGuardian();
 
   INLINE int get_pfnum() const;
-  INLINE const FrameBufferProperties &get_pfnum_properties() const;
+  INLINE bool pfnum_supports_pbuffer() const;
+  INLINE const FrameBufferProperties &get_fb_properties() const;
   INLINE bool made_context() const;
   INLINE HGLRC get_context(HDC hdc);
-  bool choose_pixel_format(const FrameBufferProperties &properties);
+  void get_properties(FrameBufferProperties &properties, HDC hdc, int pfnum);
+  bool get_properties_advanced(FrameBufferProperties &properties, HDC hdc, int pfnum);
+  void choose_pixel_format(const FrameBufferProperties &properties, bool need_pbuffer);
   virtual void reset();
 
   INLINE HDC get_twindow_dc();
@@ -56,6 +58,7 @@ private:
   void make_context(HDC hdc);
   HGLRC get_share_context() const;
   void redirect_share_pool(wglGraphicsStateGuardian *share_with);
+  
 
   bool make_twindow();
   void release_twindow();
@@ -67,12 +70,11 @@ private:
   // constructor.
   PT(wglGraphicsStateGuardian) _share_with;
 
-  // All windows that share a particular GL context must also share
-  // the same pixel format; therefore, we store the pixel format
-  // number and the actual properties in the GSG.
+  // These properties are for all wglGraphicsWindow that use this gsg.
   FrameBufferProperties _pfnum_properties;
+  bool _pfnum_supports_pbuffer;
   int _pfnum;
-
+  
   bool _made_context;
   HGLRC _context;
 

+ 30 - 9
panda/src/wgldisplay/wglGraphicsWindow.cxx

@@ -276,18 +276,28 @@ open_window() {
     return false;
   }
 
-  wglGraphicsStateGuardian *wglgsg;
-  DCAST_INTO_R(wglgsg, _gsg, false);
-
-  _hdc = GetDC(_hWnd);
+  // GSG creation/initialization.
 
-  // Make sure a pixel format is chosen, and take its properties.
-  if (wglgsg->get_pfnum() < 0) {
-    wglgsg->choose_pixel_format(_fb_properties);
+  wglGraphicsStateGuardian *wglgsg;
+  if (_gsg == 0) {
+    // There is no old gsg.  Create a new one.
+    wglgsg = new wglGraphicsStateGuardian(_pipe, NULL);
+    wglgsg->choose_pixel_format(_fb_properties, false);
+    _gsg = wglgsg;
+  } else {
+    // If the old gsg has the wrong pixel format, create a
+    // new one that shares with the old gsg.
+    DCAST_INTO_R(wglgsg, _gsg, false);
+    if (!wglgsg->get_fb_properties().subsumes(_fb_properties)) {
+      wglgsg = new wglGraphicsStateGuardian(_pipe, wglgsg);
+      wglgsg->choose_pixel_format(_fb_properties, false);
+      _gsg = wglgsg;
+    }
   }
-  _fb_properties = wglgsg->get_pfnum_properties();
-
+  
   // Set up the pixel format of the window appropriately for GL.
+
+  _hdc = GetDC(_hWnd);
   int pfnum = wglgsg->get_pfnum();
   PIXELFORMATDESCRIPTOR pixelformat;
   DescribePixelFormat(_hdc, pfnum, sizeof(PIXELFORMATDESCRIPTOR), 
@@ -318,6 +328,17 @@ open_window() {
   // Initializes _colormap
   setup_colormap(pixelformat);
 
+  // Initialize the gsg.
+  wglGraphicsPipe::wgl_make_current(_hdc, wglgsg->get_context(_hdc), &_make_current_pcollector);
+  wglgsg->reset_if_new();
+  wglgsg->report_my_gl_errors();
+  if (!wglgsg->get_fb_properties().verify_hardware_software
+      (_fb_properties,wglgsg->get_gl_renderer())) {
+    close_window();
+    return false;
+  }
+  _fb_properties = wglgsg->get_fb_properties();
+
   return true;
 }
 

+ 10 - 11
pandatool/src/bam/eggToBam.cxx

@@ -435,19 +435,13 @@ make_buffer() {
 
   // Some graphics drivers can only create single-buffered offscreen
   // buffers.  So request that.
-  fbprops.set_frame_buffer_mode((fbprops.get_frame_buffer_mode() & ~FrameBufferProperties::FM_buffer) | FrameBufferProperties::FM_single_buffer);
-
-  PT(GraphicsStateGuardian) gsg = 
-    _engine->make_gsg(_pipe, fbprops);
-  if (gsg == (GraphicsStateGuardian *)NULL) {
-    nout << "Unable to create GraphicsStateGuardian.\n";
-    return false;
-  }
-  _gsg = gsg;
+  fbprops.set_back_buffers(0);
 
   // We don't care how big the buffer is; we just need it to manifest
   // the GSG.
-  _buffer = _engine->make_buffer(_gsg, "buffer", 0, 1, 1);
+  _buffer = _engine->make_output(_pipe, "buffer", 0, fbprops, 1, 1, 
+                                 GraphicsPipe::BF_refuse_window |
+                                 GraphicsPipe::BF_fb_props_optional);
   _engine->open_windows();
   if (_buffer == (GraphicsOutput *)NULL || !_buffer->is_valid()) {
     if (_buffer != (GraphicsOutput *)NULL) {
@@ -455,7 +449,11 @@ make_buffer() {
     }
 
     // Couldn't create a buffer; try for a window instead.
-    GraphicsWindow *window = _engine->make_window(_gsg, "window", 0);
+    fbprops = FrameBufferProperties::get_default();
+    _buffer = _engine->make_output(_pipe, "window", 0, fbprops, 1, 1,
+                                   GraphicsPipe::BF_require_window |
+                                   GraphicsPipe::BF_fb_props_optional);
+    GraphicsWindow *window = (GraphicsWindow*)_buffer;
     if (window == (GraphicsWindow *)NULL) {
       nout << "Unable to create graphics window.\n";
       return false;
@@ -470,6 +468,7 @@ make_buffer() {
     _buffer = window;
     _engine->open_windows();
   }
+  _gsg = _buffer->get_gsg();
 
   return true;
 }