Browse Source

Buffer overhaul phase one

Josh Yelon 20 years ago
parent
commit
a176d3627c
43 changed files with 762 additions and 472 deletions
  1. 7 8
      panda/src/display/graphicsBuffer.cxx
  2. 5 2
      panda/src/display/graphicsBuffer.h
  3. 53 9
      panda/src/display/graphicsEngine.I
  4. 148 106
      panda/src/display/graphicsEngine.cxx
  5. 22 11
      panda/src/display/graphicsEngine.h
  6. 27 118
      panda/src/display/graphicsOutput.cxx
  7. 7 2
      panda/src/display/graphicsOutput.h
  8. 9 15
      panda/src/display/graphicsPipe.cxx
  9. 48 8
      panda/src/display/graphicsPipe.h
  10. 8 11
      panda/src/display/graphicsWindow.cxx
  11. 5 2
      panda/src/display/graphicsWindow.h
  12. 13 9
      panda/src/display/parasiteBuffer.cxx
  13. 2 3
      panda/src/display/parasiteBuffer.h
  14. 6 4
      panda/src/dxgsg8/wdxGraphicsBuffer8.cxx
  15. 5 3
      panda/src/dxgsg8/wdxGraphicsBuffer8.h
  16. 50 25
      panda/src/dxgsg8/wdxGraphicsPipe8.cxx
  17. 6 3
      panda/src/dxgsg8/wdxGraphicsPipe8.h
  18. 6 3
      panda/src/dxgsg8/wdxGraphicsWindow8.cxx
  19. 5 2
      panda/src/dxgsg8/wdxGraphicsWindow8.h
  20. 6 4
      panda/src/dxgsg9/wdxGraphicsBuffer9.cxx
  21. 5 3
      panda/src/dxgsg9/wdxGraphicsBuffer9.h
  22. 51 25
      panda/src/dxgsg9/wdxGraphicsPipe9.cxx
  23. 7 3
      panda/src/dxgsg9/wdxGraphicsPipe9.h
  24. 6 3
      panda/src/dxgsg9/wdxGraphicsWindow9.cxx
  25. 5 2
      panda/src/dxgsg9/wdxGraphicsWindow9.h
  26. 5 3
      panda/src/glxdisplay/glxGraphicsBuffer.cxx
  27. 4 3
      panda/src/glxdisplay/glxGraphicsBuffer.h
  28. 61 19
      panda/src/glxdisplay/glxGraphicsPipe.cxx
  29. 6 5
      panda/src/glxdisplay/glxGraphicsPipe.h
  30. 6 3
      panda/src/glxdisplay/glxGraphicsWindow.cxx
  31. 5 2
      panda/src/glxdisplay/glxGraphicsWindow.h
  32. 6 4
      panda/src/mesadisplay/osMesaGraphicsBuffer.cxx
  33. 4 3
      panda/src/mesadisplay/osMesaGraphicsBuffer.h
  34. 32 6
      panda/src/mesadisplay/osMesaGraphicsPipe.cxx
  35. 6 3
      panda/src/mesadisplay/osMesaGraphicsPipe.h
  36. 5 3
      panda/src/wgldisplay/wglGraphicsBuffer.cxx
  37. 4 2
      panda/src/wgldisplay/wglGraphicsBuffer.h
  38. 74 16
      panda/src/wgldisplay/wglGraphicsPipe.cxx
  39. 10 6
      panda/src/wgldisplay/wglGraphicsPipe.h
  40. 6 3
      panda/src/wgldisplay/wglGraphicsWindow.cxx
  41. 5 2
      panda/src/wgldisplay/wglGraphicsWindow.h
  42. 6 3
      panda/src/windisplay/winGraphicsWindow.cxx
  43. 5 2
      panda/src/windisplay/winGraphicsWindow.h

+ 7 - 8
panda/src/display/graphicsBuffer.cxx

@@ -28,9 +28,12 @@ TypeHandle GraphicsBuffer::_type_handle;
 //               GraphicsEngine::make_buffer() function.
 ////////////////////////////////////////////////////////////////////
 GraphicsBuffer::
