Changeset View
Changeset View
Standalone View
Standalone View
source/blender/sequencer/intern/image_cache.c
| Show First 20 Lines • Show All 818 Lines • ▼ Show 20 Lines | static void seq_cache_valfree(void *val) | ||||
| if (item->ibuf) { | if (item->ibuf) { | ||||
| IMB_freeImBuf(item->ibuf); | IMB_freeImBuf(item->ibuf); | ||||
| } | } | ||||
| BLI_mempool_free(item->cache_owner->items_pool, item); | BLI_mempool_free(item->cache_owner->items_pool, item); | ||||
| } | } | ||||
| static void seq_cache_put_ex(SeqCache *cache, SeqCacheKey *key, ImBuf *ibuf) | static int get_stored_types_flag(Scene *scene, SeqCacheKey *key) | ||||
| { | { | ||||
| int flag; | |||||
| if (key->seq->cache_flag & SEQ_CACHE_OVERRIDE) { | |||||
| flag = key->seq->cache_flag; | |||||
| } | |||||
| else { | |||||
| flag = scene->ed->cache_flag; | |||||
| } | |||||
| /* SEQ_CACHE_STORE_FINAL_OUT can not be overridden by strip cache */ | |||||
| flag |= (scene->ed->cache_flag & SEQ_CACHE_STORE_FINAL_OUT); | |||||
| return flag; | |||||
| } | |||||
| static void seq_cache_put_ex(Scene *scene, SeqCacheKey *key, ImBuf *ibuf) | |||||
| { | |||||
| SeqCache *cache = seq_cache_get_from_scene(scene); | |||||
| SeqCacheItem *item; | SeqCacheItem *item; | ||||
| item = BLI_mempool_alloc(cache->items_pool); | item = BLI_mempool_alloc(cache->items_pool); | ||||
| item->cache_owner = cache; | item->cache_owner = cache; | ||||
| item->ibuf = ibuf; | item->ibuf = ibuf; | ||||
| const int stored_types_flag = get_stored_types_flag(scene, key); | |||||
| /* Item stored for later use. */ | |||||
| if (stored_types_flag & key->type) { | |||||
| key->is_temp_cache = false; | |||||
| key->link_prev = cache->last_key; | |||||
| } | |||||
| /* Store pointer to last cached key. */ | |||||
| SeqCacheKey *temp_last_key = cache->last_key; | |||||
| if (BLI_ghash_reinsert(cache->hash, key, item, seq_cache_keyfree, seq_cache_valfree)) { | if (BLI_ghash_reinsert(cache->hash, key, item, seq_cache_keyfree, seq_cache_valfree)) { | ||||
| IMB_refImBuf(ibuf); | IMB_refImBuf(ibuf); | ||||
| if (!key->is_temp_cache) { | |||||
| cache->last_key = key; | cache->last_key = key; | ||||
| } | } | ||||
| } | } | ||||
| /* Set last_key's reference to this key so we can look up chain backwards. | |||||
| * Item is already put in cache, so cache->last_key points to current key. | |||||
| */ | |||||
| if (!key->is_temp_cache && temp_last_key) { | |||||
| temp_last_key->link_next = cache->last_key; | |||||
| } | |||||
| /* Reset linking. */ | |||||
| if (key->type == SEQ_CACHE_STORE_FINAL_OUT) { | |||||
| cache->last_key = NULL; | |||||
| } | |||||
| } | |||||
| static ImBuf *seq_cache_get_ex(SeqCache *cache, SeqCacheKey *key) | static ImBuf *seq_cache_get_ex(SeqCache *cache, SeqCacheKey *key) | ||||
| { | { | ||||
| SeqCacheItem *item = BLI_ghash_lookup(cache->hash, key); | SeqCacheItem *item = BLI_ghash_lookup(cache->hash, key); | ||||
| if (item && item->ibuf) { | if (item && item->ibuf) { | ||||
| IMB_refImBuf(item->ibuf); | IMB_refImBuf(item->ibuf); | ||||
| return item->ibuf; | return item->ibuf; | ||||
| ▲ Show 20 Lines • Show All 242 Lines • ▼ Show 20 Lines | if (scene->ed->cache == NULL) { | ||||
| if (scene->ed->disk_cache_timestamp == 0) { | if (scene->ed->disk_cache_timestamp == 0) { | ||||
| scene->ed->disk_cache_timestamp = time(NULL); | scene->ed->disk_cache_timestamp = time(NULL); | ||||
| } | } | ||||
| } | } | ||||
| BLI_mutex_unlock(&cache_create_lock); | BLI_mutex_unlock(&cache_create_lock); | ||||
| } | } | ||||
| static void seq_cache_populate_key(SeqCacheKey *key, | |||||
| const SeqRenderData *context, | |||||
| Sequence *seq, | |||||
| const float timeline_frame, | |||||
| const int type) | |||||
| { | |||||
| key->cache_owner = seq_cache_get_from_scene(context->scene); | |||||
| key->seq = seq; | |||||
| key->context = *context; | |||||
| key->frame_index = seq_cache_timeline_frame_to_frame_index(seq, timeline_frame, type); | |||||
| key->timeline_frame = timeline_frame; | |||||
| key->type = type; | |||||
| key->link_prev = NULL; | |||||
| key->link_next = NULL; | |||||
| key->is_temp_cache = true; | |||||
| key->task_id = context->task_id; | |||||
| } | |||||
| static SeqCacheKey *seq_cache_allocate_key(SeqCache *cache, | |||||
| const SeqRenderData *context, | |||||
| Sequence *seq, | |||||
| const float timeline_frame, | |||||
| const int type) | |||||
| { | |||||
| SeqCacheKey *key = BLI_mempool_alloc(cache->keys_pool); | |||||
| seq_cache_populate_key(key, context, seq, timeline_frame, type); | |||||
| return key; | |||||
| } | |||||
| /* ***************************** API ****************************** */ | /* ***************************** API ****************************** */ | ||||
| void seq_cache_free_temp_cache(Scene *scene, short id, int timeline_frame) | void seq_cache_free_temp_cache(Scene *scene, short id, int timeline_frame) | ||||
| { | { | ||||
| SeqCache *cache = seq_cache_get_from_scene(scene); | SeqCache *cache = seq_cache_get_from_scene(scene); | ||||
| if (!cache) { | if (!cache) { | ||||
| return; | return; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 132 Lines • ▼ Show 20 Lines | void seq_cache_cleanup_sequence(Scene *scene, | ||||
| } | } | ||||
| cache->last_key = NULL; | cache->last_key = NULL; | ||||
| seq_cache_unlock(scene); | seq_cache_unlock(scene); | ||||
| } | } | ||||
| struct ImBuf *seq_cache_get(const SeqRenderData *context, | struct ImBuf *seq_cache_get(const SeqRenderData *context, | ||||
| Sequence *seq, | Sequence *seq, | ||||
| float timeline_frame, | float timeline_frame, | ||||
| int type, | int type) | ||||
| bool skip_disk_cache) | |||||
| { | { | ||||
| if (context->skip_cache || context->is_proxy_render || !seq) { | if (context->skip_cache || context->is_proxy_render || !seq) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| Scene *scene = context->scene; | Scene *scene = context->scene; | ||||
| Show All 13 Lines | struct ImBuf *seq_cache_get(const SeqRenderData *context, | ||||
| seq_cache_lock(scene); | seq_cache_lock(scene); | ||||
| SeqCache *cache = seq_cache_get_from_scene(scene); | SeqCache *cache = seq_cache_get_from_scene(scene); | ||||
| ImBuf *ibuf = NULL; | ImBuf *ibuf = NULL; | ||||
| SeqCacheKey key; | SeqCacheKey key; | ||||
| /* Try RAM cache: */ | /* Try RAM cache: */ | ||||
| if (cache && seq) { | if (cache && seq) { | ||||
| key.seq = seq; | seq_cache_populate_key(&key, context, seq, timeline_frame, type); | ||||
| key.context = *context; | |||||
| key.frame_index = seq_cache_timeline_frame_to_frame_index(seq, timeline_frame, type); | |||||
| key.type = type; | |||||
| ibuf = seq_cache_get_ex(cache, &key); | ibuf = seq_cache_get_ex(cache, &key); | ||||
| } | } | ||||
| seq_cache_unlock(scene); | seq_cache_unlock(scene); | ||||
| if (ibuf) { | if (ibuf) { | ||||
| return ibuf; | return ibuf; | ||||
| } | } | ||||
| /* Try disk cache: */ | /* Try disk cache: */ | ||||
| if (!skip_disk_cache && seq_disk_cache_is_enabled(context->bmain)) { | if (seq_disk_cache_is_enabled(context->bmain)) { | ||||
| if (cache->disk_cache == NULL) { | if (cache->disk_cache == NULL) { | ||||
| seq_disk_cache_create(context->bmain, context->scene); | seq_disk_cache_create(context->bmain, context->scene); | ||||
| } | } | ||||
| BLI_mutex_lock(&cache->disk_cache->read_write_mutex); | BLI_mutex_lock(&cache->disk_cache->read_write_mutex); | ||||
| ibuf = seq_disk_cache_read_file(cache->disk_cache, &key); | ibuf = seq_disk_cache_read_file(cache->disk_cache, &key); | ||||
| BLI_mutex_unlock(&cache->disk_cache->read_write_mutex); | BLI_mutex_unlock(&cache->disk_cache->read_write_mutex); | ||||
| if (ibuf) { | |||||
| if (key.type == SEQ_CACHE_STORE_FINAL_OUT) { | if (ibuf == NULL) { | ||||
| seq_cache_put_if_possible(context, seq, timeline_frame, type, ibuf, true); | return NULL; | ||||
| } | |||||
| else { | |||||
| seq_cache_put(context, seq, timeline_frame, type, ibuf, true); | |||||
| } | } | ||||
| /* Store read image in RAM. Only recycle item for final type. */ | |||||
| if (key.type != SEQ_CACHE_STORE_FINAL_OUT || seq_cache_recycle_item(scene)) { | |||||
| SeqCacheKey *new_key = seq_cache_allocate_key(cache, context, seq, timeline_frame, type); | |||||
| seq_cache_put_ex(scene, new_key, ibuf); | |||||
| } | } | ||||
| } | } | ||||
| return ibuf; | return ibuf; | ||||
| } | } | ||||
| bool seq_cache_put_if_possible(const SeqRenderData *context, | bool seq_cache_put_if_possible( | ||||
| Sequence *seq, | const SeqRenderData *context, Sequence *seq, float timeline_frame, int type, ImBuf *ibuf) | ||||
| float timeline_frame, | |||||
| int type, | |||||
| ImBuf *ibuf, | |||||
| bool skip_disk_cache) | |||||
| { | { | ||||
| Scene *scene = context->scene; | Scene *scene = context->scene; | ||||
| if (context->is_prefetch_render) { | if (context->is_prefetch_render) { | ||||
| context = seq_prefetch_get_original_context(context); | context = seq_prefetch_get_original_context(context); | ||||
| scene = context->scene; | scene = context->scene; | ||||
| seq = seq_prefetch_get_original_sequence(seq, scene); | seq = seq_prefetch_get_original_sequence(seq, scene); | ||||
| } | } | ||||
| if (!seq) { | if (!seq) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (seq_cache_recycle_item(scene)) { | if (seq_cache_recycle_item(scene)) { | ||||
| seq_cache_put(context, seq, timeline_frame, type, ibuf, skip_disk_cache); | seq_cache_put(context, seq, timeline_frame, type, ibuf); | ||||
| return true; | return true; | ||||
| } | } | ||||
| seq_cache_set_temp_cache_linked(scene, scene->ed->cache->last_key); | seq_cache_set_temp_cache_linked(scene, scene->ed->cache->last_key); | ||||
| scene->ed->cache->last_key = NULL; | scene->ed->cache->last_key = NULL; | ||||
| return false; | return false; | ||||
| } | } | ||||
| void seq_cache_put(const SeqRenderData *context, | void seq_cache_put( | ||||
| Sequence *seq, | const SeqRenderData *context, Sequence *seq, float timeline_frame, int type, ImBuf *i) | ||||
| float timeline_frame, | |||||
| int type, | |||||
| ImBuf *i, | |||||
| bool skip_disk_cache) | |||||
| { | { | ||||
| if (i == NULL || context->skip_cache || context->is_proxy_render || !seq) { | if (i == NULL || context->skip_cache || context->is_proxy_render || !seq) { | ||||
| return; | return; | ||||
| } | } | ||||
| Scene *scene = context->scene; | Scene *scene = context->scene; | ||||
| if (context->is_prefetch_render) { | if (context->is_prefetch_render) { | ||||
| context = seq_prefetch_get_original_context(context); | context = seq_prefetch_get_original_context(context); | ||||
| scene = context->scene; | scene = context->scene; | ||||
| seq = seq_prefetch_get_original_sequence(seq, scene); | seq = seq_prefetch_get_original_sequence(seq, scene); | ||||
| BLI_assert(seq != NULL); | BLI_assert(seq != NULL); | ||||
| } | } | ||||
| /* Prevent reinserting, it breaks cache key linking. */ | /* Prevent reinserting, it breaks cache key linking. */ | ||||
| ImBuf *test = seq_cache_get(context, seq, timeline_frame, type, true); | ImBuf *test = seq_cache_get(context, seq, timeline_frame, type); | ||||
| if (test) { | if (test) { | ||||
| IMB_freeImBuf(test); | IMB_freeImBuf(test); | ||||
| return; | return; | ||||
| } | } | ||||
| if (!scene->ed->cache) { | if (!scene->ed->cache) { | ||||
| seq_cache_create(context->bmain, scene); | seq_cache_create(context->bmain, scene); | ||||
| } | } | ||||
| seq_cache_lock(scene); | seq_cache_lock(scene); | ||||
| SeqCache *cache = seq_cache_get_from_scene(scene); | SeqCache *cache = seq_cache_get_from_scene(scene); | ||||
| int flag; | SeqCacheKey *key = seq_cache_allocate_key(cache, context, seq, timeline_frame, type); | ||||
| seq_cache_put_ex(scene, key, i); | |||||
| if (seq->cache_flag & SEQ_CACHE_OVERRIDE) { | |||||
| flag = seq->cache_flag; | |||||
| /* Final_out is invalid in context of sequence override. */ | |||||
| flag -= seq->cache_flag & SEQ_CACHE_STORE_FINAL_OUT; | |||||
| /* If global setting is enabled however, use it. */ | |||||
| flag |= scene->ed->cache_flag & SEQ_CACHE_STORE_FINAL_OUT; | |||||
| } | |||||
| else { | |||||
| flag = scene->ed->cache_flag; | |||||
| } | |||||
| SeqCacheKey *key; | |||||
| key = BLI_mempool_alloc(cache->keys_pool); | |||||
| key->cache_owner = cache; | |||||
| key->seq = seq; | |||||
| key->context = *context; | |||||
| key->frame_index = seq_cache_timeline_frame_to_frame_index(seq, timeline_frame, type); | |||||
| key->timeline_frame = timeline_frame; | |||||
| key->type = type; | |||||
| key->link_prev = NULL; | |||||
| key->link_next = NULL; | |||||
| key->is_temp_cache = true; | |||||
| key->task_id = context->task_id; | |||||
| /* Item stored for later use */ | |||||
| if (flag & type) { | |||||
| key->is_temp_cache = false; | |||||
| key->link_prev = cache->last_key; | |||||
| } | |||||
| SeqCacheKey *temp_last_key = cache->last_key; | |||||
| seq_cache_put_ex(cache, key, i); | |||||
| /* Restore pointer to previous item as this one will be freed when stack is rendered. */ | |||||
| if (key->is_temp_cache) { | |||||
| cache->last_key = temp_last_key; | |||||
| } | |||||
| /* Set last_key's reference to this key so we can look up chain backwards. | |||||
| * Item is already put in cache, so cache->last_key points to current key. | |||||
| */ | |||||
| if (flag & type && temp_last_key) { | |||||
| temp_last_key->link_next = cache->last_key; | |||||
| } | |||||
| /* Reset linking. */ | |||||
| if (key->type == SEQ_CACHE_STORE_FINAL_OUT) { | |||||
| cache->last_key = NULL; | |||||
| } | |||||
| seq_cache_unlock(scene); | seq_cache_unlock(scene); | ||||
| if (!key->is_temp_cache && !skip_disk_cache) { | if (!key->is_temp_cache) { | ||||
| if (seq_disk_cache_is_enabled(context->bmain)) { | if (seq_disk_cache_is_enabled(context->bmain)) { | ||||
| if (cache->disk_cache == NULL) { | if (cache->disk_cache == NULL) { | ||||
| seq_disk_cache_create(context->bmain, context->scene); | seq_disk_cache_create(context->bmain, context->scene); | ||||
| } | } | ||||
| BLI_mutex_lock(&cache->disk_cache->read_write_mutex); | BLI_mutex_lock(&cache->disk_cache->read_write_mutex); | ||||
| seq_disk_cache_write_file(cache->disk_cache, key, i); | seq_disk_cache_write_file(cache->disk_cache, key, i); | ||||
| BLI_mutex_unlock(&cache->disk_cache->read_write_mutex); | BLI_mutex_unlock(&cache->disk_cache->read_write_mutex); | ||||
| Show All 37 Lines | |||||