]> git.tdb.fi Git - libs/gl.git/blob - source/resourcemanager.h
Make buffer storage immutable and use ARB_buffer_storage
[libs/gl.git] / source / resourcemanager.h
1 #ifndef MSP_GL_RESOURCEMANAGER_H_
2 #define MSP_GL_RESOURCEMANAGER_H_
3
4 #include <msp/core/inttypes.h>
5 #include <msp/core/mutex.h>
6 #include <msp/core/semaphore.h>
7 #include <msp/core/thread.h>
8 #include <msp/datafile/collection.h>
9 #include "resource.h"
10
11 namespace Msp {
12 namespace GL {
13
14 class ResourceObserver;
15
16 class resource_load_error: public std::runtime_error
17 {
18 public:
19         resource_load_error(const std::string &, const std::string &);
20         resource_load_error(const std::string &, const std::exception &);
21         virtual ~resource_load_error() throw() { }
22 };
23
24
25 class ResourceManager
26 {
27 public:
28         enum LoadingPolicy
29         {
30                 LOAD_IMMEDIATELY,
31                 LOAD_ON_DEMAND,
32                 LOAD_MANUALLY
33         };
34
35         struct ResourceLocation
36         {
37                 DataFile::Collection *collection;
38                 std::string name;
39
40                 ResourceLocation();
41                 ResourceLocation(DataFile::Collection &, const std::string &);
42         };
43
44 private:
45         struct ManagedResource
46         {
47                 enum State
48                 {
49                         NOT_LOADED,
50                         LOAD_QUEUED,
51                         LOADING,
52                         LOAD_FINISHED,
53                         LOADED,
54                         LOAD_ERROR
55                 };
56
57                 Resource *resource;
58                 ResourceLocation location;
59                 bool load_priority;
60                 IO::Seekable *io;
61                 Resource::AsyncLoader *loader;
62                 State state;
63                 unsigned last_used;
64                 UInt64 data_size;
65                 std::vector<ResourceObserver *> observers;
66
67                 ManagedResource(Resource &);
68
69                 void start_loading();
70                 bool process(bool);
71                 void finish_loading(bool);
72                 void finish_loading();
73                 void unload();
74
75                 void add_observer(ResourceObserver &);
76                 void remove_observer(ResourceObserver &);
77         };
78
79         typedef std::list<ManagedResource *> LoadQueue;
80
81         class LoadingThread: public Thread
82         {
83         private:
84                 Semaphore sem;
85                 Mutex queue_mutex;
86                 LoadQueue async_queue;
87                 LoadQueue sync_queue;
88                 unsigned capacity;
89                 unsigned size;
90                 std::list<resource_load_error> error_queue;
91                 Mutex data_size_mutex;
92                 UInt64 loaded_data_size;
93                 volatile bool done;
94
95         public:
96                 LoadingThread();
97
98         private:
99                 virtual void main();
100
101                 ManagedResource *front(LoadQueue &);
102
103         public:
104                 void add_resource(ManagedResource &);
105                 void remove_resource(ManagedResource &);
106         private:
107                 bool try_remove_resource(ManagedResource &);
108         public:
109                 bool sync();
110                 bool needs_work() const { return size<capacity; }
111                 UInt64 get_and_reset_loaded_data_size();
112
113                 void terminate();
114         };
115
116         typedef std::map<const Resource *, ManagedResource> ResourceMap;
117
118         LoadingPolicy policy;
119         bool async_loads;
120         mutable Mutex map_mutex;
121         ResourceMap resources;
122         LoadQueue queue;
123         UInt64 total_data_size;
124         UInt64 size_limit;
125         unsigned frame;
126         unsigned min_retain_frames;
127         unsigned max_retain_frames;
128         unsigned next_unload;
129         LoadingThread thread;
130
131 public:
132         ResourceManager();
133         ~ResourceManager();
134
135         void set_loading_policy(LoadingPolicy);
136         void set_async_loads(bool);
137         void set_size_limit(UInt64);
138         void set_min_retain_frames(unsigned);
139         void set_max_retain_frames(unsigned);
140
141         void add_resource(Resource &);
142 private:
143         const ManagedResource &get_managed_resource(const Resource &) const;
144         ManagedResource &get_managed_resource(const Resource &);
145 public:
146         void *get_data_for_resource(const Resource &r) { return &get_managed_resource(r); }
147         void set_resource_location(Resource &, DataFile::Collection &, const std::string &);
148         void set_resource_location(Resource &, const ResourceLocation &);
149         const ResourceLocation *get_resource_location(const Resource &) const;
150         void load_resource(Resource &);
151         bool is_resource_loaded(const Resource &) const;
152         void resource_used(const Resource &);
153         void remove_resource(Resource &);
154
155         void observe_resource(const Resource &, ResourceObserver &);
156         void unobserve_resource(const Resource &, ResourceObserver &);
157
158         void tick();
159 private:
160         void dispatch_work();
161         void unload_by_age();
162         void unload_by_size();
163 public:
164         UInt64 get_total_data_size() const { return total_data_size; }
165
166 private:
167         static bool age_order(ManagedResource *, ManagedResource *);
168 };
169
170 } // namespace GL
171 } // namespace Msp
172
173 #endif