2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program 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.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * Peter Schlaile <peter [at] schlaile [dot] de> 2010
20 * Contributor(s): Sergey Sharybin
22 * ***** END GPL LICENSE BLOCK *****
25 /** \file blender/blenkernel/intern/seqcache.c
31 #include "BLI_sys_types.h" /* for intptr_t */
33 #include "MEM_guardedalloc.h"
35 #include "DNA_sequence_types.h"
37 #include "IMB_moviecache.h"
38 #include "IMB_imbuf.h"
39 #include "IMB_imbuf_types.h"
41 #include "BLI_listbase.h"
43 #include "BKE_sequencer.h"
45 typedef struct SeqCacheKey {
47 SeqRenderData context;
49 seq_stripelem_ibuf_t type;
52 typedef struct SeqPreprocessCacheElem {
53 struct SeqPreprocessCacheElem *next, *prev;
56 SeqRenderData context;
57 seq_stripelem_ibuf_t type;
60 } SeqPreprocessCacheElem;
62 typedef struct SeqPreprocessCache {
67 static struct MovieCache *moviecache = NULL;
68 static struct SeqPreprocessCache *preprocess_cache = NULL;
70 static void preprocessed_cache_destruct(void);
72 static int seq_cmp_render_data(const SeqRenderData *a, const SeqRenderData *b)
74 if (a->preview_render_size < b->preview_render_size) {
77 if (a->preview_render_size > b->preview_render_size) {
81 if (a->rectx < b->rectx) {
84 if (a->rectx > b->rectx) {
88 if (a->recty < b->recty) {
91 if (a->recty > b->recty) {
95 if (a->bmain < b->bmain) {
98 if (a->bmain > b->bmain) {
102 if (a->scene < b->scene) {
105 if (a->scene > b->scene) {
109 if (a->motion_blur_shutter < b->motion_blur_shutter) {
112 if (a->motion_blur_shutter > b->motion_blur_shutter) {
116 if (a->motion_blur_samples < b->motion_blur_samples) {
119 if (a->motion_blur_samples > b->motion_blur_samples) {
126 static unsigned int seq_hash_render_data(const SeqRenderData *a)
128 unsigned int rval = a->rectx + a->recty;
130 rval ^= a->preview_render_size;
131 rval ^= ((intptr_t) a->bmain) << 6;
132 rval ^= ((intptr_t) a->scene) << 6;
133 rval ^= (int)(a->motion_blur_shutter * 100.0f) << 10;
134 rval ^= a->motion_blur_samples << 24;
139 static unsigned int seqcache_hashhash(const void *key_)
141 const SeqCacheKey *key = (SeqCacheKey *) key_;
142 unsigned int rval = seq_hash_render_data(&key->context);
144 rval ^= *(unsigned int *) &key->cfra;
146 rval ^= ((intptr_t) key->seq) << 6;
151 static int seqcache_hashcmp(const void *a_, const void *b_)
153 const SeqCacheKey *a = (SeqCacheKey *) a_;
154 const SeqCacheKey *b = (SeqCacheKey *) b_;
156 if (a->seq < b->seq) {
159 if (a->seq > b->seq) {
163 if (a->cfra < b->cfra) {
166 if (a->cfra > b->cfra) {
170 if (a->type < b->type) {
173 if (a->type > b->type) {
177 return seq_cmp_render_data(&a->context, &b->context);
180 void BKE_sequencer_cache_destruct(void)
183 IMB_moviecache_free(moviecache);
185 preprocessed_cache_destruct();
188 void BKE_sequencer_cache_cleanup(void)
191 IMB_moviecache_free(moviecache);
192 moviecache = IMB_moviecache_create("seqcache", sizeof(SeqCacheKey), seqcache_hashhash, seqcache_hashcmp);
195 BKE_sequencer_preprocessed_cache_cleanup();
198 static bool seqcache_key_check_seq(ImBuf *UNUSED(ibuf), void *userkey, void *userdata)
200 SeqCacheKey *key = (SeqCacheKey *) userkey;
201 Sequence *seq = (Sequence *) userdata;
203 return key->seq == seq;
206 void BKE_sequencer_cache_cleanup_sequence(Sequence *seq)
209 IMB_moviecache_cleanup(moviecache, seqcache_key_check_seq, seq);
212 struct ImBuf *BKE_sequencer_cache_get(const SeqRenderData *context, Sequence *seq, float cfra, seq_stripelem_ibuf_t type)
214 if (moviecache && seq) {
218 key.context = *context;
219 key.cfra = cfra - seq->start;
222 return IMB_moviecache_get(moviecache, &key);
228 void BKE_sequencer_cache_put(const SeqRenderData *context, Sequence *seq, float cfra, seq_stripelem_ibuf_t type, ImBuf *i)
232 if (i == NULL || context->skip_cache) {
237 moviecache = IMB_moviecache_create("seqcache", sizeof(SeqCacheKey), seqcache_hashhash, seqcache_hashcmp);
241 key.context = *context;
242 key.cfra = cfra - seq->start;
245 IMB_moviecache_put(moviecache, &key, i);
248 void BKE_sequencer_preprocessed_cache_cleanup(void)
250 SeqPreprocessCacheElem *elem;
252 if (!preprocess_cache)
255 for (elem = preprocess_cache->elems.first; elem; elem = elem->next) {
256 IMB_freeImBuf(elem->ibuf);
258 BLI_freelistN(&preprocess_cache->elems);
260 preprocess_cache->elems.first = preprocess_cache->elems.last = NULL;
263 static void preprocessed_cache_destruct(void)
265 if (!preprocess_cache)
268 BKE_sequencer_preprocessed_cache_cleanup();
270 MEM_freeN(preprocess_cache);
271 preprocess_cache = NULL;
274 ImBuf *BKE_sequencer_preprocessed_cache_get(const SeqRenderData *context, Sequence *seq, float cfra, seq_stripelem_ibuf_t type)
276 SeqPreprocessCacheElem *elem;
278 if (!preprocess_cache)
281 if (preprocess_cache->cfra != cfra)
284 for (elem = preprocess_cache->elems.first; elem; elem = elem->next) {
285 if (elem->seq != seq)
288 if (elem->type != type)
291 if (seq_cmp_render_data(&elem->context, context) != 0)
294 IMB_refImBuf(elem->ibuf);
301 void BKE_sequencer_preprocessed_cache_put(const SeqRenderData *context, Sequence *seq, float cfra, seq_stripelem_ibuf_t type, ImBuf *ibuf)
303 SeqPreprocessCacheElem *elem;
305 if (!preprocess_cache) {
306 preprocess_cache = MEM_callocN(sizeof(SeqPreprocessCache), "sequencer preprocessed cache");
309 if (preprocess_cache->cfra != cfra)
310 BKE_sequencer_preprocessed_cache_cleanup();
313 elem = MEM_callocN(sizeof(SeqPreprocessCacheElem), "sequencer preprocessed cache element");
317 elem->context = *context;
320 preprocess_cache->cfra = cfra;
324 BLI_addtail(&preprocess_cache->elems, elem);
327 void BKE_sequencer_preprocessed_cache_cleanup_sequence(Sequence *seq)
329 SeqPreprocessCacheElem *elem, *elem_next;
331 if (!preprocess_cache)
334 for (elem = preprocess_cache->elems.first; elem; elem = elem_next) {
335 elem_next = elem->next;
337 if (elem->seq == seq) {
338 IMB_freeImBuf(elem->ibuf);
340 BLI_freelinkN(&preprocess_cache->elems, elem);