Procházet zdrojové kódy

don't consume all available memory when running opt-pal

David Rose před 21 roky
rodič
revize
760cdde42d

+ 107 - 9
pandatool/src/palettizer/eggFile.cxx

@@ -49,10 +49,11 @@ TypeHandle EggFile::_type_handle;
 EggFile::
 EggFile() {
   _data = (EggData *)NULL;
+  _first_txa_match = false;
   _default_group = (PaletteGroup *)NULL;
   _is_surprise = true;
   _is_stale = true;
-  _first_txa_match = false;
+  _had_data = false;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -67,6 +68,7 @@ from_command_line(EggData *data,
                   const Filename &dest_filename,
                   const string &egg_comment) {
   _data = data;
+  _had_data = true;
   remove_backstage(_data);
 
   // We save the current directory at the time the egg file appeared
@@ -468,14 +470,25 @@ choose_placements() {
 ////////////////////////////////////////////////////////////////////
 //     Function: EggFile::has_data
 //       Access: Public
-//  Description: Returns true if the EggData for this EggFile has ever
-//               been loaded.
+//  Description: Returns true if the EggData for this EggFile has 
+//               been loaded, and not yet released.
 ////////////////////////////////////////////////////////////////////
 bool EggFile::
 has_data() const {
   return (_data != (EggData *)NULL);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggFile::had_data
+//       Access: Public
+//  Description: Returns true if the EggData for this EggFile has ever
+//               been loaded.
+////////////////////////////////////////////////////////////////////
+bool EggFile::
+had_data() const {
+  return _had_data;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: EggFile::update_egg
 //       Access: Public
@@ -485,6 +498,8 @@ has_data() const {
 ////////////////////////////////////////////////////////////////////
 void EggFile::
 update_egg() {
+  nassertv(_data != (EggData *)NULL);
+
   Textures::iterator ti;
   for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
     TextureReference *reference = (*ti);
@@ -515,6 +530,10 @@ remove_egg() {
 //               is only valid to call this if it has not already been
 //               read in, e.g. from the command line.  Returns true if
 //               successful, false if there is an error.
+//
+//               This may also be called after a previous call to
+//               release_egg_data(), in order to re-read the same egg
+//               file.
 ////////////////////////////////////////////////////////////////////
 bool EggFile::
 read_egg() {
@@ -529,13 +548,24 @@ read_egg() {
     return false;
   }
 
-  EggData *data = new EggData;
+  PT(EggData) data = new EggData;
   if (!data->read(_source_filename, user_source_filename)) {
     // Failure reading.
-    delete data;
     return false;
   }
 
+
+  // Extract the set of textures referenced by this egg file.
+  EggTextureCollection tc;
+  tc.find_used_textures(_data);
+  
+  // Make sure each tref name is unique within a given file.
+  tc.uniquify_trefs();
+
+  // Now build up a list of new TextureReference objects that
+  // represent the textures actually used and their uv range, etc.
+  Textures new_textures;
+
   // We want to search for filenames based on the egg directory, and
   // also on our current directory from which we originally loaded the
   // egg file.  This is important because it's possible the egg file
@@ -551,20 +581,43 @@ read_egg() {
 
   if (!data->load_externals()) {
     // Failure reading an external.
-    delete data;
     return false;
   }
 
   _data = data;
+  _had_data = true;
   remove_backstage(_data);
 
-  // Replace the comment that shows how we first generated the egg
-  // file.
-  _data->insert(_data->begin(), new EggComment("", _egg_comment));
+  // Insert a comment that shows how we first generated the egg file.
+  PT(EggNode) comment = new EggComment("", _egg_comment);
+  _data->insert(_data->begin(), comment);
+
+  if (!_textures.empty()) {
+    // If we already have textures, assume we're re-reading the file.
+    rescan_textures();
+  }
 
   return true;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggFile::release_egg_data
+//       Access: Public
+//  Description: Releases the memory that was loaded by a previous
+//               call to read_egg().
+////////////////////////////////////////////////////////////////////
+void EggFile::
+release_egg_data() {
+  if (_data != (EggData *)NULL) {
+    _data = NULL;
+  }
+  Textures::iterator ti;
+  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
+    TextureReference *reference = (*ti);
+    reference->release_egg_data();
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: EggFile::write_egg
 //       Access: Public
@@ -663,6 +716,51 @@ remove_backstage(EggGroupNode *node) {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggFile::rescan_textures
+//       Access: Private
+//  Description: After reloading the egg file for the second time in a
+//               given session, rematches the texture pointers with
+//               the TextureReference objects.
+////////////////////////////////////////////////////////////////////
+void EggFile::
+rescan_textures() {
+  nassertv(_data != (EggData *)NULL);
+
+  // Extract the set of textures referenced by this egg file.
+  EggTextureCollection tc;
+  tc.find_used_textures(_data);
+  
+  // Make sure each tref name is unique within a given file.
+  tc.uniquify_trefs();
+
+  typedef pmap<string, TextureReference *> ByTRefName;
+  ByTRefName by_tref_name;
+  for (Textures::const_iterator ti = _textures.begin();
+       ti != _textures.end();
+       ++ti) {
+    TextureReference *ref = (*ti);
+    by_tref_name[ref->get_tref_name()] = ref;
+  }
+
+  EggTextureCollection::iterator eti;
+  for (eti = tc.begin(); eti != tc.end(); ++eti) {
+    EggTexture *egg_tex = (*eti);
+
+    ByTRefName::const_iterator tni = by_tref_name.find(egg_tex->get_name());
+    if (tni == by_tref_name.end()) {
+      // We didn't find this TRef name last time around!
+      nout << _source_filename.get_basename()
+           << " modified during session--TRef " << egg_tex->get_name() 
+           << " is new!\n";
+
+    } else {
+      TextureReference *ref = (*tni).second;
+      ref->rebind_egg_data(_data, egg_tex);
+    }
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: EggFile::register_with_read_factory
 //       Access: Public, Static

+ 7 - 4
pandatool/src/palettizer/eggFile.h

@@ -23,14 +23,13 @@
 
 #include "paletteGroups.h"
 #include "textureReference.h"
-
+#include "eggData.h"
 #include "filename.h"
 #include "namable.h"
 #include "typedWritable.h"
-
+#include "pointerTo.h"
 #include "pset.h"
 
-class EggData;
 class TextureImage;
 
 ////////////////////////////////////////////////////////////////////
@@ -71,10 +70,12 @@ public:
   void choose_placements();
 
   bool has_data() const;
+  bool had_data() const;
 
   void update_egg();
   void remove_egg();
   bool read_egg();
+  void release_egg_data();
   bool write_egg();
 
   void write_description(ostream &out, int indent_level = 0) const;
@@ -82,9 +83,10 @@ public:
 
 private:
   void remove_backstage(EggGroupNode *node);
+  void rescan_textures();
 
 private:
-  EggData *_data;
+  PT(EggData) _data;
   Filename _current_directory;
   Filename _source_filename;
   Filename _dest_filename;
@@ -99,6 +101,7 @@ private:
   PaletteGroups _complete_groups;
   bool _is_surprise;
   bool _is_stale;
+  bool _had_data;
 
 
   // The TypedWritable interface follows.

+ 18 - 5
pandatool/src/palettizer/palettizer.cxx

@@ -652,7 +652,7 @@ generate_images(bool redo_all) {
 bool Palettizer::
 read_stale_eggs(bool redo_all) {
   bool okflag = true;
-  
+
   pvector<EggFiles::iterator> invalid_eggs;
 
   EggFiles::iterator ei;
@@ -666,6 +666,7 @@ read_stale_eggs(bool redo_all) {
       } else {
         egg_file->scan_textures();
         egg_file->choose_placements();
+        egg_file->release_egg_data();
       }
     }
   }
@@ -697,10 +698,22 @@ write_eggs() {
   EggFiles::iterator ei;
   for (ei = _egg_files.begin(); ei != _egg_files.end(); ++ei) {
     EggFile *egg_file = (*ei).second;
-    if (egg_file->has_data()) {
-      egg_file->update_egg();
-      if (!egg_file->write_egg()) {
-        okflag = false;
+    if (egg_file->had_data()) {
+      if (!egg_file->has_data()) {
+        // Re-read the egg file.
+        bool read_ok = egg_file->read_egg();
+        if (!read_ok) {
+          nout << "Error!  Unable to re-read egg file.\n";
+          okflag = false;
+        }
+      }
+
+      if (egg_file->has_data()) {
+        egg_file->update_egg();
+        if (!egg_file->write_egg()) {
+          okflag = false;
+        }
+        egg_file->release_egg_data();
       }
     }
   }

+ 7 - 7
pandatool/src/palettizer/textureMemoryCounter.cxx

@@ -78,13 +78,13 @@ add_placement(TexturePlacement *placement) {
 
   } else {
     DestTextureImage *dest = placement->get_dest();
-    nassertv(dest != (DestTextureImage *)NULL);
-
-    int bytes = count_bytes(dest);
-    add_texture(texture, bytes);
-
-    _bytes += bytes;
-    _num_unplaced++;
+    if (dest != (DestTextureImage *)NULL) {
+      int bytes = count_bytes(dest);
+      add_texture(texture, bytes);
+      
+      _bytes += bytes;
+      _num_unplaced++;
+    }
   }
 }
 

+ 2 - 0
pandatool/src/palettizer/texturePlacement.cxx

@@ -862,6 +862,8 @@ fill_image(PNMImage &image) {
       }
     }
   }
+
+  _texture->release_source_image();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 28 - 0
pandatool/src/palettizer/textureReference.cxx

@@ -154,6 +154,34 @@ from_egg_quick(const TextureReference &other) {
   _egg_data = other._egg_data;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: TextureReference::release_egg_data
+//       Access: Public
+//  Description: Called to indicate that the EggData previously passed
+//               to from_egg() is about to be deallocated, and all of
+//               its pointers should be cleared.
+////////////////////////////////////////////////////////////////////
+void TextureReference::
+release_egg_data() {
+  _egg_tex = NULL;
+  _egg_data = NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TextureReference::rebind_egg_data
+//       Access: Public
+//  Description: After an EggData has previously been released via
+//               release_egg_data(), this can be called to indicate
+//               that the egg file has been reloaded and we should
+//               assign the indicated pointers.
+////////////////////////////////////////////////////////////////////
+void TextureReference::
+rebind_egg_data(EggData *data, EggTexture *egg_tex) {
+  nassertv(_tref_name == egg_tex->get_name());
+  _egg_data = data;
+  _egg_tex = egg_tex;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: TextureReference::get_egg_file
 //       Access: Public

+ 3 - 0
pandatool/src/palettizer/textureReference.h

@@ -51,6 +51,8 @@ public:
 
   void from_egg(EggFile *egg_file, EggData *data, EggTexture *egg_tex);
   void from_egg_quick(const TextureReference &other);
+  void release_egg_data();
+  void rebind_egg_data(EggData *data, EggTexture *egg_tex);
 
   EggFile *get_egg_file() const;
   SourceTextureImage *get_source() const;
@@ -79,6 +81,7 @@ public:
   void output(ostream &out) const;
   void write(ostream &out, int indent_level = 0) const;
 
+
 private:
   bool get_uv_range(EggGroupNode *group, Palettizer::RemapUV remap);
   void update_uv_range(EggGroupNode *group, Palettizer::RemapUV remap);