Browse Source

manage texture memory for tinydisplay

David Rose 17 years ago
parent
commit
07ee48ae07

+ 12 - 1
panda/src/gobj/simpleLru.cxx

@@ -17,6 +17,7 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "simpleLru.h"
+#include "clockObject.h"
 
 // We define this as a reference to an allocated object, instead of as
 // a concrete object, so that it won't get destructed when the program
@@ -71,6 +72,10 @@ enqueue_lru(SimpleLru *lru) {
   MutexHolder holder(SimpleLru::_global_lock);
 
   if (_lru == lru) {
+    if (_lru != (SimpleLru *)NULL) {
+      remove_from_list();
+      insert_before(_lru);
+    }
     return;
   }
 
@@ -116,7 +121,8 @@ count_active_size() const {
 //     Function: SimpleLru::do_evict
 //       Access: Private
 //  Description: Evicts pages until the LRU is within tolerance.
-//               Assumes the lock is already held.
+//               Assumes the lock is already held.  Does not evict
+//               "active" pages that were added within this epoch.
 ////////////////////////////////////////////////////////////////////
 void SimpleLru::
 do_evict() {
@@ -144,6 +150,11 @@ do_evict() {
       // If we reach the original tail of the list, stop.
       return;
     }
+    if (node == _active_marker) {
+      // Also stop if we reach the active marker.  Nodes beyond this
+      // were added within this epoch.
+      return;
+    }
     node = next;
   }
 }

+ 1 - 0
panda/src/pstatclient/pStatProperties.cxx

@@ -155,6 +155,7 @@ static TimeCollectorProperties time_properties[] = {
   { 1, "Draw:Clear",                       { 0.0, 0.8, 0.6 } },
   { 1, "Draw:Flush",                       { 0.9, 0.2, 0.7 } },
   { 1, "Draw:Sync",                        { 0.5, 0.7, 0.7 } },
+  { 0, "Draw:Transform",                   { 0.0, 0.5, 0.0 } },
   { 0, "Draw:Primitive",                   { 0.0, 0.0, 0.5 } },
   { 0, "Draw:Set State",                   { 0.2, 0.6, 0.8 } },
   { 1, "Draw:Wait occlusion",              { 1.0, 0.5, 0.0 } },

+ 10 - 0
panda/src/tinydisplay/config_tinydisplay.cxx

@@ -58,6 +58,16 @@ ConfigVariableInt x_wheel_down_button
           "mouse button number does the system report when the mouse wheel "
           "is rolled one notch down?"));
 
+ConfigVariableInt td_texture_ram
+("td-texture-ram", -1,
+ PRC_DESC("This specifies the maximum amount of RAM to devote to keeping "
+          "textures resident with the tinydisplay software renderer.  When "
+          "this limit is exceeded, textures over the limit that have not "
+          "been rendered within the current frame will be evicted.  "
+          "(Textures will not be evicted while they are still in the "
+          "frame, even if this means this limit remains exceeded.)  "
+          "Set it to -1 for no limit."));
+
 ////////////////////////////////////////////////////////////////////
 //     Function: init_libtinydisplay
 //  Description: Initializes the library.  This must be called at

+ 2 - 0
panda/src/tinydisplay/config_tinydisplay.h

@@ -34,4 +34,6 @@ extern ConfigVariableBool x_error_abort;
 extern ConfigVariableInt x_wheel_up_button;
 extern ConfigVariableInt x_wheel_down_button;
 
+extern ConfigVariableInt td_texture_ram;
+
 #endif

+ 14 - 14
panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx

@@ -504,7 +504,8 @@ static const ZB_fillTriangleFunc fill_tri_funcs
 TinyGraphicsStateGuardian::
 TinyGraphicsStateGuardian(GraphicsPipe *pipe,
 			 TinyGraphicsStateGuardian *share_with) :
-  GraphicsStateGuardian(CS_yup_right, pipe)
+  GraphicsStateGuardian(CS_yup_right, pipe),
+  _textures_lru("textures_lru", td_texture_ram)
 {
   _c = NULL;
   _vertices = NULL;
@@ -825,6 +826,9 @@ end_frame(Thread *current_thread) {
 
   // Flush any PCollectors specific to this kind of GSG.
   _vertices_immediate_pcollector.flush_level();
+
+  // Evict any textures that exceed our texture memory.
+  _textures_lru.begin_epoch();
 }
 
 
@@ -1399,10 +1403,9 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
     fo += _c->zb->linesize / PSZB;
   }
 
-#ifdef DO_PSTATS 
   gtc->update_data_size_bytes(gltex->xsize * gltex->ysize * 4);
-#endif
   gtc->mark_loaded();
+  gtc->enqueue_lru(&_textures_lru);
 }
 
 
@@ -1614,6 +1617,7 @@ release_texture(TextureContext *tc) {
   }
 
   gl_free(gltex);
+  gtc->dequeue_lru();
 
   delete gtc;
 }
