Sequencer: refactor clipboard copy to no longer increase user count.
[blender.git] / source / blender / blenkernel / intern / seqcache.c
index 387ec67eb1cccd50465a945e7b9e37360c15867f..435d9369faab2a021c0206b1ea2e4db4d118ec2c 100644 (file)
  *  \ingroup bke
  */
 
-
 #include <stddef.h>
 
-#include "BLO_sys_types.h"  /* for intptr_t */
+#include "BLI_sys_types.h"  /* for intptr_t */
 
 #include "MEM_guardedalloc.h"
 
 #include "DNA_sequence_types.h"
-#include "BKE_sequencer.h"
+#include "DNA_scene_types.h"
 
 #include "IMB_moviecache.h"
+#include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
 
+#include "BLI_listbase.h"
+
+#include "BKE_sequencer.h"
+#include "BKE_scene.h"
+
 typedef struct SeqCacheKey {
        struct Sequence *seq;
        SeqRenderData context;
        float cfra;
-       seq_stripelem_ibuf_t type;
+       eSeqStripElemIBuf type;
 } SeqCacheKey;
 
-static struct MovieCache *moviecache = NULL;
+typedef struct SeqPreprocessCacheElem {
+       struct SeqPreprocessCacheElem *next, *prev;
 
-static int seq_cmp_render_data(const SeqRenderData *a, const SeqRenderData *b)
-{
-       if (a->preview_render_size < b->preview_render_size) {
-               return -1;
-       }
-       if (a->preview_render_size > b->preview_render_size) {
-               return 1;
-       }
-
-       if (a->rectx < b->rectx) {
-               return -1;
-       }
-       if (a->rectx > b->rectx) {
-               return 1;
-       }
-
-       if (a->recty < b->recty) {
-               return -1;
-       }
-       if (a->recty > b->recty) {
-               return 1;
-       }
+       struct Sequence *seq;
+       SeqRenderData context;
+       eSeqStripElemIBuf type;
 
-       if (a->bmain < b->bmain) {
-               return -1;
-       }
-       if (a->bmain > b->bmain) {
-               return 1;
-       }
+       ImBuf *ibuf;
+} SeqPreprocessCacheElem;
 
-       if (a->scene < b->scene) {
-               return -1;
-       }
-       if (a->scene > b->scene) {
-               return 1;
-       }
+typedef struct SeqPreprocessCache {
+       int cfra;
+       ListBase elems;
+} SeqPreprocessCache;
 
-       if (a->motion_blur_shutter < b->motion_blur_shutter) {
-               return -1;
-       }
-       if (a->motion_blur_shutter > b->motion_blur_shutter) {
-               return 1;
-       }
+static struct MovieCache *moviecache = NULL;
+static struct SeqPreprocessCache *preprocess_cache = NULL;
 
-       if (a->motion_blur_samples < b->motion_blur_samples) {
-               return -1;
-       }
-       if (a->motion_blur_samples > b->motion_blur_samples) {
-               return 1;
-       }
+static void preprocessed_cache_destruct(void);
 
-       return 0;
+static bool seq_cmp_render_data(const SeqRenderData *a, const SeqRenderData *b)
+{
+       return ((a->preview_render_size != b->preview_render_size) ||
+               (a->rectx != b->rectx) ||
+               (a->recty != b->recty) ||
+               (a->bmain != b->bmain) ||
+               (a->scene != b->scene) ||
+               (a->motion_blur_shutter != b->motion_blur_shutter) ||
+               (a->motion_blur_samples != b->motion_blur_samples) ||
+               (a->scene->r.views_format != b->scene->r.views_format) ||
+               (a->view_id != b->view_id));
 }
 
 static unsigned int seq_hash_render_data(const SeqRenderData *a)
@@ -110,56 +92,41 @@ static unsigned int seq_hash_render_data(const SeqRenderData *a)
        rval ^= ((intptr_t) a->bmain) << 6;
        rval ^= ((intptr_t) a->scene) << 6;
        rval ^= (int)(a->motion_blur_shutter * 100.0f) << 10;
-       rval ^= a->motion_blur_samples << 24;
+       rval ^= a->motion_blur_samples << 16;
+       rval ^= ((a->scene->r.views_format * 2) + a->view_id) << 24;
 
        return rval;
 }
 
 static unsigned int seqcache_hashhash(const void *key_)
 {
-       const SeqCacheKey *key = (SeqCacheKey *) key_;
+       const SeqCacheKey *key = key_;
        unsigned int rval = seq_hash_render_data(&key->context);
 
-       rval ^= *(unsigned int *) &key->cfra;
+       rval ^= *(const unsigned int *) &key->cfra;
        rval += key->type;
        rval ^= ((intptr_t) key->seq) << 6;
 
        return rval;
 }
 
