Browse Source

dump texture ram between frames, not during a frame

David Rose 17 years ago
parent
commit
1a4a978b3a

+ 31 - 0
panda/src/display/graphicsEngine.cxx

@@ -695,6 +695,14 @@ render_frame() {
       }
       }
     }
     }
     _windows.swap(new_windows);
     _windows.swap(new_windows);
+
+    // Go ahead and release any textures' ram images for textures that
+    // were drawn in the previous frame.
+    LoadedTextures::iterator lti;
+    for (lti = _loaded_textures.begin(); lti != _loaded_textures.end(); ++lti) {
+      (*lti)->texture_uploaded();
+    }
+    _loaded_textures.clear();
     
     
     // Now it's time to do any drawing from the main frame--after all of
     // Now it's time to do any drawing from the main frame--after all of
     // the App code has executed, but before we begin the next frame.
     // the App code has executed, but before we begin the next frame.
@@ -1054,6 +1062,29 @@ remove_callback(const string &thread_name,
   return wr->remove_callback(callback_time, Callback(func, data));
   return wr->remove_callback(callback_time, Callback(func, data));
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::texture_uploaded
+//       Access: Public
+//  Description: This method is called by the GraphicsStateGuardian
+//               after a texture has been successfully uploaded to
+//               graphics memory.  It is intended as a callback so the
+//               texture can release its RAM image, if _keep_ram_image
+//               is false.
+//
+//               Normally, this is not called directly except by the
+//               GraphicsStateGuardian.  It will be called in the draw
+//               thread.
+////////////////////////////////////////////////////////////////////
+void GraphicsEngine::
+texture_uploaded(Texture *tex) {
+  LightReMutexHolder holder(_lock);
+  // We defer this until the end of the frame; multiple GSG's might be
+  // rendering the texture within the same frame, and we don't want to
+  // dump the texture image until they've all had a chance at it.
+  _loaded_textures.push_back(tex);
+}
+
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::scene_root_func
 //     Function: GraphicsEngine::scene_root_func
 //       Access: Private, Static
 //       Access: Private, Static

+ 5 - 0
panda/src/display/graphicsEngine.h

@@ -127,6 +127,8 @@ public:
                     CallbackFunction *func, void *data);
                     CallbackFunction *func, void *data);
   bool remove_callback(const string &thread_name, CallbackTime callback_time,
   bool remove_callback(const string &thread_name, CallbackTime callback_time,
                        CallbackFunction *func, void *data);
                        CallbackFunction *func, void *data);
