cache any non-cached textures in the load thread to save holding onto memory for...
authorJonathan Marshall <jmarshall@never.you.mind>
Wed, 2 May 2012 01:34:36 +0000 (13:34 +1200)
committerJonathan Marshall <jmarshall@never.you.mind>
Wed, 2 May 2012 03:32:42 +0000 (15:32 +1200)
xbmc/GUILargeTextureManager.cpp
xbmc/TextureCache.cpp
xbmc/TextureCache.h

index f4f5664..962b6ed 100644 (file)
@@ -57,19 +57,11 @@ bool CImageLoader::DoWork()
   if (loadPath.IsEmpty())
   {
     // not in our texture cache, so try and load directly and then cache the result
-    bool flipped;
-    unsigned int width, height;
-    CStdString image = CTextureCacheJob::DecodeImageURL(texturePath, width, height, flipped);
-
-    if (image.IsEmpty())
-      return false; // nothing to load
-
-    m_texture = CTextureCacheJob::LoadImage(image, width, height, flipped);
-
+    loadPath = CTextureCache::Get().CacheTexture(texturePath, &m_texture);
     if (m_texture)
-      CTextureCache::Get().BackgroundCacheTexture(texturePath, m_texture);
+      return true; // we're done
   }
-  else
+  if (!loadPath.IsEmpty())
   {
     // direct route - load the image
     m_texture = new CTexture();
index b4db777..64d23eb 100644 (file)
@@ -154,23 +154,38 @@ void CTextureCache::BackgroundCacheImage(const CStdString &url)
   AddJob(new CTextureCacheJob(url, cacheHash));
 }
 
-void CTextureCache::BackgroundCacheTexture(const CStdString &url, const CBaseTexture *texture)
+CStdString CTextureCache::CacheTexture(const CStdString &url, CBaseTexture **texture)
 {
-  AddJob(new CTextureCacheJob(url, texture));
+  CSingleLock lock(m_processingSection);
+  if (m_processing.find(url) == m_processing.end())
+  {
+    m_processing.insert(url);
+    lock.Leave();
+    // cache the texture directly
+    CTextureCacheJob job(url);
+    bool success = job.CacheTexture(texture);
+    OnJobComplete(0, success, &job);
+    return success ? GetCachedPath(job.m_details.file) : "";
+  }
+  lock.Leave();
+
+  // wait for currently processing job to end.
+  while (true)
+  {
+    m_completeEvent.WaitMSec(1000);
+    {
+      CSingleLock lock(m_processingSection);
+      if (m_processing.find(url) == m_processing.end())
+        break;
+    }
+  }
+  CStdString cachedHash;
+  return GetCachedImage(url, cachedHash);
 }
 
 CStdString CTextureCache::CacheImageFile(const CStdString &url)
 {
-  // Cache image so that the texture manager can load it.
-  CTextureCacheJob job(url, "");
-  if (job.DoWork() && !job.m_details.hash.empty())
-  {
-    AddCachedTexture(url, job.m_details);
-    if (g_advancedSettings.m_useDDSFanart && !job.m_details.file.empty())
-      AddJob(new CTextureDDSJob(GetCachedPath(job.m_details.file)));
-    return GetCachedPath(job.m_details.file);
-  }
-  return "";
+  return CacheTexture(url);
 
   // TODO: In the future we need a cache job to callback when the image is loaded
   //       thus automatically updating the images.  We'd also need fallback code inside
@@ -289,6 +304,8 @@ void CTextureCache::OnJobComplete(unsigned int jobID, bool success, CJob *job)
         m_processing.erase(i);
     }
 
+    m_completeEvent.Set();
+
     // TODO: call back to the UI indicating that it can update it's image...
     if (g_advancedSettings.m_useDDSFanart && !cacheJob->m_details.file.empty())
       AddJob(new CTextureDDSJob(GetCachedPath(cacheJob->m_details.file)));
index e32270d..b56f2a2 100644 (file)
@@ -25,6 +25,7 @@
 #include "utils/StdString.h"
 #include "utils/JobManager.h"
 #include "TextureDatabase.h"
+#include "threads/Event.h"
 
 class CBaseTexture;
 
@@ -89,7 +90,17 @@ public:
    \sa CheckAndCacheImage
    */
   void BackgroundCacheImage(const CStdString &image);
-  void BackgroundCacheTexture(const CStdString &image, const CBaseTexture *texture);
+
+  /*! \brief Cache an image to image cache, optionally return the texture
+
+   Caches the given image, returning the texture if the caller wants it.
+
+   \param image url of the image to cache
+   \param texture [out] the loaded image
+   \return cached url of this image
+   \sa CTextureCacheJob::CacheTexture
+   */
+  CStdString CacheTexture(const CStdString &url, CBaseTexture **texture = NULL);
 
   /*! \brief Take image URL and add it to image cache
 
@@ -215,5 +226,6 @@ private:
   CTextureDatabase m_database;
   std::set<CStdString> m_processing; ///< currently processing list to avoid 2 jobs being processed at once
   CCriticalSection     m_processingSection;
+  CEvent               m_completeEvent; ///< Set whenever a job has finished
 };