From 1a4a978b3ae29f2398a2c42c37aec67de3b10fa6 Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 4 Feb 2009 16:30:28 +0000 Subject: [PATCH] dump texture ram between frames, not during a frame --- panda/src/display/graphicsEngine.cxx | 31 +++++++++++++++++++ panda/src/display/graphicsEngine.h | 5 +++ panda/src/display/graphicsStateGuardian.cxx | 7 ++++- panda/src/dxgsg8/dxTextureContext8.cxx | 3 +- panda/src/dxgsg9/dxTextureContext9.cxx | 3 +- .../glstuff/glGraphicsStateGuardian_src.cxx | 3 +- panda/src/gobj/texture.cxx | 17 +++++----- panda/src/gobj/texture.h | 2 +- .../tinydisplay/tinyGraphicsStateGuardian.cxx | 3 +- 9 files changed, 59 insertions(+), 15 deletions(-) diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index f7f75d9239..0c33637296 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -695,6 +695,14 @@ render_frame() { } } _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 // 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)); } +//////////////////////////////////////////////////////////////////// +// 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 // Access: Private, Static diff --git a/panda/src/display/graphicsEngine.h b/panda/src/display/graphicsEngine.h index d53539530f..cee553e8d5 100644 --- a/panda/src/display/graphicsEngine.h +++ b/panda/src/display/graphicsEngine.h @@ -127,6 +127,8 @@ public: CallbackFunction *func, void *data); bool remove_callback(const string &thread_name, CallbackTime callback_time, CallbackFunction *func, void *data); + + void texture_uploaded(Texture *tex); private: class Callback { @@ -344,6 +346,9 @@ private: bool _singular_warning_last_frame; bool _singular_warning_this_frame; + typedef pvector< PT(Texture) > LoadedTextures; + LoadedTextures _loaded_textures; + LightReMutex _lock; static PT(GraphicsEngine) _global_ptr; diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index ca8e5f3f49..49c0a703e7 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -386,6 +386,7 @@ restore_gamma() { //////////////////////////////////////////////////////////////////// PyObject *GraphicsStateGuardian:: get_prepared_textures() const { + ReMutexHolder holder(_prepared_objects->_lock); size_t num_textures = _prepared_objects->_prepared_textures.size(); PyObject *list = PyList_New(num_textures); @@ -394,15 +395,18 @@ get_prepared_textures() const { for (ti = _prepared_objects->_prepared_textures.begin(); ti != _prepared_objects->_prepared_textures.end(); ++ti) { - Texture *tex = (*ti)->get_texture(); + PT(Texture) tex = (*ti)->get_texture(); PyObject *element = DTool_CreatePyInstanceTyped(tex, Dtool_Texture, true, false, tex->get_type_index()); + tex->ref(); + nassertr(i < num_textures, NULL); PyList_SetItem(list, i, element); ++i; } + nassertr(i == num_textures, NULL); return list; } @@ -418,6 +422,7 @@ get_prepared_textures() const { void GraphicsStateGuardian:: traverse_prepared_textures(GraphicsStateGuardian::TextureCallback *func, void *callback_arg) { + ReMutexHolder holder(_prepared_objects->_lock); PreparedGraphicsObjects::Textures::const_iterator ti; for (ti = _prepared_objects->_prepared_textures.begin(); ti != _prepared_objects->_prepared_textures.end(); diff --git a/panda/src/dxgsg8/dxTextureContext8.cxx b/panda/src/dxgsg8/dxTextureContext8.cxx index 8953333a1d..190f4ae512 100644 --- a/panda/src/dxgsg8/dxTextureContext8.cxx +++ b/panda/src/dxgsg8/dxTextureContext8.cxx @@ -18,6 +18,7 @@ #include "pStatTimer.h" #include "dxgsg8base.h" #include "bamCache.h" +#include "graphicsEngine.h" #include #include @@ -794,7 +795,7 @@ create_texture(DXScreenData &scrn) { } } - tex->texture_uploaded(scrn._dxgsg8); + scrn._dxgsg8->get_engine()->texture_uploaded(tex); mark_loaded(); return true; diff --git a/panda/src/dxgsg9/dxTextureContext9.cxx b/panda/src/dxgsg9/dxTextureContext9.cxx index d7d688cb00..ce701fa394 100755 --- a/panda/src/dxgsg9/dxTextureContext9.cxx +++ b/panda/src/dxgsg9/dxTextureContext9.cxx @@ -17,6 +17,7 @@ #include "pStatTimer.h" #include "dxTextureContext9.h" #include "bamCache.h" +#include "graphicsEngine.h" #include #include #include @@ -946,7 +947,7 @@ create_texture(DXScreenData &scrn) { // must not put render to texture into LRU if (!_managed && !tex->get_render_to_texture()) { - tex->texture_uploaded(scrn._dxgsg9); + scrn._dxgsg9->get_engine()->texture_uploaded(tex); } mark_loaded(); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 51ae2ec03d..e357b2c357 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -59,6 +59,7 @@ #include "stencilAttrib.h" #include "lightAttrib.h" #include "scissorAttrib.h" +#include "graphicsEngine.h" #ifdef HAVE_CG #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(); report_my_gl_errors(); diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index fd2da54fd3..ccda616769 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -1564,18 +1564,17 @@ down_to_power_2(int value) { //////////////////////////////////////////////////////////////////// // Function: Texture::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. +// 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:: -texture_uploaded(GraphicsStateGuardianBase *gsg) { +texture_uploaded() { MutexHolder holder(_lock); if (!keep_texture_ram && !_keep_ram_image) { diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index 359634b91c..c7c0c1040c 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -428,7 +428,7 @@ PUBLISHED: static int down_to_power_2(int value); public: - void texture_uploaded(GraphicsStateGuardianBase *gsg); + void texture_uploaded(); virtual bool has_cull_callback() const; virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const; diff --git a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx index fd94e7a662..62984489f9 100644 --- a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx +++ b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx @@ -38,6 +38,7 @@ #include "zmath.h" #include "ztriangle_table.h" #include "store_pixel_table.h" +#include "graphicsEngine.h" TypeHandle TinyGraphicsStateGuardian::_type_handle; @@ -2536,7 +2537,7 @@ upload_texture(TinyTextureContext *gtc, bool force) { gtc->update_data_size_bytes(bytecount); - tex->texture_uploaded(this); + get_engine()->texture_uploaded(tex); gtc->mark_loaded(); return true;