+
+  void texture_uploaded(Texture *tex);
   
   
 private:
 private:
   class Callback {
   class Callback {
@@ -344,6 +346,9 @@ private:
   bool _singular_warning_last_frame;
   bool _singular_warning_last_frame;
   bool _singular_warning_this_frame;
   bool _singular_warning_this_frame;
 
 
+  typedef pvector< PT(Texture) > LoadedTextures;
+  LoadedTextures _loaded_textures;
+
   LightReMutex _lock;
   LightReMutex _lock;
 
 
   static PT(GraphicsEngine) _global_ptr;
   static PT(GraphicsEngine) _global_ptr;

+ 6 - 1
panda/src/display/graphicsStateGuardian.cxx

@@ -386,6 +386,7 @@ restore_gamma() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PyObject *GraphicsStateGuardian::
 PyObject *GraphicsStateGuardian::
 get_prepared_textures() const {
 get_prepared_textures() const {
+  ReMutexHolder holder(_prepared_objects->_lock);
   size_t num_textures = _prepared_objects->_prepared_textures.size();
   size_t num_textures = _prepared_objects->_prepared_textures.size();
   PyObject *list = PyList_New(num_textures);
   PyObject *list = PyList_New(num_textures);
 
 
@@ -394,15 +395,18 @@ get_prepared_textures() const {
   for (ti = _prepared_objects->_prepared_textures.begin();
   for (ti = _prepared_objects->_prepared_textures.begin();
        ti != _prepared_objects->_prepared_textures.end();
        ti != _prepared_objects->_prepared_textures.end();
        ++ti) {
        ++ti) {
-    Texture *tex = (*ti)->get_texture();
+    PT(Texture) tex = (*ti)->get_texture();
 
 
     PyObject *element = 
     PyObject *element = 
       DTool_CreatePyInstanceTyped(tex, Dtool_Texture,
       DTool_CreatePyInstanceTyped(tex, Dtool_Texture,
                                   true, false, tex->get_type_index());
                                   true, false, tex->get_type_index());
+    tex->ref();
 
 
+    nassertr(i < num_textures, NULL);
     PyList_SetItem(list, i, element);
     PyList_SetItem(list, i, element);
     ++i;
     ++i;
   }
   }
+  nassertr(i == num_textures, NULL);
 
 
   return list;
   return list;
 }
 }
@@ -418,6 +422,7 @@ get_prepared_textures() const {
 void GraphicsStateGuardian::
 void GraphicsStateGuardian::
 traverse_prepared_textures(GraphicsStateGuardian::TextureCallback *func, 
 traverse_prepared_textures(GraphicsStateGuardian::TextureCallback *func, 
                            void *callback_arg) {
                            void *callback_arg) {
+  ReMutexHolder holder(_prepared_objects->_lock);
   PreparedGraphicsObjects::Textures::const_iterator ti;
   PreparedGraphicsObjects::Textures::const_iterator ti;
   for (ti = _prepared_objects->_prepared_textures.begin();
   for (ti = _prepared_objects->_prepared_textures.begin();
        ti != _prepared_objects->_prepared_textures.end();
        ti != _prepared_objects->_prepared_textures.end();

+ 2 - 1
panda/src/dxgsg8/dxTextureContext8.cxx

@@ -18,6 +18,7 @@
 #include "pStatTimer.h"
 #include "pStatTimer.h"
 #include "dxgsg8base.h"
 #include "dxgsg8base.h"
 #include "bamCache.h"
 #include "bamCache.h"
+#include "graphicsEngine.h"
 
 
 #include <assert.h>
 #include <assert.h>
 #include <time.h>
 #include <time.h>
@@ -794,7 +795,7 @@ create_texture(DXScreenData &scrn) {
     }
     }
   }
   }
 
 
-  tex->texture_uploaded(scrn._dxgsg8);
+  scrn._dxgsg8->get_engine()->texture_uploaded(tex);
   mark_loaded();
   mark_loaded();
   return true;
   return true;
 
 

+ 2 - 1
panda/src/dxgsg9/dxTextureContext9.cxx

@@ -17,6 +17,7 @@
 #include "pStatTimer.h"
 #include "pStatTimer.h"
 #include "dxTextureContext9.h"
 #include "dxTextureContext9.h"
 #include "bamCache.h"
 #include "bamCache.h"
+#include "graphicsEngine.h"
 #include <d3dx9tex.h>
 #include <d3dx9tex.h>
 #include <assert.h>
 #include <assert.h>
 #include <time.h>
 #include <time.h>
@@ -946,7 +947,7 @@ create_texture(DXScreenData &scrn) {
 
 
   // must not put render to texture into LRU
   // must not put render to texture into LRU
   if (!_managed && !tex->get_render_to_texture()) {
   if (!_managed && !tex->get_render_to_texture()) {
-    tex->texture_uploaded(scrn._dxgsg9);
+    scrn._dxgsg9->get_engine()->texture_uploaded(tex);
   }
   }
   mark_loaded();
   mark_loaded();
   
   

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

@@ -59,6 +59,7 @@
 #include "stencilAttrib.h"
 #include "stencilAttrib.h"
 #include "lightAttrib.h"
 #include "lightAttrib.h"
 #include "scissorAttrib.h"
 #include "scissorAttrib.h"
+#include "graphicsEngine.h"
 
 
 #ifdef HAVE_CG
 #ifdef HAVE_CG
 #include "Cg/cgGL.h"
 #include "Cg/cgGL.h"
@@ -7462,7 +7463,7 @@ upload_texture(CLP(TextureContext) *gtc, bool force) {
       }
       }
     }
     }
 
 
-    tex->texture_uploaded(this);
+    get_engine()->texture_uploaded(tex);
     gtc->mark_loaded();
     gtc->mark_loaded();
 
 
     report_my_gl_errors();
     report_my_gl_errors();

+ 8 - 9
panda/src/gobj/texture.cxx

@@ -1564,18 +1564,17 @@ down_to_power_2(int value) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: Texture::texture_uploaded
 //     Function: Texture::texture_uploaded
 //       Access: Public
 //       Access: Public
-//  Description: This method is called by the GraphicsStateGuardian
-//               after a texture has been successfully uploaded to
-//               graphics memory.  It is intended as a callback so the
-//               texture can release its RAM image, if _keep_ram_image
-//               is false.
+//  Description: This method is called by the GraphicsEngine at the
+//               beginning of the frame *after* a texture has been
+//               successfully uploaded to graphics memory.  It is
+//               intended as a callback so the texture can release its
+//               RAM image, if _keep_ram_image is false.
 //
 //
-//               Normally, this is not called directly except by the
-//               GraphicsStateGuardian.  It will be called in the draw
-//               thread.
+//               This is called indirectly when the GSG calls
+//               GraphicsEngine::texture_uploaded().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void Texture::
 void Texture::
-texture_uploaded(GraphicsStateGuardianBase *gsg) {
+texture_uploaded() {
   MutexHolder holder(_lock);
   MutexHolder holder(_lock);
 
 
   if (!keep_texture_ram && !_keep_ram_image) {
   if (!keep_texture_ram && !_keep_ram_image) {

+ 1 - 1
panda/src/gobj/texture.h

@@ -428,7 +428,7 @@ PUBLISHED:
   static int down_to_power_2(int value);
   static int down_to_power_2(int value);
 
 
 public:
 public:
-  void texture_uploaded(GraphicsStateGuardianBase *gsg);
+  void texture_uploaded();
   
   
   virtual bool has_cull_callback() const;
   virtual bool has_cull_callback() const;
   virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const;
   virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const;

+ 2 - 1
panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx

@@ -38,6 +38,7 @@
 #include "zmath.h"
 #include "zmath.h"
 #include "ztriangle_table.h"
 #include "ztriangle_table.h"
 #include "store_pixel_table.h"
 #include "store_pixel_table.h"
+#include "graphicsEngine.h"
 
 
 TypeHandle TinyGraphicsStateGuardian::_type_handle;
 TypeHandle TinyGraphicsStateGuardian::_type_handle;
 
 
@@ -2536,7 +2537,7 @@ upload_texture(TinyTextureContext *gtc, bool force) {
 
 
   gtc->update_data_size_bytes(bytecount);
   gtc->update_data_size_bytes(bytecount);
   
   
-  tex->texture_uploaded(this);
+  get_engine()->texture_uploaded(tex);
   gtc->mark_loaded();
   gtc->mark_loaded();
 
 
   return true;
   return true;