瀏覽代碼

add callback support

David Rose 22 年之前
父節點
當前提交
abd0db5458
共有 3 個文件被更改,包括 174 次插入0 次删除
  1. 36 0
      panda/src/display/graphicsEngine.I
  2. 104 0
      panda/src/display/graphicsEngine.cxx
  3. 34 0
      panda/src/display/graphicsEngine.h

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

@@ -93,3 +93,39 @@ INLINE void GraphicsEngine::
 close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) {
 close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) {
   pipe->close_gsg(gsg);
   pipe->close_gsg(gsg);
 }
 }
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::Callback::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE GraphicsEngine::Callback::
+Callback(CallbackFunction *func, void *data) :
+  _func(func),
+  _data(data)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::Callback::operator <
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool GraphicsEngine::Callback::
+operator < (const GraphicsEngine::Callback &other) const {
+  if (_func != other._func) {
+    return _func < other._func;
+  }
+  return _data < other._data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::Callback::do_callback
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsEngine::Callback::
+do_callback() const {
+  (*_func)(_data);
+}

+ 104 - 0
panda/src/display/graphicsEngine.cxx

@@ -564,6 +564,51 @@ render_subframe(GraphicsStateGuardian *gsg, DisplayRegion *dr,
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::add_callback
+//       Access: Public
+//  Description: Adds the indicated C/C++ function and an arbitrary
+//               associated data pointer to the list of functions that
+//               will be called in the indicated thread at the
+//               indicated point of the frame.
+//
+//               The thread name may be one of the cull or draw names
+//               specified in set_threading_model(), or it may be the
+//               empty string to indicated the app or main thread.
+//
+//               The return value is true if the function and data
+//               pointer are successfully added to the appropriate
+//               callback list, or false if the same function and data
+//               pointer were already there.
+////////////////////////////////////////////////////////////////////
+bool GraphicsEngine::
+add_callback(const string &thread_name, 
+             GraphicsEngine::CallbackTime callback_time,
+             GraphicsEngine::CallbackFunction *func, void *data) {
+  WindowRenderer *wr = get_window_renderer(thread_name);
+  return wr->add_callback(callback_time, Callback(func, data));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::remove_callback
+//       Access: Public
+//  Description: Removes a callback added by a previous call to
+//               add_callback().  All parameters must match the same
+//               parameters passed to add_callback().  The return
+//               value is true if the callback is successfully
+//               removed, or false if it was not on the list (either
+//               one or more of the parameters did not match the call
+//               to add_callback(), or the callback has already been
+//               removed).
+////////////////////////////////////////////////////////////////////
+bool GraphicsEngine::
+remove_callback(const string &thread_name, 
+                GraphicsEngine::CallbackTime callback_time,
+                GraphicsEngine::CallbackFunction *func, void *data) {
+  WindowRenderer *wr = get_window_renderer(thread_name);
+  return wr->remove_callback(callback_time, Callback(func, data));
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::set_window_sort
 //     Function: GraphicsEngine::set_window_sort
 //       Access: Private
 //       Access: Private
@@ -1248,6 +1293,9 @@ resort_windows() {
 void GraphicsEngine::WindowRenderer::
 void GraphicsEngine::WindowRenderer::
 do_frame(GraphicsEngine *engine) {
 do_frame(GraphicsEngine *engine) {
   MutexHolder holder(_wl_lock);
   MutexHolder holder(_wl_lock);
+
+  do_callbacks(CB_pre_frame);
+
   engine->cull_bin_draw(_cull);
   engine->cull_bin_draw(_cull);
   engine->cull_and_draw_together(_cdraw);
   engine->cull_and_draw_together(_cdraw);
   engine->process_events(_window);
   engine->process_events(_window);
@@ -1271,6 +1319,8 @@ do_frame(GraphicsEngine *engine) {
 
 
     _gsgs.swap(new_gsgs);
     _gsgs.swap(new_gsgs);
   }
   }
+
+  do_callbacks(CB_post_frame);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1393,6 +1443,60 @@ any_done_gsgs() const {
   return false;
   return false;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::WindowRenderer::add_callback
+//       Access: Public
+//  Description: Adds the indicated callback to this renderer's list
+//               for the indicated callback time.  Returns true if it
+//               is successfully added, false if it was already there.
+////////////////////////////////////////////////////////////////////
+bool GraphicsEngine::WindowRenderer::
+add_callback(GraphicsEngine::CallbackTime callback_time, 
+             const GraphicsEngine::Callback &callback) {
+  nassertr(callback_time >= 0 && callback_time < CB_len, false);
+  MutexHolder holder(_wl_lock);
+  return _callbacks[callback_time].insert(callback).second;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::WindowRenderer::remove_callback
+//       Access: Public
+//  Description: Removes the indicated callback from this renderer's
+//               list for the indicated callback time.  Returns true
+//               if it is successfully removed, or false if it was not
+//               on the list.
+////////////////////////////////////////////////////////////////////
+bool GraphicsEngine::WindowRenderer::
+remove_callback(GraphicsEngine::CallbackTime callback_time, 
+                const GraphicsEngine::Callback &callback) {
+  nassertr(callback_time >= 0 && callback_time < CB_len, false);
+  MutexHolder holder(_wl_lock);
+  Callbacks::iterator cbi = _callbacks[callback_time].find(callback);
+  if (cbi != _callbacks[callback_time].end()) {
+    _callbacks[callback_time].erase(cbi);
+    return true;
+  }
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::WindowRenderer::do_callbacks
+//       Access: Private
+//  Description: Calls all of the callback functions on the indicated
+//               list.  Intended to be called internally when we have
+//               reached the indicated point on the frame.
+////////////////////////////////////////////////////////////////////
+void GraphicsEngine::WindowRenderer::
+do_callbacks(GraphicsEngine::CallbackTime callback_time) {
+  nassertv(callback_time >= 0 && callback_time < CB_len);
+  Callbacks::const_iterator cbi;
+  for (cbi = _callbacks[callback_time].begin();
+       cbi != _callbacks[callback_time].end();
+       ++cbi) {
+    (*cbi).do_callback();
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::RenderThread::Constructor
 //     Function: GraphicsEngine::RenderThread::Constructor
 //       Access: Public
 //       Access: Public

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

@@ -103,9 +103,34 @@ public:
     TS_terminate
     TS_terminate
   };
   };
 
 
+  enum CallbackTime {
+    CB_pre_frame,
+    CB_post_frame,
+    CB_len  // Not an option; just indicates the size of the list.
+  };
+
+  typedef void CallbackFunction(void *data);
+
+  bool add_callback(const string &thread_name, CallbackTime callback_time,
+                    CallbackFunction *func, void *data);
+  bool remove_callback(const string &thread_name, CallbackTime callback_time,
+                       CallbackFunction *func, void *data);
+
 private:
 private:
+  class Callback {
+  public:
+    INLINE Callback(CallbackFunction *func, void *data);
+    INLINE bool operator < (const Callback &other) const;
+    INLINE void do_callback() const;
+
+  private:
+    CallbackFunction *_func;
+    void *_data;
+  };
+
   typedef ov_multiset< PT(GraphicsOutput), IndirectLess<GraphicsOutput> > Windows;
   typedef ov_multiset< PT(GraphicsOutput), IndirectLess<GraphicsOutput> > Windows;
   typedef pset< PT(GraphicsStateGuardian) > GSGs;
   typedef pset< PT(GraphicsStateGuardian) > GSGs;
+  typedef pset< Callback > Callbacks;
 
 
   void set_window_sort(GraphicsOutput *window, int sort);
   void set_window_sort(GraphicsOutput *window, int sort);
 
 
@@ -152,6 +177,13 @@ private:
     void do_pending(GraphicsEngine *engine);
     void do_pending(GraphicsEngine *engine);
     bool any_done_gsgs() const;
     bool any_done_gsgs() const;
 
 
+    bool add_callback(CallbackTime callback_time, const Callback &callback);
+    bool remove_callback(CallbackTime callback_time, const Callback &callback);
+
+  private:
+    void do_callbacks(CallbackTime callback_time);
+
+  public:
     Windows _cull;    // cull stage
     Windows _cull;    // cull stage
     Windows _cdraw;   // cull-and-draw-together stage
     Windows _cdraw;   // cull-and-draw-together stage
     Windows _draw;    // draw stage
     Windows _draw;    // draw stage
@@ -162,6 +194,8 @@ private:
     Windows _pending_close;   // moved from _window, pending close.
     Windows _pending_close;   // moved from _window, pending close.
 
 
     GSGs _gsgs;       // draw stage
     GSGs _gsgs;       // draw stage
+
+    Callbacks _callbacks[CB_len];
     Mutex _wl_lock;
     Mutex _wl_lock;
   };
   };