]> git.tdb.fi Git - libs/gltk.git/commitdiff
Reuse meshes in PartCache to avoid buffer create/delete spam
authorMikko Rasa <tdb@tdb.fi>
Sat, 11 Jan 2014 18:05:15 +0000 (20:05 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sat, 11 Jan 2014 18:05:15 +0000 (20:05 +0200)
source/partcache.cpp
source/partcache.h
source/widget.cpp

index 5589b0dd8b7c948685964fe5c49aa6cb2dda50a4..4747cb50b3e585fd45bb6a5be8fe864bd2937266 100644 (file)
@@ -18,9 +18,10 @@ CachedPart::~CachedPart()
 }
 
 
-void PartCache::clear()
+void PartCache::begin_rebuild()
 {
-       parts.clear();
+       next = parts.begin();
+       current = parts.end();
 }
 
 void PartCache::insert_special(const Part &part)
@@ -28,21 +29,54 @@ void PartCache::insert_special(const Part &part)
        if(part.get_name().empty())
                throw invalid_argument("PartCache::insert_special");
 
-       parts.push_back(CachedPart());
-       parts.back().part = &part;
+       for(current=next; current!=parts.end(); ++current)
+               if(current->part==&part)
+               {
+                       parts.erase(next, current);
+                       break;
+               }
+
+       if(current==parts.end())
+               current = parts.insert(next, CachedPart());
+       else
+               *current = CachedPart();
+       current->part = &part;
+
+       next = current;
+       ++next;
 }
 
 GL::Mesh &PartCache::create_mesh(const Part &part, const GL::Texture2D &tex)
 {
-       if(!parts.empty() && parts.back().texture==&tex)
-               return *parts.back().mesh;
-
-       parts.push_back(CachedPart());
-       CachedPart &cpart = parts.back();
-       cpart.part = &part;
-       cpart.texture = &tex;
-       cpart.mesh = new GL::Mesh((GL::TEXCOORD2, GL::COLOR4_UBYTE, GL::VERTEX2));
-       return *cpart.mesh;
+       if(current!=parts.end() && current->texture==&tex)
+               return *current->mesh;
+
+       for(current=next; current!=parts.end(); ++current)
+               if(current->texture==&tex)
+               {
+                       parts.erase(next, current);
+                       break;
+               }
+
+       if(current==parts.end())
+       {
+               current = parts.insert(next, CachedPart());
+               current->texture = &tex;
+               current->mesh = new GL::Mesh((GL::TEXCOORD2, GL::COLOR4_UBYTE, GL::VERTEX2));
+       }
+       else
+               current->mesh->clear();
+       current->part = &part;
+
+       next = current;
+       ++next;
+
+       return *current->mesh;
+}
+
+void PartCache::end_rebuild()
+{
+       parts.erase(next, parts.end());
 }
 
 } // namespace GLtk
index 86a3f364abe21260395493f40580d278f5b5775c..90d1c94f5e36e90a19614cc39a9e8a56033d7945 100644 (file)
@@ -26,11 +26,14 @@ public:
 
 private:
        PartList parts;
+       PartList::iterator next;
+       PartList::iterator current;
 
 public:
-       void clear();
+       void begin_rebuild();
        void insert_special(const Part &);
        GL::Mesh &create_mesh(const Part &, const GL::Texture2D &);
+       void end_rebuild();
 
        const PartList &get_parts() const { return parts; }
 };
index 8b7f1cbd88b351305a83f6dd56b2c9d5e32ac69b..76b6e615712c29c459d208abe8300671aae5bc6e 100644 (file)
@@ -193,7 +193,7 @@ void Widget::rebuild()
        if(!style)
                return;
 
-       part_cache.clear();
+       part_cache.begin_rebuild();
        const Style::PartSeq &parts = style->get_parts();
        for(Style::PartSeq::const_iterator i=parts.begin(); i!=parts.end(); ++i)
        {
@@ -202,6 +202,7 @@ void Widget::rebuild()
                else
                        rebuild_special(*i);
        }
+       part_cache.end_rebuild();
 }
 
 void Widget::rebuild_special(const Part &part)