/src/ogre/OgreMain/include/OgreResource.h
Line | Count | Source |
1 | | /* |
2 | | ----------------------------------------------------------------------------- |
3 | | This source file is part of OGRE |
4 | | (Object-oriented Graphics Rendering Engine) |
5 | | For the latest info, see http://www.ogre3d.org/ |
6 | | |
7 | | Copyright (c) 2000-2014 Torus Knot Software Ltd |
8 | | |
9 | | Permission is hereby granted, free of charge, to any person obtaining a copy |
10 | | of this software and associated documentation files (the "Software"), to deal |
11 | | in the Software without restriction, including without limitation the rights |
12 | | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
13 | | copies of the Software, and to permit persons to whom the Software is |
14 | | furnished to do so, subject to the following conditions: |
15 | | |
16 | | The above copyright notice and this permission notice shall be included in |
17 | | all copies or substantial portions of the Software. |
18 | | |
19 | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
20 | | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
21 | | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
22 | | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
23 | | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
24 | | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
25 | | THE SOFTWARE. |
26 | | ----------------------------------------------------------------------------- |
27 | | */ |
28 | | #ifndef _Resource_H__ |
29 | | #define _Resource_H__ |
30 | | |
31 | | #include "OgrePrerequisites.h" |
32 | | #include "OgreStringInterface.h" |
33 | | #include "OgreHeaderPrefix.h" |
34 | | #include "Threading/OgreThreadHeaders.h" |
35 | | |
36 | | namespace Ogre { |
37 | | |
38 | | typedef size_t ResourceHandle; |
39 | | |
40 | | |
41 | | // Forward declaration |
42 | | class ManualResourceLoader; |
43 | | |
44 | | /** \addtogroup Core |
45 | | * @{ |
46 | | */ |
47 | | /** \addtogroup Resources |
48 | | * @{ |
49 | | */ |
50 | | /** Abstract class representing a loadable resource |
51 | | |
52 | | @see @ref Resource-Management |
53 | | |
54 | | Subclasses must implement: |
55 | | <ol> |
56 | | <li>A constructor, overriding the same parameters as the constructor |
57 | | defined by this class. Subclasses are not allowed to define |
58 | | constructors with other parameters; other settings must be |
59 | | settable through accessor methods before loading.</li> |
60 | | <li>The loadImpl() and unloadImpl() methods - mSize must be set |
61 | | after loadImpl()</li> |
62 | | <li>StringInterface ParamCommand and ParamDictionary setups |
63 | | in order to allow setting of core parameters (prior to load) |
64 | | through a generic interface.</li> |
65 | | </ol> |
66 | | */ |
67 | | class _OgreExport Resource : public StringInterface, public ResourceAlloc |
68 | | { |
69 | | public: |
70 | | OGRE_AUTO_MUTEX; // public to allow external locking |
71 | | class Listener |
72 | | { |
73 | | public: |
74 | 0 | virtual ~Listener() {} |
75 | | |
76 | | /** Called whenever the resource finishes loading. |
77 | | |
78 | | If a Resource has been marked as background loaded (@see Resource::setBackgroundLoaded), |
79 | | the call does not itself occur in the thread which is doing the loading; |
80 | | when loading is complete a response indicator is placed with the |
81 | | ResourceGroupManager, which will then be sent back to the |
82 | | listener as part of the application's primary frame loop thread. |
83 | | */ |
84 | 0 | virtual void loadingComplete(Resource*) {} |
85 | | |
86 | | |
87 | | /** Called whenever the resource finishes preparing (paging into memory). |
88 | | |
89 | | If a Resource has been marked as background loaded (@see Resource::setBackgroundLoaded) |
90 | | the call does not itself occur in the thread which is doing the preparing; |
91 | | when preparing is complete a response indicator is placed with the |
92 | | ResourceGroupManager, which will then be sent back to the |
93 | | listener as part of the application's primary frame loop thread. |
94 | | */ |
95 | 0 | virtual void preparingComplete(Resource*) {} |
96 | | |
97 | | /** Called whenever the resource has been unloaded. */ |
98 | 0 | virtual void unloadingComplete(Resource*) {} |
99 | | }; |
100 | | |
101 | | /// Enum identifying the loading state of the resource |
102 | | enum LoadingState |
103 | | { |
104 | | /// Not loaded |
105 | | LOADSTATE_UNLOADED, |
106 | | /// Loading is in progress |
107 | | LOADSTATE_LOADING, |
108 | | /// Fully loaded |
109 | | LOADSTATE_LOADED, |
110 | | /// Currently unloading |
111 | | LOADSTATE_UNLOADING, |
112 | | /// Fully prepared |
113 | | LOADSTATE_PREPARED, |
114 | | /// Preparing is in progress |
115 | | LOADSTATE_PREPARING |
116 | | }; |
117 | | |
118 | | /// Enum that allow to choose subset of unloaded/reloaded resources and to adjust reloading behavior |
119 | | enum LoadingFlags |
120 | | { |
121 | | /// Only reloadable resources are processed, reload restores initial state. |
122 | | LF_DEFAULT = 0, |
123 | | /// Process non-reloadable resources too. |
124 | | LF_INCLUDE_NON_RELOADABLE = 1, |
125 | | /// Process only resources which are not referenced by any other object. Useful to reduce resource consumption. |
126 | | LF_ONLY_UNREFERENCED = 2, |
127 | | /// Combination of LF_ONLY_UNREFERENCED and LF_INCLUDE_NON_RELOADABLE |
128 | | LF_ONLY_UNREFERENCED_INCLUDE_NON_RELOADABLE = 3, |
129 | | /// Preserve some states during reloading, for example stencil shadows prepareness for Meshes |
130 | | LF_PRESERVE_STATE = 4, |
131 | | }; |
132 | | |
133 | | protected: |
134 | | /// Creator |
135 | | ResourceManager* mCreator; |
136 | | /// Unique name of the resource |
137 | | String mName; |
138 | | /// The name of the resource group |
139 | | String mGroup; |
140 | | /// Numeric handle for more efficient look up than name |
141 | | ResourceHandle mHandle; |
142 | | /// Is the resource currently loaded? |
143 | | std::atomic<LoadingState> mLoadingState; |
144 | | /// Is this resource going to be background loaded? Only applicable for multithreaded |
145 | | volatile bool mIsBackgroundLoaded; |
146 | | /// Is this file manually loaded? |
147 | | bool mIsManual; |
148 | | /// The size of the resource in bytes |
149 | | size_t mSize; |
150 | | /// Origin of this resource (e.g. script name) - optional |
151 | | String mOrigin; |
152 | | /// Optional manual loader; if provided, data is loaded from here instead of a file |
153 | | ManualResourceLoader* mLoader; |
154 | | private: |
155 | | /// State count, the number of times this resource has changed state |
156 | | size_t mStateCount; |
157 | | |
158 | | typedef std::set<Listener*> ListenerList; |
159 | | ListenerList mListenerList; |
160 | | OGRE_MUTEX(mListenerListMutex); |
161 | | protected: |
162 | | /** Protected unnamed constructor to prevent default construction. |
163 | | */ |
164 | | Resource() |
165 | | : mCreator(0), mHandle(0), mLoadingState(LOADSTATE_UNLOADED), |
166 | | mIsBackgroundLoaded(0), mIsManual(0), mSize(0), mLoader(0), mStateCount(0) |
167 | 0 | { |
168 | 0 | } |
169 | | |
170 | | /// protected assignment as this is merely abstract |
171 | | Resource& operator=(const Resource& rhs); |
172 | | |
173 | | /** Internal hook to perform actions before the load process, but |
174 | | after the resource has been marked as 'loading'. |
175 | | @note Mutex will have already been acquired by the loading thread. |
176 | | Also, this call will occur even when using a ManualResourceLoader |
177 | | (when loadImpl is not actually called) |
178 | | */ |
179 | 0 | virtual void preLoadImpl(void) {} |
180 | | /** Internal hook to perform actions after the load process, but |
181 | | before the resource has been marked as fully loaded. |
182 | | @note Mutex will have already been acquired by the loading thread. |
183 | | Also, this call will occur even when using a ManualResourceLoader |
184 | | (when loadImpl is not actually called) |
185 | | */ |
186 | 0 | virtual void postLoadImpl(void) {} |
187 | | |
188 | | /** Internal hook to perform actions before the unload process. |
189 | | @note Mutex will have already been acquired by the unloading thread. |
190 | | */ |
191 | 0 | virtual void preUnloadImpl(void) {} |
192 | | /** Internal hook to perform actions after the unload process, but |
193 | | before the resource has been marked as fully unloaded. |
194 | | @note Mutex will have already been acquired by the unloading thread. |
195 | | */ |
196 | 0 | virtual void postUnloadImpl(void) {} |
197 | | |
198 | | /** Internal implementation of the meat of the 'prepare' action, only called if this |
199 | | resource is not being loaded from a ManualResourceLoader. |
200 | | */ |
201 | 0 | virtual void prepareImpl(void) {} |
202 | | /** Internal function for undoing the 'prepare' action. Only called during |
203 | | unload if this resource is prepared but not yet loaded. |
204 | | */ |
205 | 0 | virtual void unprepareImpl(void) {} |
206 | | /** Internal implementation of the meat of the 'load' action, only called if this |
207 | | resource is not being loaded from a ManualResourceLoader. |
208 | | */ |
209 | | virtual void loadImpl(void) = 0; |
210 | | /** Internal implementation of the 'unload' action; called regardless of |
211 | | whether this resource is being loaded from a ManualResourceLoader. |
212 | | */ |
213 | | virtual void unloadImpl(void) = 0; |
214 | | |
215 | | /** Calculate the size of a resource; this will only be called after 'load' */ |
216 | | virtual size_t calculateSize(void) const; |
217 | | public: |
218 | | /** Standard constructor. |
219 | | @param creator Pointer to the ResourceManager that is creating this resource |
220 | | @param name The unique name of the resource |
221 | | @param handle Handle to the resource |
222 | | @param group The name of the resource group to which this resource belongs |
223 | | @param isManual Is this resource manually loaded? If so, you should really |
224 | | populate the loader parameter in order that the load process |
225 | | can call the loader back when loading is required. |
226 | | @param loader Pointer to a ManualResourceLoader implementation which will be called |
227 | | when the Resource wishes to load (should be supplied if you set |
228 | | isManual to true). You can in fact leave this parameter null |
229 | | if you wish, but the Resource will never be able to reload if |
230 | | anything ever causes it to unload. Therefore provision of a proper |
231 | | ManualResourceLoader instance is strongly recommended. |
232 | | */ |
233 | | Resource(ResourceManager* creator, const String& name, ResourceHandle handle, |
234 | | const String& group, bool isManual = false, ManualResourceLoader* loader = 0); |
235 | | |
236 | | /** Virtual destructor. Shouldn't need to be overloaded, as the resource |
237 | | deallocation code should reside in unload() |
238 | | @see |
239 | | Resource::unload() |
240 | | */ |
241 | | virtual ~Resource(); |
242 | | |
243 | | /** Prepares the resource for load, if it is not already. One can call prepare() |
244 | | before load(), but this is not required as load() will call prepare() |
245 | | itself, if needed. When OGRE_THREAD_SUPPORT==1 both load() and prepare() |
246 | | are thread-safe. When OGRE_THREAD_SUPPORT==2 however, only prepare() |
247 | | is thread-safe. The reason for this function is to allow a background |
248 | | thread to do some of the loading work, without requiring the whole render |
249 | | system to be thread-safe. The background thread would call |
250 | | prepare() while the main render loop would later call load(). So long as |
251 | | prepare() remains thread-safe, subclasses can arbitrarily split the work of |
252 | | loading a resource between load() and prepare(). It is best to try and |
253 | | do as much work in prepare(), however, since this will leave less work for |
254 | | the main render thread to do and thus increase FPS. |
255 | | @param backgroundThread Whether this is occurring in a background thread |
256 | | */ |
257 | | virtual void prepare(bool backgroundThread = false); |
258 | | |
259 | | /** Loads the resource, if it is not already. |
260 | | |
261 | | If the resource is loaded from a file, loading is automatic. If not, |
262 | | if for example this resource gained it's data from procedural calls |
263 | | rather than loading from a file, then this resource will not reload |
264 | | on it's own. |
265 | | @param backgroundThread Indicates whether the caller of this method is |
266 | | the background resource loading thread. |
267 | | |
268 | | */ |
269 | | virtual void load(bool backgroundThread = false); |
270 | | |
271 | | /** Reloads the resource, if it is already loaded. |
272 | | |
273 | | Calls unload() and then load() again, if the resource is already |
274 | | loaded. If it is not loaded already, then nothing happens. |
275 | | */ |
276 | | virtual void reload(LoadingFlags flags = LF_DEFAULT); |
277 | | |
278 | | /** Returns true if the Resource is reloadable, false otherwise. |
279 | | */ |
280 | | bool isReloadable(void) const |
281 | 0 | { |
282 | 0 | return !mIsManual || mLoader; |
283 | 0 | } |
284 | | |
285 | | /** Is this resource manually loaded? |
286 | | */ |
287 | | bool isManuallyLoaded(void) const |
288 | 0 | { |
289 | 0 | return mIsManual; |
290 | 0 | } |
291 | | |
292 | | /** Unloads the resource; this is not permanent, the resource can be |
293 | | reloaded later if required. |
294 | | */ |
295 | | virtual void unload(void); |
296 | | |
297 | | /** Retrieves info about the size of the resource. |
298 | | */ |
299 | | size_t getSize(void) const |
300 | 0 | { |
301 | 0 | return mSize; |
302 | 0 | } |
303 | | |
304 | | /** 'Touches' the resource to indicate it has been used. |
305 | | */ |
306 | | virtual void touch(void); |
307 | | |
308 | | /** Gets resource name. |
309 | | */ |
310 | 0 | const String& getName(void) const { return mName; } |
311 | | |
312 | 0 | ResourceHandle getHandle(void) const { return mHandle; } |
313 | | |
314 | | /** Returns true if the Resource has been prepared, false otherwise. |
315 | | */ |
316 | | bool isPrepared(void) const |
317 | 0 | { |
318 | 0 | // No lock required to read this state since no modify |
319 | 0 | return (mLoadingState.load() == LOADSTATE_PREPARED); |
320 | 0 | } |
321 | | |
322 | | /** Returns true if the Resource has been loaded, false otherwise. |
323 | | */ |
324 | | bool isLoaded(void) const |
325 | 0 | { |
326 | 0 | // No lock required to read this state since no modify |
327 | 0 | return (mLoadingState.load() == LOADSTATE_LOADED); |
328 | 0 | } |
329 | | |
330 | | /** Returns whether the resource is currently in the process of |
331 | | background loading. |
332 | | */ |
333 | | bool isLoading() const |
334 | 0 | { |
335 | 0 | return (mLoadingState.load() == LOADSTATE_LOADING); |
336 | 0 | } |
337 | | |
338 | | /** Returns the current loading state. |
339 | | */ |
340 | | LoadingState getLoadingState() const |
341 | 0 | { |
342 | 0 | return mLoadingState.load(); |
343 | 0 | } |
344 | | |
345 | | |
346 | | |
347 | | /** Returns whether this Resource has been earmarked for background loading. |
348 | | |
349 | | This option only makes sense when you have built Ogre with |
350 | | thread support (OGRE_THREAD_SUPPORT). If a resource has been marked |
351 | | for background loading, then it won't load on demand like normal |
352 | | when load() is called. Instead, it will ignore request to load() |
353 | | except if the caller indicates it is the background loader. Any |
354 | | other users of this resource should check isLoaded(), and if that |
355 | | returns false, don't use the resource and come back later. |
356 | | */ |
357 | 0 | bool isBackgroundLoaded(void) const { return mIsBackgroundLoaded; } |
358 | | |
359 | | /** Tells the resource whether it is background loaded or not. |
360 | | |
361 | | @see Resource::isBackgroundLoaded. Note that calling this only |
362 | | defers the normal on-demand loading behaviour of a resource, it |
363 | | does not actually set up a thread to make sure the resource gets |
364 | | loaded in the background. You should use ResourceBackgroundLoadingQueue |
365 | | to manage the actual loading (which will call this method itself). |
366 | | */ |
367 | 0 | void setBackgroundLoaded(bool bl) { mIsBackgroundLoaded = bl; } |
368 | | |
369 | | /** Escalates the loading of a background loaded resource. |
370 | | |
371 | | If a resource is set to load in the background, but something needs |
372 | | it before it's been loaded, there could be a problem. If the user |
373 | | of this resource really can't wait, they can escalate the loading |
374 | | which basically pulls the loading into the current thread immediately. |
375 | | If the resource is already being loaded but just hasn't quite finished |
376 | | then this method will simply wait until the background load is complete. |
377 | | */ |
378 | | virtual void escalateLoading(); |
379 | | |
380 | | /** Register a listener on this resource. |
381 | | @see Resource::Listener |
382 | | */ |
383 | | virtual void addListener(Listener* lis); |
384 | | |
385 | | /** Remove a listener on this resource. |
386 | | @see Resource::Listener |
387 | | */ |
388 | | virtual void removeListener(Listener* lis); |
389 | | |
390 | | /// Gets the group which this resource is a member of |
391 | 0 | const String& getGroup(void) const { return mGroup; } |
392 | | |
393 | | /** Change the resource group ownership of a Resource. |
394 | | |
395 | | This method is generally reserved for internal use, although |
396 | | if you really know what you're doing you can use it to move |
397 | | this resource from one group to another. |
398 | | @param newGroup Name of the new group |
399 | | */ |
400 | | virtual void changeGroupOwnership(const String& newGroup); |
401 | | |
402 | | /// Gets the manager which created this resource |
403 | 0 | ResourceManager* getCreator(void) { return mCreator; } |
404 | | /** Get the origin of this resource, e.g. a script file name. |
405 | | |
406 | | This property will only contain something if the creator of |
407 | | this resource chose to populate it. Script loaders are advised |
408 | | to populate it. |
409 | | */ |
410 | 0 | const String& getOrigin(void) const { return mOrigin; } |
411 | | /// Notify this resource of it's origin |
412 | 0 | void _notifyOrigin(const String& origin) { mOrigin = origin; } |
413 | | |
414 | | /** Returns the number of times this resource has changed state, which |
415 | | generally means the number of times it has been loaded. Objects that |
416 | | build derived data based on the resource can check this value against |
417 | | a copy they kept last time they built this derived data, in order to |
418 | | know whether it needs rebuilding. This is a nice way of monitoring |
419 | | changes without having a tightly-bound callback. |
420 | | */ |
421 | 0 | virtual size_t getStateCount() const { return mStateCount; } |
422 | | |
423 | | /** Manually mark the state of this resource as having been changed. |
424 | | |
425 | | You only need to call this from outside if you explicitly want derived |
426 | | objects to think this object has changed. @see getStateCount. |
427 | | */ |
428 | | virtual void _dirtyState(); |
429 | | |
430 | | |
431 | | /** Firing of loading complete event |
432 | | |
433 | | You should call this from the thread that runs the main frame loop |
434 | | to avoid having to make the receivers of this event thread-safe. |
435 | | If you use %Ogre's built in frame loop you don't need to call this |
436 | | yourself. |
437 | | */ |
438 | | void _fireLoadingComplete(bool unused = false); |
439 | | |
440 | | /** Firing of preparing complete event |
441 | | |
442 | | @copydetails _fireLoadingComplete |
443 | | */ |
444 | | void _firePreparingComplete(bool unused = false); |
445 | | |
446 | | /** Firing of unloading complete event |
447 | | |
448 | | @copydetails _fireLoadingComplete |
449 | | */ |
450 | | void _fireUnloadingComplete(void); |
451 | | }; |
452 | | |
453 | | /** Interface describing a manual resource loader. |
454 | | |
455 | | Resources are usually loaded from files; however in some cases you |
456 | | want to be able to set the data up manually instead. This provides |
457 | | some problems, such as how to reload a Resource if it becomes |
458 | | unloaded for some reason, either because of memory constraints, or |
459 | | because a device fails and some or all of the data is lost. |
460 | | |
461 | | This interface should be implemented by all classes which wish to |
462 | | provide manual data to a resource. They provide a pointer to themselves |
463 | | when defining the resource (via the appropriate ResourceManager), |
464 | | and will be called when the Resource tries to load. |
465 | | They should implement the loadResource method such that the Resource |
466 | | is in the end set up exactly as if it had loaded from a file, |
467 | | although the implementations will likely differ between subclasses |
468 | | of Resource, which is why no generic algorithm can be stated here. |
469 | | @note |
470 | | The loader must remain valid for the entire life of the resource, |
471 | | so that if need be it can be called upon to re-load the resource |
472 | | at any time. |
473 | | */ |
474 | | class _OgreExport ManualResourceLoader |
475 | | { |
476 | | public: |
477 | 0 | ManualResourceLoader() {} |
478 | 0 | virtual ~ManualResourceLoader() {} |
479 | | |
480 | | /** Called when a resource wishes to prepare instead of Resource::prepareImpl |
481 | | * @note this could get |
482 | | * called in a background thread even in just a semithreaded ogre |
483 | | * (OGRE_THREAD_SUPPORT==2). Thus, you must not access the RenderSystem from |
484 | | * this callback. Do that stuff in #loadResource. |
485 | | @param resource The resource which wishes to prepare |
486 | | */ |
487 | | virtual void prepareResource(Resource* resource) |
488 | 0 | { (void)resource; } |
489 | | |
490 | | /** Called when a resource wishes to load instead of Resource::loadImpl |
491 | | @param resource The resource which wishes to load |
492 | | */ |
493 | | virtual void loadResource(Resource* resource) = 0; |
494 | | }; |
495 | | /** @} */ |
496 | | /** @} */ |
497 | | } |
498 | | |
499 | | #include "OgreHeaderSuffix.h" |
500 | | |
501 | | #endif |