Jelajahi Sumber

remove texture images from ram after preparing them

David Rose 24 tahun lalu
induk
melakukan
97e33c8c95

+ 5 - 1
panda/src/dxgsg/dxTextureContext.cxx

@@ -1537,7 +1537,11 @@ CreateTexture(LPDIRECT3DDEVICE7 pd3dDevice, int cNumTexPixFmts, LPDDPIXELFORMAT
 
 
 HRESULT DXTextureContext::
 HRESULT DXTextureContext::
 FillDDSurfTexturePixels(void) {
 FillDDSurfTexturePixels(void) {
-    PixelBuffer *pbuf = _texture->_pbuffer;
+    PixelBuffer *pbuf = _texture->get_ram_image();
+    if (pbuf == (PixelBuffer *)NULL) {
+      // The texture doesn't have an image to load.
+      return E_FAIL;
+    }
     DWORD cNumColorChannels = pbuf->get_num_components();
     DWORD cNumColorChannels = pbuf->get_num_components();
 
 
     HRESULT hr = ConvertPixBuftoDDSurf((ConversionType)_PixBufConversionType,pbuf->_image.p(),_surface);
     HRESULT hr = ConvertPixBuftoDDSurf((ConversionType)_PixBufConversionType,pbuf->_image.p(),_surface);

File diff ditekan karena terlalu besar
+ 302 - 291
panda/src/glgsg/glGraphicsStateGuardian.cxx


+ 1 - 1
panda/src/glgsg/glGraphicsStateGuardian.h

@@ -244,7 +244,7 @@ protected:
 
 
   void bind_texture(TextureContext *tc);
   void bind_texture(TextureContext *tc);
   void specify_texture(Texture *tex);
   void specify_texture(Texture *tex);
-  void apply_texture_immediate(Texture *tex);
+  bool apply_texture_immediate(Texture *tex);
 
 
   GLenum get_texture_wrap_mode(Texture::WrapMode wm);
   GLenum get_texture_wrap_mode(Texture::WrapMode wm);
   GLenum get_texture_filter_type(Texture::FilterType ft);
   GLenum get_texture_filter_type(Texture::FilterType ft);

+ 10 - 0
panda/src/gobj/config_gobj.cxx

@@ -66,6 +66,16 @@ bool textures_down_power_2 = false;
 bool textures_up_square = false;
 bool textures_up_square = false;
 bool textures_down_square = false;
 bool textures_down_square = false;
 
 
+
+// Set this to true to retain the ram image for each texture after it
+// has been prepared with the GSG.  This will allow the texture to be
+// prepared with multiple GSG, or to be re-prepared later after it is
+// explicitly released from the GSG, without having to reread the
+// texture image from disk; but it will consume memory somewhat
+// wastefully.
+bool keep_texture_ram = config_gobj.GetBool("keep-texture-ram", false);
+
+
 // Set this to specify how textures should be written into Bam files.
 // Set this to specify how textures should be written into Bam files.
 // Currently, the options are:
 // Currently, the options are:
 
 

+ 1 - 0
panda/src/gobj/config_gobj.h

@@ -30,6 +30,7 @@ extern EXPCL_PANDA bool textures_up_power_2;
 extern EXPCL_PANDA bool textures_down_power_2;
 extern EXPCL_PANDA bool textures_down_power_2;
 extern EXPCL_PANDA bool textures_up_square;
 extern EXPCL_PANDA bool textures_up_square;
 extern EXPCL_PANDA bool textures_down_square;
 extern EXPCL_PANDA bool textures_down_square;
+extern EXPCL_PANDA bool keep_texture_ram;
 
 
 enum BamTextureMode {
 enum BamTextureMode {
   BTM_fullpath,
   BTM_fullpath,

+ 13 - 11
panda/src/gobj/texture.I

@@ -18,24 +18,26 @@
 
 
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Texture::apply
+//     Function: Texture::has_ram_image
 //       Access: Public
 //       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void Texture::
-apply(GraphicsStateGuardianBase *gsg) {
-  gsg->apply_texture(prepare(gsg));
+//  Description: Returns true if the Texture keeps has its image
+//               contents available in main RAM, false if it exists
+//               only in texture memory or in the prepared GSG
+//               context.
+////////////////////////////////////////////////////////////////////
+INLINE bool Texture::
+has_ram_image() const {
+  return !_pbuffer->_image.empty();
 }
 }
 
 
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Texture::get_level
+//     Function: Texture::apply
 //       Access: Public
 //       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE int Texture::
-get_level() const {
-  return _level;
+INLINE void Texture::
+apply(GraphicsStateGuardianBase *gsg) {
+  gsg->apply_texture(prepare(gsg));
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 80 - 34
panda/src/gobj/texture.cxx

@@ -103,7 +103,7 @@ consider_rescale(PNMImage &pnmimage, const string &name) {
       << new_x_size << " by " << new_y_size << "\n";
       << new_x_size << " by " << new_y_size << "\n";
 
 
     PNMImage scaled(new_x_size, new_y_size, pnmimage.get_num_channels(),
     PNMImage scaled(new_x_size, new_y_size, pnmimage.get_num_channels(),
-            pnmimage.get_maxval(), pnmimage.get_type());
+                    pnmimage.get_maxval(), pnmimage.get_type());
     scaled.quick_filter_from(pnmimage);
     scaled.quick_filter_from(pnmimage);
     pnmimage = scaled;
     pnmimage = scaled;
   }
   }
@@ -116,7 +116,6 @@ consider_rescale(PNMImage &pnmimage, const string &name) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 Texture::
 Texture::
 Texture() : ImageBuffer() {
 Texture() : ImageBuffer() {
-  _level = 0; // Mipmap level
   _magfilter = FT_nearest;
   _magfilter = FT_nearest;
   _minfilter = FT_nearest;
   _minfilter = FT_nearest;
   _wrapu = WM_repeat;
   _wrapu = WM_repeat;
@@ -139,10 +138,10 @@ Texture::
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: read
 //     Function: read
 //       Access: Published
 //       Access: Published
-//  Description:
+//  Description: Reads the texture from the indicated filename.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool Texture::
 bool Texture::
-read(const string& name) {
+read(const string &name) {
   PNMImage pnmimage;
   PNMImage pnmimage;
 
 
   if (!pnmimage.read(name)) {
   if (!pnmimage.read(name)) {
@@ -163,7 +162,7 @@ read(const string& name) {
 //     Function: read
 //     Function: read
 //       Access: Published
 //       Access: Published
 //  Description: Combine a 3-component image with a grayscale image
 //  Description: Combine a 3-component image with a grayscale image
-//       to get a 4-component image
+//               to get a 4-component image
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool Texture::
 bool Texture::
 read(const string &name, const string &gray) {
 read(const string &name, const string &gray) {
@@ -193,8 +192,8 @@ read(const string &name, const string &gray) {
       << pnmimage.get_x_size() << " by " << pnmimage.get_y_size() << "\n";
       << pnmimage.get_x_size() << " by " << pnmimage.get_y_size() << "\n";
 
 
     PNMImage scaled(pnmimage.get_x_size(), pnmimage.get_y_size(),
     PNMImage scaled(pnmimage.get_x_size(), pnmimage.get_y_size(),
-            grayimage.get_num_channels(),
-            grayimage.get_maxval(), grayimage.get_type());
+                    grayimage.get_num_channels(),
+                    grayimage.get_maxval(), grayimage.get_type());
     scaled.quick_filter_from(grayimage);
     scaled.quick_filter_from(grayimage);
     grayimage = scaled;
     grayimage = scaled;
   }
   }
@@ -215,35 +214,36 @@ read(const string &name, const string &gray) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: write
 //     Function: write
 //       Access: Published
 //       Access: Published
-//  Description:
+//  Description: Writes the texture to the indicated filename.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-bool Texture::write(const string& name) const
-{
+bool Texture::
+write(const string &name) const {
+  nassertr(has_ram_image(), false);
   return _pbuffer->write(name);
   return _pbuffer->write(name);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: load
 //     Function: load
 //       Access: Public
 //       Access: Public
-//  Description:
+//  Description: Creates the texture from the already-read PNMImage.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-bool Texture::load(const PNMImage& pnmimage)
-{
-  if (_pbuffer->load( pnmimage ) == false)
+bool Texture::
+load(const PNMImage &pnmimage) {
+  if (!_pbuffer->load(pnmimage))
     return false;
     return false;
 
 
   unprepare();
   unprepare();
-
   return true;
   return true;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: store
 //     Function: store
 //       Access: Public
 //       Access: Public
-//  Description:
+//  Description: Saves the texture to the indicated PNMImage, but does
+//               not write it to disk.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-bool Texture::store(PNMImage& pnmimage) const
-{
+bool Texture::
+store(PNMImage &pnmimage) const {
   return _pbuffer->store( pnmimage );
   return _pbuffer->store( pnmimage );
 }
 }
 
 
@@ -264,6 +264,19 @@ prepare(GraphicsStateGuardianBase *gsg) {
 
 
   TextureContext *tc = gsg->prepare_texture(this);
   TextureContext *tc = gsg->prepare_texture(this);
   _contexts[gsg] = tc;
   _contexts[gsg] = tc;
+
+  if (!keep_texture_ram) {
+    // Once we have prepared the texture, we can generally safely
+    // remove the pixels from main RAM.  The GSG is now responsible
+    // for remembering what it looks like.
+
+    if (gobj_cat.is_debug()) {
+      gobj_cat.debug()
+        << "Dumping RAM for texture " << get_name() << "\n";
+    }
+    _pbuffer->_image.clear();
+  }
+
   return tc;
   return tc;
 }
 }
 
 
@@ -331,12 +344,48 @@ clear_gsg(GraphicsStateGuardianBase *gsg) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: Texture::get_ram_image
+//       Access: Public
+//  Description: Returns the PixelBuffer associated with the texture.
+//               If the PixelBuffer does not currently have an
+//               associated RAM image, and the texture was generated
+//               by loading an image from a disk file (the most common
+//               case), this forces the reload of the same texture.
+//               This can happen if keep_texture_ram is configured to
+//               false, and we have previously prepared this texture
+//               with a GSG.
+//
+//               It is possible that the RAM image is still
+//               unavailable.  If that happens, this function returns
+//               NULL.
+////////////////////////////////////////////////////////////////////
+PixelBuffer *Texture::
+get_ram_image() {
+  if (!has_ram_image()) {
+    // Now we have to reload the texture image.
+    gobj_cat.info()
+      << "Reloading texture " << get_name() << "\n";
+    if (has_alpha_name()) {
+      read(get_name(), get_alpha_name());
+    } else {
+      read(get_name());
+    }
+  }
+
+  if (has_ram_image()) {
+    return _pbuffer;
+  } else {
+    return (PixelBuffer *)NULL;
+  }
+}
+
 void Texture::copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr) {
 void Texture::copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr) {
   gsg->copy_texture(prepare(gsg), dr);
   gsg->copy_texture(prepare(gsg), dr);
 }
 }
 
 
 void Texture::copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr,
 void Texture::copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr,
-            const RenderBuffer &rb) {
+                   const RenderBuffer &rb) {
   gsg->copy_texture(prepare(gsg), dr, rb);
   gsg->copy_texture(prepare(gsg), dr, rb);
 }
 }
 
 
@@ -350,7 +399,7 @@ void Texture::draw(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr) {
 }
 }
 
 
 void Texture::draw(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr,
 void Texture::draw(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr,
-            const RenderBuffer &rb) {
+                   const RenderBuffer &rb) {
   gsg->draw_texture(prepare(gsg), dr, rb);
   gsg->draw_texture(prepare(gsg), dr, rb);
 }
 }
 
 
@@ -430,10 +479,9 @@ set_anisotropic_degree(int anisotropic_degree) {
 //               the particular object to a Datagram
 //               the particular object to a Datagram
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void Texture::
 void Texture::
-write_datagram(BamWriter *manager, Datagram &me)
-{
+write_datagram(BamWriter *manager, Datagram &me) {
   ImageBuffer::write_datagram(manager, me);
   ImageBuffer::write_datagram(manager, me);
-  me.add_uint32(_level);
+  me.add_uint32(0);  // For historical purposes
   me.add_uint8(_wrapu);
   me.add_uint8(_wrapu);
   me.add_uint8(_wrapv);
   me.add_uint8(_wrapv);
   me.add_uint8(_minfilter);
   me.add_uint8(_minfilter);
@@ -469,7 +517,7 @@ fillin(DatagramIterator &scan, BamReader *manager) {
   //Texture to know how the parent write_datagram works.  And
   //Texture to know how the parent write_datagram works.  And
   //makes the assumption that the only data being written is
   //makes the assumption that the only data being written is
   //the name
   //the name
-  _level = scan.get_uint32();
+  scan.get_uint32();  // For historical purposes
   _wrapu = (enum WrapMode) scan.get_uint8();
   _wrapu = (enum WrapMode) scan.get_uint8();
   _wrapv = (enum WrapMode) scan.get_uint8();
   _wrapv = (enum WrapMode) scan.get_uint8();
   _minfilter = (enum FilterType) scan.get_uint8();
   _minfilter = (enum FilterType) scan.get_uint8();
@@ -485,15 +533,15 @@ fillin(DatagramIterator &scan, BamReader *manager) {
       PixelBuffer::Format format = (PixelBuffer::Format)scan.get_uint8();
       PixelBuffer::Format format = (PixelBuffer::Format)scan.get_uint8();
       int num_components = -1;
       int num_components = -1;
       if (scan.get_remaining_size() > 0) {
       if (scan.get_remaining_size() > 0) {
-    num_components = scan.get_uint8();
+        num_components = scan.get_uint8();
       }
       }
 
 
       if (_pbuffer != (PixelBuffer *)NULL) {
       if (_pbuffer != (PixelBuffer *)NULL) {
-    if (num_components == _pbuffer->get_num_components()) {
-      // Only reset the format if the number of components hasn't
-      // changed.
-      _pbuffer->set_format(format);
-    }
+        if (num_components == _pbuffer->get_num_components()) {
+          // Only reset the format if the number of components hasn't
+          // changed.
+          _pbuffer->set_format(format);
+        }
       }
       }
     }
     }
   }
   }
@@ -505,8 +553,7 @@ fillin(DatagramIterator &scan, BamReader *manager) {
 //  Description: Factory method to generate a Texture object
 //  Description: Factory method to generate a Texture object
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 TypedWritable* Texture::
 TypedWritable* Texture::
-make_Texture(const FactoryParams &params)
-{
+make_Texture(const FactoryParams &params) {
   //The process of making a texture is slightly
   //The process of making a texture is slightly
   //different than making other Writable objects.
   //different than making other Writable objects.
   //That is because all creation of Textures should
   //That is because all creation of Textures should
@@ -551,8 +598,7 @@ make_Texture(const FactoryParams &params)
 //  Description: Factory method to generate a Texture object
 //  Description: Factory method to generate a Texture object
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void Texture::
 void Texture::
-register_with_read_factory(void)
-{
+register_with_read_factory() {
   BamReader::get_factory()->register_factory(get_class_type(), make_Texture);
   BamReader::get_factory()->register_factory(get_class_type(), make_Texture);
 }
 }
 
 

+ 10 - 15
panda/src/gobj/texture.h

@@ -74,34 +74,31 @@ PUBLISHED:
   Texture();
   Texture();
   ~Texture();
   ~Texture();
 
 
-  virtual bool read(const string& name);
+  virtual bool read(const string &name);
   virtual bool read(const string &name, const string &gray);
   virtual bool read(const string &name, const string &gray);
-  virtual bool write(const string& name = "") const;
+  virtual bool write(const string &name = "") const;
 
 
 public:
 public:
-  bool load( const PNMImage& pnmimage );
-  bool store( PNMImage& pnmimage ) const;
+  bool load(const PNMImage &pnmimage);
+  bool store(PNMImage &pnmimage) const;
 
 
   TextureContext *prepare(GraphicsStateGuardianBase *gsg);
   TextureContext *prepare(GraphicsStateGuardianBase *gsg);
   void unprepare();
   void unprepare();
   void unprepare(GraphicsStateGuardianBase *gsg);
   void unprepare(GraphicsStateGuardianBase *gsg);
   void clear_gsg(GraphicsStateGuardianBase *gsg);
   void clear_gsg(GraphicsStateGuardianBase *gsg);
 
 
-  INLINE void apply( GraphicsStateGuardianBase *gsg );
+  INLINE bool has_ram_image() const;
+  PixelBuffer *get_ram_image();
+
+  INLINE void apply(GraphicsStateGuardianBase *gsg);
 
 
   virtual void copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr);
   virtual void copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr);
   virtual void copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr,
   virtual void copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr,
-                        const RenderBuffer &rb);
+                    const RenderBuffer &rb);
   virtual void draw(GraphicsStateGuardianBase *gsg);
   virtual void draw(GraphicsStateGuardianBase *gsg);
   virtual void draw(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr);
   virtual void draw(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr);
   virtual void draw(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr,
   virtual void draw(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr,
-                        const RenderBuffer &rb);
-
-  INLINE bool has_ram_image(void) const {
-    return !_pbuffer->_image.empty();
-  }
-
-  INLINE int get_level() const;
+                    const RenderBuffer &rb);
 
 
 PUBLISHED:
 PUBLISHED:
   void set_wrapu(WrapMode wrap);
   void set_wrapu(WrapMode wrap);
@@ -126,7 +123,6 @@ protected:
   void fillin(DatagramIterator& scan, BamReader* manager);
   void fillin(DatagramIterator& scan, BamReader* manager);
 
 
 public:
 public:
-
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;
   }
   }
@@ -148,7 +144,6 @@ private:
 
 
 protected:
 protected:
 
 
-  int _level;
   WrapMode _wrapu;
   WrapMode _wrapu;
   WrapMode _wrapv;
   WrapMode _wrapv;
   FilterType _minfilter;
   FilterType _minfilter;

+ 3 - 1
panda/src/gobj/texturePool.cxx

@@ -199,8 +199,10 @@ ns_list_contents(ostream &out) {
   out << _textures.size() << " textures:\n";
   out << _textures.size() << " textures:\n";
   Textures::iterator ti;
   Textures::iterator ti;
   for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
   for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
+    Texture *texture = (*ti).second;
     out << "  " << (*ti).first
     out << "  " << (*ti).first
-        << " (count = " << (*ti).second->get_ref_count() << ")\n";
+        << " (count = " << texture->get_ref_count() << ", ram = "
+        << texture->_pbuffer->_image.size() / 1024 << " Kb)\n";
   }
   }
 }
 }
 
 

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini