Cleanup: remove redundant doxygen \file argument
[blender.git] / source / blender / blenkernel / intern / seqcache.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Peter Schlaile <peter [at] schlaile [dot] de> 2010
17  */
18
19 /** \file \ingroup bke
20  */
21
22 #include <stddef.h>
23
24 #include "BLI_sys_types.h"  /* for intptr_t */
25
26 #include "MEM_guardedalloc.h"
27
28 #include "DNA_sequence_types.h"
29 #include "DNA_scene_types.h"
30
31 #include "IMB_moviecache.h"
32 #include "IMB_imbuf.h"
33 #include "IMB_imbuf_types.h"
34
35 #include "BLI_listbase.h"
36
37 #include "BKE_sequencer.h"
38 #include "BKE_scene.h"
39
40 typedef struct SeqCacheKey {
41         struct Sequence *seq;
42         SeqRenderData context;
43         float cfra;
44         eSeqStripElemIBuf type;
45 } SeqCacheKey;
46
47 typedef struct SeqPreprocessCacheElem {
48         struct SeqPreprocessCacheElem *next, *prev;
49
50         struct Sequence *seq;
51         SeqRenderData context;
52         eSeqStripElemIBuf type;
53
54         ImBuf *ibuf;
55 } SeqPreprocessCacheElem;
56
57 typedef struct SeqPreprocessCache {
58         int cfra;
59         ListBase elems;
60 } SeqPreprocessCache;
61
62 static struct MovieCache *moviecache = NULL;
63 static struct SeqPreprocessCache *preprocess_cache = NULL;
64
65 static void preprocessed_cache_destruct(void);
66
67 static bool seq_cmp_render_data(const SeqRenderData *a, const SeqRenderData *b)
68 {
69         return ((a->preview_render_size != b->preview_render_size) ||
70                 (a->rectx != b->rectx) ||
71                 (a->recty != b->recty) ||
72                 (a->bmain != b->bmain) ||
73                 (a->scene != b->scene) ||
74                 (a->motion_blur_shutter != b->motion_blur_shutter) ||
75                 (a->motion_blur_samples != b->motion_blur_samples) ||
76                 (a->scene->r.views_format != b->scene->r.views_format) ||
77                 (a->view_id != b->view_id));
78 }
79
80 static unsigned int seq_hash_render_data(const SeqRenderData *a)
81 {
82         unsigned int rval = a->rectx + a->recty;
83
84         rval ^= a->preview_render_size;
85         rval ^= ((intptr_t) a->bmain) << 6;
86         rval ^= ((intptr_t) a->scene) << 6;
87         rval ^= (int)(a->motion_blur_shutter * 100.0f) << 10;
88         rval ^= a->motion_blur_samples << 16;
89         rval ^= ((a->scene->r.views_format * 2) + a->view_id) << 24;
90
91         return rval;
92 }
93
94 static unsigned int seqcache_hashhash(const void *key_)
95 {
96         const SeqCacheKey *key = key_;
97         unsigned int rval = seq_hash_render_data(&key->context);
98
99         rval ^= *(const unsigned int *) &key->cfra;
100         rval += key->type;
101         rval ^= ((intptr_t) key->seq) << 6;
102
103         return rval;
104 }
105
106 static bool seqcache_hashcmp(const void *a_, const void *b_)
107 {
108         const SeqCacheKey *a = a_;
109         const SeqCacheKey *b = b_;
110
111         return ((a->seq != b->seq) ||
112                 (a->cfra != b->cfra) ||
113                 (a->type != b->type) ||
114                 seq_cmp_render_data(&a->context, &b->context));
115 }
116
117 void BKE_sequencer_cache_destruct(void)
118 {
119         if (moviecache)
120                 IMB_moviecache_free(moviecache);
121
122         preprocessed_cache_destruct();
123 }
124
125 void BKE_sequencer_cache_cleanup(void)
126 {
127         if (moviecache) {
128                 IMB_moviecache_free(moviecache);
129                 moviecache = IMB_moviecache_create("seqcache", sizeof(SeqCacheKey), seqcache_hashhash, seqcache_hashcmp);
130         }
131
132         BKE_sequencer_preprocessed_cache_cleanup();
133 }
134
135 static bool seqcache_key_check_seq(ImBuf *UNUSED(ibuf), void *userkey, void *userdata)
136 {
137         SeqCacheKey *key = (SeqCacheKey *) userkey;
138         Sequence *seq = (Sequence *) userdata;
139
140         return key->seq == seq;
141 }
142
143 void BKE_sequencer_cache_cleanup_sequence(Sequence *seq)
144 {
145         if (moviecache)
146                 IMB_moviecache_cleanup(moviecache, seqcache_key_check_seq, seq);
147 }
148
149 struct ImBuf *BKE_sequencer_cache_get(const SeqRenderData *context, Sequence *seq, float cfra, eSeqStripElemIBuf type)
150 {
151         if (moviecache && seq) {
152                 SeqCacheKey key;
153
154                 key.seq = seq;
155                 key.context = *context;
156                 key.cfra = cfra - seq->start;
157                 key.type = type;
158
159                 return IMB_moviecache_get(moviecache, &key);
160         }
161
162         return NULL;
163 }
164
165 void BKE_sequencer_cache_put(const SeqRenderData *context, Sequence *seq, float cfra, eSeqStripElemIBuf type, ImBuf *i)
166 {
167         SeqCacheKey key;
168
169         if (i == NULL || context->skip_cache) {
170                 return;
171         }
172
173         if (!moviecache) {
174                 moviecache = IMB_moviecache_create("seqcache", sizeof(SeqCacheKey), seqcache_hashhash, seqcache_hashcmp);
175         }
176
177         key.seq = seq;
178         key.context = *context;
179         key.cfra = cfra - seq->start;
180         key.type = type;
181
182         IMB_moviecache_put(moviecache, &key, i);
183 }
184
185 void BKE_sequencer_preprocessed_cache_cleanup(void)
186 {
187         SeqPreprocessCacheElem *elem;
188
189         if (!preprocess_cache)
190                 return;
191
192         for (elem = preprocess_cache->elems.first; elem; elem = elem->next) {
193                 IMB_freeImBuf(elem->ibuf);
194         }
195         BLI_freelistN(&preprocess_cache->elems);
196
197         BLI_listbase_clear(&preprocess_cache->elems);
198 }
199
200 static void preprocessed_cache_destruct(void)
201 {
202         if (!preprocess_cache)
203                 return;
204
205         BKE_sequencer_preprocessed_cache_cleanup();
206
207         MEM_freeN(preprocess_cache);
208         preprocess_cache = NULL;
209 }
210
211 ImBuf *BKE_sequencer_preprocessed_cache_get(const SeqRenderData *context, Sequence *seq, float cfra, eSeqStripElemIBuf type)
212 {
213         SeqPreprocessCacheElem *elem;
214
215         if (!preprocess_cache)
216                 return NULL;
217
218         if (preprocess_cache->cfra != cfra)
219                 return NULL;
220
221         for (elem = preprocess_cache->elems.first; elem; elem = elem->next) {
222                 if (elem->seq != seq)
223                         continue;
224
225                 if (elem->type != type)
226                         continue;
227
228                 if (seq_cmp_render_data(&elem->context, context) != 0)
229                         continue;
230
231                 IMB_refImBuf(elem->ibuf);
232                 return elem->ibuf;
233         }
234
235         return NULL;
236 }
237
238 void BKE_sequencer_preprocessed_cache_put(const SeqRenderData *context, Sequence *seq, float cfra, eSeqStripElemIBuf type, ImBuf *ibuf)
239 {
240         SeqPreprocessCacheElem *elem;
241
242         if (!preprocess_cache) {
243                 preprocess_cache = MEM_callocN(sizeof(SeqPreprocessCache), "sequencer preprocessed cache");
244         }
245         else {
246                 if (preprocess_cache->cfra != cfra)
247                         BKE_sequencer_preprocessed_cache_cleanup();
248         }
249
250         elem = MEM_callocN(sizeof(SeqPreprocessCacheElem), "sequencer preprocessed cache element");
251
252         elem->seq = seq;
253         elem->type = type;
254         elem->context = *context;
255         elem->ibuf = ibuf;
256
257         preprocess_cache->cfra = cfra;
258
259         IMB_refImBuf(ibuf);
260
261         BLI_addtail(&preprocess_cache->elems, elem);
262 }
263
264 void BKE_sequencer_preprocessed_cache_cleanup_sequence(Sequence *seq)
265 {
266         SeqPreprocessCacheElem *elem, *elem_next;
267
268         if (!preprocess_cache)
269                 return;
270
271         for (elem = preprocess_cache->elems.first; elem; elem = elem_next) {
272                 elem_next = elem->next;
273
274                 if (elem->seq == seq) {
275                         IMB_freeImBuf(elem->ibuf);
276
277                         BLI_freelinkN(&preprocess_cache->elems, elem);
278                 }
279         }
280 }