tornavis/source/blender/imbuf/intern/moviecache.cc

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

612 lines
15 KiB
C++
Raw Normal View History

/* SPDX-FileCopyrightText: 2011 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bke
*/
#undef DEBUG_MESSAGES
2022-03-14 16:55:17 +01:00
#include <cstdlib> /* for qsort */
#include <memory.h>
#include <mutex>
#include "MEM_CacheLimiterC-Api.h"
#include "MEM_guardedalloc.h"
#include "BLI_ghash.h"
#include "BLI_mempool.h"
#include "BLI_string.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
#include "IMB_moviecache.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#ifdef DEBUG_MESSAGES
# if defined __GNUC__
# define PRINT(format, args...) printf(format, ##args)
# else
# define PRINT(format, ...) printf(__VA_ARGS__)
# endif
#else
# define PRINT(format, ...)
#endif
2022-03-14 16:55:17 +01:00
static MEM_CacheLimiterC *limitor = nullptr;
/* Image buffers managed by a moviecache might be using their own movie caches (used by color
* management). In practice this means that, for example, freeing MovieCache used by MovieClip
* will request freeing MovieCache owned by ImBuf. Freeing MovieCache needs to be thread-safe,
* so regular mutex will not work here, hence the recursive lock. */
static std::recursive_mutex limitor_lock;
2022-03-14 16:55:17 +01:00
struct MovieCache {
char name[64];
GHash *hash;
GHashHashFP hashfp;
GHashCmpFP cmpfp;
MovieCacheGetKeyDataFP getdatafp;
MovieCacheGetPriorityDataFP getprioritydatafp;
MovieCacheGetItemPriorityFP getitempriorityfp;
MovieCachePriorityDeleterFP prioritydeleterfp;
BLI_mempool *keys_pool;
BLI_mempool *items_pool;
BLI_mempool *userkeys_pool;
int keysize;
void *last_userkey;
2012-05-16 11:26:37 +02:00
int totseg, *points, proxy, render_flags; /* for visual statistics optimization */
int pad;
2022-03-14 16:55:17 +01:00
};
2022-03-14 16:55:17 +01:00
struct MovieCacheKey {
MovieCache *cache_owner;
void *userkey;
2022-03-14 16:55:17 +01:00
};
2022-03-14 16:55:17 +01:00
struct MovieCacheItem {
MovieCache *cache_owner;
ImBuf *ibuf;
2012-05-16 11:26:37 +02:00
MEM_CacheLimiterHandleC *c_handle;
void *priority_data;
/* Indicates that #ibuf is null, because there was an error during load. */
bool added_empty;
2022-03-14 16:55:17 +01:00
};
static uint moviecache_hashhash(const void *keyv)
{
2022-03-14 11:28:45 +01:00
const MovieCacheKey *key = (const MovieCacheKey *)keyv;
return key->cache_owner->hashfp(key->userkey);
}
static bool moviecache_hashcmp(const void *av, const void *bv)
{
2022-03-14 11:28:45 +01:00
const MovieCacheKey *a = (const MovieCacheKey *)av;
const MovieCacheKey *b = (const MovieCacheKey *)bv;
return a->cache_owner->cmpfp(a->userkey, b->userkey);
}
static void moviecache_keyfree(void *val)
{
2022-03-14 11:28:45 +01:00
MovieCacheKey *key = (MovieCacheKey *)val;
BLI_mempool_free(key->cache_owner->userkeys_pool, key->userkey);
BLI_mempool_free(key->cache_owner->keys_pool, key);
}
static void moviecache_valfree(void *val)
{
2012-05-16 11:26:37 +02:00
MovieCacheItem *item = (MovieCacheItem *)val;
MovieCache *cache = item->cache_owner;
PRINT("%s: cache '%s' free item %p buffer %p\n", __func__, cache->name, item, item->ibuf);
if (item->c_handle) {
limitor_lock.lock();
MEM_CacheLimiter_unmanage(item->c_handle);
limitor_lock.unlock();
}
if (item->ibuf) {
IMB_freeImBuf(item->ibuf);
}
if (item->priority_data && cache->prioritydeleterfp) {
cache->prioritydeleterfp(item->priority_data);
}
BLI_mempool_free(item->cache_owner->items_pool, item);
}
static void check_unused_keys(MovieCache *cache)
{
2015-02-06 05:31:08 +01:00
GHashIterator gh_iter;
BLI_ghashIterator_init(&gh_iter, cache->hash);
while (!BLI_ghashIterator_done(&gh_iter)) {
2022-03-14 11:28:45 +01:00
const MovieCacheKey *key = (const MovieCacheKey *)BLI_ghashIterator_getKey(&gh_iter);
const MovieCacheItem *item = (const MovieCacheItem *)BLI_ghashIterator_getValue(&gh_iter);
BLI_ghashIterator_step(&gh_iter);
if (item->added_empty) {
/* Don't remove entries that have been added empty. Those indicate that the image couldn't be
* loaded correctly. */
continue;
}
bool remove = !item->ibuf;
if (remove) {
PRINT("%s: cache '%s' remove item %p without buffer\n", __func__, cache->name, item);
}
2019-04-23 03:01:30 +02:00
if (remove) {
BLI_ghash_remove(cache->hash, key, moviecache_keyfree, moviecache_valfree);
2019-04-23 03:01:30 +02:00
}
}
}
static int compare_int(const void *av, const void *bv)
{
2022-03-14 11:28:45 +01:00
const int *a = (int *)av;
const int *b = (int *)bv;
2012-03-26 18:04:10 +02:00
return *a - *b;
}
static void moviecache_destructor(void *p)
{
MovieCacheItem *item = (MovieCacheItem *)p;
if (item && item->ibuf) {
MovieCache *cache = item->cache_owner;
PRINT("%s: cache '%s' destroy item %p buffer %p\n", __func__, cache->name, item, item->ibuf);
IMB_freeImBuf(item->ibuf);
2022-03-14 16:55:17 +01:00
item->ibuf = nullptr;
item->c_handle = nullptr;
/* force cached segments to be updated */
2021-08-06 05:59:38 +02:00
MEM_SAFE_FREE(cache->points);
}
}
static size_t get_size_in_memory(ImBuf *ibuf)
{
/* Keep textures in the memory to avoid constant file reload on viewport update. */
if (ibuf->userflags & IB_PERSISTENT) {
return 0;
}
return IMB_get_size_in_memory(ibuf);
}
2012-05-16 11:26:37 +02:00
static size_t get_item_size(void *p)
{
2012-03-26 18:04:10 +02:00
size_t size = sizeof(MovieCacheItem);
MovieCacheItem *item = (MovieCacheItem *)p;
2019-04-23 03:01:30 +02:00
if (item->ibuf) {
size += get_size_in_memory(item->ibuf);
2019-04-23 03:01:30 +02:00
}
return size;
}
static int get_item_priority(void *item_v, int default_priority)
{
MovieCacheItem *item = (MovieCacheItem *)item_v;
MovieCache *cache = item->cache_owner;
int priority;
if (!cache->getitempriorityfp) {
PRINT("%s: cache '%s' item %p use default priority %d\n",
__func__,
cache->name,
item,
default_priority);
return default_priority;
}
priority = cache->getitempriorityfp(cache->last_userkey, item->priority_data);
PRINT("%s: cache '%s' item %p priority %d\n", __func__, cache->name, item, priority);
return priority;
}
static bool get_item_destroyable(void *item_v)
{
MovieCacheItem *item = (MovieCacheItem *)item_v;
2022-03-14 16:55:17 +01:00
if (item->ibuf == nullptr) {
return true;
}
/* IB_BITMAPDIRTY means image was modified from inside blender and
* changes are not saved to disk.
*
* Such buffers are never to be freed.
*/
if ((item->ibuf->userflags & IB_BITMAPDIRTY) || (item->ibuf->userflags & IB_PERSISTENT)) {
return false;
}
return true;
}
void IMB_moviecache_init()
{
limitor = new_MEM_CacheLimiter(moviecache_destructor, get_item_size);
MEM_CacheLimiter_ItemPriority_Func_set(limitor, get_item_priority);
MEM_CacheLimiter_ItemDestroyable_Func_set(limitor, get_item_destroyable);
}
void IMB_moviecache_destruct()
{
2019-04-23 03:01:30 +02:00
if (limitor) {
delete_MEM_CacheLimiter(limitor);
2022-03-14 16:55:17 +01:00
limitor = nullptr;
2019-04-23 03:01:30 +02:00
}
}
MovieCache *IMB_moviecache_create(const char *name,
int keysize,
GHashHashFP hashfp,
GHashCmpFP cmpfp)
2012-05-18 01:21:11 +02:00
{
MovieCache *cache;
PRINT("%s: cache '%s' create\n", __func__, name);
2022-03-14 11:28:45 +01:00
cache = (MovieCache *)MEM_callocN(sizeof(MovieCache), "MovieCache");
2023-05-09 04:50:37 +02:00
STRNCPY(cache->name, name);
cache->keys_pool = BLI_mempool_create(sizeof(MovieCacheKey), 0, 64, BLI_MEMPOOL_NOP);
cache->items_pool = BLI_mempool_create(sizeof(MovieCacheItem), 0, 64, BLI_MEMPOOL_NOP);
cache->userkeys_pool = BLI_mempool_create(keysize, 0, 64, BLI_MEMPOOL_NOP);
2012-03-26 18:04:10 +02:00
cache->hash = BLI_ghash_new(
moviecache_hashhash, moviecache_hashcmp, "MovieClip ImBuf cache hash");
2012-03-26 18:04:10 +02:00
cache->keysize = keysize;
cache->hashfp = hashfp;
cache->cmpfp = cmpfp;
cache->proxy = -1;
return cache;
}
void IMB_moviecache_set_getdata_callback(MovieCache *cache, MovieCacheGetKeyDataFP getdatafp)
{
cache->getdatafp = getdatafp;
}
void IMB_moviecache_set_priority_callback(MovieCache *cache,
MovieCacheGetPriorityDataFP getprioritydatafp,
MovieCacheGetItemPriorityFP getitempriorityfp,
MovieCachePriorityDeleterFP prioritydeleterfp)
{
cache->last_userkey = MEM_mallocN(cache->keysize, "movie cache last user key");
cache->getprioritydatafp = getprioritydatafp;
cache->getitempriorityfp = getitempriorityfp;
cache->prioritydeleterfp = prioritydeleterfp;
}
static void do_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf, bool need_lock)
{
MovieCacheKey *key;
MovieCacheItem *item;
2019-04-23 03:01:30 +02:00
if (!limitor) {
IMB_moviecache_init();
2019-04-23 03:01:30 +02:00
}
2022-03-14 16:55:17 +01:00
if (ibuf != nullptr) {
IMB_refImBuf(ibuf);
}
2022-03-14 11:28:45 +01:00
key = (MovieCacheKey *)BLI_mempool_alloc(cache->keys_pool);
2012-03-26 18:04:10 +02:00
key->cache_owner = cache;
key->userkey = BLI_mempool_alloc(cache->userkeys_pool);
memcpy(key->userkey, userkey, cache->keysize);
2022-03-14 11:28:45 +01:00
item = (MovieCacheItem *)BLI_mempool_alloc(cache->items_pool);
PRINT("%s: cache '%s' put %p, item %p\n", __func__, cache->name, ibuf, item);
2012-03-26 18:04:10 +02:00
item->ibuf = ibuf;
item->cache_owner = cache;
2022-03-14 16:55:17 +01:00
item->c_handle = nullptr;
item->priority_data = nullptr;
item->added_empty = ibuf == nullptr;
if (cache->getprioritydatafp) {
item->priority_data = cache->getprioritydatafp(userkey);
}
BLI_ghash_reinsert(cache->hash, key, item, moviecache_keyfree, moviecache_valfree);
if (cache->last_userkey) {
memcpy(cache->last_userkey, userkey, cache->keysize);
}
2019-04-23 03:01:30 +02:00
if (need_lock) {
limitor_lock.lock();
2019-04-23 03:01:30 +02:00
}
item->c_handle = MEM_CacheLimiter_insert(limitor, item);
MEM_CacheLimiter_ref(item->c_handle);
MEM_CacheLimiter_enforce_limits(limitor);
MEM_CacheLimiter_unref(item->c_handle);
2019-04-23 03:01:30 +02:00
if (need_lock) {
limitor_lock.unlock();
2019-04-23 03:01:30 +02:00
}
/* cache limiter can't remove unused keys which points to destroyed values */
check_unused_keys(cache);
2021-08-06 05:59:38 +02:00
MEM_SAFE_FREE(cache->points);
}
Prefetching for movie clips This commit basically implements frames prefetching for movie clip datablock. Number of frames to be prefetched is controlled in User Preferences, System tab, Prefetch Frames option. Currently prefetching is destructive-less for movie cache, meaning mo frames will be removed from the cache when while prefetching. This is because it's half of simplier to implement, but it also makes sense from tracking point of view -- we could want to playback in both directions and removing frames from behind time cursor is not always a good idea. Anyway, smarter prefetching strategy could be developed later. Some implementation notes: - Added MEM_CacheLimiter_get_memory_in_use function to get memory usage of specified memory limiter. - Fixed prototype of MEM_CacheLimiter_get_maximum which was simply wrong (used wrong data type for output). - Added some utility functions to movie clip and movie cache for direct cache interaction and obtaining cache statistics. - Prefetching is implemented using general jobs system. which is invoking from clip draw function. - Prefetcing will stop as soon other job or playback starts. This is done from performance point of view. Jobs will likely require lots of CPU power and better to provide whole CPU to it. Playback is a bit more complicated case. For jpeg sequence playback prefetching while paying back is nice. But trying to prefetch heavy exr images and doing color space conversion slows down both playback and prefetching. TODO: - Think of better policy of dealing with already cached frames (like when cached frames from other clips prevents frames from current clip to be prefetched) - Currently a bit funky redraw notification happens from prefetch job. Perhaps own ND_ is better to have here. - Hiding clip while prefetch is active in theory shall stop prefetching job. - Having multiple clips opened on file load will prefetch frames for only one of them.
2013-03-20 18:03:20 +01:00
void IMB_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf)
{
do_moviecache_put(cache, userkey, ibuf, true);
Prefetching for movie clips This commit basically implements frames prefetching for movie clip datablock. Number of frames to be prefetched is controlled in User Preferences, System tab, Prefetch Frames option. Currently prefetching is destructive-less for movie cache, meaning mo frames will be removed from the cache when while prefetching. This is because it's half of simplier to implement, but it also makes sense from tracking point of view -- we could want to playback in both directions and removing frames from behind time cursor is not always a good idea. Anyway, smarter prefetching strategy could be developed later. Some implementation notes: - Added MEM_CacheLimiter_get_memory_in_use function to get memory usage of specified memory limiter. - Fixed prototype of MEM_CacheLimiter_get_maximum which was simply wrong (used wrong data type for output). - Added some utility functions to movie clip and movie cache for direct cache interaction and obtaining cache statistics. - Prefetching is implemented using general jobs system. which is invoking from clip draw function. - Prefetcing will stop as soon other job or playback starts. This is done from performance point of view. Jobs will likely require lots of CPU power and better to provide whole CPU to it. Playback is a bit more complicated case. For jpeg sequence playback prefetching while paying back is nice. But trying to prefetch heavy exr images and doing color space conversion slows down both playback and prefetching. TODO: - Think of better policy of dealing with already cached frames (like when cached frames from other clips prevents frames from current clip to be prefetched) - Currently a bit funky redraw notification happens from prefetch job. Perhaps own ND_ is better to have here. - Hiding clip while prefetch is active in theory shall stop prefetching job. - Having multiple clips opened on file load will prefetch frames for only one of them.
2013-03-20 18:03:20 +01:00
}
2014-02-03 08:55:59 +01:00
bool IMB_moviecache_put_if_possible(MovieCache *cache, void *userkey, ImBuf *ibuf)
Prefetching for movie clips This commit basically implements frames prefetching for movie clip datablock. Number of frames to be prefetched is controlled in User Preferences, System tab, Prefetch Frames option. Currently prefetching is destructive-less for movie cache, meaning mo frames will be removed from the cache when while prefetching. This is because it's half of simplier to implement, but it also makes sense from tracking point of view -- we could want to playback in both directions and removing frames from behind time cursor is not always a good idea. Anyway, smarter prefetching strategy could be developed later. Some implementation notes: - Added MEM_CacheLimiter_get_memory_in_use function to get memory usage of specified memory limiter. - Fixed prototype of MEM_CacheLimiter_get_maximum which was simply wrong (used wrong data type for output). - Added some utility functions to movie clip and movie cache for direct cache interaction and obtaining cache statistics. - Prefetching is implemented using general jobs system. which is invoking from clip draw function. - Prefetcing will stop as soon other job or playback starts. This is done from performance point of view. Jobs will likely require lots of CPU power and better to provide whole CPU to it. Playback is a bit more complicated case. For jpeg sequence playback prefetching while paying back is nice. But trying to prefetch heavy exr images and doing color space conversion slows down both playback and prefetching. TODO: - Think of better policy of dealing with already cached frames (like when cached frames from other clips prevents frames from current clip to be prefetched) - Currently a bit funky redraw notification happens from prefetch job. Perhaps own ND_ is better to have here. - Hiding clip while prefetch is active in theory shall stop prefetching job. - Having multiple clips opened on file load will prefetch frames for only one of them.
2013-03-20 18:03:20 +01:00
{
size_t mem_in_use, mem_limit, elem_size;
2014-02-03 08:55:59 +01:00
bool result = false;
Prefetching for movie clips This commit basically implements frames prefetching for movie clip datablock. Number of frames to be prefetched is controlled in User Preferences, System tab, Prefetch Frames option. Currently prefetching is destructive-less for movie cache, meaning mo frames will be removed from the cache when while prefetching. This is because it's half of simplier to implement, but it also makes sense from tracking point of view -- we could want to playback in both directions and removing frames from behind time cursor is not always a good idea. Anyway, smarter prefetching strategy could be developed later. Some implementation notes: - Added MEM_CacheLimiter_get_memory_in_use function to get memory usage of specified memory limiter. - Fixed prototype of MEM_CacheLimiter_get_maximum which was simply wrong (used wrong data type for output). - Added some utility functions to movie clip and movie cache for direct cache interaction and obtaining cache statistics. - Prefetching is implemented using general jobs system. which is invoking from clip draw function. - Prefetcing will stop as soon other job or playback starts. This is done from performance point of view. Jobs will likely require lots of CPU power and better to provide whole CPU to it. Playback is a bit more complicated case. For jpeg sequence playback prefetching while paying back is nice. But trying to prefetch heavy exr images and doing color space conversion slows down both playback and prefetching. TODO: - Think of better policy of dealing with already cached frames (like when cached frames from other clips prevents frames from current clip to be prefetched) - Currently a bit funky redraw notification happens from prefetch job. Perhaps own ND_ is better to have here. - Hiding clip while prefetch is active in theory shall stop prefetching job. - Having multiple clips opened on file load will prefetch frames for only one of them.
2013-03-20 18:03:20 +01:00
2022-03-14 16:55:17 +01:00
elem_size = (ibuf == nullptr) ? 0 : get_size_in_memory(ibuf);
Prefetching for movie clips This commit basically implements frames prefetching for movie clip datablock. Number of frames to be prefetched is controlled in User Preferences, System tab, Prefetch Frames option. Currently prefetching is destructive-less for movie cache, meaning mo frames will be removed from the cache when while prefetching. This is because it's half of simplier to implement, but it also makes sense from tracking point of view -- we could want to playback in both directions and removing frames from behind time cursor is not always a good idea. Anyway, smarter prefetching strategy could be developed later. Some implementation notes: - Added MEM_CacheLimiter_get_memory_in_use function to get memory usage of specified memory limiter. - Fixed prototype of MEM_CacheLimiter_get_maximum which was simply wrong (used wrong data type for output). - Added some utility functions to movie clip and movie cache for direct cache interaction and obtaining cache statistics. - Prefetching is implemented using general jobs system. which is invoking from clip draw function. - Prefetcing will stop as soon other job or playback starts. This is done from performance point of view. Jobs will likely require lots of CPU power and better to provide whole CPU to it. Playback is a bit more complicated case. For jpeg sequence playback prefetching while paying back is nice. But trying to prefetch heavy exr images and doing color space conversion slows down both playback and prefetching. TODO: - Think of better policy of dealing with already cached frames (like when cached frames from other clips prevents frames from current clip to be prefetched) - Currently a bit funky redraw notification happens from prefetch job. Perhaps own ND_ is better to have here. - Hiding clip while prefetch is active in theory shall stop prefetching job. - Having multiple clips opened on file load will prefetch frames for only one of them.
2013-03-20 18:03:20 +01:00
mem_limit = MEM_CacheLimiter_get_maximum();
limitor_lock.lock();
Prefetching for movie clips This commit basically implements frames prefetching for movie clip datablock. Number of frames to be prefetched is controlled in User Preferences, System tab, Prefetch Frames option. Currently prefetching is destructive-less for movie cache, meaning mo frames will be removed from the cache when while prefetching. This is because it's half of simplier to implement, but it also makes sense from tracking point of view -- we could want to playback in both directions and removing frames from behind time cursor is not always a good idea. Anyway, smarter prefetching strategy could be developed later. Some implementation notes: - Added MEM_CacheLimiter_get_memory_in_use function to get memory usage of specified memory limiter. - Fixed prototype of MEM_CacheLimiter_get_maximum which was simply wrong (used wrong data type for output). - Added some utility functions to movie clip and movie cache for direct cache interaction and obtaining cache statistics. - Prefetching is implemented using general jobs system. which is invoking from clip draw function. - Prefetcing will stop as soon other job or playback starts. This is done from performance point of view. Jobs will likely require lots of CPU power and better to provide whole CPU to it. Playback is a bit more complicated case. For jpeg sequence playback prefetching while paying back is nice. But trying to prefetch heavy exr images and doing color space conversion slows down both playback and prefetching. TODO: - Think of better policy of dealing with already cached frames (like when cached frames from other clips prevents frames from current clip to be prefetched) - Currently a bit funky redraw notification happens from prefetch job. Perhaps own ND_ is better to have here. - Hiding clip while prefetch is active in theory shall stop prefetching job. - Having multiple clips opened on file load will prefetch frames for only one of them.
2013-03-20 18:03:20 +01:00
mem_in_use = MEM_CacheLimiter_get_memory_in_use(limitor);
if (mem_in_use + elem_size <= mem_limit) {
do_moviecache_put(cache, userkey, ibuf, false);
result = true;
Prefetching for movie clips This commit basically implements frames prefetching for movie clip datablock. Number of frames to be prefetched is controlled in User Preferences, System tab, Prefetch Frames option. Currently prefetching is destructive-less for movie cache, meaning mo frames will be removed from the cache when while prefetching. This is because it's half of simplier to implement, but it also makes sense from tracking point of view -- we could want to playback in both directions and removing frames from behind time cursor is not always a good idea. Anyway, smarter prefetching strategy could be developed later. Some implementation notes: - Added MEM_CacheLimiter_get_memory_in_use function to get memory usage of specified memory limiter. - Fixed prototype of MEM_CacheLimiter_get_maximum which was simply wrong (used wrong data type for output). - Added some utility functions to movie clip and movie cache for direct cache interaction and obtaining cache statistics. - Prefetching is implemented using general jobs system. which is invoking from clip draw function. - Prefetcing will stop as soon other job or playback starts. This is done from performance point of view. Jobs will likely require lots of CPU power and better to provide whole CPU to it. Playback is a bit more complicated case. For jpeg sequence playback prefetching while paying back is nice. But trying to prefetch heavy exr images and doing color space conversion slows down both playback and prefetching. TODO: - Think of better policy of dealing with already cached frames (like when cached frames from other clips prevents frames from current clip to be prefetched) - Currently a bit funky redraw notification happens from prefetch job. Perhaps own ND_ is better to have here. - Hiding clip while prefetch is active in theory shall stop prefetching job. - Having multiple clips opened on file load will prefetch frames for only one of them.
2013-03-20 18:03:20 +01:00
}
limitor_lock.unlock();
Prefetching for movie clips This commit basically implements frames prefetching for movie clip datablock. Number of frames to be prefetched is controlled in User Preferences, System tab, Prefetch Frames option. Currently prefetching is destructive-less for movie cache, meaning mo frames will be removed from the cache when while prefetching. This is because it's half of simplier to implement, but it also makes sense from tracking point of view -- we could want to playback in both directions and removing frames from behind time cursor is not always a good idea. Anyway, smarter prefetching strategy could be developed later. Some implementation notes: - Added MEM_CacheLimiter_get_memory_in_use function to get memory usage of specified memory limiter. - Fixed prototype of MEM_CacheLimiter_get_maximum which was simply wrong (used wrong data type for output). - Added some utility functions to movie clip and movie cache for direct cache interaction and obtaining cache statistics. - Prefetching is implemented using general jobs system. which is invoking from clip draw function. - Prefetcing will stop as soon other job or playback starts. This is done from performance point of view. Jobs will likely require lots of CPU power and better to provide whole CPU to it. Playback is a bit more complicated case. For jpeg sequence playback prefetching while paying back is nice. But trying to prefetch heavy exr images and doing color space conversion slows down both playback and prefetching. TODO: - Think of better policy of dealing with already cached frames (like when cached frames from other clips prevents frames from current clip to be prefetched) - Currently a bit funky redraw notification happens from prefetch job. Perhaps own ND_ is better to have here. - Hiding clip while prefetch is active in theory shall stop prefetching job. - Having multiple clips opened on file load will prefetch frames for only one of them.
2013-03-20 18:03:20 +01:00
return result;
}
Add support for tiled images and the UDIM naming scheme This patch contains the work that I did during my week at the Code Quest - adding support for tiled images to Blender. With this patch, images now contain a list of tiles. By default, this just contains one tile, but if the source type is set to Tiled, the user can add additional tiles. When acquiring an ImBuf, the tile to be loaded is specified in the ImageUser. Therefore, code that is not yet aware of tiles will just access the default tile as usual. The filenames of the additional tiles are derived from the original filename according to the UDIM naming scheme - the filename contains an index that is calculated as (1001 + 10*<y coordinate of the tile> + <x coordinate of the tile>), where the x coordinate never goes above 9. Internally, the various tiles are stored in a cache just like sequences. When acquired for the first time, the code will try to load the corresponding file from disk. Alternatively, a new operator can be used to initialize the tile similar to the New Image operator. The following features are supported so far: - Automatic detection and loading of all tiles when opening the first tile (1001) - Saving all tiles - Adding and removing tiles - Filling tiles with generated images - Drawing all tiles in the Image Editor - Viewing a tiled grid even if no image is selected - Rendering tiled images in Eevee - Rendering tiled images in Cycles (in SVM mode) - Automatically skipping loading of unused tiles in Cycles - 2D texture painting (also across tiles) - 3D texture painting (also across tiles, only limitation: individual faces can not cross tile borders) - Assigning custom labels to individual tiles (drawn in the Image Editor instead of the ID) - Different resolutions between tiles There still are some missing features that will be added later (see T72390): - Workbench engine support - Packing/Unpacking support - Baking support - Cycles OSL support - many other Blender features that rely on images Thanks to Brecht for the review and to all who tested the intermediate versions! Differential Revision: https://developer.blender.org/D3509
2019-12-12 16:06:08 +01:00
void IMB_moviecache_remove(MovieCache *cache, void *userkey)
{
MovieCacheKey key;
key.cache_owner = cache;
key.userkey = userkey;
BLI_ghash_remove(cache->hash, &key, moviecache_keyfree, moviecache_valfree);
}
ImBuf *IMB_moviecache_get(MovieCache *cache, void *userkey, bool *r_is_cached_empty)
{
MovieCacheKey key;
MovieCacheItem *item;
2012-03-26 18:04:10 +02:00
key.cache_owner = cache;
key.userkey = userkey;
2012-05-16 11:26:37 +02:00
item = (MovieCacheItem *)BLI_ghash_lookup(cache->hash, &key);
if (r_is_cached_empty) {
*r_is_cached_empty = false;
}
if (item) {
if (item->ibuf) {
limitor_lock.lock();
MEM_CacheLimiter_touch(item->c_handle);
limitor_lock.unlock();
IMB_refImBuf(item->ibuf);
return item->ibuf;
}
if (r_is_cached_empty) {
*r_is_cached_empty = true;
}
}
2022-03-14 16:55:17 +01:00
return nullptr;
}
2014-02-03 08:55:59 +01:00
bool IMB_moviecache_has_frame(MovieCache *cache, void *userkey)
Prefetching for movie clips This commit basically implements frames prefetching for movie clip datablock. Number of frames to be prefetched is controlled in User Preferences, System tab, Prefetch Frames option. Currently prefetching is destructive-less for movie cache, meaning mo frames will be removed from the cache when while prefetching. This is because it's half of simplier to implement, but it also makes sense from tracking point of view -- we could want to playback in both directions and removing frames from behind time cursor is not always a good idea. Anyway, smarter prefetching strategy could be developed later. Some implementation notes: - Added MEM_CacheLimiter_get_memory_in_use function to get memory usage of specified memory limiter. - Fixed prototype of MEM_CacheLimiter_get_maximum which was simply wrong (used wrong data type for output). - Added some utility functions to movie clip and movie cache for direct cache interaction and obtaining cache statistics. - Prefetching is implemented using general jobs system. which is invoking from clip draw function. - Prefetcing will stop as soon other job or playback starts. This is done from performance point of view. Jobs will likely require lots of CPU power and better to provide whole CPU to it. Playback is a bit more complicated case. For jpeg sequence playback prefetching while paying back is nice. But trying to prefetch heavy exr images and doing color space conversion slows down both playback and prefetching. TODO: - Think of better policy of dealing with already cached frames (like when cached frames from other clips prevents frames from current clip to be prefetched) - Currently a bit funky redraw notification happens from prefetch job. Perhaps own ND_ is better to have here. - Hiding clip while prefetch is active in theory shall stop prefetching job. - Having multiple clips opened on file load will prefetch frames for only one of them.
2013-03-20 18:03:20 +01:00
{
MovieCacheKey key;
MovieCacheItem *item;
key.cache_owner = cache;
key.userkey = userkey;
item = (MovieCacheItem *)BLI_ghash_lookup(cache->hash, &key);
2022-03-14 16:55:17 +01:00
return item != nullptr;
Prefetching for movie clips This commit basically implements frames prefetching for movie clip datablock. Number of frames to be prefetched is controlled in User Preferences, System tab, Prefetch Frames option. Currently prefetching is destructive-less for movie cache, meaning mo frames will be removed from the cache when while prefetching. This is because it's half of simplier to implement, but it also makes sense from tracking point of view -- we could want to playback in both directions and removing frames from behind time cursor is not always a good idea. Anyway, smarter prefetching strategy could be developed later. Some implementation notes: - Added MEM_CacheLimiter_get_memory_in_use function to get memory usage of specified memory limiter. - Fixed prototype of MEM_CacheLimiter_get_maximum which was simply wrong (used wrong data type for output). - Added some utility functions to movie clip and movie cache for direct cache interaction and obtaining cache statistics. - Prefetching is implemented using general jobs system. which is invoking from clip draw function. - Prefetcing will stop as soon other job or playback starts. This is done from performance point of view. Jobs will likely require lots of CPU power and better to provide whole CPU to it. Playback is a bit more complicated case. For jpeg sequence playback prefetching while paying back is nice. But trying to prefetch heavy exr images and doing color space conversion slows down both playback and prefetching. TODO: - Think of better policy of dealing with already cached frames (like when cached frames from other clips prevents frames from current clip to be prefetched) - Currently a bit funky redraw notification happens from prefetch job. Perhaps own ND_ is better to have here. - Hiding clip while prefetch is active in theory shall stop prefetching job. - Having multiple clips opened on file load will prefetch frames for only one of them.
2013-03-20 18:03:20 +01:00
}
void IMB_moviecache_free(MovieCache *cache)
{
PRINT("%s: cache '%s' free\n", __func__, cache->name);
BLI_ghash_free(cache->hash, moviecache_keyfree, moviecache_valfree);
BLI_mempool_destroy(cache->keys_pool);
BLI_mempool_destroy(cache->items_pool);
BLI_mempool_destroy(cache->userkeys_pool);
2019-04-23 03:01:30 +02:00
if (cache->points) {
MEM_freeN(cache->points);
2019-04-23 03:01:30 +02:00
}
2019-04-23 03:01:30 +02:00
if (cache->last_userkey) {
MEM_freeN(cache->last_userkey);
2019-04-23 03:01:30 +02:00
}
MEM_freeN(cache);
}
Image cache rewrite to using generic movie cache Summary: Behaves very much the same as cache for Movie Clip datablock: - Image now have `MovieCache *cache` field which replaced legacy `ListBase ibufs`. This allows image datablock to easily keep of image buffers which are owned by itself. This field isn't saved to the file and getting restored on undo steps. However, cache limit is global for movies, sequences and image datablocks now. So overall cached image buffers size will not go above cache limit size in user preferences. - Image buffers which are marked as BITMAPDIRTY will never be freed from the cache. - Added utility function to iterate over image buffers saved in movie cache. - Movie cache cleanup check callback now have ImBuf argument which can be used in a condition of cleanup. - Added some utility functions which replaces legacy ibufs iterations with image cache iteration which happens from inside a lock. - Fixed `image_mem_size()` which was only counting one of the buffers if both float and byte buffer present. Additional notes: - `BKE_image_get_first_ibuf()` is rather stupid, but direct access to ibufs->first was also the same stupid idea. Would consider avoid this function is another project. - There are some places which doesn't look threadsafe, but they already were not so much threadsafe anyway before. So think not a big deal with solving this later. Finally solves infinite memory usage by image sequences! :) Reviewers: brecht, campbellbarton Reviewed By: brecht CC: sebastian_k Differential Revision: http://developer.blender.org/D95
2013-12-13 11:22:08 +01:00
void IMB_moviecache_cleanup(MovieCache *cache,
bool(cleanup_check_cb)(ImBuf *ibuf, void *userkey, void *userdata),
void *userdata)
{
2015-02-06 05:31:08 +01:00
GHashIterator gh_iter;
check_unused_keys(cache);
2015-02-06 17:39:26 +01:00
BLI_ghashIterator_init(&gh_iter, cache->hash);
while (!BLI_ghashIterator_done(&gh_iter)) {
2022-03-14 11:28:45 +01:00
MovieCacheKey *key = (MovieCacheKey *)BLI_ghashIterator_getKey(&gh_iter);
MovieCacheItem *item = (MovieCacheItem *)BLI_ghashIterator_getValue(&gh_iter);
2015-02-06 17:39:26 +01:00
BLI_ghashIterator_step(&gh_iter);
if (cleanup_check_cb(item->ibuf, key->userkey, userdata)) {
PRINT("%s: cache '%s' remove item %p\n", __func__, cache->name, item);
BLI_ghash_remove(cache->hash, key, moviecache_keyfree, moviecache_valfree);
}
}
}
void IMB_moviecache_get_cache_segments(
MovieCache *cache, int proxy, int render_flags, int *r_totseg, int **r_points)
{
*r_totseg = 0;
2022-03-14 16:55:17 +01:00
*r_points = nullptr;
2019-04-23 03:01:30 +02:00
if (!cache->getdatafp) {
return;
2019-04-23 03:01:30 +02:00
}
2012-03-26 18:04:10 +02:00
if (cache->proxy != proxy || cache->render_flags != render_flags) {
2021-08-06 05:59:38 +02:00
MEM_SAFE_FREE(cache->points);
}
if (cache->points) {
*r_totseg = cache->totseg;
*r_points = cache->points;
}
else {
int totframe = BLI_ghash_len(cache->hash);
2022-03-14 11:28:45 +01:00
int *frames = (int *)MEM_callocN(totframe * sizeof(int), "movieclip cache frames");
2012-03-26 18:04:10 +02:00
int a, totseg = 0;
2015-02-06 05:31:08 +01:00
GHashIterator gh_iter;
2012-05-04 01:47:39 +02:00
a = 0;
2015-02-06 05:31:08 +01:00
GHASH_ITER (gh_iter, cache->hash) {
2022-03-14 11:28:45 +01:00
MovieCacheKey *key = (MovieCacheKey *)BLI_ghashIterator_getKey(&gh_iter);
MovieCacheItem *item = (MovieCacheItem *)BLI_ghashIterator_getValue(&gh_iter);
int framenr, curproxy, curflags;
if (item->ibuf) {
cache->getdatafp(key->userkey, &framenr, &curproxy, &curflags);
2019-04-23 03:01:30 +02:00
if (curproxy == proxy && curflags == render_flags) {
2012-03-26 18:04:10 +02:00
frames[a++] = framenr;
2019-04-23 03:01:30 +02:00
}
}
}
qsort(frames, totframe, sizeof(int), compare_int);
/* count */
2012-03-26 18:04:10 +02:00
for (a = 0; a < totframe; a++) {
2019-04-23 03:01:30 +02:00
if (a && frames[a] - frames[a - 1] != 1) {
totseg++;
2019-04-23 03:01:30 +02:00
}
2019-04-23 03:01:30 +02:00
if (a == totframe - 1) {
totseg++;
2019-04-23 03:01:30 +02:00
}
}
if (totseg) {
int b, *points;
2022-03-14 11:28:45 +01:00
points = (int *)MEM_callocN(sizeof(int[2]) * totseg, "movieclip cache segments");
/* fill */
2012-03-26 18:04:10 +02:00
for (a = 0, b = 0; a < totframe; a++) {
2019-04-23 03:01:30 +02:00
if (a == 0) {
2012-03-26 18:04:10 +02:00
points[b++] = frames[a];
2019-04-23 03:01:30 +02:00
}
2012-03-26 18:04:10 +02:00
if (a && frames[a] - frames[a - 1] != 1) {
points[b++] = frames[a - 1];
points[b++] = frames[a];
}
2019-04-23 03:01:30 +02:00
if (a == totframe - 1) {
2012-03-26 18:04:10 +02:00
points[b++] = frames[a];
2019-04-23 03:01:30 +02:00
}
}
*r_totseg = totseg;
*r_points = points;
2012-03-26 18:04:10 +02:00
cache->totseg = totseg;
cache->points = points;
cache->proxy = proxy;
cache->render_flags = render_flags;
}
MEM_freeN(frames);
}
}
Image cache rewrite to using generic movie cache Summary: Behaves very much the same as cache for Movie Clip datablock: - Image now have `MovieCache *cache` field which replaced legacy `ListBase ibufs`. This allows image datablock to easily keep of image buffers which are owned by itself. This field isn't saved to the file and getting restored on undo steps. However, cache limit is global for movies, sequences and image datablocks now. So overall cached image buffers size will not go above cache limit size in user preferences. - Image buffers which are marked as BITMAPDIRTY will never be freed from the cache. - Added utility function to iterate over image buffers saved in movie cache. - Movie cache cleanup check callback now have ImBuf argument which can be used in a condition of cleanup. - Added some utility functions which replaces legacy ibufs iterations with image cache iteration which happens from inside a lock. - Fixed `image_mem_size()` which was only counting one of the buffers if both float and byte buffer present. Additional notes: - `BKE_image_get_first_ibuf()` is rather stupid, but direct access to ibufs->first was also the same stupid idea. Would consider avoid this function is another project. - There are some places which doesn't look threadsafe, but they already were not so much threadsafe anyway before. So think not a big deal with solving this later. Finally solves infinite memory usage by image sequences! :) Reviewers: brecht, campbellbarton Reviewed By: brecht CC: sebastian_k Differential Revision: http://developer.blender.org/D95
2013-12-13 11:22:08 +01:00
MovieCacheIter *IMB_moviecacheIter_new(MovieCache *cache)
Image cache rewrite to using generic movie cache Summary: Behaves very much the same as cache for Movie Clip datablock: - Image now have `MovieCache *cache` field which replaced legacy `ListBase ibufs`. This allows image datablock to easily keep of image buffers which are owned by itself. This field isn't saved to the file and getting restored on undo steps. However, cache limit is global for movies, sequences and image datablocks now. So overall cached image buffers size will not go above cache limit size in user preferences. - Image buffers which are marked as BITMAPDIRTY will never be freed from the cache. - Added utility function to iterate over image buffers saved in movie cache. - Movie cache cleanup check callback now have ImBuf argument which can be used in a condition of cleanup. - Added some utility functions which replaces legacy ibufs iterations with image cache iteration which happens from inside a lock. - Fixed `image_mem_size()` which was only counting one of the buffers if both float and byte buffer present. Additional notes: - `BKE_image_get_first_ibuf()` is rather stupid, but direct access to ibufs->first was also the same stupid idea. Would consider avoid this function is another project. - There are some places which doesn't look threadsafe, but they already were not so much threadsafe anyway before. So think not a big deal with solving this later. Finally solves infinite memory usage by image sequences! :) Reviewers: brecht, campbellbarton Reviewed By: brecht CC: sebastian_k Differential Revision: http://developer.blender.org/D95
2013-12-13 11:22:08 +01:00
{
GHashIterator *iter;
check_unused_keys(cache);
iter = BLI_ghashIterator_new(cache->hash);
return (MovieCacheIter *)iter;
Image cache rewrite to using generic movie cache Summary: Behaves very much the same as cache for Movie Clip datablock: - Image now have `MovieCache *cache` field which replaced legacy `ListBase ibufs`. This allows image datablock to easily keep of image buffers which are owned by itself. This field isn't saved to the file and getting restored on undo steps. However, cache limit is global for movies, sequences and image datablocks now. So overall cached image buffers size will not go above cache limit size in user preferences. - Image buffers which are marked as BITMAPDIRTY will never be freed from the cache. - Added utility function to iterate over image buffers saved in movie cache. - Movie cache cleanup check callback now have ImBuf argument which can be used in a condition of cleanup. - Added some utility functions which replaces legacy ibufs iterations with image cache iteration which happens from inside a lock. - Fixed `image_mem_size()` which was only counting one of the buffers if both float and byte buffer present. Additional notes: - `BKE_image_get_first_ibuf()` is rather stupid, but direct access to ibufs->first was also the same stupid idea. Would consider avoid this function is another project. - There are some places which doesn't look threadsafe, but they already were not so much threadsafe anyway before. So think not a big deal with solving this later. Finally solves infinite memory usage by image sequences! :) Reviewers: brecht, campbellbarton Reviewed By: brecht CC: sebastian_k Differential Revision: http://developer.blender.org/D95
2013-12-13 11:22:08 +01:00
}
void IMB_moviecacheIter_free(MovieCacheIter *iter)
Image cache rewrite to using generic movie cache Summary: Behaves very much the same as cache for Movie Clip datablock: - Image now have `MovieCache *cache` field which replaced legacy `ListBase ibufs`. This allows image datablock to easily keep of image buffers which are owned by itself. This field isn't saved to the file and getting restored on undo steps. However, cache limit is global for movies, sequences and image datablocks now. So overall cached image buffers size will not go above cache limit size in user preferences. - Image buffers which are marked as BITMAPDIRTY will never be freed from the cache. - Added utility function to iterate over image buffers saved in movie cache. - Movie cache cleanup check callback now have ImBuf argument which can be used in a condition of cleanup. - Added some utility functions which replaces legacy ibufs iterations with image cache iteration which happens from inside a lock. - Fixed `image_mem_size()` which was only counting one of the buffers if both float and byte buffer present. Additional notes: - `BKE_image_get_first_ibuf()` is rather stupid, but direct access to ibufs->first was also the same stupid idea. Would consider avoid this function is another project. - There are some places which doesn't look threadsafe, but they already were not so much threadsafe anyway before. So think not a big deal with solving this later. Finally solves infinite memory usage by image sequences! :) Reviewers: brecht, campbellbarton Reviewed By: brecht CC: sebastian_k Differential Revision: http://developer.blender.org/D95
2013-12-13 11:22:08 +01:00
{
BLI_ghashIterator_free((GHashIterator *)iter);
}
bool IMB_moviecacheIter_done(MovieCacheIter *iter)
Image cache rewrite to using generic movie cache Summary: Behaves very much the same as cache for Movie Clip datablock: - Image now have `MovieCache *cache` field which replaced legacy `ListBase ibufs`. This allows image datablock to easily keep of image buffers which are owned by itself. This field isn't saved to the file and getting restored on undo steps. However, cache limit is global for movies, sequences and image datablocks now. So overall cached image buffers size will not go above cache limit size in user preferences. - Image buffers which are marked as BITMAPDIRTY will never be freed from the cache. - Added utility function to iterate over image buffers saved in movie cache. - Movie cache cleanup check callback now have ImBuf argument which can be used in a condition of cleanup. - Added some utility functions which replaces legacy ibufs iterations with image cache iteration which happens from inside a lock. - Fixed `image_mem_size()` which was only counting one of the buffers if both float and byte buffer present. Additional notes: - `BKE_image_get_first_ibuf()` is rather stupid, but direct access to ibufs->first was also the same stupid idea. Would consider avoid this function is another project. - There are some places which doesn't look threadsafe, but they already were not so much threadsafe anyway before. So think not a big deal with solving this later. Finally solves infinite memory usage by image sequences! :) Reviewers: brecht, campbellbarton Reviewed By: brecht CC: sebastian_k Differential Revision: http://developer.blender.org/D95
2013-12-13 11:22:08 +01:00
{
return BLI_ghashIterator_done((GHashIterator *)iter);
}
void IMB_moviecacheIter_step(MovieCacheIter *iter)
Image cache rewrite to using generic movie cache Summary: Behaves very much the same as cache for Movie Clip datablock: - Image now have `MovieCache *cache` field which replaced legacy `ListBase ibufs`. This allows image datablock to easily keep of image buffers which are owned by itself. This field isn't saved to the file and getting restored on undo steps. However, cache limit is global for movies, sequences and image datablocks now. So overall cached image buffers size will not go above cache limit size in user preferences. - Image buffers which are marked as BITMAPDIRTY will never be freed from the cache. - Added utility function to iterate over image buffers saved in movie cache. - Movie cache cleanup check callback now have ImBuf argument which can be used in a condition of cleanup. - Added some utility functions which replaces legacy ibufs iterations with image cache iteration which happens from inside a lock. - Fixed `image_mem_size()` which was only counting one of the buffers if both float and byte buffer present. Additional notes: - `BKE_image_get_first_ibuf()` is rather stupid, but direct access to ibufs->first was also the same stupid idea. Would consider avoid this function is another project. - There are some places which doesn't look threadsafe, but they already were not so much threadsafe anyway before. So think not a big deal with solving this later. Finally solves infinite memory usage by image sequences! :) Reviewers: brecht, campbellbarton Reviewed By: brecht CC: sebastian_k Differential Revision: http://developer.blender.org/D95
2013-12-13 11:22:08 +01:00
{
BLI_ghashIterator_step((GHashIterator *)iter);
}
ImBuf *IMB_moviecacheIter_getImBuf(MovieCacheIter *iter)
Image cache rewrite to using generic movie cache Summary: Behaves very much the same as cache for Movie Clip datablock: - Image now have `MovieCache *cache` field which replaced legacy `ListBase ibufs`. This allows image datablock to easily keep of image buffers which are owned by itself. This field isn't saved to the file and getting restored on undo steps. However, cache limit is global for movies, sequences and image datablocks now. So overall cached image buffers size will not go above cache limit size in user preferences. - Image buffers which are marked as BITMAPDIRTY will never be freed from the cache. - Added utility function to iterate over image buffers saved in movie cache. - Movie cache cleanup check callback now have ImBuf argument which can be used in a condition of cleanup. - Added some utility functions which replaces legacy ibufs iterations with image cache iteration which happens from inside a lock. - Fixed `image_mem_size()` which was only counting one of the buffers if both float and byte buffer present. Additional notes: - `BKE_image_get_first_ibuf()` is rather stupid, but direct access to ibufs->first was also the same stupid idea. Would consider avoid this function is another project. - There are some places which doesn't look threadsafe, but they already were not so much threadsafe anyway before. So think not a big deal with solving this later. Finally solves infinite memory usage by image sequences! :) Reviewers: brecht, campbellbarton Reviewed By: brecht CC: sebastian_k Differential Revision: http://developer.blender.org/D95
2013-12-13 11:22:08 +01:00
{
2022-03-14 11:28:45 +01:00
MovieCacheItem *item = (MovieCacheItem *)BLI_ghashIterator_getValue((GHashIterator *)iter);
Image cache rewrite to using generic movie cache Summary: Behaves very much the same as cache for Movie Clip datablock: - Image now have `MovieCache *cache` field which replaced legacy `ListBase ibufs`. This allows image datablock to easily keep of image buffers which are owned by itself. This field isn't saved to the file and getting restored on undo steps. However, cache limit is global for movies, sequences and image datablocks now. So overall cached image buffers size will not go above cache limit size in user preferences. - Image buffers which are marked as BITMAPDIRTY will never be freed from the cache. - Added utility function to iterate over image buffers saved in movie cache. - Movie cache cleanup check callback now have ImBuf argument which can be used in a condition of cleanup. - Added some utility functions which replaces legacy ibufs iterations with image cache iteration which happens from inside a lock. - Fixed `image_mem_size()` which was only counting one of the buffers if both float and byte buffer present. Additional notes: - `BKE_image_get_first_ibuf()` is rather stupid, but direct access to ibufs->first was also the same stupid idea. Would consider avoid this function is another project. - There are some places which doesn't look threadsafe, but they already were not so much threadsafe anyway before. So think not a big deal with solving this later. Finally solves infinite memory usage by image sequences! :) Reviewers: brecht, campbellbarton Reviewed By: brecht CC: sebastian_k Differential Revision: http://developer.blender.org/D95
2013-12-13 11:22:08 +01:00
return item->ibuf;
}
void *IMB_moviecacheIter_getUserKey(MovieCacheIter *iter)
Image cache rewrite to using generic movie cache Summary: Behaves very much the same as cache for Movie Clip datablock: - Image now have `MovieCache *cache` field which replaced legacy `ListBase ibufs`. This allows image datablock to easily keep of image buffers which are owned by itself. This field isn't saved to the file and getting restored on undo steps. However, cache limit is global for movies, sequences and image datablocks now. So overall cached image buffers size will not go above cache limit size in user preferences. - Image buffers which are marked as BITMAPDIRTY will never be freed from the cache. - Added utility function to iterate over image buffers saved in movie cache. - Movie cache cleanup check callback now have ImBuf argument which can be used in a condition of cleanup. - Added some utility functions which replaces legacy ibufs iterations with image cache iteration which happens from inside a lock. - Fixed `image_mem_size()` which was only counting one of the buffers if both float and byte buffer present. Additional notes: - `BKE_image_get_first_ibuf()` is rather stupid, but direct access to ibufs->first was also the same stupid idea. Would consider avoid this function is another project. - There are some places which doesn't look threadsafe, but they already were not so much threadsafe anyway before. So think not a big deal with solving this later. Finally solves infinite memory usage by image sequences! :) Reviewers: brecht, campbellbarton Reviewed By: brecht CC: sebastian_k Differential Revision: http://developer.blender.org/D95
2013-12-13 11:22:08 +01:00
{
2022-03-14 11:28:45 +01:00
MovieCacheKey *key = (MovieCacheKey *)BLI_ghashIterator_getKey((GHashIterator *)iter);
Image cache rewrite to using generic movie cache Summary: Behaves very much the same as cache for Movie Clip datablock: - Image now have `MovieCache *cache` field which replaced legacy `ListBase ibufs`. This allows image datablock to easily keep of image buffers which are owned by itself. This field isn't saved to the file and getting restored on undo steps. However, cache limit is global for movies, sequences and image datablocks now. So overall cached image buffers size will not go above cache limit size in user preferences. - Image buffers which are marked as BITMAPDIRTY will never be freed from the cache. - Added utility function to iterate over image buffers saved in movie cache. - Movie cache cleanup check callback now have ImBuf argument which can be used in a condition of cleanup. - Added some utility functions which replaces legacy ibufs iterations with image cache iteration which happens from inside a lock. - Fixed `image_mem_size()` which was only counting one of the buffers if both float and byte buffer present. Additional notes: - `BKE_image_get_first_ibuf()` is rather stupid, but direct access to ibufs->first was also the same stupid idea. Would consider avoid this function is another project. - There are some places which doesn't look threadsafe, but they already were not so much threadsafe anyway before. So think not a big deal with solving this later. Finally solves infinite memory usage by image sequences! :) Reviewers: brecht, campbellbarton Reviewed By: brecht CC: sebastian_k Differential Revision: http://developer.blender.org/D95
2013-12-13 11:22:08 +01:00
return key->userkey;
}