Browse Source

more factoring of Thread::get_current_thread

David Rose 19 years ago
parent
commit
ffc92f23c8
39 changed files with 790 additions and 372 deletions
  1. 3 3
      panda/src/cull/cullBinBackToFront.cxx
  2. 1 1
      panda/src/cull/cullBinBackToFront.h
  3. 3 3
      panda/src/cull/cullBinFixed.cxx
  4. 1 1
      panda/src/cull/cullBinFixed.h
  5. 2 2
      panda/src/cull/cullBinFrontToBack.cxx
  6. 1 1
      panda/src/cull/cullBinFrontToBack.h
  7. 17 17
      panda/src/cull/cullBinOcclusionTest.cxx
  8. 6 5
      panda/src/cull/cullBinOcclusionTest.h
  9. 3 3
      panda/src/cull/cullBinStateSorted.cxx
  10. 1 1
      panda/src/cull/cullBinStateSorted.h
  11. 3 3
      panda/src/cull/cullBinUnsorted.cxx
  12. 1 1
      panda/src/cull/cullBinUnsorted.h
  13. 1 1
      panda/src/cull/drawCullHandler.cxx
  14. 465 0
      panda/src/display/displayRegion.I
  15. 12 163
      panda/src/display/displayRegion.cxx
  16. 64 13
      panda/src/display/displayRegion.h
  17. 126 80
      panda/src/display/graphicsEngine.cxx
  18. 25 23
      panda/src/display/graphicsEngine.h
  19. 5 4
      panda/src/display/graphicsOutput.cxx
  20. 2 2
      panda/src/display/graphicsOutput.h
  21. 3 2
      panda/src/display/graphicsStateGuardian.cxx
  22. 2 1
      panda/src/display/graphicsStateGuardian.h
  23. 4 3
      panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx
  24. 2 1
      panda/src/dxgsg8/dxGraphicsStateGuardian8.h
  25. 4 3
      panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx
  26. 2 1
      panda/src/dxgsg9/dxGraphicsStateGuardian9.h
  27. 5 4
      panda/src/glstuff/glGraphicsStateGuardian_src.cxx
  28. 2 1
      panda/src/glstuff/glGraphicsStateGuardian_src.h
  29. 1 2
      panda/src/gobj/geom.cxx
  30. 2 1
      panda/src/gobj/geom.h
  31. 0 10
      panda/src/pgraph/cullBin.cxx
  32. 1 1
      panda/src/pgraph/cullBin.h
  33. 4 3
      panda/src/pgraph/cullHandler.I
  34. 5 4
      panda/src/pgraph/cullHandler.cxx
  35. 4 2
      panda/src/pgraph/cullHandler.h
  36. 2 2
      panda/src/pgraph/cullResult.cxx
  37. 1 1
      panda/src/pgraph/cullResult.h
  38. 2 2
      panda/src/pgraph/cullableObject.I
  39. 2 1
      panda/src/pgraph/cullableObject.h

+ 3 - 3
panda/src/cull/cullBinBackToFront.cxx