-static int seqcache_hashcmp(const void *a_, const void *b_)
+static bool seqcache_hashcmp(const void *a_, const void *b_)
 {
-       const SeqCacheKey *a = (SeqCacheKey *) a_;
-       const SeqCacheKey *b = (SeqCacheKey *) b_;
+       const SeqCacheKey *a = a_;
+       const SeqCacheKey *b = b_;
 
-       if (a->seq < b->seq) {
-               return -1;
-       }
-       if (a->seq > b->seq) {
-               return 1;
-       }
-
-       if (a->cfra < b->cfra) {
-               return -1;
-       }
-       if (a->cfra > b->cfra) {
-               return 1;
-       }
-
-       if (a->type < b->type) {
-               return -1;
-       }
-       if (a->type > b->type) {
-               return 1;
-       }
-
-       return seq_cmp_render_data(&a->context, &b->context);
+       return ((a->seq != b->seq) ||
+               (a->cfra != b->cfra) ||
+               (a->type != b->type) ||
+               seq_cmp_render_data(&a->context, &b->context));
 }
 
 void BKE_sequencer_cache_destruct(void)
 {
        if (moviecache)
                IMB_moviecache_free(moviecache);
+
+       preprocessed_cache_destruct();
 }
 
 void BKE_sequencer_cache_cleanup(void)
@@ -168,9 +135,11 @@ void BKE_sequencer_cache_cleanup(void)
                IMB_moviecache_free(moviecache);
                moviecache = IMB_moviecache_create("seqcache", sizeof(SeqCacheKey), seqcache_hashhash, seqcache_hashcmp);
        }
+
+       BKE_sequencer_preprocessed_cache_cleanup();
 }
 
-static int seqcache_key_check_seq(void *userkey, void *userdata)
+static bool seqcache_key_check_seq(ImBuf *UNUSED(ibuf), void *userkey, void *userdata)
 {
        SeqCacheKey *key = (SeqCacheKey *) userkey;
        Sequence *seq = (Sequence *) userdata;
@@ -184,13 +153,13 @@ void BKE_sequencer_cache_cleanup_sequence(Sequence *seq)
                IMB_moviecache_cleanup(moviecache, seqcache_key_check_seq, seq);
 }
 
