Browse Source

glxGraphicsPixmap

David Rose 17 years ago
parent
commit
6e64da12a6

+ 1 - 0
panda/src/glxdisplay/Sources.pp

@@ -16,6 +16,7 @@
     config_glxdisplay.cxx config_glxdisplay.h \
     config_glxdisplay.cxx config_glxdisplay.h \
     glxGraphicsBuffer.h glxGraphicsBuffer.I glxGraphicsBuffer.cxx \
     glxGraphicsBuffer.h glxGraphicsBuffer.I glxGraphicsBuffer.cxx \
     glxGraphicsPipe.I glxGraphicsPipe.cxx glxGraphicsPipe.h \
     glxGraphicsPipe.I glxGraphicsPipe.cxx glxGraphicsPipe.h \
+    glxGraphicsPixmap.h glxGraphicsPixmap.I glxGraphicsPixmap.cxx \
     glxGraphicsWindow.h glxGraphicsWindow.I glxGraphicsWindow.cxx \
     glxGraphicsWindow.h glxGraphicsWindow.I glxGraphicsWindow.cxx \
     glxGraphicsStateGuardian.h glxGraphicsStateGuardian.I \
     glxGraphicsStateGuardian.h glxGraphicsStateGuardian.I \
     glxGraphicsStateGuardian.cxx \
     glxGraphicsStateGuardian.cxx \

+ 2 - 0
panda/src/glxdisplay/config_glxdisplay.cxx

@@ -15,6 +15,7 @@
 #include "config_glxdisplay.h"
 #include "config_glxdisplay.h"
 #include "glxGraphicsBuffer.h"
 #include "glxGraphicsBuffer.h"
 #include "glxGraphicsPipe.h"
 #include "glxGraphicsPipe.h"
+#include "glxGraphicsPixmap.h"
 #include "glxGraphicsWindow.h"
 #include "glxGraphicsWindow.h"
 #include "glxGraphicsStateGuardian.h"
 #include "glxGraphicsStateGuardian.h"
 #include "graphicsPipeSelection.h"
 #include "graphicsPipeSelection.h"
@@ -97,6 +98,7 @@ init_libglxdisplay() {
   glxGraphicsBuffer::init_type();
   glxGraphicsBuffer::init_type();
 #endif  // HAVE_GLXFBCONFIG
 #endif  // HAVE_GLXFBCONFIG
   glxGraphicsPipe::init_type();
   glxGraphicsPipe::init_type();
+  glxGraphicsPixmap::init_type();
   glxGraphicsWindow::init_type();
   glxGraphicsWindow::init_type();
   glxGraphicsStateGuardian::init_type();
   glxGraphicsStateGuardian::init_type();
 
 

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

@@ -161,7 +161,6 @@ close_buffer() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool glxGraphicsBuffer::
 bool glxGraphicsBuffer::
 open_buffer() {
 open_buffer() {
-
   glxGraphicsPipe *glx_pipe;
   glxGraphicsPipe *glx_pipe;
   DCAST_INTO_R(glx_pipe, _pipe, false);
   DCAST_INTO_R(glx_pipe, _pipe, false);
 
 
@@ -170,7 +169,7 @@ open_buffer() {
   if (_gsg == 0) {
   if (_gsg == 0) {
     // There is no old gsg.  Create a new one.
     // There is no old gsg.  Create a new one.
     glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, NULL);
     glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, NULL);
-    glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), true);
+    glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), true, false);
     _gsg = glxgsg;
     _gsg = glxgsg;
   } else {
   } else {
     // If the old gsg has the wrong pixel format, create a
     // If the old gsg has the wrong pixel format, create a
@@ -178,7 +177,7 @@ open_buffer() {
     DCAST_INTO_R(glxgsg, _gsg, false);
     DCAST_INTO_R(glxgsg, _gsg, false);
     if (!glxgsg->get_fb_properties().subsumes(_fb_properties)) {
     if (!glxgsg->get_fb_properties().subsumes(_fb_properties)) {
       glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, glxgsg);
       glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, glxgsg);
-      glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), true);
+      glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), true, false);
       _gsg = glxgsg;
       _gsg = glxgsg;
     }
     }
   }
   }

+ 32 - 6
panda/src/glxdisplay/glxGraphicsPipe.cxx