@@ -93,17 +93,17 @@ finish_cull(SceneSetup *) {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: CullBinBackToFront::draw
-//       Access: Public
+//       Access: Public, Virtual
 //  Description: Draws all the geoms in the bin, in the appropriate
 //               order.
 ////////////////////////////////////////////////////////////////////
 void CullBinBackToFront::
-draw() {
+draw(Thread *current_thread) {
   PStatTimer timer(_draw_this_pcollector);
   Objects::const_iterator oi;
   for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
     CullableObject *object = (*oi)._object;
-    CullHandler::draw(object, _gsg);
+    CullHandler::draw(object, _gsg, current_thread);
   }
 }
 

+ 1 - 1
panda/src/cull/cullBinBackToFront.h

@@ -45,7 +45,7 @@ public:
 
   virtual void add_object(CullableObject *object);
   virtual void finish_cull(SceneSetup *scene_setup);
-  virtual void draw();
+  virtual void draw(Thread *current_thread);
 
 private:
   class ObjectData {

+ 3 - 3
panda/src/cull/cullBinFixed.cxx

@@ -81,17 +81,17 @@ finish_cull(SceneSetup *) {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: CullBinFixed::draw
-//       Access: Public
+//       Access: Public, Virtual
 //  Description: Draws all the geoms in the bin, in the appropriate
 //               order.
 ////////////////////////////////////////////////////////////////////
 void CullBinFixed::
-draw() {
+draw(Thread *current_thread) {
   PStatTimer timer(_draw_this_pcollector);
   Objects::const_iterator oi;
   for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
     CullableObject *object = (*oi)._object;
-    CullHandler::draw(object, _gsg);
+    CullHandler::draw(object, _gsg, current_thread);
   }
 }
 

+ 1 - 1
panda/src/cull/cullBinFixed.h

@@ -47,7 +47,7 @@ public:
 
   virtual void add_object(CullableObject *object);
   virtual void finish_cull(SceneSetup *scene_setup);
-  virtual void draw();
+  virtual void draw(Thread *current_thread);
 
 private:
   class ObjectData {

+ 2 - 2
panda/src/cull/cullBinFrontToBack.cxx

@@ -98,12 +98,12 @@ finish_cull(SceneSetup *) {
 //               order.
 ////////////////////////////////////////////////////////////////////
 void CullBinFrontToBack::
-draw() {
+draw(Thread *current_thread) {
   PStatTimer timer(_draw_this_pcollector);
   Objects::const_iterator oi;
   for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
     CullableObject *object = (*oi)._object;
-    CullHandler::draw(object, _gsg);
+    CullHandler::draw(object, _gsg, current_thread);
   }
 }
 

+ 1 - 1
panda/src/cull/cullBinFrontToBack.h

@@ -45,7 +45,7 @@ public:
 
   virtual void add_object(CullableObject *object);
   virtual void finish_cull(SceneSetup *scene_setup);
-  virtual void draw();
+  virtual void draw(Thread *current_thread);
 
 private:
   class ObjectData {

+ 17 - 17
panda/src/cull/cullBinOcclusionTest.cxx

@@ -195,7 +195,7 @@ finish_cull(SceneSetup *scene_setup) {
 //               order.
 ////////////////////////////////////////////////////////////////////
 void CullBinOcclusionTest::
-draw() {
+draw(Thread *current_thread) {
   PStatTimer timer(_draw_this_pcollector);
 
   // We'll want to know the near plane distance.
@@ -205,7 +205,7 @@ draw() {
   int num_drawn_previous;
   {
     MutexHolder holder(_prev_draw->_visible_lock);
-    num_drawn_previous = _root.draw_previous(*this);
+    num_drawn_previous = _root.draw_previous(*this, current_thread);
   }
 
   if (cull_cat.is_spam()) {
@@ -215,9 +215,9 @@ draw() {
 
   // Now draw the objects that may or may not remain.
   int num_drawn;
-  num_drawn = _root.draw(*this);
+  num_drawn = _root.draw(*this, current_thread);
   if (show_octree) {
-    _root.draw_wireframe(*this);
+    _root.draw_wireframe(*this, current_thread);
   }
 
   while (!_pending_nodes.empty()) {
@@ -239,9 +239,9 @@ draw() {
     if (num_fragments != 0) {
       // The octree cell is at least partially visible.  Draw it, and
       // continue recursion.
-      num_drawn += pending._octree_node->draw(*this);
+      num_drawn += pending._octree_node->draw(*this, current_thread);
       if (show_octree) {
-        pending._octree_node->draw_wireframe(*this);
+        pending._octree_node->draw_wireframe(*this, current_thread);
       }
     }
     _pending_nodes.pop_front();
@@ -475,7 +475,7 @@ compute_distance(const LMatrix4f &world_mat,
 //               occlusion query object representing this test.
 ////////////////////////////////////////////////////////////////////
 PT(OcclusionQueryContext) CullBinOcclusionTest::OctreeNode::
-occlusion_test(CullBinOcclusionTest &bin) {
+occlusion_test(CullBinOcclusionTest &bin, Thread *current_thread) {
   // Draw the bounding volume for visualization.  This is
   // complicated because we're doing this at such a low level, here
   // in the middle of the draw task--we've already completed the
@@ -500,7 +500,7 @@ occlusion_test(CullBinOcclusionTest &bin) {
 
   PStatTimer timer(bin._draw_occlusion_pcollector);
   bin._gsg->begin_occlusion_query();
-  viz->draw(bin._gsg, munger, munged_data);
+  viz->draw(bin._gsg, munger, munged_data, current_thread);
   return bin._gsg->end_occlusion_query();
 }
 
@@ -512,7 +512,7 @@ occlusion_test(CullBinOcclusionTest &bin) {
 //               objects drawn.
 ////////////////////////////////////////////////////////////////////
 int CullBinOcclusionTest::OctreeNode::
-draw_previous(CullBinOcclusionTest &bin) {
+draw_previous(CullBinOcclusionTest &bin, Thread *current_thread) {
   int num_drawn = 0;
 
   if (!_objects.empty()) {
@@ -523,7 +523,7 @@ draw_previous(CullBinOcclusionTest &bin) {
         VisibleGeom vg(object->_geom, object->_net_transform);
         if (bin._prev_draw->_visible_geoms.find(vg) != bin._prev_draw->_visible_geoms.end()) {
           // This object is visible.
-          CullHandler::draw(object, bin._gsg);
+          CullHandler::draw(object, bin._gsg, current_thread);
           object->_already_drawn = true;
           ++num_drawn;
         }
@@ -536,7 +536,7 @@ draw_previous(CullBinOcclusionTest &bin) {
     // farthest.
     int index = bin._corners_front_to_back[i];
     if (_corners[index] != (OctreeNode *)NULL) {
-      num_drawn += _corners[index]->draw_previous(bin);
+      num_drawn += _corners[index]->draw_previous(bin, current_thread);
     }
   }
 
@@ -551,7 +551,7 @@ draw_previous(CullBinOcclusionTest &bin) {
 //               nested nodes.  Returns the number of objects drawn.
 ////////////////////////////////////////////////////////////////////
 int CullBinOcclusionTest::OctreeNode::
-draw(CullBinOcclusionTest &bin) {
+draw(CullBinOcclusionTest &bin, Thread *current_thread) {
   // If the node is being drawn, it must have passed the occlusion
   // test.  Flag it as such.
   _is_visible = true;
@@ -568,7 +568,7 @@ draw(CullBinOcclusionTest &bin) {
     for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
       CullableObject *object = (*oi)._object;
       if (!object->_already_drawn) {
-        CullHandler::draw(object, bin._gsg);
+        CullHandler::draw(object, bin._gsg, current_thread);
         object->_already_drawn = true;
         ++num_drawn;
       }
@@ -588,7 +588,7 @@ draw(CullBinOcclusionTest &bin) {
         // some or all of the cube would be clipped), but it's not
         // likely that anything will be occluding something so close
         // to the camera anyway.
-        _corners[index]->draw(bin);
+        _corners[index]->draw(bin, current_thread);
 
       } else {
         // Otherwise, if the entire cube is in front of the near
@@ -597,7 +597,7 @@ draw(CullBinOcclusionTest &bin) {
         // through the depth test.
         PendingNode pending;
         pending._octree_node = _corners[index];
-        pending._query = _corners[index]->occlusion_test(bin);
+        pending._query = _corners[index]->occlusion_test(bin, current_thread);
 
         // We push it onto the list of nodes that are awaiting
         // feedback from the graphics pipe.  This way we can go work
@@ -617,7 +617,7 @@ draw(CullBinOcclusionTest &bin) {
 //               for debugging and visualization purposes.
 ////////////////////////////////////////////////////////////////////
 void CullBinOcclusionTest::OctreeNode::
-draw_wireframe(CullBinOcclusionTest &bin) {
+draw_wireframe(CullBinOcclusionTest &bin, Thread *current_thread) {
   // As above, this is complicated because we're doing this at such a
   // low level.
   CPT(TransformState) net_transform = TransformState::make_pos_hpr_scale
@@ -635,7 +635,7 @@ draw_wireframe(CullBinOcclusionTest &bin) {
   munger->munge_geom(viz, munged_data);
   
   bin._gsg->set_state_and_transform(state, internal_transform);
-  viz->draw(bin._gsg, munger, munged_data);
+  viz->draw(bin._gsg, munger, munged_data, current_thread);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 6 - 5
panda/src/cull/cullBinOcclusionTest.h

@@ -59,7 +59,7 @@ public:
 
   virtual void add_object(CullableObject *object);
   virtual void finish_cull(SceneSetup *scene_setup);
-  virtual void draw();
+  virtual void draw(Thread *current_thread);
 
 private:
   void draw_next();
@@ -121,10 +121,11 @@ private:
     void compute_distance(const LMatrix4f &world_mat,
                           CullBinOcclusionTest &bin);
 
-    PT(OcclusionQueryContext) occlusion_test(CullBinOcclusionTest &bin);
-    int draw_previous(CullBinOcclusionTest &bin);
-    int draw(CullBinOcclusionTest &bin);
-    void draw_wireframe(CullBinOcclusionTest &bin);
+    PT(OcclusionQueryContext) occlusion_test(CullBinOcclusionTest &bin,
+                                             Thread *current_thread);
+    int draw_previous(CullBinOcclusionTest &bin, Thread *current_thread);
+    int draw(CullBinOcclusionTest &bin, Thread *current_thread);
+    void draw_wireframe(CullBinOcclusionTest &bin, Thread *current_thread);
     void record_visible_geoms(VisibleGeoms &visible_geoms);
     INLINE void initial_assign(const ObjectData &object_data);
 

+ 3 - 3
panda/src/cull/cullBinStateSorted.cxx

@@ -80,17 +80,17 @@ finish_cull(SceneSetup *) {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: CullBinStateSorted::draw
-//       Access: Public
+//       Access: Public, Virtual
 //  Description: Draws all the geoms in the bin, in the appropriate
 //               order.
 ////////////////////////////////////////////////////////////////////
 void CullBinStateSorted::
-draw() {
+draw(Thread *current_thread) {
   PStatTimer timer(_draw_this_pcollector);
   Objects::const_iterator oi;
   for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
     CullableObject *object = (*oi)._object;
-    CullHandler::draw(object, _gsg);
+    CullHandler::draw(object, _gsg, current_thread);
   }
 }
 

+ 1 - 1
panda/src/cull/cullBinStateSorted.h

@@ -49,7 +49,7 @@ public:
 
   virtual void add_object(CullableObject *object);
   virtual void finish_cull(SceneSetup *scene_setup);
-  virtual void draw();
+  virtual void draw(Thread *current_thread);
 
 private:
   class ObjectData {

+ 3 - 3
panda/src/cull/cullBinUnsorted.cxx

@@ -61,17 +61,17 @@ add_object(CullableObject *object) {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: CullBinUnsorted::draw
-//       Access: Public
+//       Access: Public, Virtual
 //  Description: Draws all the objects in the bin, in the appropriate
 //               order.
 ////////////////////////////////////////////////////////////////////
 void CullBinUnsorted::
-draw() {
+draw(Thread *current_thread) {
   PStatTimer timer(_draw_this_pcollector);
   Objects::iterator oi;
   for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
     CullableObject *object = (*oi);
-    CullHandler::draw(object, _gsg);
+    CullHandler::draw(object, _gsg, current_thread);
   }
 }
 

+ 1 - 1
panda/src/cull/cullBinUnsorted.h

@@ -39,7 +39,7 @@ public:
   static CullBin *make_bin(const string &name, GraphicsStateGuardianBase *gsg);
 
   virtual void add_object(CullableObject *object);
-  virtual void draw();
+  virtual void draw(Thread *current_thread);
 
 private:
   typedef pvector<CullableObject *> Objects;

+ 1 - 1
panda/src/cull/drawCullHandler.cxx

@@ -38,6 +38,6 @@ record_object(CullableObject *object, const CullTraverser *traverser) {
   object->munge_geom(_gsg, _gsg->get_geom_munger(object->_state), traverser);
 
   // And draw the object, then dispense with it.
-  draw(object, _gsg);
+  draw(object, _gsg, Thread::get_current_thread());
   delete object;
 }

+ 465 - 0
panda/src/display/displayRegion.I

@@ -28,6 +28,99 @@ operator < (const DisplayRegion &other) const {
   return get_sort() < other.get_sort();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_dimensions
+//       Access: Published
+//  Description: Retrieves the coordinates of the DisplayRegion's
+//               rectangle within its GraphicsOutput.  These numbers
+//               will be in the range [0..1].
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegion::
+get_dimensions(float &l, float &r, float &b, float &t) const {
+  CDReader cdata(_cycler);
+  l = cdata->_l;
+  r = cdata->_r;
+  b = cdata->_b;
+  t = cdata->_t;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_left
+//       Access: Published
+//  Description: Retrieves the x coordinate of the left edge of the
+//               rectangle within its GraphicsOutput.  This number
+//               will be in the range [0..1].
+////////////////////////////////////////////////////////////////////
+INLINE float DisplayRegion::
+get_left() const {
+  CDReader cdata(_cycler);
+  return cdata->_l;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_right
+//       Access: Published
+//  Description: Retrieves the x coordinate of the right edge of the
+//               rectangle within its GraphicsOutput.  This number
+//               will be in the range [0..1].
+////////////////////////////////////////////////////////////////////
+INLINE float DisplayRegion::
+get_right() const {
+  CDReader cdata(_cycler);
+  return cdata->_r;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_bottom
+//       Access: Published
+//  Description: Retrieves the y coordinate of the bottom edge of 
+//               the rectangle within its GraphicsOutput.  This 
+//               number will be in the range [0..1].
+////////////////////////////////////////////////////////////////////
+INLINE float DisplayRegion::
+get_bottom() const {
+  CDReader cdata(_cycler);
+  return cdata->_b;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_top
+//       Access: Published
+//  Description: Retrieves the y coordinate of the top edge of the
+//               rectangle within its GraphicsOutput.  This number
+//               will be in the range [0..1].
+////////////////////////////////////////////////////////////////////
+INLINE float DisplayRegion::
+get_top() const {
+  CDReader cdata(_cycler);
+  return cdata->_t;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_window
+//       Access: Published
+//  Description: Returns the GraphicsOutput that this DisplayRegion is
+//               ultimately associated with, or NULL if no window is
+//               associated.
+////////////////////////////////////////////////////////////////////
+INLINE GraphicsOutput *DisplayRegion::
+get_window() const {
+  return _window;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_camera
+//       Access: Published
+//  Description: Returns the camera associated with this
+//               DisplayRegion, or an empty NodePath if no camera is
+//               associated.
+////////////////////////////////////////////////////////////////////
+INLINE NodePath DisplayRegion::
+get_camera() const {
+  CDReader cdata(_cycler);
+  return cdata->_camera;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DisplayRegion::is_active
 //       Access: Published
@@ -130,6 +223,76 @@ get_cube_map_index() const {
   return cdata->_cube_map_index;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_pixels
+//       Access: Published
+//  Description: Retrieves the coordinates of the DisplayRegion within
+//               its window, in pixels.
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegion::
+get_pixels(int &pl, int &pr, int &pb, int &pt) const {
+  CDReader cdata(_cycler);
+  pl = cdata->_pl;
+  pr = cdata->_pr;
+  pb = cdata->_pb;
+  pt = cdata->_pt;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_region_pixels
+//       Access: Published
+//  Description: Retrieves the coordinates of the DisplayRegion within
+//               its window, as the pixel location of its bottom-left
+//               corner, along with a pixel width and height.
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegion::
+get_region_pixels(int &xo, int &yo, int &w, int &h) const {
+  CDReader cdata(_cycler);
+  xo = cdata->_pl;
+  yo = cdata->_pb;
+  w = cdata->_pr - cdata->_pl;
+  h = cdata->_pt - cdata->_pb;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_region_pixels_i
+//       Access: Published
+//  Description: Similar to get_region_pixels(), but returns the upper
+//               left corner, and the pixel numbers are numbered from
+//               the top-left corner down, in the DirectX way of
+//               things.
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegion::
+get_region_pixels_i(int &xo, int &yo, int &w, int &h) const {
+  CDReader cdata(_cycler);
+  xo = cdata->_pl;
+  yo = cdata->_pti;
+  w = cdata->_pr - cdata->_pl;
+  h = cdata->_pbi - cdata->_pti;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_pixel_width
+//       Access: Published
+//  Description: Returns the width of the DisplayRegion in pixels.
+////////////////////////////////////////////////////////////////////
+INLINE int DisplayRegion::
+get_pixel_width() const {
+  CDReader cdata(_cycler);
+  return cdata->_pr - cdata->_pl;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_pixel_height
+//       Access: Published
+//  Description: Returns the height of the DisplayRegion in pixels.
+////////////////////////////////////////////////////////////////////
+INLINE int DisplayRegion::
+get_pixel_height() const {
+  CDReader cdata(_cycler);
+  return cdata->_pt - cdata->_pb;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DisplayRegion::set_cull_result
 //       Access: Public
@@ -199,6 +362,308 @@ CDataCull(const DisplayRegion::CDataCull &copy) :
 {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE DisplayRegionPipelineReader::
+DisplayRegionPipelineReader(DisplayRegion *object, Thread *current_thread) :
+  _object(object),
+  _current_thread(current_thread),
+  _cdata(object->_cycler.read(current_thread))
+{
+#ifdef _DEBUG
+  nassertv(_object->test_ref_count_nonzero());
+#ifdef DO_PIPELINING
+  nassertv(_cdata->test_ref_count_nonzero());
+#endif  // DO_PIPELINING
+#endif // _DEBUG
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::Copy Constructor
+//       Access: Private
+//  Description: Don't attempt to copy these objects.
+////////////////////////////////////////////////////////////////////
+INLINE DisplayRegionPipelineReader::
+DisplayRegionPipelineReader(const DisplayRegionPipelineReader &) {
+  nassertv(false);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::Copy Assignment Operator
+//       Access: Private
+//  Description: Don't attempt to copy these objects.
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegionPipelineReader::
+operator = (const DisplayRegionPipelineReader &) {
+  nassertv(false);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE DisplayRegionPipelineReader::
+~DisplayRegionPipelineReader() {
+#ifdef _DEBUG
+  nassertv(_object->test_ref_count_nonzero());
+#ifdef DO_PIPELINING
+  nassertv(_cdata->test_ref_count_nonzero());
+#endif  // DO_PIPELINING
+#endif // _DEBUG
+  _object->_cycler.release_read(_cdata);
+
+#ifdef _DEBUG
+  _object = NULL;
+  _cdata = NULL;
+#endif  // _DEBUG
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_object
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE DisplayRegion *DisplayRegionPipelineReader::
+get_object() const {
+  return _object;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_current_thread
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE Thread *DisplayRegionPipelineReader::
+get_current_thread() const {
+  return _current_thread;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::is_any_clear_active
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool DisplayRegionPipelineReader::
+is_any_clear_active() const {
+  return _object->is_any_clear_active();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_dimensions
+//       Access: Public
+//  Description: Retrieves the coordinates of the DisplayRegion's
+//               rectangle within its GraphicsOutput.  These numbers
+//               will be in the range [0..1].
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegionPipelineReader::
+get_dimensions(float &l, float &r, float &b, float &t) const {
+  l = _cdata->_l;
+  r = _cdata->_r;
+  b = _cdata->_b;
+  t = _cdata->_t;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_left
+//       Access: Public
+//  Description: Retrieves the x coordinate of the left edge of the
+//               rectangle within its GraphicsOutput.  This number
+//               will be in the range [0..1].
+////////////////////////////////////////////////////////////////////
+INLINE float DisplayRegionPipelineReader::
+get_left() const {
+  return _cdata->_l;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_right
+//       Access: Public
+//  Description: Retrieves the x coordinate of the right edge of the
+//               rectangle within its GraphicsOutput.  This number
+//               will be in the range [0..1].
+////////////////////////////////////////////////////////////////////
+INLINE float DisplayRegionPipelineReader::
+get_right() const {
+  return _cdata->_r;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_bottom
+//       Access: Public
+//  Description: Retrieves the y coordinate of the bottom edge of 
+//               the rectangle within its GraphicsOutput.  This 
+//               number will be in the range [0..1].
+////////////////////////////////////////////////////////////////////
+INLINE float DisplayRegionPipelineReader::
+get_bottom() const {
+  return _cdata->_b;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_top
+//       Access: Public
+//  Description: Retrieves the y coordinate of the top edge of the
+//               rectangle within its GraphicsOutput.  This number
+//               will be in the range [0..1].
+////////////////////////////////////////////////////////////////////
+INLINE float DisplayRegionPipelineReader::
+get_top() const {
+  return _cdata->_t;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_window
+//       Access: Public
+//  Description: Returns the GraphicsOutput that this DisplayRegion is
+//               ultimately associated with, or NULL if no window is
+//               associated.
+////////////////////////////////////////////////////////////////////
+INLINE GraphicsOutput *DisplayRegionPipelineReader::
+get_window() const {
+  return _object->_window;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_camera
+//       Access: Public
+//  Description: Returns the camera associated with this
+//               DisplayRegion, or an empty NodePath if no camera is
+//               associated.
+////////////////////////////////////////////////////////////////////
+INLINE NodePath DisplayRegionPipelineReader::
+get_camera() const {
+  return _cdata->_camera;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::is_active
+//       Access: Public
+//  Description: Returns the active flag associated with the
+//               DisplayRegion.
+////////////////////////////////////////////////////////////////////
+INLINE bool DisplayRegionPipelineReader::
+is_active() const {
+  return _cdata->_active;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_sort
+//       Access: Public
+//  Description: Returns the sort value associated with the
+//               DisplayRegion.
+////////////////////////////////////////////////////////////////////
+INLINE int DisplayRegionPipelineReader::
+get_sort() const {
+  return _cdata->_sort;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_stereo_channel
+//       Access: Public
+//  Description: Returns whether the DisplayRegion is specified as the
+//               left or right channel of a stereo pair, or whether it
+//               is a normal, monocular image.  See
+//               set_stereo_channel().
+////////////////////////////////////////////////////////////////////
+INLINE Lens::StereoChannel DisplayRegionPipelineReader::
+get_stereo_channel() {
+  return _cdata->_stereo_channel;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_clear_depth_between_eyes
+//       Access: Public
+//  Description: Returns whether the depth buffer is cleared again
+//               between the left and right eyes of a stereo
+//               DisplayRegion.  See set_clear_depth_between_eyes().
+////////////////////////////////////////////////////////////////////
+INLINE bool DisplayRegionPipelineReader::
+get_clear_depth_between_eyes() const {
+  return _object->_clear_depth_between_eyes;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_cube_map_index
+//       Access: Public
+//  Description: Returns the cube map face index associated with this
+//               particular DisplayRegion, or -1 if it is not
+//               associated with a cube map.  See
+//               set_cube_map_index().
+////////////////////////////////////////////////////////////////////
+INLINE int DisplayRegionPipelineReader::
+get_cube_map_index() const {
+  return _cdata->_cube_map_index;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_pixels
+//       Access: Public
+//  Description: Retrieves the coordinates of the DisplayRegion within
+//               its window, in pixels.
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegionPipelineReader::
+get_pixels(int &pl, int &pr, int &pb, int &pt) const {
+  pl = _cdata->_pl;
+  pr = _cdata->_pr;
+  pb = _cdata->_pb;
+  pt = _cdata->_pt;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_region_pixels
+//       Access: Public
+//  Description: Retrieves the coordinates of the DisplayRegion within
+//               its window, as the pixel location of its bottom-left
+//               corner, along with a pixel width and height.
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegionPipelineReader::
+get_region_pixels(int &xo, int &yo, int &w, int &h) const {
+  xo = _cdata->_pl;
+  yo = _cdata->_pb;
+  w = _cdata->_pr - _cdata->_pl;
+  h = _cdata->_pt - _cdata->_pb;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_region_pixels_i
+//       Access: Public
+//  Description: Similar to get_region_pixels(), but returns the upper
+//               left corner, and the pixel numbers are numbered from
+//               the top-left corner down, in the DirectX way of
+//               things.
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegionPipelineReader::
+get_region_pixels_i(int &xo, int &yo, int &w, int &h) const {
+  xo = _cdata->_pl;
+  yo = _cdata->_pti;
+  w = _cdata->_pr - _cdata->_pl;
+  h = _cdata->_pbi - _cdata->_pti;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_pixel_width
+//       Access: Public
+//  Description: Returns the width of the DisplayRegion in pixels.
+////////////////////////////////////////////////////////////////////
+INLINE int DisplayRegionPipelineReader::
+get_pixel_width() const {
+  return _cdata->_pr - _cdata->_pl;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_pixel_height
+//       Access: Public
+//  Description: Returns the height of the DisplayRegion in pixels.
+////////////////////////////////////////////////////////////////////
+INLINE int DisplayRegionPipelineReader::
+get_pixel_height() const {
+  return _cdata->_pt - _cdata->_pb;
+}
+
 INLINE ostream &operator << (ostream &out, const DisplayRegion &dr) {
   dr.output(out);
   return out;

+ 12 - 163
panda/src/display/displayRegion.cxx

@@ -105,74 +105,6 @@ cleanup() {
   cdata->_cull_result = NULL;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: DisplayRegion::get_dimensions
-//       Access: Published
-//  Description: Retrieves the coordinates of the DisplayRegion's
-//               rectangle within its GraphicsOutput.  These numbers
-//               will be in the range [0..1].
-////////////////////////////////////////////////////////////////////
-void DisplayRegion::
-get_dimensions(float &l, float &r, float &b, float &t) const {
-  CDReader cdata(_cycler);
-  l = cdata->_l;
-  r = cdata->_r;
-  b = cdata->_b;
-  t = cdata->_t;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DisplayRegion::get_left
-//       Access: Published
-//  Description: Retrieves the x coordinate of the left edge of the
-//               rectangle within its GraphicsOutput.  This number
-//               will be in the range [0..1].
-////////////////////////////////////////////////////////////////////
-float DisplayRegion::
-get_left() const {
-  CDReader cdata(_cycler);
-  return cdata->_l;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DisplayRegion::get_right
-//       Access: Published
-//  Description: Retrieves the x coordinate of the right edge of the
-//               rectangle within its GraphicsOutput.  This number
-//               will be in the range [0..1].
-////////////////////////////////////////////////////////////////////
-float DisplayRegion::
-get_right() const {
-  CDReader cdata(_cycler);
-  return cdata->_r;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DisplayRegion::get_bottom
-//       Access: Published
-//  Description: Retrieves the y coordinate of the bottom edge of 
-//               the rectangle within its GraphicsOutput.  This 
-//               number will be in the range [0..1].
-////////////////////////////////////////////////////////////////////
-float DisplayRegion::
-get_bottom() const {
-  CDReader cdata(_cycler);
-  return cdata->_b;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DisplayRegion::get_top
-//       Access: Published
-//  Description: Retrieves the y coordinate of the top edge of the
-//               rectangle within its GraphicsOutput.  This number
-//               will be in the range [0..1].
-////////////////////////////////////////////////////////////////////
-float DisplayRegion::
-get_top() const {
-  CDReader cdata(_cycler);
-  return cdata->_t;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: DisplayRegion::set_dimensions
 //       Access: Published
@@ -198,18 +130,6 @@ set_dimensions(float l, float r, float b, float t) {
   }
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: DisplayRegion::get_window
-//       Access: Published
-//  Description: Returns the GraphicsOutput that this DisplayRegion is
-//               ultimately associated with, or NULL if no window is
-//               associated.
-////////////////////////////////////////////////////////////////////
-GraphicsOutput *DisplayRegion::
-get_window() const {
-  return _window;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: DisplayRegion::get_pipe
 //       Access: Published
@@ -264,19 +184,6 @@ set_camera(const NodePath &camera) {
   cdata->_camera = camera;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: DisplayRegion::get_camera
-//       Access: Published
-//  Description: Returns the camera associated with this
-//               DisplayRegion, or an empty NodePath if no camera is
-//               associated.
-////////////////////////////////////////////////////////////////////
-NodePath DisplayRegion::
-get_camera() const {
-  CDReader cdata(_cycler);
-  return cdata->_camera;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: DisplayRegion::set_active
 //       Access: Published
@@ -425,76 +332,6 @@ compute_pixels_all_stages(int x_size, int y_size) {
   CLOSE_ITERATE_ALL_STAGES(_cycler);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: DisplayRegion::get_pixels
-//       Access: Published
-//  Description: Retrieves the coordinates of the DisplayRegion within
-//               its window, in pixels.
-////////////////////////////////////////////////////////////////////
-void DisplayRegion::
-get_pixels(int &pl, int &pr, int &pb, int &pt) const {
-  CDReader cdata(_cycler);
-  pl = cdata->_pl;
-  pr = cdata->_pr;
-  pb = cdata->_pb;
-  pt = cdata->_pt;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DisplayRegion::get_region_pixels
-//       Access: Published
-//  Description: Retrieves the coordinates of the DisplayRegion within
-//               its window, as the pixel location of its bottom-left
-//               corner, along with a pixel width and height.
-////////////////////////////////////////////////////////////////////
-void DisplayRegion::
-get_region_pixels(int &xo, int &yo, int &w, int &h) const {
-  CDReader cdata(_cycler);
-  xo = cdata->_pl;
-  yo = cdata->_pb;
-  w = cdata->_pr - cdata->_pl;
-  h = cdata->_pt - cdata->_pb;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DisplayRegion::get_region_pixels_i
-//       Access: Published
-//  Description: Similar to get_region_pixels(), but returns the upper
-//               left corner, and the pixel numbers are numbered from
-//               the top-left corner down, in the DirectX way of
-//               things.
-////////////////////////////////////////////////////////////////////
-void DisplayRegion::
-get_region_pixels_i(int &xo, int &yo, int &w, int &h) const {
-  CDReader cdata(_cycler);
-  xo = cdata->_pl;
-  yo = cdata->_pti;
-  w = cdata->_pr - cdata->_pl;
-  h = cdata->_pbi - cdata->_pti;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DisplayRegion::get_pixel_width
-//       Access: Published
-//  Description: Returns the width of the DisplayRegion in pixels.
-////////////////////////////////////////////////////////////////////
-int DisplayRegion::
-get_pixel_width() const {
-  CDReader cdata(_cycler);
-  return cdata->_pr - cdata->_pl;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DisplayRegion::get_pixel_height
-//       Access: Published
-//  Description: Returns the height of the DisplayRegion in pixels.
-////////////////////////////////////////////////////////////////////
-int DisplayRegion::
-get_pixel_height() const {
-  CDReader cdata(_cycler);
-  return cdata->_pt - cdata->_pb;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: DisplayRegion::output
 //       Access: Published
@@ -773,3 +610,15 @@ CycleData *DisplayRegion::CDataCull::
 make_copy() const {
   return new CDataCull(*this);
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_pipe
+//       Access: Public
+//  Description: Returns the GraphicsPipe that this DisplayRegion is
+//               ultimately associated with, or NULL if no pipe is
+//               associated.
+////////////////////////////////////////////////////////////////////
+GraphicsPipe *DisplayRegionPipelineReader::
+get_pipe() const {
+  return (_object->_window != (GraphicsOutput *)NULL) ? _object->_window->get_pipe() : NULL;
+}

+ 64 - 13
panda/src/display/displayRegion.h

@@ -34,7 +34,7 @@
 #include "pipelineCycler.h"
 #include "config_display.h"
 #include "lens.h"
-
+#include "deletedChain.h"
 #include "plist.h"
 
 class GraphicsOutput;
@@ -70,18 +70,18 @@ public:
   INLINE bool operator < (const DisplayRegion &other) const;
 
 PUBLISHED:
-  void get_dimensions(float &l, float &r, float &b, float &t) const;
-  float get_left() const;
-  float get_right() const;
-  float get_bottom() const;
-  float get_top() const;
+  INLINE void get_dimensions(float &l, float &r, float &b, float &t) const;
+  INLINE float get_left() const;
+  INLINE float get_right() const;
+  INLINE float get_bottom() const;
+  INLINE float get_top() const;
   void set_dimensions(float l, float r, float b, float t);
 
-  GraphicsOutput *get_window() const;
+  INLINE GraphicsOutput *get_window() const;
   GraphicsPipe *get_pipe() const;
 
   void set_camera(const NodePath &camera);
-  NodePath get_camera() const;
+  INLINE NodePath get_camera() const;
 
   void set_active(bool active);
   INLINE bool is_active() const;
@@ -102,12 +102,12 @@ PUBLISHED:
   void compute_pixels_all_stages();
   void compute_pixels(int x_size, int y_size);
   void compute_pixels_all_stages(int x_size, int y_size);
-  void get_pixels(int &pl, int &pr, int &pb, int &pt) const;
-  void get_region_pixels(int &xo, int &yo, int &w, int &h) const;
-  void get_region_pixels_i(int &xo, int &yo, int &w, int &h) const;
+  INLINE void get_pixels(int &pl, int &pr, int &pb, int &pt) const;
+  INLINE void get_region_pixels(int &xo, int &yo, int &w, int &h) const;
+  INLINE void get_region_pixels_i(int &xo, int &yo, int &w, int &h) const;
 
-  int get_pixel_width() const;
-  int get_pixel_height() const;
+  INLINE int get_pixel_width() const;
+  INLINE int get_pixel_height() const;
 
   void output(ostream &out) const;
 
@@ -212,6 +212,57 @@ private:
   static TypeHandle _type_handle;
 
   friend class GraphicsOutput;
+  friend class DisplayRegionPipelineReader;
+};
+
+////////////////////////////////////////////////////////////////////
+//       Class : DisplayRegionPipelineReader
+// Description : Encapsulates the data from a DisplayRegion,
+//               pre-fetched for one stage of the pipeline.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA DisplayRegionPipelineReader {
+public:
+  INLINE DisplayRegionPipelineReader(DisplayRegion *object, Thread *current_thread);
+private:
+  INLINE DisplayRegionPipelineReader(const DisplayRegionPipelineReader &copy);
+  INLINE void operator = (const DisplayRegionPipelineReader &copy);
+
+public:
+  INLINE ~DisplayRegionPipelineReader();
+  ALLOC_DELETED_CHAIN(DisplayRegionPipelineReader);
+
+  INLINE DisplayRegion *get_object() const;
+  INLINE Thread *get_current_thread() const;
+
+  INLINE bool is_any_clear_active() const;
+
+  INLINE void get_dimensions(float &l, float &r, float &b, float &t) const;
+  INLINE float get_left() const;
+  INLINE float get_right() const;
+  INLINE float get_bottom() const;
+  INLINE float get_top() const;
+
+  INLINE GraphicsOutput *get_window() const;
+  GraphicsPipe *get_pipe() const;
+
+  INLINE NodePath get_camera() const;
+  INLINE bool is_active() const;
+  INLINE int get_sort() const;
+  INLINE Lens::StereoChannel get_stereo_channel();
+  INLINE bool get_clear_depth_between_eyes() const;
+  INLINE int get_cube_map_index() const;
+
+  INLINE void get_pixels(int &pl, int &pr, int &pb, int &pt) const;
+  INLINE void get_region_pixels(int &xo, int &yo, int &w, int &h) const;
+  INLINE void get_region_pixels_i(int &xo, int &yo, int &w, int &h) const;
+
+  INLINE int get_pixel_width() const;
+  INLINE int get_pixel_height() const;
+
+private:
+  DisplayRegion *_object;
+  Thread *_current_thread;
+  const DisplayRegion::CData *_cdata;
 };
 
 INLINE ostream &operator << (ostream &out, const DisplayRegion &dr);

+ 126 - 80
panda/src/display/graphicsEngine.cxx

@@ -434,6 +434,8 @@ make_output(GraphicsPipe *pipe,
 ////////////////////////////////////////////////////////////////////
 bool GraphicsEngine::
 remove_window(GraphicsOutput *window) {
+  Thread *current_thread = Thread::get_current_thread();
+
   // First, make sure we know what this window is.
   PT(GraphicsOutput) ptwin = window;
   size_t count;
@@ -449,7 +451,7 @@ remove_window(GraphicsOutput *window) {
     return false;
   }
 
-  do_remove_window(window);
+  do_remove_window(window, current_thread);
 
   nassertr(count == 1, true);
   return true;
@@ -464,16 +466,18 @@ remove_window(GraphicsOutput *window) {
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
 remove_all_windows() {
+  Thread *current_thread = Thread::get_current_thread();
+
   Windows::iterator wi;
   for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
     GraphicsOutput *win = (*wi);
-    do_remove_window(win);
+    do_remove_window(win, current_thread);
   }
   
   _windows.clear();
 
-  _app.do_close(this);
-  _app.do_pending(this);
+  _app.do_close(this, current_thread);
+  _app.do_pending(this, current_thread);
   terminate_threads();
 }
 
@@ -542,6 +546,8 @@ get_window(int n) const {
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
 render_frame() {
+  Thread *current_thread = Thread::get_current_thread();
+
   // Anything that happens outside of GraphicsEngine::render_frame()
   // is deemed to be App.
 #ifdef DO_PSTATS
@@ -569,7 +575,7 @@ render_frame() {
   }
 
   if (_flip_state != FS_flip) {
-    do_flip_frame();
+    do_flip_frame(current_thread);
   }
 
   // Are any of the windows ready to be deleted?
@@ -579,7 +585,7 @@ render_frame() {
   for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
     GraphicsOutput *win = (*wi);
     if (win->get_delete_flag()) {
-      do_remove_window(win);
+      do_remove_window(win, current_thread);
       
     } else {
       new_windows.push_back(win);
@@ -612,7 +618,7 @@ render_frame() {
 
   // Now it's time to do any drawing from the main frame--after all of
   // the App code has executed, but before we begin the next frame.
-  _app.do_frame(this);
+  _app.do_frame(this, current_thread);
   
   // Grab each thread's mutex again after all windows have flipped,
   // and wait for the thread to finish.
@@ -756,6 +762,8 @@ render_frame() {
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
 open_windows() {
+  Thread *current_thread = Thread::get_current_thread();
+
   MutexHolder holder(_lock);
 
   if (!_windows_sorted) {
@@ -765,8 +773,8 @@ open_windows() {
   // We do it twice, to allow both cull and draw to process the
   // window.
   for (int i = 0; i < 2; ++i) {
-    _app.do_windows(this);
-    _app.do_pending(this);
+    _app.do_windows(this, current_thread);
+    _app.do_pending(this, current_thread);
 
     PStatTimer timer(_wait_pcollector);
     Threads::const_iterator ti;
@@ -796,10 +804,11 @@ open_windows() {
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
 sync_frame() {
+  Thread *current_thread = Thread::get_current_thread();
   MutexHolder holder(_lock);
 
   if (_flip_state == FS_draw) {
-    do_sync_frame();
+    do_sync_frame(current_thread);
   }
 }
 
@@ -814,10 +823,11 @@ sync_frame() {
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
 flip_frame() {
+  Thread *current_thread = Thread::get_current_thread();
   MutexHolder holder(_lock);
 
   if (_flip_state != FS_flip) {
-    do_flip_frame();
+    do_flip_frame(current_thread);
   }
 }
 
@@ -952,7 +962,8 @@ set_window_sort(GraphicsOutput *window, int sort) {
 //               threading model begins with the "-" character.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
-cull_and_draw_together(const GraphicsEngine::Windows &wlist) {
+cull_and_draw_together(const GraphicsEngine::Windows &wlist,
+                       Thread *current_thread) {
   PStatTimer timer(_cull_pcollector);
 
   Windows::const_iterator wi;
@@ -960,13 +971,13 @@ cull_and_draw_together(const GraphicsEngine::Windows &wlist) {
     GraphicsOutput *win = (*wi);
     if (win->is_active() && win->get_gsg()->is_active()) {
       if (win->begin_frame(GraphicsOutput::FM_render)) {
-        win->clear();
+        win->clear(current_thread);
       
         int num_display_regions = win->get_num_active_display_regions();
         for (int i = 0; i < num_display_regions; i++) {
           DisplayRegion *dr = win->get_active_display_region(i);
           if (dr != (DisplayRegion *)NULL) {
-            cull_and_draw_together(win, dr);
+            cull_and_draw_together(win, dr, current_thread);
           }
         }
         win->end_frame(GraphicsOutput::FM_render);
@@ -995,30 +1006,40 @@ cull_and_draw_together(const GraphicsEngine::Windows &wlist) {
 //               cull_and_draw_together(), above.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
-cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr) {
+cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr,
+                       Thread *current_thread) {
   GraphicsStateGuardian *gsg = win->get_gsg();
   nassertv(gsg != (GraphicsStateGuardian *)NULL);
 
-  win->change_scenes(dr);
-  gsg->prepare_display_region(dr, dr->get_stereo_channel());
+  DisplayRegionPipelineReader *dr_reader = 
+    new DisplayRegionPipelineReader(dr, current_thread);
 
-  PT(SceneSetup) scene_setup = setup_scene(gsg, dr);
+  win->change_scenes(dr_reader);
+  gsg->prepare_display_region(dr_reader, dr_reader->get_stereo_channel());
+
+  PT(SceneSetup) scene_setup = setup_scene(gsg, dr_reader);
   if (!gsg->set_scene(scene_setup)) {
     // The scene or lens is inappropriate somehow.
     display_cat.error()
       << gsg->get_type() << " cannot render scene with specified lens.\n";
 
   } else {
-    if (dr->is_any_clear_active()) {
+    if (dr_reader->is_any_clear_active()) {
       gsg->clear(dr);
     }
 
     DrawCullHandler cull_handler(gsg);
     if (gsg->begin_scene()) {
-      do_cull(&cull_handler, scene_setup, gsg);
+      delete dr_reader;
+      dr_reader = NULL;
+      do_cull(&cull_handler, scene_setup, gsg, current_thread);
       gsg->end_scene();
     }
   }
+
+  if (dr_reader != (DisplayRegionPipelineReader *)NULL) {
+    delete dr_reader;
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1030,7 +1051,7 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr) {
 //               drawing.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
-cull_to_bins(const GraphicsEngine::Windows &wlist) {
+cull_to_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
   PStatTimer timer(_cull_pcollector);
 
   // Keep track of the cameras we have already used in this thread to
@@ -1046,13 +1067,17 @@ cull_to_bins(const GraphicsEngine::Windows &wlist) {
       for (int i = 0; i < num_display_regions; ++i) {
         DisplayRegion *dr = win->get_active_display_region(i);
         if (dr != (DisplayRegion *)NULL) {
-          NodePath camera = dr->get_camera();
+          DisplayRegionPipelineReader *dr_reader = 
+            new DisplayRegionPipelineReader(dr, current_thread);
+          NodePath camera = dr_reader->get_camera();
           AlreadyCulled::iterator aci = already_culled.insert(AlreadyCulled::value_type(camera, NULL)).first;
           if ((*aci).second == NULL) {
             // We have not used this camera already in this thread.
             // Perform the cull operation.
+            delete dr_reader;
+            dr_reader = NULL;
             (*aci).second = dr;
-            cull_to_bins(win, dr);
+            cull_to_bins(win, dr, current_thread);
 
           } else {
             // We have already culled a scene using this camera in
@@ -1064,7 +1089,11 @@ cull_to_bins(const GraphicsEngine::Windows &wlist) {
             // the other DisplayRegion.
             DisplayRegion *other_dr = (*aci).second;
             dr->set_cull_result(other_dr->get_cull_result(),
-                                setup_scene(win->get_gsg(), dr));
+                                setup_scene(win->get_gsg(), dr_reader));
+          }
+
+          if (dr_reader != (DisplayRegionPipelineReader *)NULL) {
+            delete dr_reader;
           }
         }
       }
@@ -1079,7 +1108,7 @@ cull_to_bins(const GraphicsEngine::Windows &wlist) {
 //               above.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
-cull_to_bins(GraphicsOutput *win, DisplayRegion *dr) {
+cull_to_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread) {
   GraphicsStateGuardian *gsg = win->get_gsg();
   nassertv(gsg != (GraphicsStateGuardian *)NULL);
 
@@ -1093,12 +1122,13 @@ cull_to_bins(GraphicsOutput *win, DisplayRegion *dr) {
     } else {
       cull_result = new CullResult(gsg);
     }
-    scene_setup = setup_scene(gsg, dr);
+    DisplayRegionPipelineReader dr_reader(dr, current_thread);
+    scene_setup = setup_scene(gsg, &dr_reader);
   }
 
   if (scene_setup != (SceneSetup *)NULL) {
     BinCullHandler cull_handler(cull_result);
-    do_cull(&cull_handler, scene_setup, gsg);
+    do_cull(&cull_handler, scene_setup, gsg, current_thread);
 
     {
       PStatTimer timer(_cull_sort_pcollector);
@@ -1119,19 +1149,19 @@ cull_to_bins(GraphicsOutput *win, DisplayRegion *dr) {
 //               cull_to_bins().
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
-draw_bins(const GraphicsEngine::Windows &wlist) {
+draw_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
   Windows::const_iterator wi;
   for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
     GraphicsOutput *win = (*wi);
     if (win->is_active() && win->get_gsg()->is_active()) {
       if (win->begin_frame(GraphicsOutput::FM_render)) {
-        win->clear();
+        win->clear(current_thread);
       
         int num_display_regions = win->get_num_active_display_regions();
         for (int i = 0; i < num_display_regions; ++i) {
           DisplayRegion *dr = win->get_active_display_region(i);
           if (dr != (DisplayRegion *)NULL) {
-            draw_bins(win, dr);
+            draw_bins(win, dr, current_thread);
           }
         }
         win->end_frame(GraphicsOutput::FM_render);
@@ -1161,14 +1191,14 @@ draw_bins(const GraphicsEngine::Windows &wlist) {
 //               particular DisplayRegion.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
-draw_bins(GraphicsOutput *win, DisplayRegion *dr) {
+draw_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread) {
   GraphicsStateGuardian *gsg = win->get_gsg();
   nassertv(gsg != (GraphicsStateGuardian *)NULL);
 
   PT(CullResult) cull_result = dr->get_cull_result();
   PT(SceneSetup) scene_setup = dr->get_scene_setup();
   if (cull_result != (CullResult *)NULL && scene_setup != (SceneSetup *)NULL) {
-    do_draw(cull_result, scene_setup, win, dr);
+    do_draw(cull_result, scene_setup, win, dr, current_thread);
   }
 }
 
@@ -1180,7 +1210,7 @@ draw_bins(GraphicsOutput *win, DisplayRegion *dr) {
 //               graphics context both get created.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
-make_contexts(const GraphicsEngine::Windows &wlist) {
+make_contexts(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
   Windows::const_iterator wi;
   for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
     GraphicsOutput *win = (*wi);
@@ -1198,7 +1228,7 @@ make_contexts(const GraphicsEngine::Windows &wlist) {
 //               list of windows.  This is run in the window thread.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
-process_events(const GraphicsEngine::Windows &wlist) {
+process_events(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
   Windows::const_iterator wi;
   for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
     GraphicsOutput *win = (*wi);
@@ -1214,7 +1244,7 @@ process_events(const GraphicsEngine::Windows &wlist) {
 //               the given list.  This is run in the draw thread.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
-flip_windows(const GraphicsEngine::Windows &wlist) {
+flip_windows(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
   Windows::const_iterator wi;
   for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
     GraphicsOutput *win = (*wi);
@@ -1239,7 +1269,7 @@ flip_windows(const GraphicsEngine::Windows &wlist) {
 //               is already held before this method is called.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
-do_sync_frame() {
+do_sync_frame(Thread *current_thread) {
   nassertv(_lock.debug_is_locked());
 
   // Statistics
@@ -1266,7 +1296,7 @@ do_sync_frame() {
 //               is already held before this method is called.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
-do_flip_frame() {
+do_flip_frame(Thread *current_thread) {
   nassertv(_lock.debug_is_locked());
 
   // Statistics
@@ -1291,7 +1321,7 @@ do_flip_frame() {
   }
   
   // Now signal all of our threads to flip the windows.
-  _app.do_flip(this);
+  _app.do_flip(this, current_thread);
 
   {
     Threads::const_iterator ti;
@@ -1316,7 +1346,7 @@ do_flip_frame() {
 //               reason.
 ////////////////////////////////////////////////////////////////////
 PT(SceneSetup) GraphicsEngine::
-setup_scene(GraphicsStateGuardian *gsg, DisplayRegion *dr) {
+setup_scene(GraphicsStateGuardian *gsg, DisplayRegionPipelineReader *dr) {
   PStatTimer timer(_cull_setup_pcollector);
 
   GraphicsOutput *window = dr->get_window();
@@ -1380,7 +1410,7 @@ setup_scene(GraphicsStateGuardian *gsg, DisplayRegion *dr) {
     initial_state = initial_state->compose(get_invert_polygon_state());
   }
 
-  scene_setup->set_display_region(dr);
+  scene_setup->set_display_region(dr->get_object());
   scene_setup->set_viewport_size(dr->get_pixel_width(), dr->get_pixel_height());
   scene_setup->set_scene_root(scene_root);
   scene_setup->set_camera_path(camera);
@@ -1400,7 +1430,7 @@ setup_scene(GraphicsStateGuardian *gsg, DisplayRegion *dr) {
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
 do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,
-        GraphicsStateGuardian *gsg) {
+        GraphicsStateGuardian *gsg, Thread *current_thread) {
   CullTraverser trav(gsg);
   trav.set_cull_handler(cull_handler);
   trav.set_depth_offset_decals(depth_offset_decals && gsg->depth_offset_decals());
@@ -1439,21 +1469,24 @@ do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
 do_draw(CullResult *cull_result, SceneSetup *scene_setup,
-        GraphicsOutput *win, DisplayRegion *dr) {
+        GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread) {
   // Statistics
   PStatTimer timer(_draw_pcollector);
 
+  DisplayRegionPipelineReader *dr_reader = 
+    new DisplayRegionPipelineReader(dr, current_thread);
+
   GraphicsStateGuardian *gsg = win->get_gsg();
-  win->change_scenes(dr);
+  win->change_scenes(dr_reader);
 
-  if (dr->get_stereo_channel() == Lens::SC_stereo) {
+  if (dr_reader->get_stereo_channel() == Lens::SC_stereo) {
     // A special case.  For a stereo DisplayRegion, we render the left
     // eye, followed by the right eye.
-    if (dr->is_any_clear_active()) {
-      gsg->prepare_display_region(dr, Lens::SC_stereo);
-      gsg->clear(dr);
+    if (dr_reader->is_any_clear_active()) {
+      gsg->prepare_display_region(dr_reader, Lens::SC_stereo);
+      gsg->clear(dr_reader->get_object());
     }
-    gsg->prepare_display_region(dr, Lens::SC_left);
+    gsg->prepare_display_region(dr_reader, Lens::SC_left);
 
     if (!gsg->set_scene(scene_setup)) {
       // The scene or lens is inappropriate somehow.
@@ -1461,19 +1494,24 @@ do_draw(CullResult *cull_result, SceneSetup *scene_setup,
         << gsg->get_type() << " cannot render scene with specified lens.\n";
     } else {
       if (gsg->begin_scene()) {
-        cull_result->draw();
+        delete dr_reader;
+        dr_reader = NULL;
+        cull_result->draw(current_thread);
         gsg->end_scene();
+        dr_reader = new DisplayRegionPipelineReader(dr, current_thread);
       }
-      if (dr->get_clear_depth_between_eyes()) {
+      if (dr_reader->get_clear_depth_between_eyes()) {
         DrawableRegion clear_region;
         clear_region.set_clear_depth_active(true);
         clear_region.set_clear_depth(dr->get_clear_depth());
         gsg->clear(&clear_region);
       }
-      gsg->prepare_display_region(dr, Lens::SC_right);
+      gsg->prepare_display_region(dr_reader, Lens::SC_right);
       gsg->set_scene(scene_setup);
       if (gsg->begin_scene()) {
-        cull_result->draw();
+        delete dr_reader;
+        dr_reader = NULL;
+        cull_result->draw(current_thread);
         gsg->end_scene();
       }
     }
@@ -1481,22 +1519,28 @@ do_draw(CullResult *cull_result, SceneSetup *scene_setup,
   } else {
     // For a mono DisplayRegion, or a left/right eye only
     // DisplayRegion, we just render that.
-    gsg->prepare_display_region(dr, dr->get_stereo_channel());
+    gsg->prepare_display_region(dr_reader, dr_reader->get_stereo_channel());
 
     if (!gsg->set_scene(scene_setup)) {
       // The scene or lens is inappropriate somehow.
       display_cat.error()
         << gsg->get_type() << " cannot render scene with specified lens.\n";
     } else {
-      if (dr->is_any_clear_active()) {
-        gsg->clear(dr);
+      if (dr_reader->is_any_clear_active()) {
+        gsg->clear(dr_reader->get_object());
       }
       if (gsg->begin_scene()) {
-        cull_result->draw();
+        delete dr_reader;
+        dr_reader = NULL;
+        cull_result->draw(current_thread);
         gsg->end_scene();
       }
     }
   }
+
+  if (dr_reader != (DisplayRegionPipelineReader *)NULL) {
+    delete dr_reader;
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1564,7 +1608,7 @@ do_add_window(GraphicsOutput *window, GraphicsStateGuardian *gsg,
 //               _windows list itself.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
-do_remove_window(GraphicsOutput *window) {
+do_remove_window(GraphicsOutput *window, Thread *current_thread) {
   PT(GraphicsPipe) pipe = window->get_pipe();
   window->_pipe = (GraphicsPipe *)NULL;
 
@@ -1582,7 +1626,7 @@ do_remove_window(GraphicsOutput *window) {
 
   // If the window happened to be controlled by the app thread, we
   // might as well close it now rather than waiting for next frame.
-  _app.do_pending(this);
+  _app.do_pending(this, current_thread);
 
   if (display_cat.is_debug()) {
     display_cat.debug()
@@ -1858,16 +1902,16 @@ resort_windows() {
 //               the draw list, etc.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::WindowRenderer::
-do_frame(GraphicsEngine *engine) {
+do_frame(GraphicsEngine *engine, Thread *current_thread) {
   PStatTimer timer(engine->_do_frame_pcollector);
   MutexHolder holder(_wl_lock);
 
   do_callbacks(CB_pre_frame);
 
-  engine->cull_to_bins(_cull);
-  engine->cull_and_draw_together(_cdraw);
-  engine->draw_bins(_draw);
-  engine->process_events(_window);
+  engine->cull_to_bins(_cull, current_thread);
+  engine->cull_and_draw_together(_cdraw, current_thread);
+  engine->draw_bins(_draw, current_thread);
+  engine->process_events(_window, current_thread);
 
   // If any GSG's on the list have no more outstanding pointers, clean
   // them up.  (We are in the draw thread for all of these GSG's.)
@@ -1902,13 +1946,13 @@ do_frame(GraphicsEngine *engine) {
 //               only if you want these things to open immediately.)
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::WindowRenderer::
-do_windows(GraphicsEngine *engine) {
+do_windows(GraphicsEngine *engine, Thread *current_thread) {
   MutexHolder holder(_wl_lock);
 
-  engine->process_events(_window);
+  engine->process_events(_window, current_thread);
 
-  engine->make_contexts(_cdraw);
-  engine->make_contexts(_draw);
+  engine->make_contexts(_cdraw, current_thread);
+  engine->make_contexts(_draw, current_thread);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1918,10 +1962,10 @@ do_windows(GraphicsEngine *engine) {
 //               thread.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::WindowRenderer::
-do_flip(GraphicsEngine *engine) {
+do_flip(GraphicsEngine *engine, Thread *current_thread) {
   MutexHolder holder(_wl_lock);
-  engine->flip_windows(_cdraw);
-  engine->flip_windows(_draw);
+  engine->flip_windows(_cdraw, current_thread);
+  engine->flip_windows(_draw, current_thread);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1930,7 +1974,7 @@ do_flip(GraphicsEngine *engine) {
 //  Description: Closes all the windows on the _window list.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::WindowRenderer::
-do_close(GraphicsEngine *engine) {
+do_close(GraphicsEngine *engine, Thread *current_thread) {
   MutexHolder holder(_wl_lock);
   Windows::iterator wi;
   for (wi = _window.begin(); wi != _window.end(); ++wi) {
@@ -1963,7 +2007,7 @@ do_close(GraphicsEngine *engine) {
 //               removed from the WindowRenderer.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::WindowRenderer::
-do_pending(GraphicsEngine *engine) {
+do_pending(GraphicsEngine *engine, Thread *current_thread) {
   MutexHolder holder(_wl_lock);
 
   if (!_pending_close.empty()) {
@@ -2076,6 +2120,8 @@ RenderThread(const string &name, GraphicsEngine *engine) :
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::RenderThread::
 thread_main() {
+  Thread *current_thread = Thread::get_current_thread();
+
   MutexHolder holder(_cv_mutex);
   while (true) {
     nassertv(_cv_mutex.debug_is_locked());
@@ -2085,26 +2131,26 @@ thread_main() {
       break;
 
     case TS_do_frame:
-      do_pending(_engine);
-      do_frame(_engine);
+      do_pending(_engine, current_thread);
+      do_frame(_engine, current_thread);
       break;
 
     case TS_do_flip:
-      do_flip(_engine);
+      do_flip(_engine, current_thread);
       break;
 
     case TS_do_release:
-      do_pending(_engine);
+      do_pending(_engine, current_thread);
       break;
 
     case TS_do_windows:
-      do_windows(_engine);
-      do_pending(_engine);
+      do_windows(_engine, current_thread);
+      do_pending(_engine, current_thread);
       break;
 
     case TS_terminate:
-      do_pending(_engine);
-      do_close(_engine);
+      do_pending(_engine, current_thread);
+      do_close(_engine, current_thread);
       _thread_state = TS_done;
       _cv_done.signal();
       return;

+ 25 - 23
panda/src/display/graphicsEngine.h

@@ -152,30 +152,32 @@ private:
 
   void set_window_sort(GraphicsOutput *window, int sort);
 
-  void cull_and_draw_together(const Windows &wlist);
-  void cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr);
-
-  void cull_to_bins(const Windows &wlist);
-  void cull_to_bins(GraphicsOutput *win, DisplayRegion *dr);
-  void draw_bins(const Windows &wlist);
-  void draw_bins(GraphicsOutput *win, DisplayRegion *dr);
-  void make_contexts(const Windows &wlist);
-
-  void process_events(const Windows &wlist);
-  void flip_windows(const Windows &wlist);
-  void do_sync_frame();
-  void do_flip_frame();
+  void cull_and_draw_together(const Windows &wlist, Thread *current_thread);
+  void cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr,
+                              Thread *current_thread);
+
+  void cull_to_bins(const Windows &wlist, Thread *current_thread);
+  void cull_to_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread);
+  void draw_bins(const Windows &wlist, Thread *current_thread);
+  void draw_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread);
+  void make_contexts(const Windows &wlist, Thread *current_thread);
+
+  void process_events(const Windows &wlist, Thread *current_thread);
+  void flip_windows(const Windows &wlist, Thread *current_thread);
+  void do_sync_frame(Thread *current_thread);
+  void do_flip_frame(Thread *current_thread);
   INLINE void close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
 
-  PT(SceneSetup) setup_scene(GraphicsStateGuardian *gsg, DisplayRegion *dr);
+  PT(SceneSetup) setup_scene(GraphicsStateGuardian *gsg, 
+                             DisplayRegionPipelineReader *dr);
   void do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,
-               GraphicsStateGuardian *gsg);
+               GraphicsStateGuardian *gsg, Thread *current_thread);
   void do_draw(CullResult *cull_result, SceneSetup *scene_setup,
-               GraphicsOutput *win, DisplayRegion *dr);
+               GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread);
 
   void do_add_window(GraphicsOutput *window, GraphicsStateGuardian *gsg,
                      const GraphicsThreadingModel &threading_model);
-  void do_remove_window(GraphicsOutput *window);
+  void do_remove_window(GraphicsOutput *window, Thread *current_thread);
   void do_resort_windows();
   void terminate_threads();
 
@@ -275,12 +277,12 @@ private:
     void add_window(Windows &wlist, GraphicsOutput *window);
     void remove_window(GraphicsOutput *window);
     void resort_windows();
-    void do_frame(GraphicsEngine *engine);
-    void do_windows(GraphicsEngine *engine);
-    void do_flip(GraphicsEngine *engine);
-    void do_release(GraphicsEngine *engine);
-    void do_close(GraphicsEngine *engine);
-    void do_pending(GraphicsEngine *engine);
+    void do_frame(GraphicsEngine *engine, Thread *current_thread);
+    void do_windows(GraphicsEngine *engine, Thread *current_thread);
+    void do_flip(GraphicsEngine *engine, Thread *current_thread);
+    void do_release(GraphicsEngine *engine, Thread *current_thread);
+    void do_close(GraphicsEngine *engine, Thread *current_thread);
+    void do_pending(GraphicsEngine *engine, Thread *current_thread);
     bool any_done_gsgs() const;
 
     bool add_callback(CallbackTime callback_time, const Callback &callback);

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

@@ -971,7 +971,7 @@ prepare_for_deletion() {
 //               This function is called only within the draw thread.
 ////////////////////////////////////////////////////////////////////
 void GraphicsOutput::
-clear() {
+clear(Thread *current_thread) {
   if (is_any_clear_active()) {
     if (display_cat.is_spam()) {
       display_cat.spam()
@@ -981,7 +981,8 @@ clear() {
 
     nassertv(_gsg != (GraphicsStateGuardian *)NULL);
 
-    _gsg->prepare_display_region(_default_display_region, Lens::SC_mono);
+    DisplayRegionPipelineReader dr_reader(_default_display_region, current_thread);
+    _gsg->prepare_display_region(&dr_reader, Lens::SC_mono);
     _gsg->clear(this);
   }
 }
@@ -1049,14 +1050,14 @@ copy_to_textures() {
 //               of a cube map.
 ////////////////////////////////////////////////////////////////////
 void GraphicsOutput::
-change_scenes(DisplayRegion *new_dr) {
+change_scenes(DisplayRegionPipelineReader *new_dr) {
   int new_cube_map_index = new_dr->get_cube_map_index();
   if (new_cube_map_index != -1 &&
       new_cube_map_index != _cube_map_index) {
     int old_cube_map_index = _cube_map_index;
     DisplayRegion *old_cube_map_dr = _cube_map_dr;
     _cube_map_index = new_cube_map_index;
-    _cube_map_dr = new_dr;
+    _cube_map_dr = new_dr->get_object();
 
     for (int i=0; i<count_textures(); i++) {
       Texture *texture = get_texture(i);

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

@@ -208,7 +208,7 @@ public:
   // It is an error to call any of the following methods from any
   // thread other than the draw thread.  These methods are normally
   // called by the GraphicsEngine.
-  void clear();
+  void clear(Thread *current_thread);
   virtual bool begin_frame(FrameMode mode);
   virtual void end_frame(FrameMode mode);
 
@@ -221,7 +221,7 @@ public:
   //  virtual void make_current();
   //  virtual void auto_resize();
 
-  void change_scenes(DisplayRegion *new_dr);
+  void change_scenes(DisplayRegionPipelineReader *new_dr);
   virtual void select_cube_map(int cube_map_index);
 
   // These methods will be called within the app (main) thread.

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

@@ -956,8 +956,9 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
 //               case, it is Lens::SC_mono.
 ////////////////////////////////////////////////////////////////////
 void GraphicsStateGuardian::
-prepare_display_region(DisplayRegion *dr, Lens::StereoChannel stereo_channel) {
-  _current_display_region = dr;
+prepare_display_region(DisplayRegionPipelineReader *dr,
+                       Lens::StereoChannel stereo_channel) {
+  _current_display_region = dr->get_object();
   _current_stereo_channel = stereo_channel;
 
   _stereo_buffer_mask = ~0;

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

@@ -28,6 +28,7 @@
 #include "graphicsThreadingModel.h"
 #include "graphicsPipe.h"
 #include "sceneSetup.h"
+#include "displayRegion.h"
 #include "luse.h"
 #include "coordinateSystem.h"
 #include "factory.h"
@@ -174,7 +175,7 @@ public:
   const LMatrix4f *fetch_specified_value(ShaderContext::ShaderMatSpec &spec, bool altered);
   const LMatrix4f *fetch_specified_part(ShaderContext::ShaderMatInput input, InternalName *name, LMatrix4f &t);
   
-  virtual void prepare_display_region(DisplayRegion *dr,
+  virtual void prepare_display_region(DisplayRegionPipelineReader *dr,
                                       Lens::StereoChannel stereo_channel);
 
   virtual CPT(TransformState) calc_projection_mat(const Lens *lens);

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

@@ -556,12 +556,13 @@ do_clear(const RenderBuffer &buffer) {
 //       scissor region and viewport)
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian8::
-prepare_display_region(DisplayRegion *dr, Lens::StereoChannel stereo_channel) {
-  nassertv(dr != (DisplayRegion *)NULL);
+prepare_display_region(DisplayRegionPipelineReader *dr, 
+                       Lens::StereoChannel stereo_channel) {
+  nassertv(dr != (DisplayRegionPipelineReader *)NULL);
   GraphicsStateGuardian::prepare_display_region(dr, stereo_channel);
 
   int l, u, w, h;
-  _current_display_region->get_region_pixels_i(l, u, w, h);
+  dr->get_region_pixels_i(l, u, w, h);
 
   // Create the viewport
   D3DVIEWPORT8 vp = { l, u, w, h, 0.0f, 1.0f };

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

@@ -66,7 +66,8 @@ public:
 
   virtual void do_clear(const RenderBuffer &buffer);
 
-  virtual void prepare_display_region(DisplayRegion *dr, Lens::StereoChannel stereo_channel);
+  virtual void prepare_display_region(DisplayRegionPipelineReader *dr, 
+                                      Lens::StereoChannel stereo_channel);
   virtual CPT(TransformState) calc_projection_mat(const Lens *lens);
   virtual bool prepare_lens();
 

+ 4 - 3
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -772,8 +772,9 @@ do_clear(const RenderBuffer &buffer) {
 //       scissor region and viewport)
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
-prepare_display_region(DisplayRegion *dr, Lens::StereoChannel stereo_channel) {
-  nassertv(dr != (DisplayRegion *)NULL);
+prepare_display_region(DisplayRegionPipelineReader *dr,
+                       Lens::StereoChannel stereo_channel) {
+  nassertv(dr != (DisplayRegionPipelineReader *)NULL);
   GraphicsStateGuardian::prepare_display_region(dr, stereo_channel);
 
 // DBG_S dxgsg9_cat.debug ( ) << "DXGraphicsStateGuardian9::PRE prepare_display_region\n"; DBG_E
@@ -781,7 +782,7 @@ prepare_display_region(DisplayRegion *dr, Lens::StereoChannel stereo_channel) {
 // DBG_S dxgsg9_cat.debug ( ) << "DXGraphicsStateGuardian9::prepare_display_region\n"; DBG_E
 
   int l, u, w, h;
-  _current_display_region->get_region_pixels_i(l, u, w, h);
+  dr->get_region_pixels_i(l, u, w, h);
 
   DBG_S dxgsg9_cat.debug ( ) << "display_region " << l << " " << u << " "  << w << " "  << h << "\n"; DBG_E
 

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

@@ -102,7 +102,8 @@ public:
 
   virtual void do_clear(const RenderBuffer &buffer);
 
-  virtual void prepare_display_region(DisplayRegion *dr, Lens::StereoChannel stereo_channel);
+  virtual void prepare_display_region(DisplayRegionPipelineReader *dr, 
+                                      Lens::StereoChannel stereo_channel);
   virtual CPT(TransformState) calc_projection_mat(const Lens *lens);
   virtual bool prepare_lens();
 

+ 5 - 4
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -1146,12 +1146,13 @@ do_clear(const RenderBuffer &buffer) {
 //               scissor region and viewport)
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
-prepare_display_region(DisplayRegion *dr, Lens::StereoChannel stereo_channel) {
-  nassertv(dr != (DisplayRegion *)NULL);
+prepare_display_region(DisplayRegionPipelineReader *dr, 
+                       Lens::StereoChannel stereo_channel) {
+  nassertv(dr != (DisplayRegionPipelineReader *)NULL);
   GraphicsStateGuardian::prepare_display_region(dr, stereo_channel);
 
   int l, b, w, h;
-  _current_display_region->get_region_pixels(l, b, w, h);
+  dr->get_region_pixels(l, b, w, h);
   _viewport_width = w;
   _viewport_height = h;
   GLint x = GLint(l);
@@ -1159,7 +1160,7 @@ prepare_display_region(DisplayRegion *dr, Lens::StereoChannel stereo_channel) {
   GLsizei width = GLsizei(w);
   GLsizei height = GLsizei(h);
 
-  set_draw_buffer(get_render_buffer(_current_display_region->get_draw_buffer_type(),
+  set_draw_buffer(get_render_buffer(dr->get_object()->get_draw_buffer_type(),
                                     *_current_properties));
   enable_scissor(true);
   GLP(Scissor)(x, y, width, height);

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

@@ -95,7 +95,8 @@ public:
 
   virtual void do_clear(const RenderBuffer &buffer);
 
-  virtual void prepare_display_region(DisplayRegion *dr, Lens::StereoChannel stereo_channel);
+  virtual void prepare_display_region(DisplayRegionPipelineReader *dr, 
+                                      Lens::StereoChannel stereo_channel);
   virtual CPT(TransformState) calc_projection_mat(const Lens *lens);
   virtual bool prepare_lens();
 

+ 1 - 2
panda/src/gobj/geom.cxx

@@ -930,8 +930,7 @@ prepare_now(PreparedGraphicsObjects *prepared_objects,
 ////////////////////////////////////////////////////////////////////
 void Geom::
 draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger,
-     const GeomVertexData *vertex_data) const {
-  Thread *current_thread = Thread::get_current_thread();
+     const GeomVertexData *vertex_data, Thread *current_thread) const {
   GeomPipelineReader geom_reader(this, current_thread);
   geom_reader.check_usage_hint();
 

+ 2 - 1
panda/src/gobj/geom.h

@@ -126,7 +126,8 @@ public:
 
   void draw(GraphicsStateGuardianBase *gsg, 
             const GeomMunger *munger,
-            const GeomVertexData *vertex_data) const;
+            const GeomVertexData *vertex_data,
+            Thread *current_thread) const;
 
   INLINE void calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
 				bool &found_any, 

+ 0 - 10
panda/src/pgraph/cullBin.cxx

@@ -74,16 +74,6 @@ void CullBin::
 finish_cull(SceneSetup *) {
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: CullBin::draw
-//       Access: Public, Virtual
-//  Description: Draws all the geoms in the bin, in the appropriate
-//               order.
-////////////////////////////////////////////////////////////////////
-void CullBin::
-draw() {
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: CullBin::check_flash_color
 //       Access: Private

+ 1 - 1
panda/src/pgraph/cullBin.h

@@ -57,7 +57,7 @@ public:
   virtual void add_object(CullableObject *object)=0;
   virtual void finish_cull(SceneSetup *scene_setup);
 
-  virtual void draw()=0;
+  virtual void draw(Thread *current_thread)=0;
 
   INLINE bool has_flash_color() const;
   INLINE const Colorf &get_flash_color() const;

+ 4 - 3
panda/src/pgraph/cullHandler.I

@@ -25,11 +25,12 @@
 //               the object.
 ////////////////////////////////////////////////////////////////////
 INLINE void CullHandler::
-draw(CullableObject *object, GraphicsStateGuardianBase *gsg) {
+draw(CullableObject *object, GraphicsStateGuardianBase *gsg,
+     Thread *current_thread) {
   if (object->_next != (CullableObject *)NULL) {
-    draw_with_decals(object, gsg);
+    draw_with_decals(object, gsg, current_thread);
   } else {
     gsg->set_state_and_transform(object->_state, object->_internal_transform);
-    object->draw(gsg);
+    object->draw(gsg, current_thread);
   }
 }

+ 5 - 4
panda/src/pgraph/cullHandler.cxx

@@ -57,7 +57,8 @@ record_object(CullableObject *object, const CullTraverser *traverser) {
 //               attached decals.
 ////////////////////////////////////////////////////////////////////
 void CullHandler::
-draw_with_decals(CullableObject *object, GraphicsStateGuardianBase *gsg) {
+draw_with_decals(CullableObject *object, GraphicsStateGuardianBase *gsg,
+                 Thread *current_thread) {
   // We draw with a three-step process.
 
   // First, render all of the base geometry for the first pass.
@@ -66,7 +67,7 @@ draw_with_decals(CullableObject *object, GraphicsStateGuardianBase *gsg) {
   CullableObject *base = object;
   while (base != (CullableObject *)NULL && base->_geom != (Geom *)NULL) {
     gsg->set_state_and_transform(base->_state->compose(state), base->_internal_transform);
-    base->draw(gsg);
+    base->draw(gsg, current_thread);
     
     base = base->_next;
   }
@@ -78,7 +79,7 @@ draw_with_decals(CullableObject *object, GraphicsStateGuardianBase *gsg) {
     CullableObject *decal = base->_next;
     while (decal != (CullableObject *)NULL) {
       gsg->set_state_and_transform(decal->_state->compose(state), decal->_internal_transform);
-      decal->draw(gsg);
+      decal->draw(gsg, current_thread);
       decal = decal->_next;
     }
   }
@@ -89,7 +90,7 @@ draw_with_decals(CullableObject *object, GraphicsStateGuardianBase *gsg) {
     base = object;
     while (base != (CullableObject *)NULL && base->_geom != (Geom *)NULL) {
       gsg->set_state_and_transform(base->_state->compose(state), base->_internal_transform);
-      base->draw(gsg);
+      base->draw(gsg, current_thread);
       
       base = base->_next;
     }

+ 4 - 2
panda/src/pgraph/cullHandler.h

@@ -40,9 +40,11 @@ public:
                              const CullTraverser *traverser);
 
   INLINE static void draw(CullableObject *object,
-                          GraphicsStateGuardianBase *gsg);
+                          GraphicsStateGuardianBase *gsg,
+                          Thread *current_thread);
   static void draw_with_decals(CullableObject *object,
-                               GraphicsStateGuardianBase *gsg);
+                               GraphicsStateGuardianBase *gsg,
+                               Thread *current_thread);
 };
 
 #include "cullHandler.I"

+ 2 - 2
panda/src/pgraph/cullResult.cxx

@@ -248,7 +248,7 @@ finish_cull(SceneSetup *scene_setup) {
 //               order.
 ////////////////////////////////////////////////////////////////////
 void CullResult::
-draw() {
+draw(Thread *current_thread) {
   // Ask the bin manager for the correct order to draw all the bins.
   CullBinManager *bin_manager = CullBinManager::get_global_ptr();
   int num_bins = bin_manager->get_num_bins();
@@ -257,7 +257,7 @@ draw() {
     nassertv(bin_index >= 0);
 
     if (bin_index < (int)_bins.size() && _bins[bin_index] != (CullBin *)NULL) {
-      _bins[bin_index]->draw();
+      _bins[bin_index]->draw(current_thread);
     }
   }
 }

+ 1 - 1
panda/src/pgraph/cullResult.h

@@ -60,7 +60,7 @@ public:
 
   void add_object(CullableObject *object, const CullTraverser *traverser);
   void finish_cull(SceneSetup *scene_setup);
-  void draw();
+  void draw(Thread *current_thread);
 
 public:
   static void bin_removed(int bin_index);

+ 2 - 2
panda/src/pgraph/cullableObject.I

@@ -121,8 +121,8 @@ has_decals() const {
 //               from the draw thread.
 ////////////////////////////////////////////////////////////////////
 INLINE void CullableObject::
-draw(GraphicsStateGuardianBase *gsg) {
-  _geom->draw(gsg, _munger, _munged_data);
+draw(GraphicsStateGuardianBase *gsg, Thread *current_thread) {
+  _geom->draw(gsg, _munger, _munged_data, current_thread);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 2 - 1
panda/src/pgraph/cullableObject.h

@@ -63,7 +63,8 @@ public:
 
   void munge_geom(GraphicsStateGuardianBase *gsg,
                   GeomMunger *munger, const CullTraverser *traverser);
-  INLINE void draw(GraphicsStateGuardianBase *gsg);
+  INLINE void draw(GraphicsStateGuardianBase *gsg,
+                   Thread *current_thread);
 
 public:
   ~CullableObject();