-struct ImBuf *BKE_sequencer_cache_get(SeqRenderData context, Sequence *seq, float cfra, seq_stripelem_ibuf_t type)
+struct ImBuf *BKE_sequencer_cache_get(const SeqRenderData *context, Sequence *seq, float cfra, eSeqStripElemIBuf type)
 {
        if (moviecache && seq) {
                SeqCacheKey key;
 
                key.seq = seq;
-               key.context = context;
+               key.context = *context;
                key.cfra = cfra - seq->start;
                key.type = type;
 
@@ -200,11 +169,11 @@ struct ImBuf *BKE_sequencer_cache_get(SeqRenderData context, Sequence *seq, floa
        return NULL;
 }
 
-void BKE_sequencer_cache_put(SeqRenderData context, Sequence *seq, float cfra, seq_stripelem_ibuf_t type, ImBuf *i)
+void BKE_sequencer_cache_put(const SeqRenderData *context, Sequence *seq, float cfra, eSeqStripElemIBuf type, ImBuf *i)
 {
        SeqCacheKey key;
 
-       if (!i) {
+       if (i == NULL || context->skip_cache) {
                return;
        }
 
@@ -213,9 +182,106 @@ void BKE_sequencer_cache_put(SeqRenderData context, Sequence *seq, float cfra, s
        }
 
        key.seq = seq;
-       key.context = context;
+       key.context = *context;
        key.cfra = cfra - seq->start;
        key.type = type;
 
        IMB_moviecache_put(moviecache, &key, i);
 }
+
+void BKE_sequencer_preprocessed_cache_cleanup(void)
+{
+       SeqPreprocessCacheElem *elem;
+
+       if (!preprocess_cache)
+               return;
+
+       for (elem = preprocess_cache->elems.first; elem; elem = elem->next) {
+               IMB_freeImBuf(elem->ibuf);
+       }
+       BLI_freelistN(&preprocess_cache->elems);
+
+       BLI_listbase_clear(&preprocess_cache->elems);
+}
+
+static void preprocessed_cache_destruct(void)
+{
+       if (!preprocess_cache)
+               return;
+
+       BKE_sequencer_preprocessed_cache_cleanup();
+
+       MEM_freeN(preprocess_cache);
+       preprocess_cache = NULL;
+}
+
+ImBuf *BKE_sequencer_preprocessed_cache_get(const SeqRenderData *context, Sequence *seq, float cfra, eSeqStripElemIBuf type)
+{
+       SeqPreprocessCacheElem *elem;
+
+       if (!preprocess_cache)
+               return NULL;
+
+       if (preprocess_cache->cfra != cfra)
+               return NULL;
+
+       for (elem = preprocess_cache->elems.first; elem; elem = elem->next) {
+               if (elem->seq != seq)
+                       continue;
+
+               if (elem->type != type)
+                       continue;
+
+               if (seq_cmp_render_data(&elem->context, context) != 0)
+                       continue;
+
+               IMB_refImBuf(elem->ibuf);
+               return elem->ibuf;
+       }
+
+       return NULL;
+}
+
+void BKE_sequencer_preprocessed_cache_put(const SeqRenderData *context, Sequence *seq, float cfra, eSeqStripElemIBuf type, ImBuf *ibuf)
+{
+       SeqPreprocessCacheElem *elem;
+
+       if (!preprocess_cache) {
+               preprocess_cache = MEM_callocN(sizeof(SeqPreprocessCache), "sequencer preprocessed cache");
+       }
+       else {
+               if (preprocess_cache->cfra != cfra)
+                       BKE_sequencer_preprocessed_cache_cleanup();
+       }
+
+       elem = MEM_callocN(sizeof(SeqPreprocessCacheElem), "sequencer preprocessed cache element");
+
+       elem->seq = seq;
+       elem->type = type;
+       elem->context = *context;
+       elem->ibuf = ibuf;
+
+       preprocess_cache->cfra = cfra;
+
+       IMB_refImBuf(ibuf);
+
+       BLI_addtail(&preprocess_cache->elems, elem);
+}
+
+void BKE_sequencer_preprocessed_cache_cleanup_sequence(Sequence *seq)
+{
+       SeqPreprocessCacheElem *elem, *elem_next;
+
+       if (!preprocess_cache)
+               return;
+
+       for (elem = preprocess_cache->elems.first; elem; elem = elem_next) {
+               elem_next = elem->next;
+
+               if (elem->seq == seq) {
+                       IMB_freeImBuf(elem->ibuf);
+
+                       BLI_freelinkN(&preprocess_cache->elems, elem);
+               }
+       }
+}