Browse Source

add GraphicsOutput::sort

David Rose 22 years ago
parent
commit
c26166c9cc

+ 2 - 2
direct/src/showbase/ShowBase.py

@@ -380,10 +380,10 @@ class ShowBase(DirectObject.DirectObject):
         # Temporary try .. except for old Pandas.
         # Temporary try .. except for old Pandas.
         try:
         try:
             if type == 'onscreen':
             if type == 'onscreen':
-                win = self.graphicsEngine.makeWindow(gsg, name)
+                win = self.graphicsEngine.makeWindow(gsg, name, 0)
             elif type == 'offscreen':
             elif type == 'offscreen':
                 win = self.graphicsEngine.makeBuffer(
                 win = self.graphicsEngine.makeBuffer(
-                    gsg, name, props.getXSize(), props.getYSize(), 0)
+                    gsg, name, 0, props.getXSize(), props.getYSize(), 0)
         except:
         except:
             if type == 'onscreen':
             if type == 'onscreen':
                 win = self.graphicsEngine.makeWindow(pipe, gsg)
                 win = self.graphicsEngine.makeWindow(pipe, gsg)

+ 74 - 8
panda/src/display/graphicsEngine.cxx

@@ -67,6 +67,8 @@ GraphicsEngine(Pipeline *pipeline) :
     _pipeline = Pipeline::get_render_pipeline();
     _pipeline = Pipeline::get_render_pipeline();
   }
   }
 
 
+  _windows_sorted = true;
+
   // Default frame buffer properties.
   // Default frame buffer properties.
   _frame_buffer_properties.set_depth_bits(1);
   _frame_buffer_properties.set_depth_bits(1);
   _frame_buffer_properties.set_color_bits(1);
   _frame_buffer_properties.set_color_bits(1);
