Pyrogenesis  trunk
TextureManager.h
Go to the documentation of this file.
1 /* Copyright (C) 2015 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef INCLUDED_TEXTUREMANAGER
19 #define INCLUDED_TEXTUREMANAGER
20 
21 #include "Texture.h"
22 
23 #include <memory>
24 
25 #include "lib/ogl.h"
26 #include "lib/file/vfs/vfs.h"
27 #include "lib/res/handle.h"
28 
29 class CTextureProperties;
31 
32 /**
33  * Texture manager with asynchronous loading and automatic DDS conversion/compression.
34  *
35  * Input textures can be any format. They will be converted to DDS using settings defined
36  * in files named "texture.xml", in the same directory as the texture and in its parent
37  * directories. See CTextureConverter for the XML syntax. The DDS file will be cached
38  * for faster loading in the future.
39  *
40  * Typically the graphics code will initialise many textures at the start of the game,
41  * mostly for off-screen objects, by calling CreateTexture().
42  * Loading texture data may be very slow (especially if it needs to be converted
43  * to DDS), and we don't want the game to become unresponsive.
44  * CreateTexture therefore returns an object immediately, without loading the
45  * texture. If the object is never used then the data will never be loaded.
46  *
47  * Typically, the renderer will call CTexture::Bind() when it wants to use the
48  * texture. This will trigger the loading of the texture data. If it can be loaded
49  * quickly (i.e. there is already a cached DDS version), then it will be loaded before
50  * the function returns, and the texture can be rendered as normal.
51  *
52  * If loading will take a long time, then Bind() binds a default placeholder texture
53  * and starts loading the texture in the background. It will use the correct texture
54  * when the renderer next calls Bind() after the load has finished.
55  *
56  * It is also possible to prefetch textures which are not being rendered yet, but
57  * are expected to be rendered soon (e.g. for off-screen terrain tiles).
58  * These will be loaded in the background, when there are no higher-priority textures
59  * to load.
60  *
61  * The same texture file can be safely loaded multiple times with different GL parameters
62  * (but this should be avoided whenever possible, as it wastes VRAM).
63  *
64  * For release packages, DDS files can be precached by appending ".dds" to their name,
65  * which will be used instead of doing runtime conversion. This means most players should
66  * never experience the slow asynchronous conversion behaviour.
67  * These cache files will typically be packed into an archive for faster loading;
68  * if no archive cache is available then the source file will be converted and stored
69  * as a loose cache file on the user's disk.
70  */
72 {
74 
75 public:
76  /**
77  * Construct texture manager. vfs must be the VFS instance used for all textures
78  * loaded from this object.
79  * highQuality is slower and intended for batch-conversion modes.
80  * disableGL is intended for tests, and will disable all GL uploads.
81  */
82  CTextureManager(PIVFS vfs, bool highQuality, bool disableGL);
83 
85 
86  /**
87  * Create a texture with the given GL properties.
88  * The texture data will not be loaded immediately.
89  */
91 
92  /**
93  * Returns a magenta texture. Use this for highlighting errors
94  * (e.g. missing terrain textures).
95  */
97 
98  /**
99  * Work on asynchronous texture loading operations, if any.
100  * Returns true if it did any work.
101  * The caller should typically loop this per frame until it returns
102  * false or exceeds the allocated time for this frame.
103  */
104  bool MakeProgress();
105 
106  /**
107  * Synchronously converts and compresses and saves the texture,
108  * and returns the output path (minus a "cache/" prefix). This
109  * is intended for pre-caching textures in release archives.
110  * @return true on success
111  */
112  bool GenerateCachedTexture(const VfsPath& path, VfsPath& outputPath);
113 
114  /**
115  * Returns total number of bytes uploaded for all current texture.
116  */
117  size_t GetBytesUploaded() const;
118 
119 private:
121 };
122 
123 /**
124  * Represents the filename and GL parameters of a texture,
125  * for passing to CTextureManager::CreateTexture.
126  */
128 {
129  friend class CTextureManagerImpl;
130  friend struct TextureCacheCmp;
131  friend struct TPequal_to;
132  friend struct TPhash;
133 
134 public:
135  /**
136  * Use the given texture name, and default GL parameters.
137  */
138  explicit CTextureProperties(const VfsPath& path) :
139  m_Path(path), m_Filter(GL_LINEAR_MIPMAP_LINEAR),
140  m_WrapS(GL_REPEAT), m_WrapT(GL_REPEAT), m_Aniso(1.0f), m_Format(0)
141  {
142  }
143 
144  /**
145  * Set min/mag filter mode (typically GL_LINEAR_MIPMAP_LINEAR, GL_NEAREST, etc).
146  */
147  void SetFilter(GLint filter) { m_Filter = filter; }
148 
149  /**
150  * Set wrapping mode (typically GL_REPEAT, GL_CLAMP_TO_EDGE, etc).
151  */
152  void SetWrap(GLint wrap) { m_WrapS = wrap; m_WrapT = wrap; }
153 
154  /**
155  * Set wrapping mode (typically GL_REPEAT, GL_CLAMP_TO_EDGE, etc),
156  * separately for S and T.
157  */
158  void SetWrap(GLint wrap_s, GLint wrap_t) { m_WrapS = wrap_s; m_WrapT = wrap_t; }
159 
160  /**
161  * Set maximum anisotropy value. Must be >= 1.0. Should be a power of 2.
162  */
163  void SetMaxAnisotropy(float aniso) { m_Aniso = aniso; }
164 
165  /**
166  * Set GL texture upload format, to override the default.
167  * Typically GL_ALPHA or GL_LUMINANCE for 8-bit textures.
168  */
169  void SetFormatOverride(GLenum format) { m_Format = format; }
170 
171  // TODO: rather than this static definition of texture properties
172  // (especially anisotropy), maybe we want something that can be more
173  // easily tweaked in an Options menu? e.g. the caller just specifies
174  // "terrain texture mode" and we combine it with the user's options.
175  // That'd let us dynamically change texture properties easily.
176  //
177  // enum EQualityMode
178  // {
179  // NONE,
180  // TERRAIN,
181  // MODEL,
182  // GUI
183  // }
184  // void SetQuality(EQualityMode mode, float anisotropy, float lodbias, int reducemipmaps, ...);
185  //
186  // or something a bit like that.
187 
188 private:
189  // Must update TPhash, TPequal_to when changing these fields
191  GLint m_Filter;
192  GLint m_WrapS;
193  GLint m_WrapT;
194  float m_Aniso;
195  GLenum m_Format;
196 };
197 
198 /**
199  * Represents a texture object.
200  * The texture data may or may not have been loaded yet.
201  * Before it has been loaded, all operations will act on a default
202  * 1x1-pixel grey texture instead.
203  */
204 class CTexture
205 {
206  friend class CTextureManagerImpl;
207  friend struct TextureCacheCmp;
208  friend struct TPequal_to;
209  friend struct TPhash;
210 
211  // Only the texture manager can create these
212  explicit CTexture(Handle handle, const CTextureProperties& props, CTextureManagerImpl* textureManager);
213 
215 
216 public:
217 
218  ~CTexture();
219 
220  /**
221  * Returns the width (in pixels) of the current texture.
222  */
223  size_t GetWidth() const;
224 
225  /**
226  * Returns the height (in pixels) of the current texture.
227  */
228  size_t GetHeight() const;
229 
230  /**
231  * Returns whether the current texture has an alpha channel.
232  */
233  bool HasAlpha() const;
234 
235  /**
236  * Returns the ARGB value of the lowest mipmap level (i.e. the
237  * average of the whole texture).
238  * Returns 0 if the texture has no mipmaps.
239  */
240  u32 GetBaseColor() const;
241 
242  /**
243  * Returns total number of bytes uploaded for this texture.
244  */
245  size_t GetUploadedSize() const;
246 
247  /**
248  * Bind the texture to the given GL texture unit.
249  * If the texture data hasn't been loaded yet, this may wait a short while to
250  * load it. If loading takes too long then it will return sooner and the data will
251  * be loaded in a background thread, so this does not guarantee the texture really
252  * will be loaded.
253  */
254  void Bind(size_t unit = 0);
255 
256  /**
257  * Returns a ogl_tex handle, for later binding. See comments from Bind().
258  */
259  Handle GetHandle();
260 
261  /**
262  * Attempt to load the texture data quickly, as with Bind().
263  * Returns whether the texture data is currently loaded.
264  */
265  bool TryLoad();
266 
267  /**
268  * Returns whether the texture data is currently loaded.
269  */
270  bool IsLoaded();
271 
272  /**
273  * Activate the prefetching optimisation for this texture.
274  * Use this if it is likely the texture will be needed in the near future.
275  * It will be loaded in the background so that it is likely to be ready when
276  * it is used by Bind().
277  */
278  void Prefetch();
279 
280 private:
281  /**
282  * Replace the Handle stored by this object.
283  * If takeOwnership is true, it will not increment the Handle's reference count.
284  */
285  void SetHandle(Handle handle, bool takeOwnership = false);
286 
288 
291 
292  enum {
293  UNLOADED, // loading has not started
294  PREFETCH_NEEDS_LOADING, // was prefetched; currently waiting to try loading from cache
295  PREFETCH_NEEDS_CONVERTING, // was prefetched; currently waiting to be sent to the texture converter
296  PREFETCH_IS_CONVERTING, // was prefetched; currently being processed by the texture converter
297  HIGH_NEEDS_CONVERTING, // high-priority; currently waiting to be sent to the texture converter
298  HIGH_IS_CONVERTING, // high-priority; currently being processed by the texture converter
299  LOADED // loading has completed (successfully or not)
300  } m_State;
301 
303 
304  // Self-reference to let us recover the CTexturePtr for this object.
305  // (weak pointer to avoid cycles)
306  std::weak_ptr<CTexture> m_Self;
307 };
308 
309 std::size_t hash_value(const CTexturePtr& v);
310 std::size_t hash_value(const CTextureProperties& v);
311 
312 #endif // INCLUDED_TEXTUREMANAGER
bool GenerateCachedTexture(const VfsPath &path, VfsPath &outputPath)
Synchronously converts and compresses and saves the texture, and returns the output path (minus a "ca...
Definition: TextureManager.cpp:666
CTexturePtr CreateTexture(const CTextureProperties &props)
Create a texture with the given GL properties.
Definition: TextureManager.cpp:651
Definition: TextureManager.h:295
Definition: TextureManager.cpp:87
Definition: TextureManager.h:296
Handle m_Handle
Definition: TextureManager.h:289
shared_ptr< IVFS > PIVFS
Definition: vfs.h:226
Represents the filename and GL parameters of a texture, for passing to CTextureManager::CreateTexture...
Definition: TextureManager.h:127
GLint m_WrapS
Definition: TextureManager.h:192
const CTextureProperties m_Properties
Definition: TextureManager.h:287
NONCOPYABLE(CTextureManager)
std::weak_ptr< CTexture > m_Self
Definition: TextureManager.h:306
Definition: TextureManager.cpp:39
CTextureManagerImpl * m_TextureManager
Definition: TextureManager.h:302
float m_Aniso
Definition: TextureManager.h:194
Definition: TextureManager.cpp:60
~CTextureManager()
Definition: TextureManager.cpp:646
Texture manager with asynchronous loading and automatic DDS conversion/compression.
Definition: TextureManager.h:71
GLint m_WrapT
Definition: TextureManager.h:193
void SetWrap(GLint wrap_s, GLint wrap_t)
Set wrapping mode (typically GL_REPEAT, GL_CLAMP_TO_EDGE, etc), separately for S and T...
Definition: TextureManager.h:158
void format(BasicFormatter< Char > &f, const Char *format_str, const T &value)
Definition: format.h:1705
VfsPath m_Path
Definition: TextureManager.h:190
Definition: TextureManager.h:293
bool MakeProgress()
Work on asynchronous texture loading operations, if any.
Definition: TextureManager.cpp:661
uint32_t u32
Definition: types.h:39
CTextureManager(PIVFS vfs, bool highQuality, bool disableGL)
Construct texture manager.
Definition: TextureManager.cpp:641
void SetFilter(GLint filter)
Set min/mag filter mode (typically GL_LINEAR_MIPMAP_LINEAR, GL_NEAREST, etc).
Definition: TextureManager.h:147
GLenum m_Format
Definition: TextureManager.h:195
Definition: path.h:77
void SetFormatOverride(GLenum format)
Set GL texture upload format, to override the default.
Definition: TextureManager.h:169
u32 m_BaseColor
Definition: TextureManager.h:290
Definition: TextureManager.h:294
Represents a texture object.
Definition: TextureManager.h:204
CTextureProperties(const VfsPath &path)
Use the given texture name, and default GL parameters.
Definition: TextureManager.h:138
CTextureManagerImpl * m
Definition: TextureManager.h:120
i64 Handle
`handle&#39; representing a reference to a resource (sound, texture, etc.)
Definition: handle.h:41
std::shared_ptr< CTexture > CTexturePtr
Definition: Texture.h:22
void SetMaxAnisotropy(float aniso)
Set maximum anisotropy value.
Definition: TextureManager.h:163
CTexturePtr GetErrorTexture()
Returns a magenta texture.
Definition: TextureManager.cpp:656
GLint m_Filter
Definition: TextureManager.h:191
Definition: TextureManager.h:298
Definition: TextureManager.h:297
size_t GetBytesUploaded() const
Returns total number of bytes uploaded for all current texture.
Definition: TextureManager.cpp:671
static Handle handle(size_t idx, u64 tag)
Definition: h_mgr.cpp:121
Definition: vfs_util.cpp:39
void SetWrap(GLint wrap)
Set wrapping mode (typically GL_REPEAT, GL_CLAMP_TO_EDGE, etc).
Definition: TextureManager.h:152
std::size_t hash_value(const CTexturePtr &v)
Definition: TextureManager.cpp:76