Răsfoiți Sursa

further debugging in TransformState (and one important bugfix)

David Rose 14 ani în urmă
părinte
comite
e552c230a0
2 a modificat fișierele cu 156 adăugiri și 48 ștergeri
  1. 154 48
      panda/src/pgraph/transformState.cxx
  2. 2 0
      panda/src/pgraph/transformState.h

+ 154 - 48
panda/src/pgraph/transformState.cxx

@@ -768,6 +768,66 @@ unref() const {
   return false;
   return false;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: TransformState::validate_composition_cache
+//       Access: Published
+//  Description: Returns true if the composition cache and invert
+//               composition cache for this particular TransformState
+//               are self-consistent and valid, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool TransformState::
+validate_composition_cache() const {
+  LightReMutexHolder holder(*_states_lock);
+
+  int size = _composition_cache.get_size();
+  for (int i = 0; i < size; ++i) {
+    if (!_composition_cache.has_element(i)) {
+      continue;
+    }
+    const TransformState *source = _composition_cache.get_key(i);
+    if (source != (TransformState *)NULL) {
+      // Check that the source also has a pointer back to this one.  We
+      // always add entries to the composition cache in pairs.
+      int ri = source->_composition_cache.find(this);
+      if (ri == -1) {
+        // Failure!  There is no back-pointer.
+        pgraph_cat.error()
+          << "TransformState::composition cache is inconsistent!\n";
+        pgraph_cat.error(false)
+          << *this << " compose " << *source << "\n";
+        pgraph_cat.error(false)
+          << "but no reverse\n";
+        return false;
+      }
+    }
+  }
+
+  size = _invert_composition_cache.get_size();
+  for (int i = 0; i < size; ++i) {
+    if (!_invert_composition_cache.has_element(i)) {
+      continue;
+    }
+    const TransformState *source = _invert_composition_cache.get_key(i);
+    if (source != (TransformState *)NULL) {
+      // Check that the source also has a pointer back to this one.  We
+      // always add entries to the composition cache in pairs.
+      int ri = source->_invert_composition_cache.find(this);
+      if (ri == -1) {
+        // Failure!  There is no back-pointer.
+        pgraph_cat.error()
+          << "TransformState::invert composition cache is inconsistent!\n";
+        pgraph_cat.error(false)
+          << *this << " invert compose " << *source << "\n";
+        pgraph_cat.error(false)
+          << "but no reverse\n";
+        return false;
+      }
+    }
+  }
+
+  return true;
+}
+
 #ifdef HAVE_PYTHON
 #ifdef HAVE_PYTHON
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TransformState::get_composition_cache
 //     Function: TransformState::get_composition_cache
@@ -787,43 +847,47 @@ PyObject *TransformState::
 get_composition_cache() const {
 get_composition_cache() const {
   IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState;
   IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState;
   LightReMutexHolder holder(*_states_lock);
   LightReMutexHolder holder(*_states_lock);
-  size_t cache_size = _composition_cache.get_size();
-  PyObject *list = PyList_New(cache_size);
 
 
-  for (size_t i = 0; i < cache_size; ++i) {
+  size_t num_states = _composition_cache.get_num_entries();
+  PyObject *list = PyList_New(num_states);
+  size_t i = 0;
+
+  int size = _composition_cache.get_size();
+  for (int si = 0; si < size; ++si) {
+    if (!_composition_cache.has_element(si)) {
+      continue;
+    }
+
     PyObject *tuple = PyTuple_New(2);
     PyObject *tuple = PyTuple_New(2);
     PyObject *a, *b;
     PyObject *a, *b;
-    if (!_composition_cache.has_element(i)) {
+
+    const TransformState *source = _composition_cache.get_key(si);
+    if (source == (TransformState *)NULL) {
       a = Py_None;
       a = Py_None;
       Py_INCREF(a);
       Py_INCREF(a);
+    } else {
+      source->ref();
+      a = DTool_CreatePyInstanceTyped((void *)source, Dtool_TransformState, 
+                                      true, true, source->get_type_index());
+    }
+    const TransformState *result = _composition_cache.get_data(si)._result;
+    if (result == (TransformState *)NULL) {
       b = Py_None;
       b = Py_None;
       Py_INCREF(b);
       Py_INCREF(b);
     } else {
     } else {
-      const TransformState *source = _composition_cache.get_key(i);
-      if (source == (TransformState *)NULL) {
-        a = Py_None;
-        Py_INCREF(a);
-      } else {
-        source->ref();
-        a = DTool_CreatePyInstanceTyped((void *)source, Dtool_TransformState, 
-                                        true, true, source->get_type_index());
-      }
-      const TransformState *result = _composition_cache.get_data(i)._result;
-      if (result == (TransformState *)NULL) {
-        b = Py_None;
-        Py_INCREF(b);
-      } else {
-        result->ref();
-        b = DTool_CreatePyInstanceTyped((void *)result, Dtool_TransformState, 
-                                        true, true, result->get_type_index());
-      }
+      result->ref();
+      b = DTool_CreatePyInstanceTyped((void *)result, Dtool_TransformState, 
+                                      true, true, result->get_type_index());
     }
     }
+
     PyTuple_SET_ITEM(tuple, 0, a);
     PyTuple_SET_ITEM(tuple, 0, a);
     PyTuple_SET_ITEM(tuple, 1, b);
     PyTuple_SET_ITEM(tuple, 1, b);
 
 
+    nassertr(i < num_states, list);
     PyList_SET_ITEM(list, i, tuple);
     PyList_SET_ITEM(list, i, tuple);
+    ++i;
   }
   }
-
+  nassertr(i == num_states, list);
   return list;
   return list;
 }
 }
 #endif  // HAVE_PYTHON
 #endif  // HAVE_PYTHON
@@ -847,43 +911,47 @@ PyObject *TransformState::
 get_invert_composition_cache() const {
 get_invert_composition_cache() const {
   IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState;
   IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState;
   LightReMutexHolder holder(*_states_lock);
   LightReMutexHolder holder(*_states_lock);
-  size_t cache_size = _invert_composition_cache.get_size();
-  PyObject *list = PyList_New(cache_size);
 
 
-  for (size_t i = 0; i < cache_size; ++i) {
+  size_t num_states = _invert_composition_cache.get_num_entries();
+  PyObject *list = PyList_New(num_states);
+  size_t i = 0;
+
+  int size = _invert_composition_cache.get_size();
+  for (int si = 0; si < size; ++si) {
+    if (!_invert_composition_cache.has_element(si)) {
+      continue;
+    }
+
     PyObject *tuple = PyTuple_New(2);
     PyObject *tuple = PyTuple_New(2);
     PyObject *a, *b;
     PyObject *a, *b;
-    if (!_invert_composition_cache.has_element(i)) {
+
+    const TransformState *source = _invert_composition_cache.get_key(si);
+    if (source == (TransformState *)NULL) {
       a = Py_None;
       a = Py_None;
       Py_INCREF(a);
       Py_INCREF(a);
+    } else {
+      source->ref();
+      a = DTool_CreatePyInstanceTyped((void *)source, Dtool_TransformState, 
+                                      true, true, source->get_type_index());
+    }
+    const TransformState *result = _invert_composition_cache.get_data(si)._result;
+    if (result == (TransformState *)NULL) {
       b = Py_None;
       b = Py_None;
       Py_INCREF(b);
       Py_INCREF(b);
     } else {
     } else {
-      const TransformState *source = _invert_composition_cache.get_key(i);
-      if (source == (TransformState *)NULL) {
-        a = Py_None;
-        Py_INCREF(a);
-      } else {
-        source->ref();
-        a = DTool_CreatePyInstanceTyped((void *)source, Dtool_TransformState, 
-                                        true, true, source->get_type_index());
-      }
-      const TransformState *result = _invert_composition_cache.get_data(i)._result;
-      if (result == (TransformState *)NULL) {
-        b = Py_None;
-        Py_INCREF(b);
-      } else {
-        result->ref();
-        b = DTool_CreatePyInstanceTyped((void *)result, Dtool_TransformState, 
-                                        true, true, result->get_type_index());
-      }
+      result->ref();
+      b = DTool_CreatePyInstanceTyped((void *)result, Dtool_TransformState, 
+                                      true, true, result->get_type_index());
     }
     }
+
     PyTuple_SET_ITEM(tuple, 0, a);
     PyTuple_SET_ITEM(tuple, 0, a);
     PyTuple_SET_ITEM(tuple, 1, b);
     PyTuple_SET_ITEM(tuple, 1, b);
 
 
+    nassertr(i < num_states, list);
     PyList_SET_ITEM(list, i, tuple);
     PyList_SET_ITEM(list, i, tuple);
+    ++i;
   }
   }
-
+  nassertr(i == num_states, list);
   return list;
   return list;
 }
 }
 #endif  // HAVE_PYTHON
 #endif  // HAVE_PYTHON
@@ -1441,6 +1509,9 @@ validate_states() {
   while (snext < size) {
   while (snext < size) {
     nassertr(_states->get_key(snext)->get_ref_count() >= 0, false);
     nassertr(_states->get_key(snext)->get_ref_count() >= 0, false);
     const TransformState *ssi = _states->get_key(si);
     const TransformState *ssi = _states->get_key(si);
+    if (!ssi->validate_composition_cache()) {
+      return false;
+    }
     const TransformState *ssnext = _states->get_key(snext);
     const TransformState *ssnext = _states->get_key(snext);
     int c = ssi->compare_to(*ssnext);
     int c = ssi->compare_to(*ssnext);
     int ci = ssnext->compare_to(*ssi);
     int ci = ssnext->compare_to(*ssi);
@@ -1506,6 +1577,42 @@ get_states() {
 }
 }
 #endif  // HAVE_PYTHON
 #endif  // HAVE_PYTHON
 
 
+#ifdef HAVE_PYTHON
+////////////////////////////////////////////////////////////////////
+//     Function: TransformState::get_unused_states
+//       Access: Published, Static
+//  Description: Returns a list of all of the "unused" TransformState
+//               objects in the state cache.  See
+//               get_num_unused_states().
+////////////////////////////////////////////////////////////////////
+PyObject *TransformState::
+get_unused_states() {
+  IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState;
+  if (_states == (States *)NULL) {
+    return PyList_New(0);
+  }
+  LightReMutexHolder holder(*_states_lock);
+
+  PyObject *list = PyList_New(0);
+  int size = _states->get_size();
+  for (int si = 0; si < size; ++si) {
+    if (!_states->has_element(si)) {
+      continue;
+    }
+    const TransformState *state = _states->get_key(si);
+    if (state->get_cache_ref_count() == state->get_ref_count()) {
+      state->ref();
+      PyObject *a = 
+        DTool_CreatePyInstanceTyped((void *)state, Dtool_TransformState, 
+                                    true, true, state->get_type_index());
+      PyList_Append(list, a);
+      Py_DECREF(a);
+    }
+  }
+  return list;
+}
+#endif  // HAVE_PYTHON
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TransformState::init_states
 //     Function: TransformState::init_states
 //       Access: Public, Static
 //       Access: Public, Static
@@ -2322,8 +2429,7 @@ do_calc_hash() {
     // Only bother to put the rest of the stuff in the hash if the
     // Only bother to put the rest of the stuff in the hash if the
     // transform is not invalid or empty.
     // transform is not invalid or empty.
     
     
-    if ((_flags & (F_components_given | F_hpr_given | F_quat_given)) == 
-        (F_components_given | F_hpr_given | F_quat_given)) {
+    if ((_flags & F_components_given) != 0) {
       // If the transform was specified componentwise, hash it
       // If the transform was specified componentwise, hash it
       // componentwise.
       // componentwise.
       _hash = _pos.add_hash(_hash);
       _hash = _pos.add_hash(_hash);

+ 2 - 0
panda/src/pgraph/transformState.h

@@ -189,6 +189,7 @@ PUBLISHED:
   INLINE int get_invert_composition_cache_size() const;
   INLINE int get_invert_composition_cache_size() const;
   INLINE const TransformState *get_invert_composition_cache_source(int n) const;
   INLINE const TransformState *get_invert_composition_cache_source(int n) const;
   INLINE const TransformState *get_invert_composition_cache_result(int n) const;
   INLINE const TransformState *get_invert_composition_cache_result(int n) const;
+  bool validate_composition_cache() const;
 #ifdef HAVE_PYTHON
 #ifdef HAVE_PYTHON
   PyObject *get_composition_cache() const;
   PyObject *get_composition_cache() const;
   PyObject *get_invert_composition_cache() const;
   PyObject *get_invert_composition_cache() const;
@@ -207,6 +208,7 @@ PUBLISHED:
   static bool validate_states();
   static bool validate_states();
 #ifdef HAVE_PYTHON
 #ifdef HAVE_PYTHON
   static PyObject *get_states();
   static PyObject *get_states();
+  static PyObject *get_unused_states();
 #endif  // HAVE_PYTHON
 #endif  // HAVE_PYTHON