@@ -203,7 +205,7 @@ make_gsg(GraphicsPipe *pipe, const FrameBufferProperties &properties) {
 //               later.
 //               later.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 GraphicsWindow *GraphicsEngine::
 GraphicsWindow *GraphicsEngine::
-make_window(GraphicsStateGuardian *gsg, const string &name) {
+make_window(GraphicsStateGuardian *gsg, const string &name, int sort) {
   GraphicsThreadingModel threading_model = get_threading_model();
   GraphicsThreadingModel threading_model = get_threading_model();
 
 
   nassertr(gsg != (GraphicsStateGuardian *)NULL, NULL);
   nassertr(gsg != (GraphicsStateGuardian *)NULL, NULL);
@@ -213,6 +215,7 @@ make_window(GraphicsStateGuardian *gsg, const string &name) {
 
 
   // TODO: ask the window thread to make the window.
   // TODO: ask the window thread to make the window.
   PT(GraphicsWindow) window = gsg->get_pipe()->make_window(gsg, name);
   PT(GraphicsWindow) window = gsg->get_pipe()->make_window(gsg, name);
+  window->_sort = sort;
   do_add_window(window, gsg, threading_model);
   do_add_window(window, gsg, threading_model);
   return window;
   return window;
 }
 }
@@ -232,9 +235,9 @@ make_window(GraphicsStateGuardian *gsg, const string &name) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 GraphicsOutput *GraphicsEngine::
 GraphicsOutput *GraphicsEngine::
 make_buffer(GraphicsStateGuardian *gsg, const string &name, 
 make_buffer(GraphicsStateGuardian *gsg, const string &name, 
-            int x_size, int y_size, bool want_texture) {
+            int sort, int x_size, int y_size, bool want_texture) {
   if (show_buffers) {
   if (show_buffers) {
-    GraphicsWindow *window = make_window(gsg, name);
+    GraphicsWindow *window = make_window(gsg, name, sort);
     if (window != (GraphicsWindow *)NULL) {
     if (window != (GraphicsWindow *)NULL) {
       WindowProperties props;
       WindowProperties props;
       props.set_size(x_size, y_size);
       props.set_size(x_size, y_size);
@@ -261,6 +264,7 @@ make_buffer(GraphicsStateGuardian *gsg, const string &name,
   // TODO: ask the window thread to make the buffer.
   // TODO: ask the window thread to make the buffer.
   PT(GraphicsBuffer) buffer = 
   PT(GraphicsBuffer) buffer = 
     gsg->get_pipe()->make_buffer(gsg, name, x_size, y_size, want_texture);
     gsg->get_pipe()->make_buffer(gsg, name, x_size, y_size, want_texture);
+  buffer->_sort = sort;
   do_add_window(buffer, gsg, threading_model);
   do_add_window(buffer, gsg, threading_model);
   return buffer;
   return buffer;
 }
 }
@@ -378,6 +382,10 @@ render_frame() {
   // don't do that.
   // don't do that.
   MutexHolder holder(_lock);
   MutexHolder holder(_lock);
 
 
+  if (!_windows_sorted) {
+    do_resort_windows();
+  }
+
   if (_flip_state != FS_flip) {
   if (_flip_state != FS_flip) {
     do_flip_frame();
     do_flip_frame();
   }
   }
@@ -502,6 +510,23 @@ render_subframe(GraphicsStateGuardian *gsg, DisplayRegion *dr,
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::set_window_sort
+//       Access: Private
+//  Description: Changes the sort value of a particular window (or
+//               buffer) on the GraphicsEngine.  This requires
+//               securing the mutex.
+//
+//               Users shouldn't call this directly; use
+//               GraphicsOutput::set_sort() instead.
+////////////////////////////////////////////////////////////////////
+void GraphicsEngine::
+set_window_sort(GraphicsOutput *window, int sort) {
+  MutexHolder holder(_lock);
+  window->_sort = sort;
+  _windows_sorted = false;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::cull_and_draw_together
 //     Function: GraphicsEngine::cull_and_draw_together
 //       Access: Private
 //       Access: Private
@@ -895,7 +920,8 @@ do_add_window(GraphicsOutput *window, GraphicsStateGuardian *gsg,
               const GraphicsThreadingModel &threading_model) {
               const GraphicsThreadingModel &threading_model) {
   if (window != (GraphicsOutput *)NULL) {
   if (window != (GraphicsOutput *)NULL) {
     MutexHolder holder(_lock);
     MutexHolder holder(_lock);
-    _windows.insert(window);
+    _windows_sorted = false;
+    _windows.push_back(window);
 
 
     WindowRenderer *cull = get_window_renderer(threading_model.get_cull_name());
     WindowRenderer *cull = get_window_renderer(threading_model.get_cull_name());
     WindowRenderer *draw = get_window_renderer(threading_model.get_draw_name());
     WindowRenderer *draw = get_window_renderer(threading_model.get_draw_name());
@@ -937,6 +963,10 @@ do_remove_window(GraphicsOutput *window) {
   PT(GraphicsPipe) pipe = window->get_pipe();
   PT(GraphicsPipe) pipe = window->get_pipe();
   window->_pipe = (GraphicsPipe *)NULL;
   window->_pipe = (GraphicsPipe *)NULL;
 
 
+  if (!_windows_sorted) {
+    do_resort_windows();
+  }
+
   // Now remove the window from all threads that know about it.
   // Now remove the window from all threads that know about it.
   _app.remove_window(window);
   _app.remove_window(window);
   Threads::const_iterator ti;
   Threads::const_iterator ti;
@@ -950,6 +980,26 @@ do_remove_window(GraphicsOutput *window) {
   _app.do_pending(this);
   _app.do_pending(this);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::do_resort_windows
+//       Access: Private
+//  Description: Resorts all of the Windows lists.  This may need to
+//               be done if one or more of the windows' sort
+//               properties has changed.
+////////////////////////////////////////////////////////////////////
+void GraphicsEngine::
+do_resort_windows() {
+  _windows_sorted = true;
+
+  _app.resort_windows();
+  Threads::const_iterator ti;
+  for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
+    RenderThread *thread = (*ti).second;
+    thread->resort_windows();
+  }
+  _windows.sort();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::terminate_threads
 //     Function: GraphicsEngine::terminate_threads
 //       Access: Private
 //       Access: Private
@@ -1077,7 +1127,7 @@ remove_window(GraphicsOutput *window) {
     // Move it to the pending release thread so we can release the GSG
     // Move it to the pending release thread so we can release the GSG
     // when the thread next runs.  We can't do this immediately,
     // when the thread next runs.  We can't do this immediately,
     // because we might not have been called from the subthread.
     // because we might not have been called from the subthread.
-    _pending_release.insert(ptwin);
+    _pending_release.push_back(ptwin);
     _cdraw.erase(wi);
     _cdraw.erase(wi);
   }
   }
 
 
@@ -1089,7 +1139,7 @@ remove_window(GraphicsOutput *window) {
     // Move it to the pending release thread so we can release the GSG
     // Move it to the pending release thread so we can release the GSG
     // when the thread next runs.  We can't do this immediately,
     // when the thread next runs.  We can't do this immediately,
     // because we might not have been called from the subthread.
     // because we might not have been called from the subthread.
-    _pending_release.insert(ptwin);
+    _pending_release.push_back(ptwin);
     _draw.erase(wi);
     _draw.erase(wi);
   }
   }
 
 
@@ -1106,13 +1156,29 @@ remove_window(GraphicsOutput *window) {
     // it can be closed later.  We can't close it immediately, because
     // it can be closed later.  We can't close it immediately, because
     // we might not have been called from the subthread.
     // we might not have been called from the subthread.
     if (ptwin->is_valid()) {
     if (ptwin->is_valid()) {
-      _pending_close.insert(ptwin);
+      _pending_close.push_back(ptwin);
     }
     }
 
 
     _window.erase(wi);
     _window.erase(wi);
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::WindowRenderer::resort_windows
+//       Access: Public
+//  Description: Resorts all the lists of windows, assuming they may
+//               have become unsorted.
+////////////////////////////////////////////////////////////////////
+void GraphicsEngine::WindowRenderer::
+resort_windows() {
+  MutexHolder holder(_wl_lock);
+
+  _cull.sort();
+  _cdraw.sort();
+  _draw.sort();
+  _window.sort();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::WindowRenderer::do_frame
 //     Function: GraphicsEngine::WindowRenderer::do_frame
 //       Access: Public
 //       Access: Public
@@ -1242,7 +1308,7 @@ do_pending(GraphicsEngine *engine) {
       } else {
       } else {
         // If the GSG hasn't been released yet, we have to save the
         // If the GSG hasn't been released yet, we have to save the
         // close operation for next frame.
         // close operation for next frame.
-        new_pending_close.insert(win);
+        new_pending_close.push_back(win);
       }
       }
     }
     }
     _pending_close.swap(new_pending_close);
     _pending_close.swap(new_pending_close);

+ 19 - 5
panda/src/display/graphicsEngine.h

@@ -29,8 +29,10 @@
 #include "thread.h"
 #include "thread.h"
 #include "pmutex.h"
 #include "pmutex.h"
 #include "conditionVar.h"
 #include "conditionVar.h"
-#include "pset.h"
 #include "pStatCollector.h"
 #include "pStatCollector.h"
+#include "pset.h"
+#include "ordered_vector.h"
+#include "indirectLess.h"
 
 
 class Pipeline;
 class Pipeline;
 class DisplayRegion;
 class DisplayRegion;
@@ -71,8 +73,10 @@ PUBLISHED:
   PT(GraphicsStateGuardian) make_gsg(GraphicsPipe *pipe,
   PT(GraphicsStateGuardian) make_gsg(GraphicsPipe *pipe,
                                      const FrameBufferProperties &properties);
                                      const FrameBufferProperties &properties);
 
 
-  GraphicsWindow *make_window(GraphicsStateGuardian *gsg, const string &name);
+  GraphicsWindow *make_window(GraphicsStateGuardian *gsg, const string &name,
+                              int sort);
   GraphicsOutput *make_buffer(GraphicsStateGuardian *gsg, const string &name,
   GraphicsOutput *make_buffer(GraphicsStateGuardian *gsg, const string &name,
+                              int sort,
                               int x_size, int y_size, bool want_texture);
                               int x_size, int y_size, bool want_texture);
 
 
   bool remove_window(GraphicsOutput *window);
   bool remove_window(GraphicsOutput *window);
@@ -97,17 +101,19 @@ public:
   };
   };
 
 
 private:
 private:
-  typedef pset< PT(GraphicsOutput) > Windows;
+  typedef ov_multiset< PT(GraphicsOutput), IndirectLess<GraphicsOutput> > Windows;
   typedef pset< PT(GraphicsStateGuardian) > GSGs;
   typedef pset< PT(GraphicsStateGuardian) > GSGs;
 
 
+  void set_window_sort(GraphicsOutput *window, int sort);
+
   void cull_and_draw_together(const Windows &wlist);
   void cull_and_draw_together(const Windows &wlist);
   void cull_and_draw_together(GraphicsStateGuardian *gsg, DisplayRegion *dr);
   void cull_and_draw_together(GraphicsStateGuardian *gsg, DisplayRegion *dr);
 
 
   void cull_bin_draw(const Windows &wlist);
   void cull_bin_draw(const Windows &wlist);
   void cull_bin_draw(GraphicsStateGuardian *gsg, DisplayRegion *dr);
   void cull_bin_draw(GraphicsStateGuardian *gsg, DisplayRegion *dr);
 
 
-  void process_events(const GraphicsEngine::Windows &wlist);
-  void flip_windows(const GraphicsEngine::Windows &wlist);
+  void process_events(const Windows &wlist);
+  void flip_windows(const Windows &wlist);
   void do_sync_frame();
   void do_sync_frame();
   void do_flip_frame();
   void do_flip_frame();
   INLINE void close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
   INLINE void close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
@@ -124,6 +130,7 @@ private:
   void do_add_window(GraphicsOutput *window, GraphicsStateGuardian *gsg,
   void do_add_window(GraphicsOutput *window, GraphicsStateGuardian *gsg,
                      const GraphicsThreadingModel &threading_model);
                      const GraphicsThreadingModel &threading_model);
   void do_remove_window(GraphicsOutput *window);
   void do_remove_window(GraphicsOutput *window);
+  void do_resort_windows();
   void terminate_threads();
   void terminate_threads();
 
 
   // The WindowRenderer class records the stages of the pipeline that
   // The WindowRenderer class records the stages of the pipeline that
@@ -134,6 +141,7 @@ private:
     void add_gsg(GraphicsStateGuardian *gsg);
     void add_gsg(GraphicsStateGuardian *gsg);
     void add_window(Windows &wlist, GraphicsOutput *window);
     void add_window(Windows &wlist, GraphicsOutput *window);
     void remove_window(GraphicsOutput *window);
     void remove_window(GraphicsOutput *window);
+    void resort_windows();
     void do_frame(GraphicsEngine *engine);
     void do_frame(GraphicsEngine *engine);
     void do_flip(GraphicsEngine *engine);
     void do_flip(GraphicsEngine *engine);
     void do_release(GraphicsEngine *engine);
     void do_release(GraphicsEngine *engine);
@@ -145,8 +153,11 @@ private:
     Windows _cdraw;   // cull-and-draw-together stage
     Windows _cdraw;   // cull-and-draw-together stage
     Windows _draw;    // draw stage
     Windows _draw;    // draw stage
     Windows _window;  // window stage, i.e. process windowing events 
     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_release; // moved from _draw, pending release_gsg.
     Windows _pending_close;   // moved from _window, pending close.
     Windows _pending_close;   // moved from _window, pending close.
+
     GSGs _gsgs;       // draw stage
     GSGs _gsgs;       // draw stage
     Mutex _wl_lock;
     Mutex _wl_lock;
   };
   };
@@ -166,6 +177,7 @@ private:
 
 
   Pipeline *_pipeline;
   Pipeline *_pipeline;
   Windows _windows;
   Windows _windows;
+  bool _windows_sorted;
 
 
   WindowRenderer _app;
   WindowRenderer _app;
   typedef pmap<string, PT(RenderThread) > Threads;
   typedef pmap<string, PT(RenderThread) > Threads;
@@ -192,7 +204,9 @@ private:
   static PStatCollector _transform_states_unused_pcollector;
   static PStatCollector _transform_states_unused_pcollector;
   static PStatCollector _render_states_pcollector;
   static PStatCollector _render_states_pcollector;
   static PStatCollector _render_states_unused_pcollector;
   static PStatCollector _render_states_unused_pcollector;
+
   friend class WindowRenderer;
   friend class WindowRenderer;
+  friend class GraphicsOutput;
 };
 };
 
 
 #include "graphicsEngine.I"
 #include "graphicsEngine.I"

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

@@ -160,6 +160,19 @@ is_valid() const {
   return _is_valid;
   return _is_valid;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsOutput::get_sort
+//       Access: Published
+//  Description: Returns the sorting order of this particular
+//               GraphicsOutput.  The various GraphicsOutputs within a
+//               particular thread will be rendered in the indicated
+//               order.
+////////////////////////////////////////////////////////////////////
+INLINE int GraphicsOutput::
+get_sort() const {
+  return _sort;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsOutput::win_display_regions_changed
 //     Function: GraphicsOutput::win_display_regions_changed
 //       Access: Public
 //       Access: Public
@@ -173,6 +186,19 @@ win_display_regions_changed() {
   _display_regions_stale = true;
   _display_regions_stale = true;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsOutput::operator <
+//       Access: Public
+//  Description: The sorting operator is used to order the
+//               GraphicsOutput object in order by their sort number,
+//               so that they will render in the correct order in the
+//               GraphicsEngine.
+////////////////////////////////////////////////////////////////////
+INLINE bool GraphicsOutput::
+operator < (const GraphicsOutput &other) const {
+  return _sort < other._sort;
+}
+
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsOutput::determine_display_regions
 //     Function: GraphicsOutput::determine_display_regions

+ 18 - 0
panda/src/display/graphicsOutput.cxx

@@ -18,6 +18,7 @@
 
 
 #include "graphicsOutput.h"
 #include "graphicsOutput.h"
 #include "graphicsPipe.h"
 #include "graphicsPipe.h"
+#include "graphicsEngine.h"
 #include "config_display.h"
 #include "config_display.h"
 #include "mutexHolder.h"
 #include "mutexHolder.h"
 #include "hardwareChannel.h"
 #include "hardwareChannel.h"
@@ -49,6 +50,7 @@ GraphicsOutput(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
   _has_size = false;
   _has_size = false;
   _is_valid = false;
   _is_valid = false;
   _copy_texture = false;
   _copy_texture = false;
+  _sort = 0;
 
 
   _display_regions_stale = false;
   _display_regions_stale = false;
 
 
@@ -112,6 +114,22 @@ is_active() const {
   return is_valid();
   return is_valid();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsOutput::set_sort
+//       Access: Published
+//  Description: Adjusts the sorting order of this particular
+//               GraphicsOutput, relative to other GraphicsOutputs.
+////////////////////////////////////////////////////////////////////
+void GraphicsOutput::
+set_sort(int sort) {
+  if (_sort != sort) {
+    if (_gsg != (GraphicsStateGuardian *)NULL &&
+        _gsg->get_engine() != (GraphicsEngine *)NULL) {
+      _gsg->get_engine()->set_window_sort(this, sort);
+    }
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsOutput::get_channel
 //     Function: GraphicsOutput::get_channel
 //       Access: Public
 //       Access: Public

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

@@ -83,6 +83,9 @@ PUBLISHED:
 
 
   virtual bool is_active() const;
   virtual bool is_active() const;
 
 
+  INLINE int get_sort() const;
+  void set_sort(int sort);
+
   GraphicsChannel *get_channel(int index);
   GraphicsChannel *get_channel(int index);
   void remove_channel(int index);
   void remove_channel(int index);
 
 
@@ -104,6 +107,8 @@ public:
   // These are not intended to be called directly by the user.
   // These are not intended to be called directly by the user.
   INLINE void win_display_regions_changed();
   INLINE void win_display_regions_changed();
 
 
+  INLINE bool operator < (const GraphicsOutput &other) const;
+
   virtual void request_open();
   virtual void request_open();
   virtual void request_close();
   virtual void request_close();
 
 
@@ -146,6 +151,8 @@ private:
   INLINE void determine_display_regions() const;
   INLINE void determine_display_regions() const;
   void do_determine_display_regions();
   void do_determine_display_regions();
 
 
+  int _sort;
+
 protected:
 protected:
   Mutex _lock; 
   Mutex _lock; 
   // protects _channels, _display_regions.
   // protects _channels, _display_regions.

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

@@ -117,7 +117,7 @@ open_window(const WindowProperties &props, GraphicsEngine *engine,
   next_window_index++;
   next_window_index++;
   string name = stream.str();
   string name = stream.str();
 
 
-  _window = engine->make_window(ptgsg, name);
+  _window = engine->make_window(ptgsg, name, 0);
   if (_window != (GraphicsWindow *)NULL) {
   if (_window != (GraphicsWindow *)NULL) {
     _window->request_properties(props);
     _window->request_properties(props);
     set_background_type(_background_type);
     set_background_type(_background_type);