@@ -15,6 +15,7 @@
 #include "glxGraphicsPipe.h"
 #include "glxGraphicsPipe.h"
 #include "glxGraphicsWindow.h"
 #include "glxGraphicsWindow.h"
 #include "glxGraphicsBuffer.h"
 #include "glxGraphicsBuffer.h"
+#include "glxGraphicsPixmap.h"
 #include "glxGraphicsStateGuardian.h"
 #include "glxGraphicsStateGuardian.h"
 #include "config_glxdisplay.h"
 #include "config_glxdisplay.h"
 #include "frameBufferProperties.h"
 #include "frameBufferProperties.h"
@@ -272,24 +273,49 @@ make_output(const string &name,
     return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop,
     return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop,
                                 flags, gsg, host);
                                 flags, gsg, host);
   }
   }
-  
+
 #ifdef HAVE_GLXFBCONFIG
 #ifdef HAVE_GLXFBCONFIG
   // Third thing to try: a glxGraphicsBuffer
   // Third thing to try: a glxGraphicsBuffer
   
   
   if (retry == 2) {
   if (retry == 2) {
-    if ((!support_rtt)||
-        ((flags&BF_require_parasite)!=0)||
+    if (((flags&BF_require_parasite)!=0)||
         ((flags&BF_require_window)!=0)||
         ((flags&BF_require_window)!=0)||
         ((flags&BF_resizeable)!=0)||
         ((flags&BF_resizeable)!=0)||
-        ((flags&BF_size_track_host)!=0)||
-        ((flags&BF_rtt_cumulative)!=0)||
-        ((flags&BF_can_bind_every)!=0)) {
+        ((flags&BF_size_track_host)!=0)) {
       return NULL;
       return NULL;
     }
     }
+
+    if (!support_rtt) {
+      if (((flags&BF_rtt_cumulative)!=0)||
+          ((flags&BF_can_bind_every)!=0)) {
+        // If we require Render-to-Texture, but can't be sure we
+        // support it, bail.
+        return NULL;
+      }
+    }
+
     return new glxGraphicsBuffer(engine, this, name, fb_prop, win_prop,
     return new glxGraphicsBuffer(engine, this, name, fb_prop, win_prop,
                                  flags, gsg, host);
                                  flags, gsg, host);
   }
   }
 #endif  // HAVE_GLXFBCONFIG
 #endif  // HAVE_GLXFBCONFIG
+
+  // Third thing to try: a glxGraphicsPixmap.
+  if (retry == 3) {
+    if (((flags&BF_require_parasite)!=0)||
+        ((flags&BF_require_window)!=0)||
+        ((flags&BF_resizeable)!=0)||
+        ((flags&BF_size_track_host)!=0)) {
+      return NULL;
+    }
+
+    if (((flags&BF_rtt_cumulative)!=0)||
+        ((flags&BF_can_bind_every)!=0)) {
+      return NULL;
+    }
+
+    return new glxGraphicsPixmap(engine, this, name, fb_prop, win_prop,
+                                 flags, gsg, host);
+  }
   
   
   // Nothing else left to try.
   // Nothing else left to try.
   return NULL;
   return NULL;

+ 14 - 0
panda/src/glxdisplay/glxGraphicsPixmap.I

@@ -0,0 +1,14 @@
+// Filename: glxGraphicsPixmap.I
+// Created by:  drose (10Mar09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+

+ 262 - 0
panda/src/glxdisplay/glxGraphicsPixmap.cxx

