Merging r49681 through r49707 from trunk into soc-2011-tomato
[blender.git] / source / blender / blenkernel / intern / seqcache.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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.
8  *
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.
13  *
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.
17  *
18  * Peter Schlaile <peter [at] schlaile [dot] de> 2010
19  *
20  * Contributor(s): Sergey Sharybin
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /** \file blender/blenkernel/intern/seqcache.c
26  *  \ingroup bke
27  */
28
29
30 #include <stddef.h>
31
32 #include "BLO_sys_types.h"  /* for intptr_t */
33
34 #include "MEM_guardedalloc.h"
35
36 #include "DNA_sequence_types.h"
37 #include "BKE_sequencer.h"
38
39 #include "IMB_moviecache.h"
40 #include "IMB_imbuf_types.h"
41
42 typedef struct SeqCacheKey {
43         struct Sequence *seq;
44         SeqRenderData context;
45         float cfra;
46         seq_stripelem_ibuf_t type;
47 } SeqCacheKey;
48
49 static struct MovieCache *moviecache = NULL;
50
51 static int seq_cmp_render_data(const SeqRenderData *a, const SeqRenderData *b)
52 {
53         if (a->preview_render_size < b->preview_render_size) {
54                 return -1;
55         }
56         if (a->preview_render_size > b->preview_render_size) {
57                 return 1;
58         }
59
60         if (a->rectx < b->rectx) {
61                 return -1;
62         }
63         if (a->rectx > b->rectx) {
64                 return 1;
65         }
66
67         if (a->recty < b->recty) {
68                 return -1;
69         }
70         if (a->recty > b->recty) {
71                 return 1;
72         }
73
74         if (a->bmain < b->bmain) {
75                 return -1;
76         }
77         if (a->bmain > b->bmain) {
78                 return 1;
79         }
80
81         if (a->scene < b->scene) {
82                 return -1;
83         }
84         if (a->scene > b->scene) {
85                 return 1;
86         }
87
88         if (a->motion_blur_shutter < b->motion_blur_shutter) {
89                 return -1;
90         }
91         if (a->motion_blur_shutter > b->motion_blur_shutter) {
92                 return 1;
93         }
94
95         if (a->motion_blur_samples < b->motion_blur_samples) {
96                 return -1;
97         }
98         if (a->motion_blur_samples > b->motion_blur_samples) {
99                 return 1;
100         }
101
102         return 0;
103 }
104
105 static unsigned int seq_hash_render_data(const SeqRenderData *a)
106 {
107         unsigned int rval = a->rectx + a->recty;
108
109         rval ^= a->preview_render_size;
110         rval ^= ((intptr_t) a->bmain) << 6;
111         rval ^= ((intptr_t) a->scene) << 6;
112         rval ^= (int)(a->motion_blur_shutter * 100.0f) << 10;
113         rval ^= a->motion_blur_samples << 24;
114
115         return rval;
116 }
117
118 static unsigned int seqcache_hashhash(const void *key_)
119 {
120         const SeqCacheKey *key = (SeqCacheKey *) key_;
121         unsigned int rval = seq_hash_render_data(&key->context);
122
123         rval ^= *(unsigned int *) &key->cfra;
124         rval += key->type;
125         rval ^= ((intptr_t) key->seq) << 6;
126
127         return rval;
128 }
129
130 static int seqcache_hashcmp(const void *a_, const void *b_)
131 {
132         const SeqCacheKey *a = (SeqCacheKey *) a_;
133         const SeqCacheKey *b = (SeqCacheKey *) b_;
134
135         if (a->seq < b->seq) {
136                 return -1;
137         }
138         if (a->seq > b->seq) {
139                 return 1;
140         }
141
142         if (a->cfra < b->cfra) {
143                 return -1;
144         }
145         if (a->cfra > b->cfra) {
146                 return 1;
147         }
148
149         if (a->type < b->type) {
150                 return -1;
151         }
152         if (a->type > b->type) {
153                 return 1;
154         }
155
156         return seq_cmp_render_data(&a->context, &b->context);
157 }
158
159 void BKE_sequencer_cache_destruct(void)
160 {
161         if (moviecache)
162                 IMB_moviecache_free(moviecache);
163 }
164
165 void BKE_sequencer_cache_cleanup(void)
166 {
167         if (moviecache) {
168                 IMB_moviecache_free(moviecache);
169                 moviecache = IMB_moviecache_create("seqcache", sizeof(SeqCacheKey), seqcache_hashhash, seqcache_hashcmp);
170         }
171 }
172
173 static int seqcache_key_check_seq(void *userkey, void *userdata)
174 {
175         SeqCacheKey *key = (SeqCacheKey *) userkey;
176         Sequence *seq = (Sequence *) userdata;
177
178         return key->seq == seq;
179 }
180
181 void BKE_sequencer_cache_cleanup_sequence(Sequence *seq)
182 {
183         IMB_moviecache_cleanup(moviecache, seqcache_key_check_seq, seq);
184 }
185
186 struct ImBuf *BKE_sequencer_cache_get(SeqRenderData context, Sequence *seq, float cfra, seq_stripelem_ibuf_t type)
187 {
188         if (moviecache && seq) {
189                 SeqCacheKey key;
190
191                 key.seq = seq;
192                 key.context = context;
193                 key.cfra = cfra - seq->start;
194                 key.type = type;
195
196                 return IMB_moviecache_get(moviecache, &key);
197         }
198
199         return NULL;
200 }
201
202 void BKE_sequencer_cache_put(SeqRenderData context, Sequence *seq, float cfra, seq_stripelem_ibuf_t type, ImBuf *i)
203 {
204         SeqCacheKey key;
205
206         if (!i) {
207                 return;
208         }
209
210         if (!moviecache) {
211                 moviecache = IMB_moviecache_create("seqcache", sizeof(SeqCacheKey), seqcache_hashhash, seqcache_hashcmp);
212         }
213
214         key.seq = seq;
215         key.context = context;
216         key.cfra = cfra - seq->start;
217         key.type = type;
218
219         IMB_moviecache_put(moviecache, &key, i);
220 }