Stellarium 0.12.4
StelTextureCache.hpp
1 /*
2  * Stellarium
3  * Copyright (C) 2012 Ferdinand Majerech
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18  */
19 
20 #ifndef _STELTEXTURECACHE_HPP_
21 #define _STELTEXTURECACHE_HPP_
22 
23 #include <QMap>
24 #include <QString>
25 
52 template<class TextureBackend>
54 {
55 private:
57  struct TextureBackendRefCounted
58  {
60  int refCount;
62  TextureBackend* backend;
63 
65  TextureBackendRefCounted(){}
67  TextureBackendRefCounted(TextureBackend* backend):refCount(1),backend(backend){}
68  };
69 
70 public:
83  virtual TextureBackend* get(const QString& name, const TextureLoadingMode loadingMode)
84  {
85  Q_ASSERT_X(!name.isEmpty(), Q_FUNC_INFO, "Can't cache textures without a name");
86 
87  if(!cache.contains(name)) {return NULL;}
88 
89  TextureBackend* result = cache[name].backend;
90 
91  switch(loadingMode)
92  {
93  case TextureLoadingMode_Normal:
94  //If cached texture is loading (asynchronous), wait,
95  //if uninitialized(lazy), start loading and wait
96  if(result->getStatus() == TextureStatus_Uninitialized)
97  {
98  result->startAsynchronousLoading();
99  }
100  //Waiting in a hot loop, this could be done better
101  while(result->getStatus() == TextureStatus_Loading)
102  {
103  continue;
104  }
105  case TextureLoadingMode_Asynchronous:
106  //If cached texture is uninitialized (lazy), start loading and wait.
107  if(result->getStatus() == TextureStatus_Uninitialized)
108  {
109  result->startAsynchronousLoading();
110  }
111  break;
112  case TextureLoadingMode_LazyAsynchronous:
113  break;
114  default:
115  Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown texture loading mode");
116  }
117 
118  (cache[name].refCount)++;
119 
120  return result;
121  }
122 
129  virtual void add(TextureBackend* backend)
130  {
131  const QString& name = backend->getName();
132  Q_ASSERT_X(!name.isEmpty(), Q_FUNC_INFO, "Can't cache textures without a name");
133  Q_ASSERT_X(!cache.contains(name), Q_FUNC_INFO,
134  "Adding the same texture to the cache more than once");
135 
136  cache.insert(name, TextureBackendRefCounted(backend));
137  }
138 
145  virtual void remove(TextureBackend* backend)
146  {
147  const QString& name = backend->getName();
148  Q_ASSERT_X(!name.isEmpty(), Q_FUNC_INFO, "Can't cache textures without a name");
149  Q_ASSERT_X(cache.contains(name), Q_FUNC_INFO,
150  "Trying to remove unknown texture from cache");
151 
152  TextureBackendRefCounted& cached = cache[name];
153  --(cached.refCount);
154  Q_ASSERT_X(cached.refCount >= 0, Q_FUNC_INFO,
155  "Negative reference count of a texture in texture cache");
156 
157  // If reference count hits 0, delete the texture.
158  if(cached.refCount == 0)
159  {
160  // Assert that we're really deleting what we thing we're deleting
161  // instead of having two textures with the same name.
162  Q_ASSERT_X(backend == cached.backend, Q_FUNC_INFO,
163  "Texture in cache has the same name as but is not specified texture");
164  cache.remove(name);
165  delete backend;
166  }
167  }
168 
169 private:
171  QMap<QString, TextureBackendRefCounted> cache;
172 };
173 
174 #endif // _STELTEXTURECACHE_HPP_