-GraphicsBuffer(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-               const string &name, int x_size, int y_size) :
-  GraphicsOutput(pipe, gsg, name)
+GraphicsBuffer(GraphicsPipe *pipe,
+               const string &name,
+               int x_size, int y_size, int flags,
+               GraphicsStateGuardian *gsg,
+               GraphicsOutput *host) :
+  GraphicsOutput(pipe, name, x_size, y_size, flags, gsg, host)
 {
 #ifdef DO_MEMORY_USAGE
   MemoryUsage::update_type(this, this);
@@ -38,13 +41,9 @@ GraphicsBuffer(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
 
   if (display_cat.is_debug()) {
     display_cat.debug()
-      << "Creating new offscreen buffer " << get_name()
-      << " using GSG " << (void *)gsg << "\n";
+      << "Creating new offscreen buffer " << get_name() << "\n";
   }
 
-  _x_size = x_size;
-  _y_size = y_size;
-  _has_size = true;
   _default_display_region->compute_pixels(_x_size, _y_size);
   _open_request = OR_none;
 }

+ 5 - 2
panda/src/display/graphicsBuffer.h

@@ -33,8 +33,11 @@
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA GraphicsBuffer : public GraphicsOutput {
 protected:
-  GraphicsBuffer(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-                 const string &name, int x_size, int y_size);
+  GraphicsBuffer(GraphicsPipe *pipe, 
+                 const string &name,
+                 int x_size, int y_size, int flags,
+                 GraphicsStateGuardian *gsg,
+                 GraphicsOutput *host);
 
 PUBLISHED:
   virtual ~GraphicsBuffer();

+ 53 - 9
panda/src/display/graphicsEngine.I

@@ -78,6 +78,19 @@ get_portal_cull() const {
   return _portal_enabled;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::close_gsg
+//       Access: Published
+//  Description: Calls GraphicsPipe::close_gsg() on the indicated pipe
+//               and GSG.  This function mainly exists to allow
+//               GraphicsEngine::WindowRenderer to call the protected
+//               method GraphicsPipe::close_gsg().
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsEngine::
+close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) {
+  pipe->close_gsg(gsg);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::make_gsg
 //       Access: Published
@@ -103,20 +116,50 @@ make_gsg(GraphicsPipe *pipe) {
   return make_gsg(pipe, get_frame_buffer_properties(), NULL);
 }
 
-
 ////////////////////////////////////////////////////////////////////
-//     Function: GraphicsEngine::close_gsg
+//     Function: GraphicsEngine::make_window
 //       Access: Published
-//  Description: Calls GraphicsPipe::close_gsg() on the indicated pipe
-//               and GSG.  This function mainly exists to allow
-//               GraphicsEngine::WindowRenderer to call the protected
-//               method GraphicsPipe::close_gsg().
+//  Description: Syntactic shorthand for make_output
+////////////////////////////////////////////////////////////////////
+INLINE GraphicsWindow *GraphicsEngine::
+make_window(GraphicsStateGuardian *gsg, const string &name, int sort) {
+  // The hardwired size here is never used.
+  GraphicsOutput *result = make_output(gsg->get_pipe(), name, sort,
+                                       gsg->get_properties(), 50, 50,
+                                       GraphicsPipe::BF_require_window,
+                                       gsg, NULL);
+  return DCAST(GraphicsWindow, result);
+}
+
 ////////////////////////////////////////////////////////////////////
-INLINE void GraphicsEngine::
-close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) {
-  pipe->close_gsg(gsg);
+//     Function: GraphicsEngine::make_buffer
+//       Access: Published
+//  Description: Syntactic shorthand for make_output
+////////////////////////////////////////////////////////////////////
+INLINE GraphicsOutput *GraphicsEngine::
+make_buffer(GraphicsStateGuardian *gsg, const string &name,
+            int sort, int x_size, int y_size) {
+   GraphicsOutput *result = make_output(gsg->get_pipe(), name, sort,
+                                        gsg->get_properties(), x_size, y_size,
+                                        GraphicsPipe::BF_refuse_window,
+                                        gsg, NULL);
+   return result;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::make_parasite
+//       Access: Published
+//  Description: Syntactic shorthand for make_buffer.
+////////////////////////////////////////////////////////////////////
+INLINE GraphicsOutput *GraphicsEngine::
+make_parasite(GraphicsOutput *host, const string &name, 
+              int sort, int x_size, int y_size) {
+  GraphicsOutput *result = make_output(host->get_gsg()->get_pipe(), name, sort,
+                                       host->get_gsg()->get_properties(), x_size, y_size,
+                                       GraphicsPipe::BF_require_parasite,
+                                       host->get_gsg(), host);
+   return result;
+}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::Callback::Constructor
@@ -152,3 +195,4 @@ INLINE void GraphicsEngine::Callback::
 do_callback() const {
   (*_func)(_data);
 }
+

+ 148 - 106
panda/src/display/graphicsEngine.cxx

@@ -238,120 +238,160 @@ make_gsg(GraphicsPipe *pipe, const FrameBufferProperties &properties,
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: GraphicsEngine::make_window
+//     Function: GraphicsEngine::make_output
 //       Access: Published
-//  Description: Creates a new window using the indicated
-//               GraphicsStateGuardian and returns it.  The
-//               GraphicsEngine becomes the owner of the window; it
-//               will persist at least until remove_window() is called
-//               later.
-////////////////////////////////////////////////////////////////////
-GraphicsWindow *GraphicsEngine::
-make_window(GraphicsStateGuardian *gsg, const string &name, int sort) {
-  GraphicsThreadingModel threading_model = get_threading_model();
-
-  nassertr(gsg != (GraphicsStateGuardian *)NULL, NULL);
-  nassertr(this == gsg->get_engine(), NULL);
-  nassertr(threading_model.get_draw_name() ==
-           gsg->get_threading_model().get_draw_name(), NULL);
-
-  // TODO: ask the window thread to make the window.
-  PT(GraphicsWindow) window = gsg->get_pipe()->make_window(gsg, name);
-  if (window != (GraphicsWindow *)NULL) {
-    window->_sort = sort;
-    do_add_window(window, gsg, threading_model);
-  }
-  return window;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsEngine::make_buffer
-//       Access: Published
-//  Description: Creates a new offscreen buffer using the indicated
-//               GraphicsStateGuardian and returns it.  The
-//               GraphicsEngine becomes the owner of the buffer; it
-//               will persist at least until remove_window() is called
-//               later.
+//  Description: Creates a new window (or buffer) and returns it.
+//               The GraphicsEngine becomes the owner of the window,
+//               it will persist at least until remove_window() is
+//               called later.
 //
-//               This usually returns a GraphicsBuffer object, but it
-//               may actually return a GraphicsWindow if show-buffers
-//               is configured true.
+//               If a null pointer is supplied for the gsg, then this
+//               routine will create a new gsg.
+//               
+//               This routine is only called from the app thread.
 ////////////////////////////////////////////////////////////////////
+
 GraphicsOutput *GraphicsEngine::
-make_buffer(GraphicsStateGuardian *gsg, const string &name, 
-            int sort, int x_size, int y_size) {
-  // I'll remove this permanently in a few days. - Josh
-  //  if (show_buffers) {
-  //    GraphicsWindow *window = make_window(gsg, name, sort);
-  //    if (window != (GraphicsWindow *)NULL) {
-  //      WindowProperties props;
-  //      props.set_size(x_size, y_size);
-  //      props.set_fixed_size(true);
-  //      props.set_title(name);
-  //      window->request_properties(props);
-  //      return window;
-  //    }
-  //  }
+make_output(GraphicsPipe *pipe,
+            const string &name, int sort,
+            const FrameBufferProperties &prop,
+            int x_size, int y_size, int flags,
+            GraphicsStateGuardian *gsg,
+            GraphicsOutput *host) {
+  
+  //  The code here is tricky because the gsg that is passed in
+  //  might be in the uninitialized state.  As a result,
+  //  pipe::make_output may not be able to tell which DirectX
+  //  capabilities or OpenGL extensions are supported and which
+  //  are not.  Worse yet, it can't query the API, because that
+  //  can only be done from the draw thread, and this is the app
+  //  thread.
+  //
+  //  So here's the workaround: this routine calls pipe::make_output,
+  //  which returns a "non-certified" window.  That means that
+  //  the pipe doesn't promise that the draw thread will actually
+  //  succeed in initializing the window.  This routine then calls
+  //  open_windows, which attempts to initialize the window.
+  //
+  //  If open_windows fails to initialize the window, then
+  //  this routine will ask pipe::make_output to try again, this
+  //  time using a different set of OpenGL extensions or DirectX
+  //  capabilities.   This is what the "retry" parameter to
+  //  pipe::make_output is for - it specifies, in an abstract
+  //  manner, which set of capabilties/extensions to try.
+  //
+  //  The only problem with this design is that it requires the
+  //  engine to call open_windows, which is slow.  To make
+  //  things faster, we can ask pipe::make_output to "precertify"
+  //  its creations.  If we ask it to precertify, then it guarantees
+  //  that the windows it returns will not fail in open_windows.
+  //  However, we can only ask for precertification if we are
+  //  passing it an already-initialized gsg.  Long story short,
+  //  if you want make_output to be fast, use an
+  //  already-initialized gsg.
+
+  // Simplify the input parameters.
+  
+  if ((x_size==0) || (y_size == 0)) {
+    flags |= GraphicsPipe::BF_size_track_host;
+  }
+  if (host != 0) {
+    host = host->get_host();
+  }
+
+  // Sanity check everything.
 
   GraphicsThreadingModel threading_model = get_threading_model();
-  nassertr(gsg != (GraphicsStateGuardian *)NULL, NULL);
-  nassertr(this == gsg->get_engine(), NULL);
-  nassertr(threading_model.get_draw_name() ==
-           gsg->get_threading_model().get_draw_name(), NULL);
-
-  // TODO: ask the window thread to make the buffer.
-  PT(GraphicsBuffer) buffer = 
-    gsg->get_pipe()->make_buffer(gsg, name, x_size, y_size);
-  if (buffer != (GraphicsBuffer *)NULL) {
+  nassertr(pipe != (GraphicsPipe *)NULL, NULL);
+  if (gsg != (GraphicsStateGuardian *)NULL) {
+    nassertr(pipe == gsg->get_pipe(), NULL);
+    nassertr(this == gsg->get_engine(), NULL);
+    nassertr(prop == gsg->get_properties(), 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);
+  }
+  
+  // A thread could modify these flags while we create the
+  // buffer.  So we do a single atomic fetch here.
+  
+  bool precertify = gsg->_is_valid && (!gsg->_needs_reset);
+  
+  // Determine if a parasite buffer meets the user's specs.
+
+  bool can_use_parasite = false;
+  if ((host != 0)&&
+      ((flags&GraphicsPipe::BF_require_window)==0)&&
+      ((flags&GraphicsPipe::BF_refuse_parasite)==0)&&
+      ((flags&GraphicsPipe::BF_need_aux_rgba_MASK)==0)&&
+      ((flags&GraphicsPipe::BF_need_aux_hrgba_MASK)==0)&&
+      ((flags&GraphicsPipe::BF_need_aux_float_MASK)==0)&&
+      ((flags&GraphicsPipe::BF_can_bind_color)==0)&&
+      ((flags&GraphicsPipe::BF_can_bind_every)==0)) {
+    can_use_parasite = true;
+  }
+  
+  // If parasite buffers are preferred, then try a parasite first.
+  
+  if ((prefer_parasite_buffer) &&
+      (can_use_parasite) &&
+      (x_size <= host->get_x_size())&&
+      (y_size <= host->get_y_size())) {
+    ParasiteBuffer *buffer = new ParasiteBuffer(host, name, x_size, y_size, flags);
     buffer->_sort = sort;
     do_add_window(buffer, gsg, threading_model);
+    return buffer;
   }
-  return buffer;
-}
 
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsEngine::make_parasite
-//       Access: Published
-//  Description: Creates a new offscreen parasite buffer based on the
-//               indicated host.  See parasiteBuffer.h.  The
-//               GraphicsEngine becomes the owner of the buffer; it
-//               will persist at least until remove_window() is called
-//               later.
-//
-//               This usually returns a ParasiteBuffer object, but it
-//               may actually return a GraphicsWindow if show-buffers
-//               is configured true.
-////////////////////////////////////////////////////////////////////
-GraphicsOutput *GraphicsEngine::
-make_parasite(GraphicsOutput *host, const string &name, 
-              int sort, int x_size, int y_size) {
-  GraphicsStateGuardian *gsg = host->get_gsg();
-
-  // I'll remove this permanently in a few days. - Josh
-  //  if (show_buffers) {
-  //    GraphicsWindow *window = make_window(gsg, name, sort);
-  //    if (window != (GraphicsWindow *)NULL) {
-  //      WindowProperties props;
-  //      props.set_size(x_size, y_size);
-  //      props.set_fixed_size(true);
-  //      props.set_title(name);
-  //      window->request_properties(props);
-  //
-  //      return window;
-  //    }
-  //  }
-
-  GraphicsThreadingModel threading_model = get_threading_model();
-  nassertr(gsg != (GraphicsStateGuardian *)NULL, NULL);
-  nassertr(this == gsg->get_engine(), NULL);
-  nassertr(threading_model.get_draw_name() ==
-           gsg->get_threading_model().get_draw_name(), NULL);
-
-  ParasiteBuffer *buffer = new ParasiteBuffer(host, name, x_size, y_size);
-  buffer->_sort = sort;
-  do_add_window(buffer, gsg, threading_model);
+  // Ask the pipe to create a window.
+  
+  for (int retry=0; retry<10; retry++) {
+    PT(GraphicsOutput) window = 
+      pipe->make_output(name, 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) {
+        return window;
+      }
+      open_windows();
+      if (window->is_valid()) {
+        return window;
+      }
+      // No good; delete the window and keep trying.
+      bool removed = remove_window(window);
+      nassertr(removed, NULL);
+    }
+  }
+  
+  // Parasite buffers were not preferred, but the pipe could not
+  // create a window to the user's specs.  Try a parasite as a
+  // last hope.
+  
+  if (can_use_parasite) {
+    if (x_size > host->get_x_size()) {
+      x_size = Texture::down_to_power_2(host->get_x_size());
+    }
+    if (y_size > host->get_y_size()) {
+      y_size = Texture::down_to_power_2(host->get_y_size());
+    }
+    ParasiteBuffer *buffer = new ParasiteBuffer(host, name, x_size, y_size, flags);
+    buffer->_sort = sort;
+    do_add_window(buffer, gsg, threading_model);
+    return buffer;
+  }
 
-  return buffer;
+  // Could not create a window to the user's specs.
+  
+  return NULL;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1100,8 +1140,8 @@ draw_bins(GraphicsOutput *win, DisplayRegion *dr) {
 //     Function: GraphicsEngine::make_contexts
 //       Access: Private
 //  Description: Called in the draw thread, this calls make_context()
-//               on each window on the list to guarantee its graphics
-//               context gets created.
+//               on each window on the list to guarantee its gsg and
+//               graphics context both get created.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
 make_contexts(const GraphicsEngine::Windows &wlist) {
@@ -1429,7 +1469,8 @@ do_draw(CullResult *cull_result, SceneSetup *scene_setup,
 //  Description: An internal function called by make_window() and
 //               make_buffer() and similar functions to add the
 //               newly-created GraphicsOutput object to the engine's
-//               tables.
+//               list of windows, and to request that the window be
+//               opened.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
 do_add_window(GraphicsOutput *window, GraphicsStateGuardian *gsg,
@@ -1477,6 +1518,7 @@ do_add_window(GraphicsOutput *window, GraphicsStateGuardian *gsg,
   window->request_open();
 }
 
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::do_remove_window
 //       Access: Private

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

@@ -72,18 +72,29 @@ 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);
-
-  GraphicsWindow *make_window(GraphicsStateGuardian *gsg, const string &name,
-                              int sort);
-  GraphicsOutput *make_buffer(GraphicsStateGuardian *gsg, const string &name,
-                              int sort, int x_size, int y_size);
-  GraphicsOutput *make_parasite(GraphicsOutput *host, const string &name,
-                                int sort, int x_size, int y_size);
-
+  
+  GraphicsOutput *make_output(GraphicsPipe *pipe,
+                              const string &name, int sort,
+                              const FrameBufferProperties &prop,
+                              int x_size, int y_size, int flags,
+                              GraphicsStateGuardian *gsg = 0,
+                              GraphicsOutput *host = 0);
+  
+  // Syntactic shorthand versions of make_output
+  INLINE GraphicsWindow *make_window(GraphicsStateGuardian *gsg,
+                                     const string &name, int sort);
+  INLINE GraphicsOutput *make_buffer(GraphicsStateGuardian *gsg,
+                                     const string &name, int sort,
+                                     int x_size, int y_size);
+  INLINE GraphicsOutput *make_parasite(GraphicsOutput *host,
+                                       const string &name, int sort,
+                                       int x_size, int y_size);
+  
   bool remove_window(GraphicsOutput *window);
   void remove_all_windows();
   void reset_all_windows(bool swapchain);
@@ -282,9 +293,9 @@ private:
     Windows _draw;    // draw stage
     Windows _window;  // window stage, i.e. process windowing events 
 
-    // These two are not kept sorted.
-    Windows _pending_release; // moved from _draw, pending release_gsg.
-    Windows _pending_close;   // moved from _window, pending close.
+    // These are not kept sorted.
+    Windows _pending_release;  // moved from _draw, pending release_gsg.
+    Windows _pending_close;    // moved from _window, pending close.
 
     GSGs _gsgs;       // draw stage
 

+ 27 - 118
panda/src/display/graphicsOutput.cxx

@@ -69,17 +69,22 @@ static CubeFaceDef cube_faces[6] = {
 //               GraphicsEngine::make_window() function.
 ////////////////////////////////////////////////////////////////////
 GraphicsOutput::
-GraphicsOutput(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-               const string &name) {
+GraphicsOutput(GraphicsPipe *pipe,
+               const string &name,
+               int x_size, int y_size, int flags,
+               GraphicsStateGuardian *gsg,
+               GraphicsOutput *host) {
 #ifdef DO_MEMORY_USAGE
   MemoryUsage::update_type(this, this);
 #endif
   _pipe = pipe;
   _gsg = gsg;
+  _host = host;
   _name = name;
-  _x_size = 0;
-  _y_size = 0;
-  _has_size = false;
+  _creation_flags = flags;
+  _x_size = x_size;
+  _y_size = y_size;
+  _has_size = false; // Need to look into what this does.
   _is_valid = false;
   _flip_ready = false;
   _cube_map_index = -1;
@@ -99,8 +104,10 @@ GraphicsOutput(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
   if (gsg->get_properties().is_single_buffered()) {
     // Single buffered; we must draw into the front buffer.
     _draw_buffer_type = RenderBuffer::T_front;
+  } else {
+    _draw_buffer_type = RenderBuffer::T_back;
   }
-
+  
   // We start out with one DisplayRegion that covers the whole window,
   // which we may use internally for full-window operations like
   // clear() and get_screenshot().
@@ -242,6 +249,10 @@ add_render_texture(Texture *tex, RenderTextureMode mode) {
   tex->set_x_size(get_x_size());
   tex->set_y_size(get_y_size());
 
+  if ((mode == RTM_bind_or_copy)&&(support_render_texture==0)) {
+    mode = RTM_copy_texture;
+  }
+  
   RenderTexture result;
   result._texture = tex;
   result._rtm_mode = mode;
@@ -670,122 +681,19 @@ get_texture_card() {
 GraphicsOutput *GraphicsOutput::
 make_texture_buffer(const string &name, int x_size, int y_size,
                     Texture *tex, bool to_ram) {
-  GraphicsStateGuardian *gsg = get_gsg();
-  GraphicsEngine *engine = gsg->get_engine();
-  GraphicsOutput *host = get_host();
-
-  // The new buffer should be drawn before this buffer is drawn.  If
-  // the user requires more control than this, he can set the sort
-  // value himself.
-  int sort = get_sort() - 1;
-
-  GraphicsOutput *buffer = NULL;
-
-  if ((x_size == 0) && (y_size == 0)) {
-    // Currently, only parasite buffers support the tracking of the
-    // host window size.  If the user requests this, we have to use a
-    // parasite buffer.
-    buffer = engine->make_parasite(host, name, sort, x_size, y_size);
-    buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_copy_texture);
-    return buffer;
-  }
-
-  // I'll remove this permanently in a few days. - Josh
-  //  if (show_buffers) {
-  //    // If show_buffers is true, just go ahead and call make_buffer(),
-  //    // since it all amounts to the same thing anyway--this will
-  //    // actually create a new GraphicsWindow.
-  //    buffer = engine->make_buffer(gsg, name, sort, x_size, y_size);
-  //    buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_copy_texture);
-  //    return buffer;
-  //  }
 
-  bool allow_bind =
-    (prefer_texture_buffer && support_render_texture &&
-     gsg->get_supports_render_texture() && !to_ram);
-
-  // If the user so indicated in the Config.prc file, try to create a
-  // parasite buffer first.  We can only do this if the requested size
-  // fits within the available framebuffer size.  Also, don't do this
-  // if we want to try using render-to-a-texture mode, since using a
-  // ParasiteButter will preclude that.
-  if (prefer_parasite_buffer && !allow_bind &&
-      (x_size <= host->get_x_size() && y_size <= host->get_y_size())) {
-    buffer = engine->make_parasite(host, name, sort, x_size, y_size);
-    if (buffer != (GraphicsOutput *)NULL) {
-      buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_copy_texture);
-      return buffer;
-    }
-  }
-
-  // Attempt to create a single-buffered offscreen buffer.
-  if (prefer_single_buffer) {
-    FrameBufferProperties sb_props = gsg->get_properties();
-    int orig_mode = sb_props.get_frame_buffer_mode();
-    int sb_mode = (orig_mode & ~FrameBufferProperties::FM_buffer) | FrameBufferProperties::FM_single_buffer;
-    sb_props.set_frame_buffer_mode(sb_mode);
-
-    if (sb_mode != orig_mode) {
-      PT(GraphicsStateGuardian) sb_gsg =
-        engine->make_gsg(gsg->get_pipe(), sb_props, gsg);
-      if (sb_gsg != (GraphicsStateGuardian *)NULL) {
-        buffer = engine->make_buffer(sb_gsg, name, sort, x_size, y_size);
-        if (buffer != (GraphicsOutput *)NULL) {
-          // Check the buffer for goodness.
-          if (allow_bind) {
-            buffer->add_render_texture(tex, RTM_bind_or_copy);
-          } else {
-            buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_copy_texture);
-          }
-          engine->open_windows();
-          if (buffer->is_valid()) {
-            return buffer;
-          }
-
-          // No good; delete the buffer and keep trying.
-          bool removed = engine->remove_window(buffer);
-          nassertr(removed, NULL);
-          buffer = (GraphicsOutput *)NULL;
-        }
-      }
-    }
-  }
-
-  // All right, attempt to create an offscreen buffer, using the same
-  // GSG.  This will be a double-buffered offscreen buffer, if the
-  // source window is double-buffered.
-  buffer = engine->make_buffer(gsg, name, sort, x_size, y_size);
+  GraphicsOutput *buffer = get_gsg()->get_engine()->
+    make_output(get_gsg()->get_pipe(),
+                name, get_sort()-1,
+                get_gsg()->get_properties(),
+                x_size, y_size, GraphicsPipe::BF_refuse_window,
+                get_gsg(), get_host());
+  
   if (buffer != (GraphicsOutput *)NULL) {
-    if (allow_bind) {
-      buffer->add_render_texture(tex, RTM_bind_or_copy);
-    } else {
-      buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_copy_texture);
-    }
-    engine->open_windows();
-    if (buffer->is_valid()) {
-      return buffer;
-    }
-
-    bool removed = engine->remove_window(buffer);
-    nassertr(removed, NULL);
-    buffer = (GraphicsOutput *)NULL;
-  }
-
-  // Looks like we have to settle for a parasite buffer.
-
-  // make sure the size is not bigger than the display buffer by 
-  // continually halving the requested buffer size
-  while (!(x_size <= host->get_x_size() && y_size <= host->get_y_size())) {
-    x_size >>= 1;
-    y_size >>= 1;
-  }
-
-  if (x_size <= host->get_x_size() && y_size <= host->get_y_size()) {
-    buffer = engine->make_parasite(host, name, sort, x_size, y_size);
-    buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_copy_texture);
+    buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_bind_or_copy);
     return buffer;
   }
-
+  
   return NULL;
 }
 
@@ -1271,3 +1179,4 @@ do_determine_display_regions() {
 
   stable_sort(_active_display_regions.begin(), _active_display_regions.end(), IndirectLess<DisplayRegion>());
 }
+

+ 7 - 2
panda/src/display/graphicsOutput.h

@@ -61,8 +61,11 @@ class PNMImage;
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA GraphicsOutput : public TypedWritableReferenceCount, public DrawableRegion {
 protected:
-  GraphicsOutput(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-                 const string &name);
+  GraphicsOutput(GraphicsPipe *pipe, 
+                 const string &name,
+                 int x_size, int y_size, int flags,
+                 GraphicsStateGuardian *gsg,
+                 GraphicsOutput *host);
 
 private:
   GraphicsOutput(const GraphicsOutput &copy);
@@ -221,6 +224,7 @@ protected:
   };
   PT(GraphicsStateGuardian) _gsg;
   PT(GraphicsPipe) _pipe;
+  PT(GraphicsOutput) _host;
   string _name;
   pvector<RenderTexture> _textures;
   bool _flip_ready;
@@ -268,6 +272,7 @@ protected:
   bool _display_regions_stale;
 
 protected:
+  int _creation_flags;
   int _x_size;
   int _y_size;
   bool _has_size;

+ 9 - 15
panda/src/display/graphicsPipe.cxx

@@ -186,25 +186,19 @@ close_gsg(GraphicsStateGuardian *gsg) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: GraphicsPipe::make_window
+//     Function: GraphicsPipe::make_output
 //       Access: Protected, Virtual
 //  Description: Creates a new window on the pipe, if possible.
 ////////////////////////////////////////////////////////////////////
-PT(GraphicsWindow) GraphicsPipe::
-make_window(GraphicsStateGuardian *, const string &) {
+PT(GraphicsOutput) GraphicsPipe::
+make_output(const string &name,
+            int x_size, int y_size, int flags,
+            GraphicsStateGuardian *gsg,
+            GraphicsOutput *host,
+            int retry,
+            bool precertify) {
   display_cat.error()
-    << get_type() << " cannot create onscreen windows.\n";
+    << get_type() << " cannot create buffers or windows.\n";
   return NULL;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsPipe::make_buffer
-//       Access: Protected, Virtual
-//  Description: Creates a new offscreen buffer on the pipe, if possible.
-////////////////////////////////////////////////////////////////////
-PT(GraphicsBuffer) GraphicsPipe::
-make_buffer(GraphicsStateGuardian *, const string &, int, int) {
-  display_cat.error()
-    << get_type() << " cannot create offscreen buffers.\n";
-  return NULL;
-}

+ 48 - 8
panda/src/display/graphicsPipe.h

@@ -73,6 +73,44 @@ PUBLISHED:
     OT_texture_buffer    = 0x0008,
   };
 
+  enum BufferCreationFlags {
+
+    // How many RGBA aux bitplanes do you need?
+    BF_need_aux_rgba_MASK  = 0x00000003,
+    BF_need_0_aux_rgba     = 0x00000000,
+    BF_need_1_aux_rgba     = 0x00000001,
+    BF_need_2_aux_rgba     = 0x00000002,
+    BF_need_3_aux_rgba     = 0x00000003,
+
+    // How many half-float rgba aux bitplanes do you need?
+    // This is not currently implemented.
+    BF_need_aux_hrgba_MASK = 0x0000000C,
+    BF_need_0_aux_hrgba    = 0x00000000,
+    BF_need_1_aux_hrgba    = 0x00000004,
+    BF_need_2_aux_hrgba    = 0x00000008,
+    BF_need_3_aux_hrgba    = 0x0000000C,
+
+    // How many full-float single-channel bitplanes do you need?
+    // This is not currently implemented.
+    BF_need_aux_float_MASK = 0x00000030,
+    BF_need_0_aux_float    = 0x00000000,
+    BF_need_1_aux_float    = 0x00000010,
+    BF_need_2_aux_float    = 0x00000020,
+    BF_need_3_aux_float    = 0x00000040,
+
+    // Flags that control what type of output is returned.
+    BF_refuse_parasite     = 0x00000100,
+    BF_require_parasite    = 0x00000200,
+    BF_refuse_window       = 0x00000400,
+    BF_require_window      = 0x00000800,
+
+    // Miscellaneous control flags.
+    BF_can_bind_color      = 0x00010000, // Need capability: bind the color bitplane to a tex.
+    BF_can_bind_every      = 0x00020000, // Need capability: bind all bitplanes to a tex.
+    BF_size_track_host     = 0x00040000, // Buffer should track the host size.
+    BF_no_new_gsg          = 0x00080000, // Do not create a new gsg, no matter what.
+  };
+
   INLINE bool is_valid() const;
   INLINE int get_supported_types() const;
   INLINE bool supports_type(int flags) const;
@@ -90,18 +128,20 @@ public:
   virtual PT(GraphicsDevice) make_device(void *scrn = NULL);
 
 protected:
-  // The make_window() and make_gsg() interfaces on GraphicsPipe are
+  // 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 gsg.
+  // 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(GraphicsWindow) make_window(GraphicsStateGuardian *gsg, 
-                                         const string &name);
-  virtual PT(GraphicsBuffer) make_buffer(GraphicsStateGuardian *gsg, 
-                                         const string &name,
-                                         int x_size, int y_size);
-
+  
+  virtual PT(GraphicsOutput) make_output(const string &name,
+                                         int x_size, int y_size, int flags,
+                                         GraphicsStateGuardian *gsg,
+                                         GraphicsOutput *host,
+                                         int retry,
+                                         bool precertify);
+  
   Mutex _lock;
 
   bool _is_valid;

+ 8 - 11
panda/src/display/graphicsWindow.cxx

@@ -36,9 +36,12 @@ TypeHandle GraphicsWindow::_type_handle;
 //               GraphicsEngine::make_window() function.
 ////////////////////////////////////////////////////////////////////
 GraphicsWindow::
-GraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg, 
-               const string &name) :
-  GraphicsOutput(pipe, gsg, name)
+GraphicsWindow(GraphicsPipe *pipe,
+               const string &name,
+               int x_size, int y_size, int flags,
+               GraphicsStateGuardian *gsg,
+               GraphicsOutput *host) :
+  GraphicsOutput(pipe, name, x_size, y_size, flags, gsg, host)
 {
 #ifdef DO_MEMORY_USAGE
   MemoryUsage::update_type(this, this);
@@ -46,14 +49,7 @@ GraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
 
   if (display_cat.is_debug()) {
     display_cat.debug()
-      << "Creating new window " << get_name()
-      << " using GSG " << (void *)gsg << "\n";
-  }
-
-  _red_blue_stereo = red_blue_stereo && !_gsg->get_properties().is_stereo();
-  if (_red_blue_stereo) {
-    _left_eye_color_mask = parse_color_mask(red_blue_stereo_colors.get_word(0));
-    _right_eye_color_mask = parse_color_mask(red_blue_stereo_colors.get_word(1));
+      << "Creating new window " << get_name() << "\n";
   }
 
   _properties.set_open(false);
@@ -770,3 +766,4 @@ parse_color_mask(const string &word) {
 
   return result;
 }
+

+ 5 - 2
panda/src/display/graphicsWindow.h

@@ -40,8 +40,11 @@
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA GraphicsWindow : public GraphicsOutput {
 protected:
-  GraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg, 
-                 const string &name);
+  GraphicsWindow(GraphicsPipe *pipe, 
+                 const string &name,
+                 int x_size, int y_size, int flags,
+                 GraphicsStateGuardian *gsg,
+                 GraphicsOutput *host);
 
 PUBLISHED:
   virtual ~GraphicsWindow();

+ 13 - 9
panda/src/display/parasiteBuffer.cxx

@@ -30,9 +30,9 @@ TypeHandle ParasiteBuffer::_type_handle;
 ////////////////////////////////////////////////////////////////////
 ParasiteBuffer::
 ParasiteBuffer(GraphicsOutput *host, const string &name,
-               int x_size, int y_size) :
-  GraphicsOutput(host->get_pipe(), host->get_gsg(), name),
-  _host(host)
+               int x_size, int y_size, int flags) :
+  GraphicsOutput(host->get_pipe(), name, 
+                 x_size, y_size, flags, host->get_gsg(), host)
 {
 #ifdef DO_MEMORY_USAGE
   MemoryUsage::update_type(this, this);
@@ -44,12 +44,11 @@ ParasiteBuffer(GraphicsOutput *host, const string &name,
       << " on " << _host->get_name() << "\n";
   }
 
-  if ((x_size == 0)&&(y_size == 0)) {
-    _track_host_size = true;
+  _creation_flags = flags;
+  
+  if (flags & GraphicsPipe::BF_size_track_host) {
     x_size = host->get_x_size();
     y_size = host->get_y_size();
-  } else {
-    _track_host_size = false;
   }
   
   _x_size = x_size;
@@ -113,14 +112,14 @@ begin_frame(FrameMode mode) {
     return false;
   }
 
-  if (_track_host_size) {
+  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());
     }
   }
-
+  
   clear_cube_map_selection();
   return true;
 }
@@ -145,6 +144,11 @@ end_frame(FrameMode mode) {
   _host->end_frame(FM_parasite);
   
   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;
+      }
+    }
     copy_to_textures();
     if (_one_shot) {
       prepare_for_deletion();

+ 2 - 3
panda/src/display/parasiteBuffer.h

@@ -55,7 +55,7 @@
 class EXPCL_PANDA ParasiteBuffer : public GraphicsOutput {
 public:
   ParasiteBuffer(GraphicsOutput *host, const string &name,
-                 int x_size, int y_size);
+                 int x_size, int y_size, int flags);
   
 PUBLISHED:
   virtual ~ParasiteBuffer();
@@ -68,8 +68,7 @@ public:
   virtual GraphicsOutput *get_host();
   
 private:
-  PT(GraphicsOutput) _host;
-  bool _track_host_size;
+  int _creation_flags;
   
 public:
   static TypeHandle get_class_type() {

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

@@ -41,10 +41,12 @@ TypeHandle wdxGraphicsBuffer8::_type_handle;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 wdxGraphicsBuffer8::
-wdxGraphicsBuffer8(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-                  const string &name,
-                  int x_size, int y_size) :
-  GraphicsBuffer(pipe, gsg, name, x_size, y_size)
+wdxGraphicsBuffer8(GraphicsPipe *pipe,
+                   const string &name,
+                   int x_size, int y_size, int flags,
+                   GraphicsStateGuardian *gsg,
+                   GraphicsOutput *host):
+  GraphicsBuffer(pipe, name, x_size, y_size, flags, gsg, host)
 {
   // initialize all class members
   _cube_map_index = -1;

+ 5 - 3
panda/src/dxgsg8/wdxGraphicsBuffer8.h

@@ -36,9 +36,11 @@
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDADX wdxGraphicsBuffer8 : public GraphicsBuffer {
 public:
-  wdxGraphicsBuffer8(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-                    const string &name,
-                    int x_size, int y_size);
+  wdxGraphicsBuffer8(GraphicsPipe *pipe,
+                     const string &name,
+                     int x_size, int y_size, int flags,
+                     GraphicsStateGuardian *gsg,
+                     GraphicsOutput *host);
   virtual ~wdxGraphicsBuffer8();
 
   virtual bool begin_frame(FrameMode mode);

+ 50 - 25
panda/src/dxgsg8/wdxGraphicsPipe8.cxx

@@ -81,40 +81,65 @@ pipe_constructor() {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: wdxGraphicsPipe8::make_window
+//     Function: wdxGraphicsPipe8::make_output
 //       Access: Protected, Virtual
 //  Description: Creates a new window on the pipe, if possible.
 ////////////////////////////////////////////////////////////////////
-PT(GraphicsWindow) wdxGraphicsPipe8::
-make_window(GraphicsStateGuardian *gsg, const string &name) {
+PT(GraphicsOutput) wdxGraphicsPipe8::
+make_output(const string &name,
+            int x_size, int y_size, int flags,
+            GraphicsStateGuardian *gsg,
+            GraphicsOutput *host,
+            int retry,
+            bool precertify) {
+  
   if (!_is_valid) {
     return NULL;
   }
 
-  // thanks to the dumb threading requirements this constructor
-  // actually does nothing but create an empty c++ object. no windows
-  // are really opened until wdxGraphicsWindow8->open_window() is
-  // called
-  return new wdxGraphicsWindow8(this, gsg, name);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: wdxGraphicsPipe8::make_buffer
-//       Access: Protected, Virtual
-//  Description: Creates a new offscreen buffer on the pipe, if possible.
-////////////////////////////////////////////////////////////////////
-PT(GraphicsBuffer) wdxGraphicsPipe8::
-make_buffer(GraphicsStateGuardian *gsg, const string &name,
-            int x_size, int y_size) {
-
-// hmmmm must return NULL if render to texture is supported and you don't
-// want to use it, otherwise it doesn't work
-  if (support_render_texture && gsg->get_supports_render_texture ( )) {
-    return new wdxGraphicsBuffer8(this, gsg, name, x_size, y_size);
+  DXGraphicsStateGuardian8 *wdxgsg;
+  DCAST_INTO_R(wdxgsg, gsg, NULL);
+
+  
+  // First thing to try: a visible window.
+
+  if (retry == 0) {
+    if (((flags&BF_require_parasite)!=0)||
+        ((flags&BF_refuse_window)!=0)||
+        ((flags&BF_need_aux_rgba_MASK)!=0)||
+        ((flags&BF_need_aux_hrgba_MASK)!=0)||
+        ((flags&BF_need_aux_float_MASK)!=0)||
+        ((flags&BF_size_track_host)!=0)||
+        ((flags&BF_can_bind_color)!=0)||
+        ((flags&BF_can_bind_every)!=0)) {
+      return NULL;
+    }
+    return new wdxGraphicsWindow8(this, name, x_size, y_size, flags, gsg, host);
   }
-  else {
-    return NULL;
+  
+  // Second thing to try: a wdxGraphicsBuffer8
+
+  if (retry == 1) {
+    if ((!support_render_texture)||
+        ((flags&BF_require_parasite)!=0)||
+        ((flags&BF_require_window)!=0)||
+        ((flags&BF_need_aux_rgba_MASK)!=0)||
+        ((flags&BF_need_aux_hrgba_MASK)!=0)||
+        ((flags&BF_need_aux_float_MASK)!=0)||
+        ((flags&BF_size_track_host)!=0)||
+        ((flags&BF_can_bind_every)!=0)) {
+      return NULL;
+    }
+    if (precertify) {
+      if (!gsg->get_supports_render_texture()) {
+        return NULL;
+      }
+    }
+    return new wdxGraphicsBuffer8(this, name, x_size, y_size, flags, gsg, host);
   }
+  
+  // Nothing else left to try.
+  return NULL;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 6 - 3
panda/src/dxgsg8/wdxGraphicsPipe8.h

@@ -58,9 +58,12 @@ public:
    bool special_check_fullscreen_resolution(DXScreenData &scrn, UINT x_size,UINT y_size);
 
 protected:
-  virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg, const string &name);
-  virtual PT(GraphicsBuffer) make_buffer(GraphicsStateGuardian *gsg, const string &name,
-            int x_size, int y_size);
+  virtual PT(GraphicsOutput) make_output(const string &name,
+                                         int x_size, int y_size, int flags,
+                                         GraphicsStateGuardian *gsg,
+                                         GraphicsOutput *host,
+                                         int retry,
+                                         bool precertify);
 
 private:
   bool init();

+ 6 - 3
panda/src/dxgsg8/wdxGraphicsWindow8.cxx

@@ -39,9 +39,12 @@ TypeHandle wdxGraphicsWindow8::_type_handle;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 wdxGraphicsWindow8::
-wdxGraphicsWindow8(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-                   const string &name) :
-  WinGraphicsWindow(pipe, gsg, name)
+wdxGraphicsWindow8(GraphicsPipe *pipe,
+                   const string &name,
+                   int x_size, int y_size, int flags,
+                   GraphicsStateGuardian *gsg,
+                   GraphicsOutput *host):
+  WinGraphicsWindow(pipe, name, x_size, y_size, flags, gsg, host)
 {
   // dont actually create the window in the constructor.  reason:
   // multi-threading requires panda C++ window object to exist in

+ 5 - 2
panda/src/dxgsg8/wdxGraphicsWindow8.h

@@ -34,8 +34,11 @@ class wdxGraphicsPipe8;
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDADX wdxGraphicsWindow8 : public WinGraphicsWindow {
 public:
-  wdxGraphicsWindow8(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-                     const string &name);
+  wdxGraphicsWindow8(GraphicsPipe *pipe,
+                     const string &name,
+                     int x_size, int y_size, int flags,
+                     GraphicsStateGuardian *gsg,
+                     GraphicsOutput *host);
   virtual ~wdxGraphicsWindow8();
 
   virtual bool begin_frame(FrameMode mode);

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

@@ -38,10 +38,12 @@ TypeHandle wdxGraphicsBuffer9::_type_handle;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 wdxGraphicsBuffer9::
-wdxGraphicsBuffer9(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-                  const string &name,
-                  int x_size, int y_size) :
-  GraphicsBuffer(pipe, gsg, name, x_size, y_size)
+wdxGraphicsBuffer9(GraphicsPipe *pipe,
+                   const string &name,
+                   int x_size, int y_size, int flags,
+                   GraphicsStateGuardian *gsg,
+                   GraphicsOutput *host):
+  GraphicsBuffer(pipe, name, x_size, y_size, flags, gsg, host)
 {
   // initialize all class members
   _cube_map_index = -1;

+ 5 - 3
panda/src/dxgsg9/wdxGraphicsBuffer9.h

@@ -36,9 +36,11 @@
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDADX wdxGraphicsBuffer9 : public GraphicsBuffer {
 public:
-  wdxGraphicsBuffer9(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-                    const string &name,
-                    int x_size, int y_size);
+  wdxGraphicsBuffer9(GraphicsPipe *pipe,
+                     const string &name,
+                     int x_size, int y_size, int flags,
+                     GraphicsStateGuardian *gsg,
+                     GraphicsOutput *host);
   virtual ~wdxGraphicsBuffer9();
 
   virtual bool begin_frame(FrameMode mode);

+ 51 - 25
panda/src/dxgsg9/wdxGraphicsPipe9.cxx

@@ -81,39 +81,65 @@ pipe_constructor() {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: wdxGraphicsPipe9::make_window
+//     Function: wdxGraphicsPipe9::make_output
 //       Access: Protected, Virtual
 //  Description: Creates a new window on the pipe, if possible.
 ////////////////////////////////////////////////////////////////////
-PT(GraphicsWindow) wdxGraphicsPipe9::
-make_window(GraphicsStateGuardian *gsg, const string &name) {
+PT(GraphicsOutput) wdxGraphicsPipe9::
+make_output(const string &name,
+            int x_size, int y_size, int flags,
+            GraphicsStateGuardian *gsg,
+            GraphicsOutput *host,
+            int retry,
+            bool precertify) {
+  
   if (!_is_valid) {
     return NULL;
   }
 
-  // thanks to the dumb threading requirements this constructor
-  // actually does nothing but create an empty c++ object. no windows
-  // are really opened until wdxGraphicsWindow9->open_window() is
-  // called
-  return new wdxGraphicsWindow9(this, gsg, name);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: wdxGraphicsPipe9::make_buffer
-//       Access: Protected, Virtual
-//  Description: Creates a new offscreen buffer on the pipe, if possible.
-////////////////////////////////////////////////////////////////////
-PT(GraphicsBuffer) wdxGraphicsPipe9::
-make_buffer(GraphicsStateGuardian *gsg, const string &name,
-            int x_size, int y_size) {
-
-  //  if (support_render_texture && gsg->get_supports_render_texture ( )) {
-    return new wdxGraphicsBuffer9(this, gsg, name, x_size, y_size);
-    /*  }
-  else {
-    return NULL;
+  DXGraphicsStateGuardian9 *wdxgsg;
+  DCAST_INTO_R(wdxgsg, gsg, NULL);
+
+  
+  // First thing to try: a visible window.
+
+  if (retry == 0) {
+    if (((flags&BF_require_parasite)!=0)||
+        ((flags&BF_refuse_window)!=0)||
+        ((flags&BF_need_aux_rgba_MASK)!=0)||
+        ((flags&BF_need_aux_hrgba_MASK)!=0)||
+        ((flags&BF_need_aux_float_MASK)!=0)||
+        ((flags&BF_size_track_host)!=0)||
+        ((flags&BF_can_bind_color)!=0)||
+        ((flags&BF_can_bind_every)!=0)) {
+      return NULL;
+    }
+    return new wdxGraphicsWindow9(this, name, x_size, y_size, flags, gsg, host);
+  }
+  
+  // Second thing to try: a wdxGraphicsBuffer9
+
+  if (retry == 1) {
+    if ((!support_render_texture)||
+        ((flags&BF_require_parasite)!=0)||
+        ((flags&BF_require_window)!=0)||
+        ((flags&BF_need_aux_rgba_MASK)!=0)||
+        ((flags&BF_need_aux_hrgba_MASK)!=0)||
+        ((flags&BF_need_aux_float_MASK)!=0)||
+        ((flags&BF_size_track_host)!=0)||
+        ((flags&BF_can_bind_every)!=0)) {
+      return NULL;
+    }
+    if (precertify) {
+      if (!gsg->get_supports_render_texture()) {
+        return NULL;
+      }
+    }
+    return new wdxGraphicsBuffer9(this, name, x_size, y_size, flags, gsg, host);
   }
-    */
+  
+  // Nothing else left to try.
+  return NULL;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 7 - 3
panda/src/dxgsg9/wdxGraphicsPipe9.h

@@ -58,9 +58,13 @@ public:
    bool special_check_fullscreen_resolution(DXScreenData &scrn, UINT x_size,UINT y_size);
 
 protected:
-  virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg, const string &name);
-  virtual PT(GraphicsBuffer) make_buffer(GraphicsStateGuardian *gsg, const string &name,
-            int x_size, int y_size);
+  virtual PT(GraphicsOutput) make_output(const string &name,
+                                         int x_size, int y_size, int flags,
+                                         GraphicsStateGuardian *gsg,
+                                         GraphicsOutput *host,
+                                         int retry,
+                                         bool precertify);
+
 private:
   bool init();
   bool find_all_card_memavails();

+ 6 - 3
panda/src/dxgsg9/wdxGraphicsWindow9.cxx

@@ -39,9 +39,12 @@ TypeHandle wdxGraphicsWindow9::_type_handle;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 wdxGraphicsWindow9::
-wdxGraphicsWindow9(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-                   const string &name) :
-  WinGraphicsWindow(pipe, gsg, name)
+wdxGraphicsWindow9(GraphicsPipe *pipe,
+                   const string &name,
+                   int x_size, int y_size, int flags,
+                   GraphicsStateGuardian *gsg,
+                   GraphicsOutput *host):
+  WinGraphicsWindow(pipe, name, x_size, y_size, flags, gsg, host)
 {
   // dont actually create the window in the constructor.  reason:
   // multi-threading requires panda C++ window object to exist in

+ 5 - 2
panda/src/dxgsg9/wdxGraphicsWindow9.h

@@ -34,8 +34,11 @@ class wdxGraphicsPipe9;
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDADX wdxGraphicsWindow9 : public WinGraphicsWindow {
 public:
-  wdxGraphicsWindow9(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-                     const string &name);
+  wdxGraphicsWindow9(GraphicsPipe *pipe,
+                     const string &name,
+                     int x_size, int y_size, int flags,
+                     GraphicsStateGuardian *gsg,
+                     GraphicsOutput *host);
   virtual ~wdxGraphicsWindow9();
 
   virtual bool begin_frame(FrameMode mode);

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

@@ -37,10 +37,12 @@ TypeHandle glxGraphicsBuffer::_type_handle;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 glxGraphicsBuffer::
-glxGraphicsBuffer(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
+glxGraphicsBuffer(GraphicsPipe *pipe, 
                   const string &name,
-                  int x_size, int y_size) :
-  GraphicsBuffer(pipe, gsg, name, x_size, y_size) 
+                  int x_size, int y_size, int flags,
+                  GraphicsStateGuardian *gsg,
+                  GraphicsOutput *host) :
+  GraphicsBuffer(pipe, name, x_size, y_size, flags, gsg, host)
 {
   glxGraphicsPipe *glx_pipe;
   DCAST_INTO_V(glx_pipe, _pipe);

+ 4 - 3
panda/src/glxdisplay/glxGraphicsBuffer.h

@@ -35,10 +35,11 @@
 ////////////////////////////////////////////////////////////////////
 class glxGraphicsBuffer : public GraphicsBuffer {
 public:
-  glxGraphicsBuffer(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
+  glxGraphicsBuffer(GraphicsPipe *pipe, 
                     const string &name,
-                    int x_size, int y_size);
-
+                    int x_size, int y_size, int flags,
+                    GraphicsStateGuardian *gsg,
+                    GraphicsOutput *host);
   virtual ~glxGraphicsBuffer();
 
   virtual bool begin_frame(FrameMode mode);

+ 61 - 19
panda/src/glxdisplay/glxGraphicsPipe.cxx

@@ -269,38 +269,80 @@ make_gsg(const FrameBufferProperties &properties,
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: glxGraphicsPipe::make_window
+//     Function: glxGraphicsPipe::make_output
 //       Access: Protected, Virtual
 //  Description: Creates a new window on the pipe, if possible.
 ////////////////////////////////////////////////////////////////////
-PT(GraphicsWindow) glxGraphicsPipe::
-make_window(GraphicsStateGuardian *gsg, const string &name) {
+PT(GraphicsOutput) glxGraphicsPipe::
+make_output(const string &name,
+            int x_size, int y_size, int flags,
+            GraphicsStateGuardian *gsg,
+            GraphicsOutput *host,
+            int retry,
+            bool precertify) {
+  
   if (!_is_valid) {
     return NULL;
   }
 
-  return new glxGraphicsWindow(this, gsg, name);
-}
+  glxGraphicsStateGuardian *glxgsg;
+  DCAST_INTO_R(glxgsg, gsg, NULL);
 
-////////////////////////////////////////////////////////////////////
-//     Function: glxGraphicsPipe::make_buffer
-//       Access: Protected, Virtual
-//  Description: Creates a new offscreen buffer on the pipe, if possible.
-////////////////////////////////////////////////////////////////////
-PT(GraphicsBuffer) glxGraphicsPipe::
-make_buffer(GraphicsStateGuardian *gsg, const string &name,
-            int x_size, int y_size) {
-  if (!_is_valid) {
-    return NULL;
-  }
+  // First thing to try: a glxGraphicsWindow
 
+  if (retry == 0) {
+    if (((flags&BF_require_parasite)!=0)||
+        ((flags&BF_refuse_window)!=0)||
+        ((flags&BF_need_aux_rgba_MASK)!=0)||
+        ((flags&BF_need_aux_hrgba_MASK)!=0)||
+        ((flags&BF_need_aux_float_MASK)!=0)||
+        ((flags&BF_size_track_host)!=0)||
+        ((flags&BF_can_bind_color)!=0)||
+        ((flags&BF_can_bind_every)!=0)) {
+      return NULL;
+    }
+    return new glxGraphicsWindow(this, 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, x_size, y_size, flags, gsg, host);
+  //  }
+  
 #ifdef HAVE_GLXFBCONFIG
-  return new glxGraphicsBuffer(this, gsg, name, x_size, y_size);
-#else
-  return NULL;
+  // Third thing to try: a glxGraphicsBuffer
+  
+  if (retry == 2) {
+    if ((!support_render_texture)||
+        ((flags&BF_require_parasite)!=0)||
+        ((flags&BF_require_window)!=0)||
+        ((flags&BF_need_aux_rgba_MASK)!=0)||
+        ((flags&BF_need_aux_hrgba_MASK)!=0)||
+        ((flags&BF_need_aux_float_MASK)!=0)||
+        ((flags&BF_size_track_host)!=0)||
+        ((flags&BF_can_bind_every)!=0)) {
+      return NULL;
+    }
+    return new glxGraphicsBuffer(this, name, x_size, y_size, flags, gsg, host);
+  }
 #endif  // HAVE_GLXFBCONFIG
+  
+  // Nothing else left to try.
+  return NULL;
 }
 
+
 #ifdef HAVE_GLXFBCONFIG
 ////////////////////////////////////////////////////////////////////
 //     Function: glxGraphicsPipe::choose_fbconfig

+ 6 - 5
panda/src/glxdisplay/glxGraphicsPipe.h

@@ -113,11 +113,12 @@ public:
 protected:
   virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
                                              GraphicsStateGuardian *share_with);
-  virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg,
-                                         const string &name);
-  virtual PT(GraphicsBuffer) make_buffer(GraphicsStateGuardian *gsg, 
-                                         const string &name,
-                                         int x_size, int y_size);
+  virtual PT(GraphicsOutput) make_output(const string &name,
+                                         int x_size, int y_size, int flags,
+                                         GraphicsStateGuardian *gsg,
+                                         GraphicsOutput *host,
+                                         int retry,
+                                         bool precertify);
 
 private:
 #ifdef HAVE_GLXFBCONFIG

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

@@ -44,9 +44,12 @@ TypeHandle glxGraphicsWindow::_type_handle;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 glxGraphicsWindow::
-glxGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-                  const string &name) :
-  GraphicsWindow(pipe, gsg, name) 
+glxGraphicsWindow(GraphicsPipe *pipe, 
+                  const string &name,
+                  int x_size, int y_size, int flags,
+                  GraphicsStateGuardian *gsg,
+                  GraphicsOutput *host) :
+  GraphicsWindow(pipe, name, x_size, y_size, flags, gsg, host)
 {
   glxGraphicsPipe *glx_pipe;
   DCAST_INTO_V(glx_pipe, _pipe);

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

@@ -32,8 +32,11 @@
 ////////////////////////////////////////////////////////////////////
 class glxGraphicsWindow : public GraphicsWindow {
 public:
-  glxGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-                    const string &name);
+  glxGraphicsWindow(GraphicsPipe *pipe, 
+                    const string &name,
+                    int x_size, int y_size, int flags,
+                    GraphicsStateGuardian *gsg,
+                    GraphicsOutput *host);
   virtual ~glxGraphicsWindow();
 
   virtual bool move_pointer(int device, int x, int y);

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

@@ -29,10 +29,12 @@ TypeHandle OsMesaGraphicsBuffer::_type_handle;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 OsMesaGraphicsBuffer::
-OsMesaGraphicsBuffer(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-                     const string &name,
-                     int x_size, int y_size) :
-  GraphicsBuffer(pipe, gsg, name, x_size, y_size)
+OsMesaGraphicsBuffer(GraphicsPipe *pipe,
+                  const string &name,
+                  int x_size, int y_size, int flags,
+                  GraphicsStateGuardian *gsg,
+                  GraphicsOutput *host) :
+  GraphicsBuffer(pipe, name, x_size, y_size, flags, gsg, host)
 {
   _type = GL_UNSIGNED_BYTE;
 }

+ 4 - 3
panda/src/mesadisplay/osMesaGraphicsBuffer.h

@@ -32,10 +32,11 @@
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDAMESA OsMesaGraphicsBuffer : public GraphicsBuffer {
 public:
-  OsMesaGraphicsBuffer(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
+  OsMesaGraphicsBuffer(GraphicsPipe *pipe, 
                        const string &name,
-                       int x_size, int y_size);
-
+                       int x_size, int y_size, int flags,
+                       GraphicsStateGuardian *gsg,
+                       GraphicsOutput *host);
   virtual ~OsMesaGraphicsBuffer();
 
   virtual bool begin_frame(FrameMode mode);

+ 32 - 6
panda/src/mesadisplay/osMesaGraphicsPipe.cxx

@@ -119,12 +119,38 @@ make_gsg(const FrameBufferProperties &properties,
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: OsMesaGraphicsPipe::make_buffer
+//     Function: OsMesaGraphicsPipe::make_output
 //       Access: Protected, Virtual
-//  Description: Creates a new offscreen buffer on the pipe, if possible.
+//  Description: Creates a new window on the pipe, if possible.
 ////////////////////////////////////////////////////////////////////
-PT(GraphicsBuffer) OsMesaGraphicsPipe::
-make_buffer(GraphicsStateGuardian *gsg, const string &name,
-            int x_size, int y_size) {
-  return new OsMesaGraphicsBuffer(this, gsg, name, x_size, y_size);
+PT(GraphicsOutput) OsMesaGraphicsPipe::
+make_output(const string &name,
+            int x_size, int y_size, int flags,
+            GraphicsStateGuardian *gsg,
+            GraphicsOutput *host,
+            int retry,
+            bool precertify) {
+  
+  if (!_is_valid) {
+    return NULL;
+  }
+  
+  // First thing to try: an OsMesaGraphicsBuffer
+
+  if (retry == 0) {
+    if ((!support_render_texture)||
+        ((flags&BF_require_parasite)!=0)||
+        ((flags&BF_require_window)!=0)||
+        ((flags&BF_need_aux_rgba_MASK)!=0)||
+        ((flags&BF_need_aux_hrgba_MASK)!=0)||
+        ((flags&BF_need_aux_float_MASK)!=0)||
+        ((flags&BF_size_track_host)!=0)||
+        ((flags&BF_can_bind_every)!=0)) {
+      return NULL;
+    }
+    return new OsMesaGraphicsBuffer(this, name, x_size, y_size, flags, gsg, host);
+  }
+  
+  // Nothing else left to try.
+  return NULL;
 }

+ 6 - 3
panda/src/mesadisplay/osMesaGraphicsPipe.h

@@ -48,9 +48,12 @@ public:
 protected:
   virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
                                              GraphicsStateGuardian *share_with);
-  virtual PT(GraphicsBuffer) make_buffer(GraphicsStateGuardian *gsg, 
-                                         const string &name,
-                                         int x_size, int y_size);
+  virtual PT(GraphicsOutput) make_output(const string &name,
+                                         int x_size, int y_size, int flags,
+                                         GraphicsStateGuardian *gsg,
+                                         GraphicsOutput *host,
+                                         int retry,
+                                         bool precertify);
 
 private:
 

+ 5 - 3
panda/src/wgldisplay/wglGraphicsBuffer.cxx

@@ -33,10 +33,12 @@ TypeHandle wglGraphicsBuffer::_type_handle;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 wglGraphicsBuffer::
-wglGraphicsBuffer(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
+wglGraphicsBuffer(GraphicsPipe *pipe,
                   const string &name,
-                  int x_size, int y_size) :
-  GraphicsBuffer(pipe, gsg, name, x_size, y_size) 
+                  int x_size, int y_size, int flags,
+                  GraphicsStateGuardian *gsg,
+                  GraphicsOutput *host) :
+  GraphicsBuffer(pipe, name, x_size, y_size, flags, gsg, host)
 {
   _pbuffer = (HPBUFFERARB)0;
   _pbuffer_dc = (HDC)0;

+ 4 - 2
panda/src/wgldisplay/wglGraphicsBuffer.h

@@ -41,9 +41,11 @@
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDAGL wglGraphicsBuffer : public GraphicsBuffer {
 public:
-  wglGraphicsBuffer(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
+  wglGraphicsBuffer(GraphicsPipe *pipe, 
                     const string &name,
-                    int x_size, int y_size);
+                    int x_size, int y_size, int flags,
+                    GraphicsStateGuardian *gsg,
+                    GraphicsOutput *host);
   virtual ~wglGraphicsBuffer();
 
   virtual bool begin_frame(FrameMode mode);

+ 74 - 16
panda/src/wgldisplay/wglGraphicsPipe.cxx

@@ -73,7 +73,7 @@ pipe_constructor() {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: wglGraphicsPipe::make_gsg
-//       Access: Protected, Virtual
+//       Access: Private
 //  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.
@@ -190,26 +190,84 @@ make_gsg(const FrameBufferProperties &properties,
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: wglGraphicsPipe::make_window
+//     Function: wglGraphicsPipe::make_output
 //       Access: Protected, Virtual
-//  Description: Creates a new window on the pipe, if possible.
+//  Description: Creates a new window or buffer on the pipe, if possible.
+//               This routine is only called from GraphicsEngine::make_output.
 ////////////////////////////////////////////////////////////////////
-PT(GraphicsWindow) wglGraphicsPipe::
-make_window(GraphicsStateGuardian *gsg, const string &name) {
-  return new wglGraphicsWindow(this, gsg, name);
-}
+PT(GraphicsOutput) wglGraphicsPipe::
+make_output(const string &name,
+            int x_size, int y_size, int flags,
+            GraphicsStateGuardian *gsg,
+            GraphicsOutput *host,
+            int retry,
+            bool precertify) {
+  
+  if (!_is_valid) {
+    return NULL;
+  }
 
-////////////////////////////////////////////////////////////////////
-//     Function: wglGraphicsPipe::make_buffer
-//       Access: Protected, Virtual
-//  Description: Creates a new offscreen buffer on the pipe, if possible.
-////////////////////////////////////////////////////////////////////
-PT(GraphicsBuffer) wglGraphicsPipe::
-make_buffer(GraphicsStateGuardian *gsg, const string &name,
-            int x_size, int y_size) {
-  return new wglGraphicsBuffer(this, gsg, name, x_size, y_size);
+  wglGraphicsStateGuardian *wglgsg;
+  DCAST_INTO_R(wglgsg, gsg, NULL);
+
+  // First thing to try: a wglGraphicsWindow
+
+  if (retry == 0) {
+    if (((flags&BF_require_parasite)!=0)||
+        ((flags&BF_refuse_window)!=0)||
+        ((flags&BF_need_aux_rgba_MASK)!=0)||
+        ((flags&BF_need_aux_hrgba_MASK)!=0)||
+        ((flags&BF_need_aux_float_MASK)!=0)||
+        ((flags&BF_size_track_host)!=0)||
+        ((flags&BF_can_bind_color)!=0)||
+        ((flags&BF_can_bind_every)!=0)) {
+      return NULL;
+    }
+    return new wglGraphicsWindow(this, 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 (!wglgsg->_supports_framebuffer_object) {
+  //        return NULL;
+  //      }
+  //    }
+  //    return new glGraphicsBuffer(this, name, x_size, y_size, flags, gsg, host);
+  //  }
+  
+  // Third thing to try: a wglGraphicsBuffer
+  
+  if (retry == 2) {
+    if ((!support_render_texture)||
+        ((flags&BF_require_parasite)!=0)||
+        ((flags&BF_require_window)!=0)||
+        ((flags&BF_need_aux_rgba_MASK)!=0)||
+        ((flags&BF_need_aux_hrgba_MASK)!=0)||
+        ((flags&BF_need_aux_float_MASK)!=0)||
+        ((flags&BF_size_track_host)!=0)||
+        ((flags&BF_can_bind_every)!=0)) {
+      return NULL;
+    }
+    if (precertify) {
+      if (!wglgsg->_supports_pbuffer) {
+        return NULL;
+      }
+    }
+    return new wglGraphicsBuffer(this, name, x_size, y_size, flags, gsg, host);
+  }
+  
+  // Nothing else left to try.
+  return NULL;
 }
 
+
 ////////////////////////////////////////////////////////////////////
 //     Function: wglGraphicsPipe::choose_pfnum
 //       Access: Private, Static

+ 10 - 6
panda/src/wgldisplay/wglGraphicsPipe.h

@@ -39,14 +39,17 @@ public:
   static PT(GraphicsPipe) pipe_constructor();
 
 protected:
-  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
+  virtual PT(GraphicsOutput) make_output(const string &name,
+                                         int x_size, int y_size, int flags,
+                                         GraphicsStateGuardian *gsg,
+                                         GraphicsOutput *host,
+                                         int retry,
+                                         bool precertify);
+  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties, 
                                              GraphicsStateGuardian *share_with);
-  virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg,
-                                         const string &name);
-  virtual PT(GraphicsBuffer) make_buffer(GraphicsStateGuardian *gsg, 
-                                         const string &name,
-                                         int x_size, int y_size);
+
 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,
@@ -88,6 +91,7 @@ private:
   static TypeHandle _type_handle;
 
   friend class wglGraphicsBuffer;
+  friend class wglGraphicsWindow;
 };
 
 #include "wglGraphicsPipe.I"

+ 6 - 3
panda/src/wgldisplay/wglGraphicsWindow.cxx

@@ -131,9 +131,12 @@ GetAvailVidMem() {
 //  Description:
 ////////////////////////////////////////////////////////////////////
 wglGraphicsWindow::
-wglGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-                  const string &name) :
-  WinGraphicsWindow(pipe, gsg, name) 
+wglGraphicsWindow(GraphicsPipe *pipe, 
+                  const string &name,
+                  int x_size, int y_size, int flags,
+                  GraphicsStateGuardian *gsg,
+                  GraphicsOutput *host) :
+  WinGraphicsWindow(pipe, name, x_size, y_size, flags, gsg, host)
 {
   _hdc = (HDC)0;
 }

+ 5 - 2
panda/src/wgldisplay/wglGraphicsWindow.h

@@ -29,8 +29,11 @@
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDAGL wglGraphicsWindow : public WinGraphicsWindow {
 public:
-  wglGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-                    const string &name);
+  wglGraphicsWindow(GraphicsPipe *pipe, 
+                    const string &name,
+                    int x_size, int y_size, int flags,
+                    GraphicsStateGuardian *gsg,
+                    GraphicsOutput *host);
   virtual ~wglGraphicsWindow();
 
   virtual bool begin_frame(FrameMode mode);

+ 6 - 3
panda/src/windisplay/winGraphicsWindow.cxx

@@ -80,9 +80,12 @@ static tRegisterRawInputDevices  pRegisterRawInputDevices;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 WinGraphicsWindow::
-WinGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-                  const string &name) :
-  GraphicsWindow(pipe, gsg, name) 
+WinGraphicsWindow(GraphicsPipe *pipe,
+                  const string &name,
+                  int x_size, int y_size, int flags,
+                  GraphicsStateGuardian *gsg,
+                  GraphicsOutput *host) : 
+  GraphicsWindow(pipe, name, x_size, y_size, flags, gsg, host)
 {
   initialize_input_devices();
   _hWnd = (HWND)0;

+ 5 - 2
panda/src/windisplay/winGraphicsWindow.h

@@ -41,8 +41,11 @@ class WinGraphicsPipe;
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDAWIN WinGraphicsWindow : public GraphicsWindow {
 public:
-  WinGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
-                    const string &name);
+  WinGraphicsWindow(GraphicsPipe *pipe,
+                    const string &name,
+                    int x_size, int y_size, int flags,
+                    GraphicsStateGuardian *gsg,
+                    GraphicsOutput *host);
   virtual ~WinGraphicsWindow();
 
   virtual bool move_pointer(int device, int x, int y);