Line data Source code
1 : /* Copyright (C) 2021 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_TEXTURECONVERTER
19 : #define INCLUDED_TEXTURECONVERTER
20 :
21 : #include "lib/file/vfs/vfs.h"
22 :
23 : #include "TextureManager.h"
24 :
25 : #include <condition_variable>
26 : #include <deque>
27 : #include <mutex>
28 : #include <thread>
29 :
30 : class MD5;
31 :
32 : /**
33 : * Texture conversion helper class.
34 : * Provides an asynchronous API to convert input image files into compressed DDS,
35 : * given various conversion settings.
36 : * (The (potentially very slow) compression is a performed in a background thread,
37 : * so the game can remain responsive).
38 : * Also provides an API to load conversion settings from XML files.
39 : *
40 : * XML files are of the form:
41 : * @code
42 : * <Textures>
43 : * <File pattern="*" format="dxt5" mipmap="false" alpha="transparency"/>
44 : * <File pattern="button_wood.*" format="rgba"/>
45 : * </Entity>
46 : * @endcode
47 : *
48 : * 'pattern' is a wildcard expression, matching on filenames.
49 : * All other attributes are optional. Later elements override attributes from
50 : * earlier elements.
51 : *
52 : * 'format' is 'dxt1', 'dxt3', 'dxt5' or 'rgba'.
53 : *
54 : * 'mipmap' is 'true' or 'false'.
55 : *
56 : * 'normal' is 'true' or 'false'.
57 : *
58 : * 'alpha' is 'transparency' or 'player' (it determines whether the color value of
59 : * 0-alpha pixels is significant or not).
60 : *
61 : * 'filter' is 'box', 'triangle' or 'kaiser'.
62 : *
63 : * 'kaiserwidth', 'kaiseralpha', 'kaiserstretch' are floats
64 : * (see http://code.google.com/p/nvidia-texture-tools/wiki/ApiDocumentation#Mipmap_Generation)
65 : */
66 : class CTextureConverter
67 : {
68 : public:
69 : enum EFormat
70 : {
71 : FMT_UNSPECIFIED,
72 : FMT_DXT1,
73 : FMT_DXT3,
74 : FMT_DXT5,
75 : FMT_RGBA,
76 : FMT_ALPHA
77 : };
78 :
79 : enum EMipmap
80 : {
81 : MIP_UNSPECIFIED,
82 : MIP_TRUE,
83 : MIP_FALSE
84 : };
85 :
86 : enum ENormalMap
87 : {
88 : NORMAL_UNSPECIFIED,
89 : NORMAL_TRUE,
90 : NORMAL_FALSE
91 : };
92 :
93 : enum EAlpha
94 : {
95 : ALPHA_UNSPECIFIED,
96 : ALPHA_NONE,
97 : ALPHA_PLAYER,
98 : ALPHA_TRANSPARENCY
99 : };
100 :
101 : enum EFilter
102 : {
103 : FILTER_UNSPECIFIED,
104 : FILTER_BOX,
105 : FILTER_TRIANGLE,
106 : FILTER_KAISER
107 : };
108 :
109 : /**
110 : * Texture conversion settings.
111 : */
112 : struct Settings
113 : {
114 18 : Settings() :
115 : format(FMT_UNSPECIFIED), mipmap(MIP_UNSPECIFIED), normal(NORMAL_UNSPECIFIED),
116 : alpha(ALPHA_UNSPECIFIED), filter(FILTER_UNSPECIFIED),
117 18 : kaiserWidth(-1.f), kaiserAlpha(-1.f), kaiserStretch(-1.f)
118 : {
119 18 : }
120 :
121 : /**
122 : * Append this object's state to the given hash.
123 : */
124 : void Hash(MD5& hash);
125 :
126 : EFormat format;
127 : EMipmap mipmap;
128 : ENormalMap normal;
129 : EAlpha alpha;
130 : EFilter filter;
131 : float kaiserWidth;
132 : float kaiserAlpha;
133 : float kaiserStretch;
134 : };
135 :
136 : /**
137 : * Representation of \<File\> line from settings XML file.
138 : */
139 0 : struct Match
140 : {
141 : std::wstring pattern;
142 : Settings settings;
143 : };
144 :
145 : /**
146 : * Representation of settings XML file.
147 : */
148 0 : struct SettingsFile
149 : {
150 : std::vector<Match> patterns;
151 : };
152 :
153 : /**
154 : * Construct texture converter, for use with files in the given vfs.
155 : */
156 : CTextureConverter(PIVFS vfs, bool highQuality);
157 :
158 : /**
159 : * Destroy texture converter and wait to shut down worker thread.
160 : * This might take a long time (maybe seconds) if the worker is busy
161 : * processing a texture.
162 : */
163 : ~CTextureConverter();
164 :
165 : /**
166 : * Load a texture conversion settings XML file.
167 : * Returns NULL on failure.
168 : */
169 : SettingsFile* LoadSettings(const VfsPath& path) const;
170 :
171 : /**
172 : * Match a sequence of settings files against a given texture filename,
173 : * and return the resulting settings.
174 : * Later entries in settingsFiles override earlier entries.
175 : */
176 : Settings ComputeSettings(const std::wstring& filename, const std::vector<SettingsFile*>& settingsFiles) const;
177 :
178 : /**
179 : * Begin converting a texture, using the given settings.
180 : * This will load src and return false on failure.
181 : * Otherwise it will return true and start an asynchronous conversion request,
182 : * whose result will be returned from Poll() (with the texture and dest passed
183 : * into this function).
184 : */
185 : bool ConvertTexture(const CTexturePtr& texture, const VfsPath& src, const VfsPath& dest, const Settings& settings);
186 :
187 : /**
188 : * Returns the result of a successful ConvertTexture call.
189 : * If no result is available yet, returns false.
190 : * Otherwise, if the conversion succeeded, it sets ok to true and sets
191 : * texture and dest to the corresponding values passed into ConvertTexture(),
192 : * then returns true.
193 : * If the conversion failed, it sets ok to false and doesn't touch the other arguments,
194 : * then returns true.
195 : */
196 : bool Poll(CTexturePtr& texture, VfsPath& dest, bool& ok);
197 :
198 : /**
199 : * Returns whether there is currently a queued request from ConvertTexture().
200 : * (Note this may return false while the worker thread is still converting the last texture.)
201 : */
202 : bool IsBusy();
203 :
204 : private:
205 : static void RunThread(CTextureConverter* data);
206 :
207 : PIVFS m_VFS;
208 : bool m_HighQuality;
209 :
210 : #if CONFIG2_NVTT
211 : std::thread m_WorkerThread;
212 : std::mutex m_WorkerMutex;
213 : std::condition_variable m_WorkerCV;
214 : #endif // CONFIG2_NVTT
215 :
216 : struct ConversionRequest;
217 : struct ConversionResult;
218 :
219 : std::deque<std::shared_ptr<ConversionRequest>> m_RequestQueue; // protected by m_WorkerMutex
220 : std::deque<std::shared_ptr<ConversionResult>> m_ResultQueue; // protected by m_WorkerMutex
221 : bool m_Shutdown; // protected by m_WorkerMutex
222 : };
223 :
224 : #endif // INCLUDED_TEXTURECONVERTER
|