@@ -0,0 +1,262 @@
+// Filename: glxGraphicsPixmap.cxx
+// Created by:  drose (10Mar09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "glxGraphicsPixmap.h"
+#include "glxGraphicsWindow.h"
+#include "glxGraphicsStateGuardian.h"
+#include "config_glxdisplay.h"
+#include "glxGraphicsPipe.h"
+
+#include "graphicsPipe.h"
+#include "glgsg.h"
+#include "pStatTimer.h"
+
+TypeHandle glxGraphicsPixmap::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsPixmap::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+glxGraphicsPixmap::
+glxGraphicsPixmap(GraphicsEngine *engine, GraphicsPipe *pipe, 
+                  const string &name,
+                  const FrameBufferProperties &fb_prop,
+                  const WindowProperties &win_prop,
+                  int flags,
+                  GraphicsStateGuardian *gsg,
+                  GraphicsOutput *host) :
+  GraphicsBuffer(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
+{
+  glxGraphicsPipe *glx_pipe;
+  DCAST_INTO_V(glx_pipe, _pipe);
+  _display = glx_pipe->get_display();
+  _drawable = None;
+  _x_pixmap = None;
+  _glx_pixmap = None;
+
+  // Since the pixmap never gets flipped, we get screenshots from the
+  // same pixmap we draw into.
+  _screenshot_buffer_type = _draw_buffer_type;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsPixmap::Destructor
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+glxGraphicsPixmap::
+~glxGraphicsPixmap() {
+  nassertv(_x_pixmap == None && _glx_pixmap == None);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsPixmap::begin_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               before beginning rendering for a given frame.  It
+//               should do whatever setup is required, and return true
+//               if the frame should be rendered, or false if it
+//               should be skipped.
+////////////////////////////////////////////////////////////////////
+bool glxGraphicsPixmap::
+begin_frame(FrameMode mode, Thread *current_thread) {
+  PStatTimer timer(_make_current_pcollector, current_thread);
+
+  begin_frame_spam(mode);
+  if (_gsg == (GraphicsStateGuardian *)NULL) {
+    return false;
+  }
+
+  glxGraphicsStateGuardian *glxgsg;
+  DCAST_INTO_R(glxgsg, _gsg, false);
+  glXMakeCurrent(_display, _glx_pixmap, glxgsg->_context);
+
+  // 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.)
+  glxgsg->reset_if_new();
+
+  if (mode == FM_render) {
+    for (int i=0; i<count_textures(); i++) {
+      if (get_rtm_mode(i) == RTM_bind_or_copy) {
+        _textures[i]._rtm_mode = RTM_copy_texture;
+      }
+    }
+    clear_cube_map_selection();
+  }
+  
+  _gsg->set_current_properties(&get_fb_properties());
+  return _gsg->begin_frame(current_thread);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsPixmap::end_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               after rendering is completed for a given frame.  It
+//               should do whatever finalization is required.
+////////////////////////////////////////////////////////////////////
+void glxGraphicsPixmap::
+end_frame(FrameMode mode, Thread *current_thread) {
+  end_frame_spam(mode);
+  nassertv(_gsg != (GraphicsStateGuardian *)NULL);
+
+  if (mode == FM_render) {
+    copy_to_textures();
+  }
+
+  _gsg->end_frame(current_thread);
+
+  if (mode == FM_render) {
+    trigger_flip();
+    if (_one_shot) {
+      prepare_for_deletion();
+    }
+    clear_cube_map_selection();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsPixmap::close_buffer
+//       Access: Protected, Virtual
+//  Description: Closes the pixmap right now.  Called from the window
+//               thread.
+////////////////////////////////////////////////////////////////////
+void glxGraphicsPixmap::
+close_buffer() {
+  if (_gsg != (GraphicsStateGuardian *)NULL) {
+    glXMakeCurrent(_display, None, NULL);
+    _gsg.clear();
+    _active = false;
+  }
+
+  if (_glx_pixmap != None) {
+    glXDestroyGLXPixmap(_display, _glx_pixmap);
+    _glx_pixmap = None;
+  }
+
+  if (_x_pixmap != None) {
+    XFreePixmap(_display, _x_pixmap);
+    _x_pixmap = None;
+  }
+
+  _is_valid = false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsPixmap::open_buffer
+//       Access: Protected, Virtual
+//  Description: Opens the pixmap right now.  Called from the window
+//               thread.  Returns true if the pixmap is successfully
+//               opened, or false if there was a problem.
+////////////////////////////////////////////////////////////////////
+bool glxGraphicsPixmap::
+open_buffer() {
+  cerr << "open_buffer\n";
+  glxGraphicsPipe *glx_pipe;
+  DCAST_INTO_R(glx_pipe, _pipe, false);
+
+  // GSG Creation/Initialization
+  glxGraphicsStateGuardian *glxgsg;
+  if (_gsg == 0) {
+    // There is no old gsg.  Create a new one.
+    glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, NULL);
+    glxgsg->choose_pixel_format(_fb_properties, _display, glx_pipe->get_screen(), false, 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(_engine, _pipe, glxgsg);
+      glxgsg->choose_pixel_format(_fb_properties, _display, glx_pipe->get_screen(), false, true);
+      _gsg = glxgsg;
+    }
+  }
+
+  XVisualInfo *visual_info = glxgsg->_visual;
+  if (visual_info == NULL) {
+    // No X visual for this fbconfig; how can we create the pixmap?
+    glxdisplay_cat.error()
+      << "No X visual: cannot create pixmap.\n";
+    return false;
+  }
+
+  _drawable = glx_pipe->get_root();
+  if (_host != NULL) {
+    cerr << "got host: " << _host->get_type() << "\n";
+    if (_host->is_of_type(glxGraphicsWindow::get_class_type())) {
+      glxGraphicsWindow *win = DCAST(glxGraphicsWindow, _host);
+      _drawable = win->get_xwindow();
+    } else if (_host->is_of_type(glxGraphicsPixmap::get_class_type())) {
+      glxGraphicsPixmap *pix = DCAST(glxGraphicsPixmap, _host);
+      _drawable = pix->_drawable;
+    }
+  }
+
+  cerr << "creating pixmap, root = " << _drawable
+       << ", size = " << _x_size << " " << _y_size << ", depth = "
+       << visual_info->depth << "\n";
+  _x_pixmap = XCreatePixmap(_display, _drawable, 
+                            _x_size, _y_size, visual_info->depth);
+  cerr << "got " << _x_pixmap << "\n";
+  if (_x_pixmap == None) {
+    glxdisplay_cat.error()
+      << "Failed to create X pixmap.\n";
+    close_buffer();
+    return false;
+  }
+  cerr << "creating glx pixmap\n";
+
+#ifdef HAVE_GLXFBCONFIG
+  if (glxgsg->_fbconfig) {
+    // Use the FBConfig to create the pixmap.
+    cerr << "fbconfig\n";
+    _glx_pixmap = glXCreatePixmap(_display, glxgsg->_fbconfig, _x_pixmap, NULL);
+  } else
+#endif  // HAVE_GLXFBCONFIG
+    {
+      // Use the XVisual to create the pixmap.
+      _glx_pixmap = glXCreateGLXPixmap(_display, visual_info, _x_pixmap);
+    }
+
+  cerr << "got " << _glx_pixmap << "\n";
+
+  if (_glx_pixmap == None) {
+    glxdisplay_cat.error()
+      << "Failed to create GLX pixmap.\n";
+    close_buffer();
+    return false;
+  }
+
+  cerr << "making current, context = " << glxgsg->_context << "\n";
+  glXMakeCurrent(_display, _glx_pixmap, glxgsg->_context);
+  cerr << "context = " << glxgsg->_context << "\n";
+  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;
+}

+ 75 - 0
panda/src/glxdisplay/glxGraphicsPixmap.h

@@ -0,0 +1,75 @@
+// Filename: glxGraphicsPixmap.h
+// Created by:  drose (10Mar09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef GLXGRAPHICSPIXMAP_H
+#define GLXGRAPHICSPIXMAP_H
+
+#include "pandabase.h"
+
+#include "glxGraphicsPipe.h"
+#include "graphicsBuffer.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : glxGraphicsPixmap
+// Description : Another offscreen buffer in the GLX environment.  This
+//               creates a Pixmap object, which is probably less
+//               efficient than a GLXPBuffer, so this class is a
+//               second choice to glxGraphicsBuffer.  However, this
+//               might be the only option for some graphics drivers.
+////////////////////////////////////////////////////////////////////
+class glxGraphicsPixmap : public GraphicsBuffer {
+public:
+  glxGraphicsPixmap(GraphicsEngine *engine, GraphicsPipe *pipe, 
+                    const string &name,
+                    const FrameBufferProperties &fb_prop,
+                    const WindowProperties &win_prop,
+                    int flags,
+                    GraphicsStateGuardian *gsg,
+                    GraphicsOutput *host);
+  virtual ~glxGraphicsPixmap();
+
+  virtual bool begin_frame(FrameMode mode, Thread *current_thread);
+  virtual void end_frame(FrameMode mode, Thread *current_thread);
+
+protected:
+  virtual void close_buffer();
+  virtual bool open_buffer();
+
+private:
+  Display *_display;
+  Window _drawable;
+  Pixmap _x_pixmap;
+  GLXPixmap _glx_pixmap;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    GraphicsBuffer::init_type();
+    register_type(_type_handle, "glxGraphicsPixmap",
+                  GraphicsBuffer::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "glxGraphicsPixmap.I"
+
+#endif

+ 35 - 22
panda/src/glxdisplay/glxGraphicsStateGuardian.cxx

@@ -137,8 +137,8 @@ get_properties(FrameBufferProperties &properties, XVisualInfo *visual) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void glxGraphicsStateGuardian::
 void glxGraphicsStateGuardian::
 get_properties_advanced(FrameBufferProperties &properties, 
 get_properties_advanced(FrameBufferProperties &properties, 
-			bool &pbuffer_supported, bool &slow,
-                        fbconfig config) {
+			bool &pbuffer_supported, bool &pixmap_supported,
+                        bool &slow, fbconfig config) {
 
 
   properties.clear();
   properties.clear();
 
 
@@ -165,22 +165,26 @@ get_properties_advanced(FrameBufferProperties &properties,
   glXGetFBConfigAttrib(_display, config, GLX_DRAWABLE_TYPE, &drawable_type);
   glXGetFBConfigAttrib(_display, config, GLX_DRAWABLE_TYPE, &drawable_type);
   glXGetFBConfigAttrib(_display, config, GLX_CONFIG_CAVEAT, &caveat);
   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;
   pbuffer_supported = false;
   if ((drawable_type & GLX_PBUFFER_BIT)!=0) {
   if ((drawable_type & GLX_PBUFFER_BIT)!=0) {
     pbuffer_supported = true;
     pbuffer_supported = true;
   }
   }
+
+  pixmap_supported = false;
+  if ((drawable_type & GLX_PIXMAP_BIT)!=0) {
+    pixmap_supported = true;
+  }
   
   
   if (caveat & GLX_SLOW_CONFIG) {
   if (caveat & GLX_SLOW_CONFIG) {
     slow = true;
     slow = true;
   } else {
   } else {
     slow = false;
     slow = false;
   }
   }
+
+  if ((drawable_type & GLX_WINDOW_BIT)==0) {
+    // We insist on having a context that will support an onscreen window.
+    return;
+  }
   
   
   if (double_buffer) {
   if (double_buffer) {
     properties.set_back_buffers(1);
     properties.set_back_buffers(1);
@@ -216,8 +220,7 @@ get_properties_advanced(FrameBufferProperties &properties,
 void glxGraphicsStateGuardian::
 void glxGraphicsStateGuardian::
 choose_pixel_format(const FrameBufferProperties &properties,
 choose_pixel_format(const FrameBufferProperties &properties,
 		    Display *display,
 		    Display *display,
-		    int screen,
-                    bool need_pbuffer) {
+		    int screen, bool need_pbuffer, bool need_pixmap) {
 
 
   _display = display;
   _display = display;
   _screen = screen;
   _screen = screen;
@@ -248,27 +251,34 @@ choose_pixel_format(const FrameBufferProperties &properties,
   int best_quality = 0;
   int best_quality = 0;
   int best_result = 0;
   int best_result = 0;
   FrameBufferProperties best_props;
   FrameBufferProperties best_props;
-
+  
   if (configs != 0) {
   if (configs != 0) {
-    for (int i=0; i<num_configs; i++) {
+    for (int i = 0; i < num_configs; ++i) {
       FrameBufferProperties fbprops;
       FrameBufferProperties fbprops;
-      bool pbuffer_supported = false, slow = false;
-      get_properties_advanced(fbprops, pbuffer_supported, slow, configs[i]);
+      bool pbuffer_supported, pixmap_supported, slow;
+      get_properties_advanced(fbprops, pbuffer_supported, pixmap_supported,
+                              slow, configs[i]);
       if (glxdisplay_cat.is_debug()) {
       if (glxdisplay_cat.is_debug()) {
         const char *pbuffertext = pbuffer_supported ? " (pbuffer)" : "";
         const char *pbuffertext = pbuffer_supported ? " (pbuffer)" : "";
+        const char *pixmaptext = pixmap_supported ? " (pixmap)" : "";
         const char *slowtext = slow ? " (slow)" : "";
         const char *slowtext = slow ? " (slow)" : "";
         glxdisplay_cat.debug()
         glxdisplay_cat.debug()
-          << i << ": " << fbprops << pbuffertext << slowtext << "\n";
+          << i << ": " << fbprops << pbuffertext << pixmaptext << slowtext << "\n";
       }
       }
-
       int quality = fbprops.get_quality(properties);
       int quality = fbprops.get_quality(properties);
       if ((quality > 0)&&(slow)) quality -= 10000000;
       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 (need_pbuffer && !pbuffer_supported) {
+        continue;
+      }
+      if (need_pixmap && !pixmap_supported) {
+        continue;
+      }
+      
+      if (quality > best_quality) {
+        best_quality = quality;
+        best_result = i;
+        best_props = fbprops;
       }
       }
     }
     }
   }
   }
@@ -283,10 +293,13 @@ choose_pixel_format(const FrameBufferProperties &properties,
       _visual = _visuals;
       _visual = _visuals;
       if (_visual) {
       if (_visual) {
 	_fbprops = best_props;
 	_fbprops = best_props;
+        cerr << "selected " << _fbconfig << "\n";
 	return;
 	return;
       }
       }
     }
     }
     // This really shouldn't happen, so I'm not too careful about cleanup.
     // This really shouldn't happen, so I'm not too careful about cleanup.
+    glxdisplay_cat.error()
+      << "Could not create FBConfig context!\n";
     _fbconfig = 0;
     _fbconfig = 0;
     _context = 0;
     _context = 0;
     _visual = 0;
     _visual = 0;

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

@@ -78,12 +78,12 @@ public:
   INLINE const FrameBufferProperties &get_fb_properties() const;
   INLINE const FrameBufferProperties &get_fb_properties() const;
   void get_properties(FrameBufferProperties &properties, XVisualInfo *visual);
   void get_properties(FrameBufferProperties &properties, XVisualInfo *visual);
   void get_properties_advanced(FrameBufferProperties &properties,
   void get_properties_advanced(FrameBufferProperties &properties,
-			       bool &supports_pbuffer, bool &slow,
-			       fbconfig config);
+			       bool &pbuffer_supported, bool &pixmap_supported,
+                               bool &slow, fbconfig config);
   void choose_pixel_format(const FrameBufferProperties &properties, 
   void choose_pixel_format(const FrameBufferProperties &properties, 
 			   Display *_display,
 			   Display *_display,
 			   int _screen,
 			   int _screen,
-			   bool need_pbuffer);
+			   bool need_pbuffer, bool need_pixmap);
   
   
   glxGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
   glxGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
 			   glxGraphicsStateGuardian *share_with);
 			   glxGraphicsStateGuardian *share_with);

+ 10 - 0
panda/src/glxdisplay/glxGraphicsWindow.I

@@ -12,3 +12,13 @@
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
+
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsWindow::get_xwindow
+//       Access: Public
+//  Description: Returns the X11 Window handle.
+////////////////////////////////////////////////////////////////////
+INLINE Window glxGraphicsWindow::
+get_xwindow() const {
+  return _xwindow;
+}

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

@@ -620,7 +620,7 @@ open_window() {
   if (_gsg == 0) {
   if (_gsg == 0) {
     // There is no old gsg.  Create a new one.
     // There is no old gsg.  Create a new one.
     glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, NULL);
     glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, NULL);
-    glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), false);
+    glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), false, false);
     _gsg = glxgsg;
     _gsg = glxgsg;
   } else {
   } else {
     // If the old gsg has the wrong pixel format, create a
     // If the old gsg has the wrong pixel format, create a
@@ -628,17 +628,16 @@ open_window() {
     DCAST_INTO_R(glxgsg, _gsg, false);
     DCAST_INTO_R(glxgsg, _gsg, false);
     if (!glxgsg->get_fb_properties().subsumes(_fb_properties)) {
     if (!glxgsg->get_fb_properties().subsumes(_fb_properties)) {
       glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, glxgsg);
       glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, glxgsg);
-      glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), false);
+      glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), false, false);
       _gsg = glxgsg;
       _gsg = glxgsg;
     }
     }
   }
   }
   
   
-  
   XVisualInfo *visual_info = glxgsg->_visual;
   XVisualInfo *visual_info = glxgsg->_visual;
   if (visual_info == NULL) {
   if (visual_info == NULL) {
     // No X visual for this fbconfig; how can we open the window?
     // No X visual for this fbconfig; how can we open the window?
     glxdisplay_cat.error()
     glxdisplay_cat.error()
-      << "Cannot open window.\n";
+      << "No X visual: cannot open window.\n";
     return false;
     return false;
   }
   }
   Visual *visual = visual_info->visual;
   Visual *visual = visual_info->visual;

+ 2 - 0
panda/src/glxdisplay/glxGraphicsWindow.h

@@ -45,6 +45,8 @@ public:
   virtual void process_events();
   virtual void process_events();
   virtual void set_properties_now(WindowProperties &properties);
   virtual void set_properties_now(WindowProperties &properties);
 
 
+  INLINE Window get_xwindow() const;
+
 protected:
 protected:
   virtual void close_window();
   virtual void close_window();
   virtual bool open_window();
   virtual bool open_window();