diff --git a/panda/src/chan/movingPartBase.cxx b/panda/src/chan/movingPartBase.cxx index bd67cdf6ac..ad55e66664 100644 --- a/panda/src/chan/movingPartBase.cxx +++ b/panda/src/chan/movingPartBase.cxx @@ -99,14 +99,15 @@ write_with_value(ostream &out, int indent_level) const { //////////////////////////////////////////////////////////////////// bool MovingPartBase:: do_update(PartBundle *root, PartGroup *parent, - bool parent_changed, bool anim_changed) { + bool parent_changed, bool anim_changed, + Thread *current_thread) { bool any_changed = false; bool needs_update = anim_changed; // See if any of the channel values have changed since last time. { - PartBundle::CDReader cdata(root->_cycler); + PartBundle::CDReader cdata(root->_cycler, current_thread); PartBundle::ChannelBlend::const_iterator bci; for (bci = cdata->_blend.begin(); !needs_update && bci != cdata->_blend.end(); @@ -127,14 +128,15 @@ do_update(PartBundle *root, PartGroup *parent, } if (parent_changed || needs_update) { - any_changed = update_internals(parent, needs_update, parent_changed); + any_changed = update_internals(parent, needs_update, parent_changed, + current_thread); } // Now recurse. Children::iterator ci; for (ci = _children.begin(); ci != _children.end(); ++ci) { if ((*ci)->do_update(root, this, parent_changed || needs_update, - anim_changed)) { + anim_changed, current_thread)) { any_changed = true; } } @@ -155,7 +157,7 @@ do_update(PartBundle *root, PartGroup *parent, // result of the update, or false otherwise. //////////////////////////////////////////////////////////////////// bool MovingPartBase:: -update_internals(PartGroup *, bool, bool) { +update_internals(PartGroup *, bool, bool, Thread *) { return true; } diff --git a/panda/src/chan/movingPartBase.h b/panda/src/chan/movingPartBase.h index 9fac7c82c2..bc011b3bc5 100644 --- a/panda/src/chan/movingPartBase.h +++ b/panda/src/chan/movingPartBase.h @@ -57,11 +57,12 @@ PUBLISHED: public: virtual bool do_update(PartBundle *root, PartGroup *parent, - bool parent_changed, bool anim_changed); + bool parent_changed, bool anim_changed, + Thread *current_thread); virtual void get_blend_value(const PartBundle *root)=0; virtual bool update_internals(PartGroup *parent, bool self_changed, - bool parent_changed); + bool parent_changed, Thread *current_thread); protected: MovingPartBase(); diff --git a/panda/src/chan/partBundle.cxx b/panda/src/chan/partBundle.cxx index fa311aeba2..741d0f3826 100644 --- a/panda/src/chan/partBundle.cxx +++ b/panda/src/chan/partBundle.cxx @@ -240,15 +240,16 @@ bind_anim(AnimBundle *anim, int hierarchy_match_flags, //////////////////////////////////////////////////////////////////// bool PartBundle:: update() { + Thread *current_thread = Thread::get_current_thread(); bool anim_changed; { - CDReader cdata(_cycler); + CDReader cdata(_cycler, current_thread); anim_changed = cdata->_anim_changed; } - bool any_changed = do_update(this, NULL, false, anim_changed); + bool any_changed = do_update(this, NULL, false, anim_changed, current_thread); // Now update all the controls for next time. - CDWriter cdata(_cycler, false); + CDWriter cdata(_cycler, false, current_thread); ChannelBlend::const_iterator cbi; for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) { AnimControl *control = (*cbi).first; @@ -269,10 +270,11 @@ update() { //////////////////////////////////////////////////////////////////// bool PartBundle:: force_update() { - bool any_changed = do_update(this, NULL, true, true); + Thread *current_thread = Thread::get_current_thread(); + bool any_changed = do_update(this, NULL, true, true, current_thread); // Now update all the controls for next time. - CDWriter cdata(_cycler, false); + CDWriter cdata(_cycler, false, current_thread); ChannelBlend::const_iterator cbi; for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) { AnimControl *control = (*cbi).first; @@ -428,7 +430,8 @@ clear_and_stop_intersecting(AnimControl *control, CData *cdata) { //////////////////////////////////////////////////////////////////// void PartBundle:: finalize(BamReader *) { - do_update(this, NULL, true, true); + Thread *current_thread = Thread::get_current_thread(); + do_update(this, NULL, true, true, current_thread); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/chan/partGroup.cxx b/panda/src/chan/partGroup.cxx index 35d6556a4b..1dc93cee06 100644 --- a/panda/src/chan/partGroup.cxx +++ b/panda/src/chan/partGroup.cxx @@ -361,12 +361,13 @@ write_with_value(ostream &out, int indent_level) const { //////////////////////////////////////////////////////////////////// bool PartGroup:: do_update(PartBundle *root, PartGroup *, - bool parent_changed, bool anim_changed) { + bool parent_changed, bool anim_changed, Thread *current_thread) { bool any_changed = false; Children::iterator ci; for (ci = _children.begin(); ci != _children.end(); ++ci) { - if ((*ci)->do_update(root, this, parent_changed, anim_changed)) { + if ((*ci)->do_update(root, this, parent_changed, anim_changed, + current_thread)) { any_changed = true; } } diff --git a/panda/src/chan/partGroup.h b/panda/src/chan/partGroup.h index b2e55b9a71..0e00d6d0ee 100644 --- a/panda/src/chan/partGroup.h +++ b/panda/src/chan/partGroup.h @@ -25,7 +25,7 @@ #include "pointerTo.h" #include "namable.h" #include "typedef.h" - +#include "thread.h" #include "plist.h" class AnimControl; @@ -86,7 +86,8 @@ public: int hierarchy_match_flags = 0) const; virtual bool do_update(PartBundle *root, PartGroup *parent, - bool parent_changed, bool anim_changed); + bool parent_changed, bool anim_changed, + Thread *current_thread); protected: void write_descendants(ostream &out, int indent_level) const; diff --git a/panda/src/char/characterJoint.cxx b/panda/src/char/characterJoint.cxx index 986274b825..988e642a8f 100644 --- a/panda/src/char/characterJoint.cxx +++ b/panda/src/char/characterJoint.cxx @@ -60,9 +60,11 @@ CharacterJoint(PartGroup *parent, const string &name, const LMatrix4f &initial_value) : MovingPartMatrix(parent, name, initial_value) { + Thread *current_thread = Thread::get_current_thread(); + // Now that we've constructed and we're in the tree, let's call // update_internals() to get our _net_transform set properly. - update_internals(parent, true, false); + update_internals(parent, true, false, current_thread); // And then compute its inverse. This is needed for // ComputedVertices, during animation. @@ -106,7 +108,9 @@ make_copy() const { // transforms for this particular joint. //////////////////////////////////////////////////////////////////// bool CharacterJoint:: -update_internals(PartGroup *parent, bool self_changed, bool parent_changed) { +update_internals(PartGroup *parent, bool self_changed, bool parent_changed, + Thread *current_thread) { + nassertr(parent != (PartGroup *)NULL, false); bool net_changed = false; @@ -137,7 +141,7 @@ update_internals(PartGroup *parent, bool self_changed, bool parent_changed) { ai = _net_transform_nodes.begin(); while (ai != _net_transform_nodes.end()) { PandaNode *node = *ai; - node->set_transform(t); + node->set_transform(t, current_thread); ++ai; } } @@ -147,7 +151,7 @@ update_internals(PartGroup *parent, bool self_changed, bool parent_changed) { VertexTransforms::iterator vti; for (vti = _vertex_transforms.begin(); vti != _vertex_transforms.end(); ++vti) { (*vti)->_matrix_stale = true; - (*vti)->mark_modified(); + (*vti)->mark_modified(current_thread); } } @@ -158,7 +162,7 @@ update_internals(PartGroup *parent, bool self_changed, bool parent_changed) { ai = _local_transform_nodes.begin(); while (ai != _local_transform_nodes.end()) { PandaNode *node = *ai; - node->set_transform(t); + node->set_transform(t, current_thread); ++ai; } } diff --git a/panda/src/char/characterJoint.h b/panda/src/char/characterJoint.h index ef348c593f..10428dcdf5 100644 --- a/panda/src/char/characterJoint.h +++ b/panda/src/char/characterJoint.h @@ -44,7 +44,7 @@ public: virtual PartGroup *make_copy() const; virtual bool update_internals(PartGroup *parent, bool self_changed, - bool parent_changed); + bool parent_changed, Thread *current_thread); PUBLISHED: bool add_net_transform(PandaNode *node); diff --git a/panda/src/char/characterSlider.cxx b/panda/src/char/characterSlider.cxx index 5d9482712e..63c71cd09a 100644 --- a/panda/src/char/characterSlider.cxx +++ b/panda/src/char/characterSlider.cxx @@ -88,12 +88,12 @@ make_copy() const { // result of the update, or false otherwise. //////////////////////////////////////////////////////////////////// bool CharacterSlider:: -update_internals(PartGroup *, bool, bool) { +update_internals(PartGroup *, bool, bool, Thread *current_thread) { // Tell our related CharacterVertexSliders that they now need to // recompute themselves. VertexSliders::iterator vsi; for (vsi = _vertex_sliders.begin(); vsi != _vertex_sliders.end(); ++vsi) { - (*vsi)->mark_modified(); + (*vsi)->mark_modified(current_thread); } return true; diff --git a/panda/src/char/characterSlider.h b/panda/src/char/characterSlider.h index 6d623fd3fe..8ba158ff00 100644 --- a/panda/src/char/characterSlider.h +++ b/panda/src/char/characterSlider.h @@ -44,7 +44,7 @@ public: virtual PartGroup *make_copy() const; virtual bool update_internals(PartGroup *parent, bool self_changed, - bool parent_changed); + bool parent_changed, Thread *current_thread); private: typedef pset VertexSliders; diff --git a/panda/src/gobj/geomMunger.cxx b/panda/src/gobj/geomMunger.cxx index 634c876fda..41fb1b4109 100644 --- a/panda/src/gobj/geomMunger.cxx +++ b/panda/src/gobj/geomMunger.cxx @@ -37,7 +37,9 @@ GeomMunger() : _is_registered(false) { #ifndef NDEBUG - _registered_key = get_registry()->_mungers.end(); + Registry *registry = get_registry(); + MutexHolder holder(registry->_registry_lock); + _registered_key = registry->_mungers.end(); #endif } @@ -51,7 +53,9 @@ GeomMunger(const GeomMunger ©) : _is_registered(false) { #ifndef NDEBUG - _registered_key = get_registry()->_mungers.end(); + Registry *registry = get_registry(); + MutexHolder holder(registry->_registry_lock); + _registered_key = registry->_mungers.end(); #endif } @@ -180,6 +184,8 @@ do_munge_format(const GeomVertexFormat *format, nassertr(_is_registered, NULL); nassertr(format->is_registered(), NULL); + MutexHolder holder(_formats_lock); + Formats &formats = _formats_by_animation[animation]; Formats::iterator fi; @@ -373,6 +379,8 @@ register_munger(GeomMunger *munger, Thread *current_thread) { // will be automatically deleted when this function returns. PT(GeomMunger) pt_munger = munger; + MutexHolder holder(_registry_lock); + Mungers::iterator mi = _mungers.insert(munger).first; GeomMunger *new_munger = (*mi); if (!new_munger->is_registered()) { @@ -392,6 +400,8 @@ register_munger(GeomMunger *munger, Thread *current_thread) { //////////////////////////////////////////////////////////////////// void GeomMunger::Registry:: unregister_munger(GeomMunger *munger) { + MutexHolder holder(_registry_lock); + nassertv(munger->is_registered()); nassertv(munger->_registered_key != _mungers.end()); _mungers.erase(munger->_registered_key); diff --git a/panda/src/gobj/geomMunger.h b/panda/src/gobj/geomMunger.h index 4a1f85a0cc..6c2cc6e498 100644 --- a/panda/src/gobj/geomMunger.h +++ b/panda/src/gobj/geomMunger.h @@ -27,6 +27,7 @@ #include "geomCacheEntry.h" #include "indirectCompareTo.h" #include "pStatCollector.h" +#include "pmutex.h" #include "pointerTo.h" #include "pmap.h" #include "pset.h" @@ -111,6 +112,9 @@ private: typedef pmap FormatsByAnimation; FormatsByAnimation _formats_by_animation; + // This mutex protects the above. + Mutex _formats_lock; + bool _is_registered; typedef pset > Mungers; class EXPCL_PANDA Registry { @@ -120,6 +124,7 @@ private: void unregister_munger(GeomMunger *munger); Mungers _mungers; + Mutex _registry_lock; }; // We store the iterator into the above registry, while we are diff --git a/panda/src/gobj/geomPrimitive.cxx b/panda/src/gobj/geomPrimitive.cxx index 96eb0ac249..6f6f725fbb 100644 --- a/panda/src/gobj/geomPrimitive.cxx +++ b/panda/src/gobj/geomPrimitive.cxx @@ -425,13 +425,14 @@ offset_vertices(int offset) { //////////////////////////////////////////////////////////////////// void GeomPrimitive:: make_nonindexed(GeomVertexData *dest, const GeomVertexData *source) { + Thread *current_thread = Thread::get_current_thread(); int num_vertices = get_num_vertices(); int dest_start = dest->get_num_rows(); dest->set_num_rows(dest_start + num_vertices); for (int i = 0; i < num_vertices; ++i) { int v = get_vertex(i); - dest->copy_row_from(dest_start + i, source, v); + dest->copy_row_from(dest_start + i, source, v, current_thread); } set_nonindexed_vertices(dest_start, num_vertices); @@ -446,6 +447,7 @@ make_nonindexed(GeomVertexData *dest, const GeomVertexData *source) { //////////////////////////////////////////////////////////////////// void GeomPrimitive:: pack_vertices(GeomVertexData *dest, const GeomVertexData *source) { + Thread *current_thread = Thread::get_current_thread(); if (!is_indexed()) { // If the primitive is nonindexed, packing is the same as // converting (again) to nonindexed. @@ -475,7 +477,7 @@ pack_vertices(GeomVertexData *dest, const GeomVertexData *source) { if (result.second) { // This is the first time we've seen vertex v. - dest->copy_row_from(v2, source, v); + dest->copy_row_from(v2, source, v, current_thread); } } diff --git a/panda/src/gobj/geomVertexData.cxx b/panda/src/gobj/geomVertexData.cxx index 82db5f3954..c7af299c0e 100644 --- a/panda/src/gobj/geomVertexData.cxx +++ b/panda/src/gobj/geomVertexData.cxx @@ -240,9 +240,10 @@ set_usage_hint(GeomVertexData::UsageHint usage_hint) { //////////////////////////////////////////////////////////////////// void GeomVertexData:: set_format(const GeomVertexFormat *format) { + Thread *current_thread = Thread::get_current_thread(); nassertv(format->is_registered()); - CDReader cdata(_cycler); + CDReader cdata(_cycler, current_thread); if (format == cdata->_format) { // Trivially no-op. @@ -269,7 +270,7 @@ set_format(const GeomVertexFormat *format) { // Now copy the original data back in. This will automatically // convert it to the new format. - copy_from(orig_data, false); + copy_from(orig_data, false, current_thread); clear_cache_stage(); cdataw->_modified = Geom::get_next_modified(); @@ -289,7 +290,8 @@ set_format(const GeomVertexFormat *format) { //////////////////////////////////////////////////////////////////// void GeomVertexData:: clear_rows() { - CDWriter cdata(_cycler, true); + Thread *current_thread = Thread::get_current_thread(); + CDWriter cdata(_cycler, true, current_thread); nassertv(cdata->_format->get_num_arrays() == (int)cdata->_arrays.size()); Arrays::iterator ai; @@ -321,9 +323,10 @@ clear_rows() { //////////////////////////////////////////////////////////////////// void GeomVertexData:: set_transform_table(const TransformTable *table) { + Thread *current_thread = Thread::get_current_thread(); nassertv(table == (TransformTable *)NULL || table->is_registered()); - CDWriter cdata(_cycler, true); + CDWriter cdata(_cycler, true, current_thread); cdata->_transform_table = (TransformTable *)table; clear_cache_stage(); cdata->_modified = Geom::get_next_modified(); @@ -428,7 +431,8 @@ set_slider_table(const SliderTable *table) { // have recently made in an upstream thread. //////////////////////////////////////////////////////////////////// void GeomVertexData:: -copy_from(const GeomVertexData *source, bool keep_data_objects) { +copy_from(const GeomVertexData *source, bool keep_data_objects, + Thread *current_thread) { const GeomVertexFormat *source_format = source->get_format(); const GeomVertexFormat *dest_format = get_format(); @@ -626,7 +630,7 @@ copy_from(const GeomVertexData *source, bool keep_data_objects) { //////////////////////////////////////////////////////////////////// void GeomVertexData:: copy_row_from(int dest_row, const GeomVertexData *source, - int source_row) { + int source_row, Thread *current_thread) { const GeomVertexFormat *source_format = source->get_format(); const GeomVertexFormat *dest_format = get_format(); nassertv(source_format == dest_format); @@ -896,14 +900,14 @@ animate_vertices(Thread *current_thread) const { if (cdata->_transform_blend_table != (TransformBlendTable *)NULL) { if (cdata->_slider_table != (SliderTable *)NULL) { modified = - max(cdata->_transform_blend_table->get_modified(), - cdata->_slider_table->get_modified()); + max(cdata->_transform_blend_table->get_modified(current_thread), + cdata->_slider_table->get_modified(current_thread)); } else { - modified = cdata->_transform_blend_table->get_modified(); + modified = cdata->_transform_blend_table->get_modified(current_thread); } } else if (cdata->_slider_table != (SliderTable *)NULL) { - modified = cdata->_slider_table->get_modified(); + modified = cdata->_slider_table->get_modified(current_thread); } else { // No transform blend table or slider table--ergo, no vertex @@ -918,7 +922,7 @@ animate_vertices(Thread *current_thread) const { } CDWriter cdataw(((GeomVertexData *)this)->_cycler, cdata, false); cdataw->_animated_vertices_modified = modified; - ((GeomVertexData *)this)->update_animated_vertices(cdataw); + ((GeomVertexData *)this)->update_animated_vertices(cdataw, current_thread); return cdataw->_animated_vertices; } @@ -1186,7 +1190,7 @@ uint8_rgba_to_packed_argb(unsigned char *to, int to_stride, // existing animated_vertices object. //////////////////////////////////////////////////////////////////// void GeomVertexData:: -update_animated_vertices(GeomVertexData::CData *cdata) { +update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) { int num_rows = get_num_rows(); if (gobj_cat.is_debug()) { @@ -1195,7 +1199,7 @@ update_animated_vertices(GeomVertexData::CData *cdata) { << "\n"; } - PStatTimer timer(_char_pcollector); + PStatTimer timer(_char_pcollector, current_thread); const GeomVertexFormat *orig_format = cdata->_format; @@ -1203,7 +1207,7 @@ update_animated_vertices(GeomVertexData::CData *cdata) { CPT(GeomVertexFormat) new_format = orig_format->get_post_animated_format(); cdata->_animated_vertices = new GeomVertexData(get_name(), new_format, - min(get_usage_hint(), UH_dynamic)); + min(get_usage_hint(), UH_dynamic)); } PT(GeomVertexData) new_data = cdata->_animated_vertices; @@ -1275,7 +1279,7 @@ update_animated_vertices(GeomVertexData::CData *cdata) { int num_blends = tb_table->get_num_blends(); int bi; for (bi = 0; bi < num_blends; bi++) { - tb_table->get_blend(bi).update_blend(); + tb_table->get_blend(bi).update_blend(current_thread); } // Now go through and apply the transforms. @@ -1296,14 +1300,14 @@ update_animated_vertices(GeomVertexData::CData *cdata) { for (int i = 0; i < num_rows; i++) { LPoint4f vertex = data.get_data4f(); int bi = blendi.get_data1i(); - tb_table->get_blend(bi).transform_point(vertex); + tb_table->get_blend(bi).transform_point(vertex, current_thread); data.set_data4f(vertex); } } else { for (int i = 0; i < num_rows; i++) { LPoint3f vertex = data.get_data3f(); int bi = blendi.get_data1i(); - tb_table->get_blend(bi).transform_point(vertex); + tb_table->get_blend(bi).transform_point(vertex, current_thread); data.set_data3f(vertex); } } @@ -1315,7 +1319,7 @@ update_animated_vertices(GeomVertexData::CData *cdata) { for (int i = 0; i < num_rows; i++) { LVector3f vertex = data.get_data3f(); int bi = blendi.get_data1i(); - tb_table->get_blend(bi).transform_vector(vertex); + tb_table->get_blend(bi).transform_vector(vertex, current_thread); data.set_data3f(vertex); } } diff --git a/panda/src/gobj/geomVertexData.h b/panda/src/gobj/geomVertexData.h index 3f24841bb7..f817a5dfea 100644 --- a/panda/src/gobj/geomVertexData.h +++ b/panda/src/gobj/geomVertexData.h @@ -124,9 +124,10 @@ PUBLISHED: INLINE int get_num_bytes() const; INLINE UpdateSeq get_modified(Thread *current_thread = Thread::get_current_thread()) const; - void copy_from(const GeomVertexData *source, bool keep_data_objects); + void copy_from(const GeomVertexData *source, bool keep_data_objects, + Thread *current_thread = Thread::get_current_thread()); void copy_row_from(int dest_row, const GeomVertexData *source, - int source_row); + int source_row, Thread *current_thread); CPT(GeomVertexData) convert_to(const GeomVertexFormat *new_format) const; CPT(GeomVertexData) scale_color(const LVecBase4f &color_scale) const; @@ -253,7 +254,7 @@ private: Cache _cache; private: - void update_animated_vertices(CData *cdata); + void update_animated_vertices(CData *cdata, Thread *current_thread); static PStatCollector _convert_pcollector; static PStatCollector _scale_color_pcollector; diff --git a/panda/src/gobj/sliderTable.I b/panda/src/gobj/sliderTable.I index 12fad5dc33..c1d2b471d9 100644 --- a/panda/src/gobj/sliderTable.I +++ b/panda/src/gobj/sliderTable.I @@ -131,8 +131,8 @@ is_empty() const { // changes.) //////////////////////////////////////////////////////////////////// INLINE UpdateSeq SliderTable:: -get_modified() const { - CDReader cdata(_cycler); +get_modified(Thread *current_thread) const { + CDReader cdata(_cycler, current_thread); return cdata->_modified; } @@ -143,8 +143,8 @@ get_modified() const { // reports that it has been modified. //////////////////////////////////////////////////////////////////// INLINE void SliderTable:: -update_modified(UpdateSeq modified) { - CDWriter cdata(_cycler, true); +update_modified(UpdateSeq modified, Thread *current_thread) { + CDWriter cdata(_cycler, true, current_thread); cdata->_modified = modified; } diff --git a/panda/src/gobj/sliderTable.cxx b/panda/src/gobj/sliderTable.cxx index 37a67bd2a5..9db65b7c71 100644 --- a/panda/src/gobj/sliderTable.cxx +++ b/panda/src/gobj/sliderTable.cxx @@ -316,5 +316,6 @@ write_datagram(BamWriter *manager, Datagram &dg) const { //////////////////////////////////////////////////////////////////// void SliderTable::CData:: fillin(DatagramIterator &scan, BamReader *manager) { - _modified = VertexTransform::get_next_modified(); + Thread *current_thread = Thread::get_current_thread(); + _modified = VertexTransform::get_next_modified(current_thread); } diff --git a/panda/src/gobj/sliderTable.h b/panda/src/gobj/sliderTable.h index 5742bf009d..bd706db635 100644 --- a/panda/src/gobj/sliderTable.h +++ b/panda/src/gobj/sliderTable.h @@ -59,7 +59,7 @@ PUBLISHED: INLINE const VertexSlider *find_slider(const InternalName *name) const; INLINE bool has_slider(const InternalName *name) const; INLINE bool is_empty() const; - INLINE UpdateSeq get_modified() const; + INLINE UpdateSeq get_modified(Thread *current_thread) const; void set_slider(int n, const VertexSlider *slider); void remove_slider(int n); @@ -70,7 +70,7 @@ PUBLISHED: private: void do_register(); void do_unregister(); - INLINE void update_modified(UpdateSeq modified); + INLINE void update_modified(UpdateSeq modified, Thread *current_thread); private: bool _is_registered; diff --git a/panda/src/gobj/transformBlend.I b/panda/src/gobj/transformBlend.I index 3212042975..82f8c67714 100644 --- a/panda/src/gobj/transformBlend.I +++ b/panda/src/gobj/transformBlend.I @@ -100,7 +100,8 @@ TransformBlend(const TransformBlend ©) : INLINE void TransformBlend:: operator = (const TransformBlend ©) { _entries = copy._entries; - clear_result(); + Thread *current_thread = Thread::get_current_thread(); + clear_result(current_thread); } //////////////////////////////////////////////////////////////////// @@ -209,11 +210,11 @@ set_weight(int n, float weight) { // calling get_blend() or transform_point(). //////////////////////////////////////////////////////////////////// INLINE void TransformBlend:: -update_blend() const { - CDReader cdata(_cycler); - if (cdata->_global_modified != VertexTransform::get_global_modified()) { +update_blend(Thread *current_thread) const { + CDReader cdata(_cycler, current_thread); + if (cdata->_global_modified != VertexTransform::get_global_modified(current_thread)) { CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata, false); - ((TransformBlend *)this)->recompute_result(cdataw); + ((TransformBlend *)this)->recompute_result(cdataw, current_thread); } } @@ -228,9 +229,8 @@ update_blend() const { // cache is up-to-date before calling this. //////////////////////////////////////////////////////////////////// INLINE void TransformBlend:: -get_blend(LMatrix4f &result) const { - CDReader cdata(_cycler); - nassertv(cdata->_global_modified == VertexTransform::get_global_modified()); +get_blend(LMatrix4f &result, Thread *current_thread) const { + CDReader cdata(_cycler, current_thread); result = cdata->_result; } @@ -243,10 +243,9 @@ get_blend(LMatrix4f &result) const { // cache is up-to-date before calling this. //////////////////////////////////////////////////////////////////// INLINE void TransformBlend:: -transform_point(LPoint4f &point) const { +transform_point(LPoint4f &point, Thread *current_thread) const { if (!_entries.empty()) { - CDReader cdata(_cycler); - nassertv(cdata->_global_modified == VertexTransform::get_global_modified()); + CDReader cdata(_cycler, current_thread); point = point * cdata->_result; } } @@ -260,10 +259,9 @@ transform_point(LPoint4f &point) const { // cache is up-to-date before calling this. //////////////////////////////////////////////////////////////////// INLINE void TransformBlend:: -transform_point(LPoint3f &point) const { +transform_point(LPoint3f &point, Thread *current_thread) const { if (!_entries.empty()) { - CDReader cdata(_cycler); - nassertv(cdata->_global_modified == VertexTransform::get_global_modified()); + CDReader cdata(_cycler, current_thread); point = point * cdata->_result; } } @@ -277,10 +275,9 @@ transform_point(LPoint3f &point) const { // cache is up-to-date before calling this. //////////////////////////////////////////////////////////////////// INLINE void TransformBlend:: -transform_vector(LVector3f &vector) const { +transform_vector(LVector3f &vector, Thread *current_thread) const { if (!_entries.empty()) { - CDReader cdata(_cycler); - nassertv(cdata->_global_modified == VertexTransform::get_global_modified()); + CDReader cdata(_cycler, current_thread); vector = vector * cdata->_result; } } @@ -292,11 +289,11 @@ transform_vector(LVector3f &vector) const { // least as often as the result of get_blend() changes. //////////////////////////////////////////////////////////////////// INLINE UpdateSeq TransformBlend:: -get_modified() const { - CDReader cdata(_cycler); - if (cdata->_global_modified != VertexTransform::get_global_modified()) { +get_modified(Thread *current_thread) const { + CDReader cdata(_cycler, current_thread); + if (cdata->_global_modified != VertexTransform::get_global_modified(current_thread)) { CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata, false); - ((TransformBlend *)this)->recompute_result(cdataw); + ((TransformBlend *)this)->recompute_result(cdataw, current_thread); return cdataw->_modified; } else { return cdata->_modified; diff --git a/panda/src/gobj/transformBlend.cxx b/panda/src/gobj/transformBlend.cxx index e3f07c6130..0b8ec58c17 100644 --- a/panda/src/gobj/transformBlend.cxx +++ b/panda/src/gobj/transformBlend.cxx @@ -75,7 +75,8 @@ add_transform(const VertexTransform *transform, float weight) { _entries.erase(ei); } } - clear_result(); + Thread *current_thread = Thread::get_current_thread(); + clear_result(current_thread); } } @@ -93,7 +94,8 @@ remove_transform(const VertexTransform *transform) { if (ei != _entries.end()) { _entries.erase(ei); } - clear_result(); + Thread *current_thread = Thread::get_current_thread(); + clear_result(current_thread); } //////////////////////////////////////////////////////////////////// @@ -116,7 +118,8 @@ normalize_weights() { (*ei)._weight /= net_weight; } } - clear_result(); + Thread *current_thread = Thread::get_current_thread(); + clear_result(current_thread); } //////////////////////////////////////////////////////////////////// @@ -180,6 +183,7 @@ output(ostream &out) const { //////////////////////////////////////////////////////////////////// void TransformBlend:: write(ostream &out, int indent_level) const { + Thread *current_thread = Thread::get_current_thread(); Entries::const_iterator ei; for (ei = _entries.begin(); ei != _entries.end(); ++ei) { indent(out, indent_level) @@ -189,7 +193,7 @@ write(ostream &out, int indent_level) const { mat.write(out, indent_level + 4); } LMatrix4f blend; - get_blend(blend); + get_blend(blend, current_thread); indent(out, indent_level) << "Blended result =\n"; blend.write(out, indent_level + 2); @@ -202,16 +206,16 @@ write(ostream &out, int indent_level) const { // VertexTransform objects, if necessary. //////////////////////////////////////////////////////////////////// void TransformBlend:: -recompute_result(CData *cdata) { +recompute_result(CData *cdata, Thread *current_thread) { // Update the global_modified sequence number first, to prevent race // conditions. - cdata->_global_modified = VertexTransform::get_global_modified(); + cdata->_global_modified = VertexTransform::get_global_modified(current_thread); // Now see if we really need to recompute. UpdateSeq seq; Entries::const_iterator ei; for (ei = _entries.begin(); ei != _entries.end(); ++ei) { - seq = max(seq, (*ei)._transform->get_modified()); + seq = max(seq, (*ei)._transform->get_modified(current_thread)); } if (cdata->_modified != seq) { @@ -235,8 +239,8 @@ recompute_result(CData *cdata) { // recomputed. //////////////////////////////////////////////////////////////////// void TransformBlend:: -clear_result() { - CDWriter cdata(_cycler, true); +clear_result(Thread *current_thread) { + CDWriter cdata(_cycler, true, current_thread); cdata->_global_modified = UpdateSeq(); if (cdata->_modified != UpdateSeq()) { cdata->_modified = UpdateSeq(); diff --git a/panda/src/gobj/transformBlend.h b/panda/src/gobj/transformBlend.h index ceed374a04..77fc15fbf5 100644 --- a/panda/src/gobj/transformBlend.h +++ b/panda/src/gobj/transformBlend.h @@ -70,13 +70,13 @@ PUBLISHED: INLINE void set_transform(int n, const VertexTransform *transform); INLINE void set_weight(int n, float weight); - INLINE void update_blend() const; + INLINE void update_blend(Thread *current_thread) const; - INLINE void get_blend(LMatrix4f &result) const; - INLINE void transform_point(LPoint4f &point) const; - INLINE void transform_point(LPoint3f &point) const; - INLINE void transform_vector(LVector3f &point) const; - INLINE UpdateSeq get_modified() const; + INLINE void get_blend(LMatrix4f &result, Thread *current_thread) const; + INLINE void transform_point(LPoint4f &point, Thread *current_thread) const; + INLINE void transform_point(LPoint3f &point, Thread *current_thread) const; + INLINE void transform_vector(LVector3f &point, Thread *current_thread) const; + INLINE UpdateSeq get_modified(Thread *current_thread) const; void output(ostream &out) const; void write(ostream &out, int indent_level) const; @@ -84,8 +84,8 @@ PUBLISHED: private: class CData; - void recompute_result(CData *cdata); - void clear_result(); + void recompute_result(CData *cdata, Thread *current_thread); + void clear_result(Thread *current_thread); class TransformEntry { public: diff --git a/panda/src/gobj/transformBlendTable.I b/panda/src/gobj/transformBlendTable.I index 23f36e717f..b2d18120b2 100644 --- a/panda/src/gobj/transformBlendTable.I +++ b/panda/src/gobj/transformBlendTable.I @@ -47,11 +47,11 @@ get_blend(int n) const { // have changed. //////////////////////////////////////////////////////////////////// INLINE UpdateSeq TransformBlendTable:: -get_modified() const { +get_modified(Thread *current_thread) const { CDReader cdata(_cycler); - if (cdata->_global_modified != VertexTransform::get_global_modified()) { + if (cdata->_global_modified != VertexTransform::get_global_modified(current_thread)) { CDWriter cdataw(((TransformBlendTable *)this)->_cycler, cdata, false); - ((TransformBlendTable *)this)->recompute_modified(cdataw); + ((TransformBlendTable *)this)->recompute_modified(cdataw, current_thread); return cdataw->_modified; } else { return cdata->_modified; diff --git a/panda/src/gobj/transformBlendTable.cxx b/panda/src/gobj/transformBlendTable.cxx index 1ac36e39fd..90e3055438 100644 --- a/panda/src/gobj/transformBlendTable.cxx +++ b/panda/src/gobj/transformBlendTable.cxx @@ -174,16 +174,16 @@ rebuild_index() { // TransformBlend objects, if necessary. //////////////////////////////////////////////////////////////////// void TransformBlendTable:: -recompute_modified(TransformBlendTable::CData *cdata) { +recompute_modified(TransformBlendTable::CData *cdata, Thread *current_thread) { // Update the global_modified sequence number first, to prevent race // conditions. - cdata->_global_modified = VertexTransform::get_global_modified(); + cdata->_global_modified = VertexTransform::get_global_modified(current_thread); // Now get the local modified number. UpdateSeq seq; Blends::const_iterator bi; for (bi = _blends.begin(); bi != _blends.end(); ++bi) { - seq = max(seq, (*bi).get_modified()); + seq = max(seq, (*bi).get_modified(current_thread)); } cdata->_modified = seq; @@ -196,8 +196,8 @@ recompute_modified(TransformBlendTable::CData *cdata) { // recomputed. //////////////////////////////////////////////////////////////////// void TransformBlendTable:: -clear_modified() { - CDWriter cdata(_cycler, true); +clear_modified(Thread *current_thread) { + CDWriter cdata(_cycler, true, current_thread); cdata->_global_modified = UpdateSeq(); cdata->_modified = UpdateSeq(); } @@ -323,6 +323,7 @@ write_datagram(BamWriter *manager, Datagram &dg) const { //////////////////////////////////////////////////////////////////// void TransformBlendTable::CData:: fillin(DatagramIterator &scan, BamReader *manager) { - _modified = VertexTransform::get_next_modified(); - _global_modified = VertexTransform::get_global_modified(); + Thread *current_thread = Thread::get_current_thread(); + _modified = VertexTransform::get_next_modified(current_thread); + _global_modified = VertexTransform::get_global_modified(current_thread); } diff --git a/panda/src/gobj/transformBlendTable.h b/panda/src/gobj/transformBlendTable.h index b35ae8e469..b9272c4e59 100644 --- a/panda/src/gobj/transformBlendTable.h +++ b/panda/src/gobj/transformBlendTable.h @@ -58,7 +58,7 @@ PUBLISHED: INLINE int get_num_blends() const; INLINE const TransformBlend &get_blend(int n) const; - INLINE UpdateSeq get_modified() const; + INLINE UpdateSeq get_modified(Thread *current_thread) const; void set_blend(int n, const TransformBlend &blend); void remove_blend(int n); @@ -76,8 +76,8 @@ private: INLINE void consider_rebuild_index() const; void rebuild_index(); - void recompute_modified(CData *cdata); - void clear_modified(); + void recompute_modified(CData *cdata, Thread *current_thread); + void clear_modified(Thread *current_thread); private: // We don't bother with registering the table, or protecting its diff --git a/panda/src/gobj/transformTable.I b/panda/src/gobj/transformTable.I index ccbe49f2f4..6bd0179c11 100644 --- a/panda/src/gobj/transformTable.I +++ b/panda/src/gobj/transformTable.I @@ -93,8 +93,8 @@ get_transform(int n) const { // changes.) //////////////////////////////////////////////////////////////////// INLINE UpdateSeq TransformTable:: -get_modified() const { - CDReader cdata(_cycler); +get_modified(Thread *current_thread) const { + CDReader cdata(_cycler, current_thread); return cdata->_modified; } @@ -105,8 +105,8 @@ get_modified() const { // reports that it has been modified. //////////////////////////////////////////////////////////////////// INLINE void TransformTable:: -update_modified(UpdateSeq modified) { - CDWriter cdata(_cycler, true); +update_modified(UpdateSeq modified, Thread *current_thread) { + CDWriter cdata(_cycler, true, current_thread); cdata->_modified = modified; } diff --git a/panda/src/gobj/transformTable.cxx b/panda/src/gobj/transformTable.cxx index 5af2b2ddff..13fd6a55fc 100644 --- a/panda/src/gobj/transformTable.cxx +++ b/panda/src/gobj/transformTable.cxx @@ -282,5 +282,6 @@ write_datagram(BamWriter *manager, Datagram &dg) const { //////////////////////////////////////////////////////////////////// void TransformTable::CData:: fillin(DatagramIterator &scan, BamReader *manager) { - _modified = VertexTransform::get_next_modified(); + Thread *current_thread = Thread::get_current_thread(); + _modified = VertexTransform::get_next_modified(current_thread); } diff --git a/panda/src/gobj/transformTable.h b/panda/src/gobj/transformTable.h index 210e437066..fcc7cd1a9f 100644 --- a/panda/src/gobj/transformTable.h +++ b/panda/src/gobj/transformTable.h @@ -55,7 +55,7 @@ PUBLISHED: INLINE int get_num_transforms() const; INLINE const VertexTransform *get_transform(int n) const; - INLINE UpdateSeq get_modified() const; + INLINE UpdateSeq get_modified(Thread *current_thread) const; void set_transform(int n, const VertexTransform *transform); void remove_transform(int n); @@ -66,7 +66,7 @@ PUBLISHED: private: void do_register(); void do_unregister(); - INLINE void update_modified(UpdateSeq modified); + INLINE void update_modified(UpdateSeq modified, Thread *current_thread); private: bool _is_registered; diff --git a/panda/src/gobj/userVertexSlider.I b/panda/src/gobj/userVertexSlider.I index 3648f6bf70..c4d17238e8 100644 --- a/panda/src/gobj/userVertexSlider.I +++ b/panda/src/gobj/userVertexSlider.I @@ -24,9 +24,10 @@ //////////////////////////////////////////////////////////////////// INLINE void UserVertexSlider:: set_slider(float slider) { - CDWriter cdata(_cycler, true); + Thread *current_thread = Thread::get_current_thread(); + CDWriter cdata(_cycler, true, current_thread); cdata->_slider = slider; - mark_modified(); + mark_modified(current_thread); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/userVertexTransform.I b/panda/src/gobj/userVertexTransform.I index d9dbbe6ccd..0276671774 100644 --- a/panda/src/gobj/userVertexTransform.I +++ b/panda/src/gobj/userVertexTransform.I @@ -35,9 +35,10 @@ get_name() const { //////////////////////////////////////////////////////////////////// INLINE void UserVertexTransform:: set_matrix(const LMatrix4f &matrix) { - CDWriter cdata(_cycler, true); + Thread *current_thread = Thread::get_current_thread(); + CDWriter cdata(_cycler, true, current_thread); cdata->_matrix = matrix; - mark_modified(); + mark_modified(current_thread); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/vertexSlider.I b/panda/src/gobj/vertexSlider.I index 0599acf32e..4591922d15 100644 --- a/panda/src/gobj/vertexSlider.I +++ b/panda/src/gobj/vertexSlider.I @@ -38,8 +38,8 @@ get_name() const { // get_slider() changes. //////////////////////////////////////////////////////////////////// INLINE UpdateSeq VertexSlider:: -get_modified() const { - CDReader cdata(_cycler); +get_modified(Thread *current_thread) const { + CDReader cdata(_cycler, current_thread); return cdata->_modified; } diff --git a/panda/src/gobj/vertexSlider.cxx b/panda/src/gobj/vertexSlider.cxx index 0bb27a1a83..529a11e943 100644 --- a/panda/src/gobj/vertexSlider.cxx +++ b/panda/src/gobj/vertexSlider.cxx @@ -76,13 +76,13 @@ write(ostream &out, int indent_level) const { // be propagated through the system. //////////////////////////////////////////////////////////////////// void VertexSlider:: -mark_modified() { - CDWriter cdata(_cycler, true); - cdata->_modified = VertexTransform::get_next_modified(); +mark_modified(Thread *current_thread) { + CDWriter cdata(_cycler, true, current_thread); + cdata->_modified = VertexTransform::get_next_modified(current_thread); Tables::iterator ti; for (ti = _tables.begin(); ti != _tables.end(); ++ti) { - (*ti)->update_modified(cdata->_modified); + (*ti)->update_modified(cdata->_modified, current_thread); } } diff --git a/panda/src/gobj/vertexSlider.h b/panda/src/gobj/vertexSlider.h index f1aa2602ba..f6a1ed12b1 100644 --- a/panda/src/gobj/vertexSlider.h +++ b/panda/src/gobj/vertexSlider.h @@ -50,13 +50,13 @@ PUBLISHED: INLINE const InternalName *get_name() const; virtual float get_slider() const=0; - INLINE UpdateSeq get_modified() const; + INLINE UpdateSeq get_modified(Thread *current_thread) const; virtual void output(ostream &out) const; virtual void write(ostream &out, int indent_level) const; protected: - void mark_modified(); + void mark_modified(Thread *current_thread); protected: CPT(InternalName) _name; diff --git a/panda/src/gobj/vertexTransform.I b/panda/src/gobj/vertexTransform.I index 4960f75261..aea60979e1 100644 --- a/panda/src/gobj/vertexTransform.I +++ b/panda/src/gobj/vertexTransform.I @@ -25,8 +25,8 @@ // get_matrix() changes. //////////////////////////////////////////////////////////////////// INLINE UpdateSeq VertexTransform:: -get_modified() const { - CDReader cdata(_cycler); +get_modified(Thread *current_thread) const { + CDReader cdata(_cycler, current_thread); return cdata->_modified; } @@ -39,8 +39,8 @@ get_modified() const { // VertexTransforms have changed value recently. //////////////////////////////////////////////////////////////////// INLINE UpdateSeq VertexTransform:: -get_global_modified() { - CDReader cdata(_global_cycler); +get_global_modified(Thread *current_thread) { + CDReader cdata(_global_cycler, current_thread); return cdata->_modified; } diff --git a/panda/src/gobj/vertexTransform.cxx b/panda/src/gobj/vertexTransform.cxx index f1b9a43422..797c5234f2 100644 --- a/panda/src/gobj/vertexTransform.cxx +++ b/panda/src/gobj/vertexTransform.cxx @@ -139,10 +139,9 @@ write(ostream &out, int indent_level) const { // different space. //////////////////////////////////////////////////////////////////// UpdateSeq VertexTransform:: -get_next_modified() { +get_next_modified(Thread *current_thread) { + CDWriter cdatag(_global_cycler, true, current_thread); ++_next_modified; - - CDWriter cdatag(_global_cycler, true); cdatag->_modified = _next_modified; return _next_modified; @@ -157,13 +156,13 @@ get_next_modified() { // be propagated through the system. //////////////////////////////////////////////////////////////////// void VertexTransform:: -mark_modified() { - CDWriter cdata(_cycler, true); - cdata->_modified = get_next_modified(); +mark_modified(Thread *current_thread) { + CDWriter cdata(_cycler, true, current_thread); + cdata->_modified = get_next_modified(current_thread); Palettes::iterator pi; for (pi = _tables.begin(); pi != _tables.end(); ++pi) { - (*pi)->update_modified(cdata->_modified); + (*pi)->update_modified(cdata->_modified, current_thread); } } diff --git a/panda/src/gobj/vertexTransform.h b/panda/src/gobj/vertexTransform.h index 6207845116..48048b0784 100644 --- a/panda/src/gobj/vertexTransform.h +++ b/panda/src/gobj/vertexTransform.h @@ -49,16 +49,16 @@ PUBLISHED: virtual void mult_matrix(LMatrix4f &result, const LMatrix4f &previous) const; virtual void accumulate_matrix(LMatrix4f &accum, float weight) const; - INLINE UpdateSeq get_modified() const; + INLINE UpdateSeq get_modified(Thread *current_thread) const; virtual void output(ostream &out) const; virtual void write(ostream &out, int indent_level) const; - static UpdateSeq get_next_modified(); - INLINE static UpdateSeq get_global_modified(); + static UpdateSeq get_next_modified(Thread *current_thread); + INLINE static UpdateSeq get_global_modified(Thread *current_thread); protected: - void mark_modified(); + void mark_modified(Thread *current_thread); private: typedef pset Palettes; diff --git a/panda/src/pgraph/renderEffects.cxx b/panda/src/pgraph/renderEffects.cxx index bfd53d8092..706dd1272e 100644 --- a/panda/src/pgraph/renderEffects.cxx +++ b/panda/src/pgraph/renderEffects.cxx @@ -29,6 +29,7 @@ #include "indent.h" #include "compareTo.h" #include "reMutexHolder.h" +#include "mutexHolder.h" #include "thread.h" ReMutex *RenderEffects::_states_lock = NULL; @@ -44,7 +45,7 @@ TypeHandle RenderEffects::_type_handle; // spurious warning if all constructors are private. //////////////////////////////////////////////////////////////////// RenderEffects:: -RenderEffects() { +RenderEffects() : _lock("RenderEffects") { if (_states == (States *)NULL) { init_states(); } @@ -608,6 +609,12 @@ return_new(RenderEffects *state) { //////////////////////////////////////////////////////////////////// void RenderEffects:: determine_decal() { + MutexHolder holder(_lock); + if ((_flags & F_checked_decal) != 0) { + // Someone else checked it first. + return; + } + const RenderEffect *effect = get_effect(DecalEffect::get_class_type()); if (effect != (const RenderEffect *)NULL) { _flags |= F_has_decal; @@ -622,6 +629,12 @@ determine_decal() { //////////////////////////////////////////////////////////////////// void RenderEffects:: determine_show_bounds() { + MutexHolder holder(_lock); + if ((_flags & F_checked_show_bounds) != 0) { + // Someone else checked it first. + return; + } + const RenderEffect *effect = get_effect(ShowBoundsEffect::get_class_type()); if (effect != (const RenderEffect *)NULL) { _flags |= F_has_show_bounds; @@ -640,6 +653,12 @@ determine_show_bounds() { //////////////////////////////////////////////////////////////////// void RenderEffects:: determine_cull_callback() { + MutexHolder holder(_lock); + if ((_flags & F_checked_cull_callback) != 0) { + // Someone else checked it first. + return; + } + _flags |= F_checked_cull_callback; Effects::const_iterator ei; @@ -658,6 +677,12 @@ determine_cull_callback() { //////////////////////////////////////////////////////////////////// void RenderEffects:: determine_adjust_transform() { + MutexHolder holder(_lock); + if ((_flags & F_checked_adjust_transform) != 0) { + // Someone else checked it first. + return; + } + _flags |= F_checked_adjust_transform; Effects::const_iterator ei; diff --git a/panda/src/pgraph/renderEffects.h b/panda/src/pgraph/renderEffects.h index 8cffde9c1e..6c2f2402b1 100644 --- a/panda/src/pgraph/renderEffects.h +++ b/panda/src/pgraph/renderEffects.h @@ -29,6 +29,7 @@ #include "pointerTo.h" #include "ordered_vector.h" #include "reMutex.h" +#include "pmutex.h" class CullTraverser; class CullTraverserData; @@ -164,6 +165,9 @@ private: }; int _flags; + // This mutex protects _flags, and all of the above computed values. + Mutex _lock; + public: static void register_with_read_factory(); diff --git a/panda/src/pgraph/renderState.I b/panda/src/pgraph/renderState.I index 7c8eaca6d5..aaeaa4683a 100644 --- a/panda/src/pgraph/renderState.I +++ b/panda/src/pgraph/renderState.I @@ -389,6 +389,28 @@ get_shader() const { return _shader; } +//////////////////////////////////////////////////////////////////// +// Function: RenderState::determine_bin +// Access: Private +// Description: This is the private implementation of get_bin(). +//////////////////////////////////////////////////////////////////// +INLINE void RenderState:: +determine_bin() { + MutexHolder holder(_lock); + do_determine_bin(); +} + +//////////////////////////////////////////////////////////////////// +// Function: RenderState::determine_transparency +// Access: Private +// Description: This is the private implementation of get_transparency(). +//////////////////////////////////////////////////////////////////// +INLINE void RenderState:: +determine_transparency() { + MutexHolder holder(_lock); + do_determine_transparency(); +} + //////////////////////////////////////////////////////////////////// // Function: RenderState::set_destructing // Access: Private diff --git a/panda/src/pgraph/renderState.cxx b/panda/src/pgraph/renderState.cxx index 38b1cde935..6f1d8d6e01 100644 --- a/panda/src/pgraph/renderState.cxx +++ b/panda/src/pgraph/renderState.cxx @@ -36,6 +36,7 @@ #include "indent.h" #include "compareTo.h" #include "reMutexHolder.h" +#include "mutexHolder.h" #include "thread.h" #include "attribSlots.h" @@ -61,7 +62,7 @@ TypeHandle RenderState::_type_handle; // spurious warning if all constructors are private. //////////////////////////////////////////////////////////////////// RenderState:: -RenderState() { +RenderState() : _lock("RenderState") { if (_states == (States *)NULL) { init_states(); } @@ -1444,13 +1445,22 @@ remove_cache_pointers() { //////////////////////////////////////////////////////////////////// void RenderState:: determine_bin_index() { + MutexHolder holder(_lock); + if ((_flags & F_checked_bin_index) != 0) { + // Someone else checked it first. + return; + } + string bin_name; _draw_order = 0; - const CullBinAttrib *bin_attrib = get_bin(); - if (bin_attrib != (const CullBinAttrib *)NULL) { - bin_name = bin_attrib->get_bin_name(); - _draw_order = bin_attrib->get_draw_order(); + if ((_flags & F_checked_bin) == 0) { + do_determine_bin(); + } + + if (_bin != (const CullBinAttrib *)NULL) { + bin_name = _bin->get_bin_name(); + _draw_order = _bin->get_draw_order(); } if (bin_name.empty()) { @@ -1458,9 +1468,13 @@ determine_bin_index() { // either opaque or transparent, based on the transparency // setting. bin_name = "opaque"; - const TransparencyAttrib *trans = get_transparency(); - if (trans != (const TransparencyAttrib *)NULL) { - switch (trans->get_mode()) { + + if ((_flags & F_checked_transparency) == 0) { + do_determine_transparency(); + } + + if (_transparency != (const TransparencyAttrib *)NULL) { + switch (_transparency->get_mode()) { case TransparencyAttrib::M_alpha: case TransparencyAttrib::M_dual: // These transparency modes require special back-to-front sorting. @@ -1490,6 +1504,12 @@ determine_bin_index() { //////////////////////////////////////////////////////////////////// void RenderState:: determine_fog() { + MutexHolder holder(_lock); + if ((_flags & F_checked_fog) != 0) { + // Someone else checked it first. + return; + } + const RenderAttrib *attrib = get_attrib(FogAttrib::get_class_type()); _fog = (const FogAttrib *)NULL; if (attrib != (const RenderAttrib *)NULL) { @@ -1499,12 +1519,18 @@ determine_fog() { } //////////////////////////////////////////////////////////////////// -// Function: RenderState::determine_bin +// Function: RenderState::do_determine_bin // Access: Private -// Description: This is the private implementation of get_bin(). +// Description: This is the implementation of determine_bin(); it +// assumes the lock is already held. //////////////////////////////////////////////////////////////////// void RenderState:: -determine_bin() { +do_determine_bin() { + if ((_flags & F_checked_bin) != 0) { + // Someone else checked it first. + return; + } + const RenderAttrib *attrib = get_attrib(CullBinAttrib::get_class_type()); _bin = (const CullBinAttrib *)NULL; if (attrib != (const RenderAttrib *)NULL) { @@ -1514,12 +1540,19 @@ determine_bin() { } //////////////////////////////////////////////////////////////////// -// Function: RenderState::determine_transparency +// Function: RenderState::do_determine_transparency // Access: Private -// Description: This is the private implementation of get_transparency(). +// Description: This is the implementation of +// determine_transparency(); it assumes the lock is +// already held. //////////////////////////////////////////////////////////////////// void RenderState:: -determine_transparency() { +do_determine_transparency() { + if ((_flags & F_checked_transparency) != 0) { + // Someone else checked it first. + return; + } + const RenderAttrib *attrib = get_attrib(TransparencyAttrib::get_class_type()); _transparency = (const TransparencyAttrib *)NULL; @@ -1536,6 +1569,12 @@ determine_transparency() { //////////////////////////////////////////////////////////////////// void RenderState:: determine_color() { + MutexHolder holder(_lock); + if ((_flags & F_checked_color) != 0) { + // Someone else checked it first. + return; + } + const RenderAttrib *attrib = get_attrib(ColorAttrib::get_class_type()); _color = (const ColorAttrib *)NULL; if (attrib != (const RenderAttrib *)NULL) { @@ -1551,6 +1590,12 @@ determine_color() { //////////////////////////////////////////////////////////////////// void RenderState:: determine_color_scale() { + MutexHolder holder(_lock); + if ((_flags & F_checked_color_scale) != 0) { + // Someone else checked it first. + return; + } + const RenderAttrib *attrib = get_attrib(ColorScaleAttrib::get_class_type()); _color_scale = (const ColorScaleAttrib *)NULL; if (attrib != (const RenderAttrib *)NULL) { @@ -1566,6 +1611,12 @@ determine_color_scale() { //////////////////////////////////////////////////////////////////// void RenderState:: determine_texture() { + MutexHolder holder(_lock); + if ((_flags & F_checked_texture) != 0) { + // Someone else checked it first. + return; + } + const RenderAttrib *attrib = get_attrib(TextureAttrib::get_class_type()); _texture = (const TextureAttrib *)NULL; if (attrib != (const RenderAttrib *)NULL) { @@ -1581,6 +1632,12 @@ determine_texture() { //////////////////////////////////////////////////////////////////// void RenderState:: determine_tex_gen() { + MutexHolder holder(_lock); + if ((_flags & F_checked_tex_gen) != 0) { + // Someone else checked it first. + return; + } + const RenderAttrib *attrib = get_attrib(TexGenAttrib::get_class_type()); _tex_gen = (const TexGenAttrib *)NULL; if (attrib != (const RenderAttrib *)NULL) { @@ -1596,6 +1653,12 @@ determine_tex_gen() { //////////////////////////////////////////////////////////////////// void RenderState:: determine_tex_matrix() { + MutexHolder holder(_lock); + if ((_flags & F_checked_tex_matrix) != 0) { + // Someone else checked it first. + return; + } + const RenderAttrib *attrib = get_attrib(TexMatrixAttrib::get_class_type()); _tex_matrix = (const TexMatrixAttrib *)NULL; if (attrib != (const RenderAttrib *)NULL) { @@ -1611,6 +1674,12 @@ determine_tex_matrix() { //////////////////////////////////////////////////////////////////// void RenderState:: determine_render_mode() { + MutexHolder holder(_lock); + if ((_flags & F_checked_render_mode) != 0) { + // Someone else checked it first. + return; + } + const RenderAttrib *attrib = get_attrib(RenderModeAttrib::get_class_type()); _render_mode = (const RenderModeAttrib *)NULL; if (attrib != (const RenderAttrib *)NULL) { @@ -1626,6 +1695,12 @@ determine_render_mode() { //////////////////////////////////////////////////////////////////// void RenderState:: determine_clip_plane() { + MutexHolder holder(_lock); + if ((_flags & F_checked_clip_plane) != 0) { + // Someone else checked it first. + return; + } + const RenderAttrib *attrib = get_attrib(ClipPlaneAttrib::get_class_type()); _clip_plane = (const ClipPlaneAttrib *)NULL; if (attrib != (const RenderAttrib *)NULL) { @@ -1641,6 +1716,12 @@ determine_clip_plane() { //////////////////////////////////////////////////////////////////// void RenderState:: determine_shader() { + MutexHolder holder(_lock); + if ((_flags & F_checked_shader) != 0) { + // Someone else checked it first. + return; + } + const RenderAttrib *attrib = get_attrib(ShaderAttrib::get_class_type()); _shader = (const ShaderAttrib *)NULL; if (attrib != (const RenderAttrib *)NULL) { @@ -1656,6 +1737,12 @@ determine_shader() { //////////////////////////////////////////////////////////////////// void RenderState:: determine_cull_callback() { + MutexHolder holder(_lock); + if ((_flags & F_checked_cull_callback) != 0) { + // Someone else checked it first. + return; + } + Attributes::const_iterator ai; for (ai = _attributes.begin(); ai != _attributes.end(); ++ai) { const Attribute &attrib = *ai; diff --git a/panda/src/pgraph/renderState.h b/panda/src/pgraph/renderState.h index 3b302fd088..0fdffeda2b 100644 --- a/panda/src/pgraph/renderState.h +++ b/panda/src/pgraph/renderState.h @@ -33,6 +33,7 @@ #include "weakPointerTo.h" #include "shaderExpansion.h" #include "reMutex.h" +#include "pmutex.h" #include "deletedChain.h" class GraphicsStateGuardianBase; @@ -182,8 +183,10 @@ private: void determine_bin_index(); void determine_fog(); - void determine_bin(); - void determine_transparency(); + INLINE void determine_bin(); + void do_determine_bin(); + INLINE void determine_transparency(); + void do_determine_transparency(); void determine_color(); void determine_color_scale(); void determine_texture(); @@ -324,6 +327,9 @@ private: }; unsigned short _flags; + // This mutex protects _flags, and all of the above computed values. + Mutex _lock; + public: static void register_with_read_factory(); virtual void write_datagram(BamWriter *manager, Datagram &dg); diff --git a/panda/src/pgraph/transformState.I b/panda/src/pgraph/transformState.I index 4a36d0d3b6..a75e5918c6 100644 --- a/panda/src/pgraph/transformState.I +++ b/panda/src/pgraph/transformState.I @@ -824,6 +824,40 @@ check_mat() const { } } +//////////////////////////////////////////////////////////////////// +// Function: TransformState::calc_components +// Access: Private +// Description: Derives the components from the matrix, if possible. +//////////////////////////////////////////////////////////////////// +INLINE void TransformState:: +calc_components() { + MutexHolder holder(_lock); + do_calc_components(); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformState::calc_hpr +// Access: Private +// Description: Derives the hpr, from the matrix if necessary, or +// from the quat. +//////////////////////////////////////////////////////////////////// +INLINE void TransformState:: +calc_hpr() { + MutexHolder holder(_lock); + do_calc_hpr(); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformState::calc_mat +// Access: Private +// Description: Computes the matrix from the components. +//////////////////////////////////////////////////////////////////// +INLINE void TransformState:: +calc_mat() { + MutexHolder holder(_lock); + do_calc_mat(); +} + //////////////////////////////////////////////////////////////////// // Function: TransformState::check_uniform_scale // Access: Private @@ -831,6 +865,9 @@ check_mat() const { // F_has_components) is set, this checks for a // identity and/or uniform scale (as well as a non-zero // shear) and sets the bit appropriately. +// +// It does not matter whether the lock is or is not held +// before calling this method. //////////////////////////////////////////////////////////////////// INLINE void TransformState:: check_uniform_scale() { @@ -854,6 +891,9 @@ check_uniform_scale() { // F_has_components) is set, for a known 2-d scale, this // checks for a identity and/or uniform scale (as well // as a non-zero shear) and sets the bit appropriately. +// +// It does not matter whether the lock is or is not held +// before calling this method. //////////////////////////////////////////////////////////////////// INLINE void TransformState:: check_uniform_scale2d() { diff --git a/panda/src/pgraph/transformState.cxx b/panda/src/pgraph/transformState.cxx index d7c18cf30e..ccf47a71ab 100644 --- a/panda/src/pgraph/transformState.cxx +++ b/panda/src/pgraph/transformState.cxx @@ -26,6 +26,7 @@ #include "pStatTimer.h" #include "config_pgraph.h" #include "reMutexHolder.h" +#include "mutexHolder.h" #include "thread.h" ReMutex *TransformState::_states_lock = NULL; @@ -48,7 +49,7 @@ TypeHandle TransformState::_type_handle; // spurious warning if all constructors are private. //////////////////////////////////////////////////////////////////// TransformState:: -TransformState() { +TransformState() : _lock("TransformState") { if (_states == (States *)NULL) { init_states(); } @@ -1743,6 +1744,11 @@ remove_cache_pointers() { //////////////////////////////////////////////////////////////////// void TransformState:: calc_singular() { + MutexHolder holder(_lock); + if ((_flags & F_singular_known) != 0) { + // Someone else computed it first. + return; + } nassertv((_flags & F_is_invalid) == 0); // We determine if a matrix is singular by attempting to invert it @@ -1753,7 +1759,11 @@ calc_singular() { // This should be NULL if no one has called calc_singular() yet. nassertv(_inv_mat == (LMatrix4f *)NULL); _inv_mat = new LMatrix4f; - bool inverted = _inv_mat->invert_from(get_mat()); + + if ((_flags & F_mat_known) == 0) { + do_calc_mat(); + } + bool inverted = _inv_mat->invert_from(_mat); if (!inverted) { _flags |= F_is_singular; @@ -1764,12 +1774,18 @@ calc_singular() { } //////////////////////////////////////////////////////////////////// -// Function: TransformState::calc_components +// Function: TransformState::do_calc_components // Access: Private -// Description: Derives the components from the matrix, if possible. +// Description: This is the implementation of calc_components(); it +// assumes the lock is already held. //////////////////////////////////////////////////////////////////// void TransformState:: -calc_components() { +do_calc_components() { + if ((_flags & F_components_known) != 0) { + // Someone else computed it first. + return; + } + nassertv((_flags & F_is_invalid) == 0); if ((_flags & F_is_identity) != 0) { _scale.set(1.0f, 1.0f, 1.0f); @@ -1784,8 +1800,10 @@ calc_components() { // other explanation is that we were constructed via a matrix. nassertv((_flags & F_mat_known) != 0); - const LMatrix4f &mat = get_mat(); - bool possible = decompose_matrix(mat, _scale, _shear, _hpr, _pos); + if ((_flags & F_mat_known) == 0) { + do_calc_mat(); + } + bool possible = decompose_matrix(_mat, _scale, _shear, _hpr, _pos); if (!possible) { // Some matrices can't be decomposed into scale, hpr, pos. In // this case, we now know that we cannot compute the components; @@ -1799,20 +1817,27 @@ calc_components() { } // However, we can always get at least the pos. - mat.get_row3(_pos, 3); + _mat.get_row3(_pos, 3); } } //////////////////////////////////////////////////////////////////// -// Function: TransformState::calc_hpr +// Function: TransformState::do_calc_hpr // Access: Private -// Description: Derives the hpr, from the matrix if necessary, or -// from the quat. +// Description: This is the implementation of calc_hpr(); it +// assumes the lock is already held. //////////////////////////////////////////////////////////////////// void TransformState:: -calc_hpr() { +do_calc_hpr() { + if ((_flags & F_hpr_known) != 0) { + // Someone else computed it first. + return; + } + nassertv((_flags & F_is_invalid) == 0); - check_components(); + if ((_flags & F_components_known) == 0) { + do_calc_components(); + } if ((_flags & F_hpr_known) == 0) { // If we don't know the hpr yet, we must have been given a quat. // Decompose it. @@ -1829,8 +1854,16 @@ calc_hpr() { //////////////////////////////////////////////////////////////////// void TransformState:: calc_quat() { + MutexHolder holder(_lock); + if ((_flags & F_quat_known) != 0) { + // Someone else computed it first. + return; + } + nassertv((_flags & F_is_invalid) == 0); - check_components(); + if ((_flags & F_components_known) == 0) { + do_calc_components(); + } if ((_flags & F_quat_known) == 0) { // If we don't know the quat yet, we must have been given a hpr. // Decompose it. @@ -1841,12 +1874,18 @@ calc_quat() { } //////////////////////////////////////////////////////////////////// -// Function: TransformState::calc_mat +// Function: TransformState::do_calc_mat // Access: Private -// Description: Computes the matrix from the components. +// Description: This is the implementation of calc_mat(); it +// assumes the lock is already held. //////////////////////////////////////////////////////////////////// void TransformState:: -calc_mat() { +do_calc_mat() { + if ((_flags & F_mat_known) != 0) { + // Someone else computed it first. + return; + } + nassertv((_flags & F_is_invalid) == 0); if ((_flags & F_is_identity) != 0) { _mat = LMatrix4f::ident_mat(); @@ -1855,6 +1894,10 @@ calc_mat() { // If we don't have a matrix and we're not identity, the only // other explanation is that we were constructed via components. nassertv((_flags & F_components_known) != 0); + if ((_flags & F_hpr_known) == 0) { + do_calc_hpr(); + } + compose_matrix(_mat, _scale, _shear, get_hpr(), _pos); } _flags |= F_mat_known; diff --git a/panda/src/pgraph/transformState.h b/panda/src/pgraph/transformState.h index 04b93108f9..1f27475510 100644 --- a/panda/src/pgraph/transformState.h +++ b/panda/src/pgraph/transformState.h @@ -30,6 +30,7 @@ #include "pStatCollector.h" #include "geomEnums.h" #include "reMutex.h" +#include "pmutex.h" #include "config_pgraph.h" #include "deletedChain.h" @@ -271,10 +272,13 @@ private: INLINE void check_quat() const; INLINE void check_mat() const; void calc_singular(); - void calc_components(); - void calc_hpr(); + INLINE void calc_components(); + void do_calc_components(); + INLINE void calc_hpr(); + void do_calc_hpr(); void calc_quat(); - void calc_mat(); + INLINE void calc_mat(); + void do_calc_mat(); INLINE void check_uniform_scale(); INLINE void check_uniform_scale2d(); @@ -312,6 +316,9 @@ private: unsigned int _flags; + // This mutex protects _flags, and all of the above computed values. + Mutex _lock; + public: static void register_with_read_factory(); virtual void write_datagram(BamWriter *manager, Datagram &dg);