@@ -1998,20 +2002,17 @@ apply_texture(TextureContext *tc) {
   _c->current_texture = gtc->_gltex;
   _c->texture_2d_enabled = true;
 
-  if (gtc->was_image_modified()) {
+  GLTexture *gltex = gtc->_gltex;
+
+  if (gtc->was_image_modified() || gltex->pixmap == NULL) {
     // If the texture image was modified, reload the texture.
     if (!upload_texture(gtc)) {
       _c->texture_2d_enabled = false;
     }
     gtc->mark_loaded();
-
-  } else if (gtc->was_properties_modified()) {
-    // If only the properties have been modified, we don't need to
-    // reload the texture.
-    gtc->mark_loaded();
   }
+  gtc->enqueue_lru(&_textures_lru);
 
-  GLTexture *gltex = gtc->_gltex;
   _c->zb->current_texture.pixmap = gltex->pixmap;
   _c->zb->current_texture.s_mask = gltex->s_mask;
   _c->zb->current_texture.t_mask = gltex->t_mask;
@@ -2091,10 +2092,9 @@ upload_texture(TinyTextureContext *gtc) {
     copy_la_image(gltex, tex);
     break;
   }
-  
-#ifdef DO_PSTATS 
-  gtc->update_data_size_bytes(gltex->xsize * gltex->ysize * 4);
-#endif
+
+  int bytecount = gltex->xsize * gltex->ysize * 4;
+  gtc->update_data_size_bytes(bytecount);
   
   tex->texture_uploaded();
 

+ 3 - 0
panda/src/tinydisplay/tinyGraphicsStateGuardian.h

@@ -23,6 +23,7 @@
 
 #include "graphicsStateGuardian.h"
 #include "tinySDLGraphicsPipe.h"
+#include "simpleLru.h"
 
 extern "C" {
   #include "zmath.h"
@@ -134,6 +135,8 @@ private:
   };
   int _color_material_flags;
 
+  SimpleLru _textures_lru;
+
   // Used during being_draw_primitives() .. end_draw_primitives().
   int _min_vertex;
   int _max_vertex;

+ 14 - 1
panda/src/tinydisplay/tinyTextureContext.I

@@ -24,7 +24,7 @@
 ////////////////////////////////////////////////////////////////////
 INLINE TinyTextureContext::
 TinyTextureContext(PreparedGraphicsObjects *pgo, Texture *tex) :
-  TextureContext(pgo, tex)
+  TextureContext(pgo, tex), SimpleLruPage(0)
 {
   _gltex = NULL;
 }
@@ -38,3 +38,16 @@ INLINE TinyTextureContext::
 ~TinyTextureContext() {
   nassertv(_gltex == NULL);
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyTextureContext::update_data_size_bytes
+//       Access: Public
+//  Description: This is overloaded (non-virtually) to update both the
+//               BufferContext and the LRU page with the same
+//               information.
+////////////////////////////////////////////////////////////////////
+INLINE void TinyTextureContext::
+update_data_size_bytes(size_t new_data_size_bytes) {
+  TextureContext::update_data_size_bytes(new_data_size_bytes);
+  SimpleLruPage::set_lru_size(new_data_size_bytes);
+}

+ 31 - 0
panda/src/tinydisplay/tinyTextureContext.cxx

@@ -18,4 +18,35 @@
 
 #include "tinyTextureContext.h"
 
+extern "C" {
+#include "zgl.h"
+}
+
 TypeHandle TinyTextureContext::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyTextureContext::evict_lru
+//       Access: Public, Virtual
+//  Description: Evicts the page from the LRU.  Called internally when
+//               the LRU determines that it is full.  May also be
+//               called externally when necessary to explicitly evict
+//               the page.
+//
+//               It is legal for this method to either evict the page
+//               as requested, do nothing (in which case the eviction
+//               will be requested again at the next epoch), or
+//               requeue itself on the tail of the queue (in which
+//               case the eviction will be requested again much
+//               later).
+////////////////////////////////////////////////////////////////////
+void TinyTextureContext::
+evict_lru() {
+  dequeue_lru();
+
+  if (_gltex->pixmap != NULL) {
+    gl_free(_gltex->pixmap);
+    _gltex->pixmap = NULL;
+  }
+
+  set_resident(false);
+}

+ 5 - 1
panda/src/tinydisplay/tinyTextureContext.h

@@ -22,6 +22,7 @@
 #include "pandabase.h"
 #include "textureContext.h"
 #include "deletedChain.h"
+#include "simpleLru.h"
 
 struct GLTexture;
 
@@ -29,13 +30,16 @@ struct GLTexture;
 //       Class : TinyTextureContext
 // Description :
 ////////////////////////////////////////////////////////////////////
-class TinyTextureContext : public TextureContext {
+class TinyTextureContext : public TextureContext, public SimpleLruPage {
 public:
   INLINE TinyTextureContext(PreparedGraphicsObjects *pgo, Texture *tex);
   ALLOC_DELETED_CHAIN(TinyTextureContext);
 
   INLINE ~TinyTextureContext();
 
+  INLINE void update_data_size_bytes(size_t new_data_size_bytes);
+  virtual void evict_lru();
+
   GLTexture *_gltex;
 
 public: