Color management: refactor of cache to deal better with movie clip cache

There were some crashes discovered in some circumstances of using
color management within the clip editor which ended up some refactoring
of color management cache.

Switch from global movie cache instance to per-image buffer instances

This only means keys for color managed buffers could be much simpier
and that look up would happen much faster in there're lots of frames
cached. Memory limiter stuff is still global for all color management
and in fact it's also shared with movie clip cache .

This allowed to get rid of original image buffer stored in cache
key and allowed to easily remove all display buffers when source
image buffer is being freed. This was main culptrit leading to
crashes.

Additional changes:

- Add option to make moviecache verbose. If DEBUG_MESSAGES is
  defined in moviecache.c detailed logs would be printed to the
  console.

- Movie caches are now named which helps reading debug messages.

- Improved a bit behavior of cache element removing when buffer
  overflows on adding new display buffer and there're frames from
  movie clip.
This commit is contained in:
Sergey Sharybin
2012-07-05 09:41:00 +00:00
parent 60113a4b63
commit 83758c4154
9 changed files with 209 additions and 148 deletions

View File

@@ -255,7 +255,7 @@ private:
int priority;
/* by default 0 means higherst priority element */
priority = queue.size() - i - 1;
priority = -(queue.size() - i - 1);
if (getItemPriority) {
priority = getItemPriority(elem->get()->get_data(), priority);

View File

@@ -437,9 +437,12 @@ static void put_imbuf_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, i
if (!clip->cache) {
struct MovieCache *moviecache;
// char cache_name[64];
// BLI_snprintf(cache_name, sizeof(cache_name), "movie %s", clip->id.name);
clip->cache = MEM_callocN(sizeof(MovieClipCache), "movieClipCache");
moviecache = IMB_moviecache_create(sizeof(MovieClipImBufCacheKey), moviecache_hashhash, moviecache_hashcmp);
moviecache = IMB_moviecache_create("movieclip", sizeof(MovieClipImBufCacheKey), moviecache_hashhash, moviecache_hashcmp);
IMB_moviecache_set_getdata_callback(moviecache, moviecache_keydata);
IMB_moviecache_set_priority_callback(moviecache, moviecache_getprioritydata, moviecache_getitempriority,

View File

@@ -98,7 +98,7 @@ void seq_stripelem_cache_cleanup(void)
{
if (moviecache) {
IMB_moviecache_free(moviecache);
moviecache = IMB_moviecache_create(sizeof(SeqCacheKey), seqcache_hashhash, seqcache_hashcmp);
moviecache = IMB_moviecache_create("seqcache", sizeof(SeqCacheKey), seqcache_hashhash, seqcache_hashcmp);
}
}
@@ -132,7 +132,7 @@ void seq_stripelem_cache_put(
}
if (!moviecache) {
moviecache = IMB_moviecache_create(sizeof(SeqCacheKey), seqcache_hashhash, seqcache_hashcmp);
moviecache = IMB_moviecache_create("seqcache", sizeof(SeqCacheKey), seqcache_hashhash, seqcache_hashcmp);
}
key.seq = seq;

View File

@@ -49,10 +49,7 @@ void IMB_colormanagement_exit(void);
/* ** Public display buffers interfaces ** */
void IMB_colormanage_flags_allocate(struct ImBuf *ibuf);
void IMB_colormanage_flags_free(struct ImBuf *ibuf);
void IMB_colormanage_cache_data_free(struct ImBuf *ibuf);
void IMB_colormanage_cache_free(struct ImBuf *ibuf);
unsigned char *IMB_display_buffer_acquire(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings,
const struct ColorManagedDisplaySettings *display_settings, void **cache_handle);

View File

@@ -128,11 +128,9 @@ typedef struct ImBuf {
unsigned int encodedbuffersize; /* Size of encodedbuffer */
/* color management */
int colormanage_refcounter;
unsigned int colormanage_flags;
unsigned int *display_buffer_flags; /* array of per-display display buffers dirty flags */
void *colormanage_cache_data; /* cache data which is being assigned when */
/* put ImBuf to colormanage cache */
struct ColormanageCache *colormanage_cache; /* cache used by color management */
/* information for compressed textures */
struct DDSData dds_data;
} ImBuf;
@@ -258,7 +256,4 @@ extern const char *imb_ext_image_qt[];
extern const char *imb_ext_movie[];
extern const char *imb_ext_audio[];
/* colormanage flags */
#define IMB_COLORMANAGED (1 << 0)
#endif

View File

@@ -53,7 +53,7 @@ typedef void (*MovieCachePriorityDeleterFP) (void *priority_data);
void IMB_moviecache_init(void);
void IMB_moviecache_destruct(void);
struct MovieCache *IMB_moviecache_create(int keysize, GHashHashFP hashfp, GHashCmpFP cmpfp);
struct MovieCache *IMB_moviecache_create(const char *name, int keysize, GHashHashFP hashfp, GHashCmpFP cmpfp);
void IMB_moviecache_set_key_deleter_callback(struct MovieCache *cache, MovieCacheKeyDeleterFP keydeleterfp);
void IMB_moviecache_set_getdata_callback(struct MovieCache *cache, MovieCacheGetKeyDataFP getdatafp);
void IMB_moviecache_set_check_unused_callback(struct MovieCache *cache, MovieCacheCheckKeyUnusedFP checkkeyunusedfp);

View File

@@ -163,8 +163,7 @@ void IMB_freeImBuf(ImBuf *ibuf)
IMB_freezbuffloatImBuf(ibuf);
freeencodedbufferImBuf(ibuf);
IMB_metadata_free(ibuf);
IMB_colormanage_flags_free(ibuf);
IMB_colormanage_cache_data_free(ibuf);
IMB_colormanage_cache_free(ibuf);
if (ibuf->dds_data.data != NULL) {
free(ibuf->dds_data.data); /* dds_data.data is allocated by DirectDrawSurface::readData(), so don't use MEM_freeN! */
@@ -448,10 +447,7 @@ ImBuf *IMB_dupImBuf(ImBuf *ibuf1)
*ibuf2 = tbuf;
IMB_display_buffer_invalidate(ibuf2);
IMB_colormanage_cache_data_free(ibuf2);
ibuf2->colormanage_flags &= ~ IMB_COLORMANAGED;
IMB_colormanage_cache_free(ibuf2);
return(ibuf2);
}

View File

@@ -83,46 +83,59 @@ static int global_tot_view = 0;
/*********************** Color managed cache *************************/
/* Currently it's original ImBuf pointer is used to distinguish which
* datablock, frame number, possible postprocessing display buffer was
* created for.
/* Cache Implementation Notes
* ==========================
*
* This makes it's possible to easy define key for color managed cache
* which would work for Images, Movie Clips, Sequencer Strips and so.
* All color management cache stuff is stored in two properties of
* image buffers:
*
* This also allows to easily control memory usage -- all color managed
* buffers are concentrated in single cache and it's really easy to
* control maximal memory usage for all color management related stuff
* (currently supports only maximal memory usage, but it could be
* improved further to support removing buffers when they are not needed
* anymore but memory usage didn't exceed it's limit).
* 1. display_buffer_flags
*
* This ImBuf is being referenced by cache key, so it could accessed
* anytime on runtime while cache element is valid. This is needed to
* support removing display buffers from cache when ImBuf they were
* created for is being freed.
* This is a bit field which used to mark calculated transformations
* for particular image buffer. Index inside of this array means index
* of a color managed display. Element with given index matches view
* transformations applied for a given display. So if bit B of array
* element B is set to 1, this means display buffer with display index
* of A and view transform of B was ever calculated for this imbuf.
*
* Technically it works in the following way:
* - ImBuf is being referenced first time when display buffer is
* creating for it and being put into the cache
* - On any further display buffer created for this ImBuf user
* reference counter is not being incremented
* - There's count of color management users in ImBuf which is
* being incremented every time display buffer is creating for
* giver ImBuf.
* - Hence, we always know how many display buffers is created
* for the ImBuf and if there's any display buffers created
* this ImBuf would be referenced by color management stuff and
* actual data for it wouldn't be freed even when this ImBuf is
* being freed by user, who created it.
* - When all external users finished working with this ImBuf it's
* reference counter would be 0.
* - On every new display buffer adding to the cache review of
* the cache happens and all cached display buffers who's ImBuf's
* user counter is zero are being removed from the cache.
* - On every display buffer removed from the cache ImBuf's color
* management user counter is being decremented. As soon as it's
* becoming zero, original ImBuf is being freed completely.
* In contrast with indices in global lists of displays and views this
* indices are 0-based, not 1-based. This is needed to save some bytes
* of memory.
*
* 2. colormanage_cache
*
* This is a pointer to a structure which holds all data which is
* needed for color management cache to work.
*
* It contains two parts:
* - data
* - moviecache
*
* Data field is used to store additional information about cached
* buffers which affects on whether cached buffer could be used.
* This data can't go to cache key because changes in this data
* shouldn't lead extra buffers adding to cache, it shall
* invalidate cached images.
*
* Currently such a data contains only exposure and gamma, but
* would likely extended further.
*
* data field is not null only for elements of cache, not used for
* original image buffers.
*
* Color management cache is using generic MovieCache implementation
* to make it easier to deal with memory limitation.
*
* Currently color management is using the same memory limitation
* pool as sequencer and clip editor are using which means color
* managed buffers would be removed from the cache as soon as new
* frames are loading for the movie clip and there's no space in
* cache.
*
* Every image buffer has got own movie cache instance, which
* means keys for color managed buffers could be really simple
* and look up in this cache would be fast and independent from
* overall amount of color managed images.
*/
/* NOTE: ColormanageCacheViewSettings and ColormanageCacheDisplaySettings are
@@ -145,23 +158,43 @@ typedef struct ColormanageCacheDisplaySettings {
} ColormanageCacheDisplaySettings;
typedef struct ColormanageCacheKey {
ImBuf *ibuf; /* image buffer for which display buffer was created */
int view; /* view transformation used for display buffer */
int display; /* display device name */
} ColormanageCacheKey;
typedef struct ColormnaageCacheImBufData {
typedef struct ColormnaageCacheData {
float exposure; /* exposure value cached buffer is calculated with */
float gamma; /* gamma value cached buffer is calculated with */
} ColormnaageCacheImBufData;
} ColormnaageCacheData;
static struct MovieCache *colormanage_cache = NULL;
typedef struct ColormanageCache {
struct MovieCache *moviecache;
ColormnaageCacheData *data;
} ColormanageCache;
static struct MovieCache *colormanage_moviecache_get(const ImBuf *ibuf)
{
if (!ibuf->colormanage_cache)
return NULL;
return ibuf->colormanage_cache->moviecache;
}
static ColormnaageCacheData *colormanage_cachedata_get(const ImBuf *ibuf)
{
if (!ibuf->colormanage_cache)
return NULL;
return ibuf->colormanage_cache->data;
}
#ifdef WITH_OCIO
static unsigned int colormanage_hashhash(const void *key_v)
{
ColormanageCacheKey *key = (ColormanageCacheKey *)key_v;
unsigned int rval = *(unsigned int *) key->ibuf;
unsigned int rval = (key->display << 16) | (key->view % 0xffff);
return rval;
}
@@ -171,11 +204,6 @@ static int colormanage_hashcmp(const void *av, const void *bv)
const ColormanageCacheKey *a = (ColormanageCacheKey *) av;
const ColormanageCacheKey *b = (ColormanageCacheKey *) bv;
if (a->ibuf < b->ibuf)
return -1;
else if (a->ibuf > b->ibuf)
return 1;
if (a->view < b->view)
return -1;
else if (a->view > b->view)
@@ -189,39 +217,32 @@ static int colormanage_hashcmp(const void *av, const void *bv)
return 0;
}
static int colormanage_checkkeyunused(void *key_v)
static struct MovieCache *colormanage_moviecache_ensure(ImBuf *ibuf)
{
ColormanageCacheKey *key = (ColormanageCacheKey *)key_v;
return key->ibuf->refcounter == 0;
}
static void colormanage_keydeleter(void *key_v)
{
ColormanageCacheKey *key = (ColormanageCacheKey *)key_v;
ImBuf *cache_ibuf = key->ibuf;
cache_ibuf->colormanage_refcounter--;
if (cache_ibuf->colormanage_refcounter == 0) {
IMB_freeImBuf(key->ibuf);
if (!ibuf->colormanage_cache) {
ibuf->colormanage_cache = MEM_callocN(sizeof(ColormanageCache), "imbuf colormanage ca cache");
}
if (!ibuf->colormanage_cache->moviecache) {
struct MovieCache *moviecache;
moviecache = IMB_moviecache_create("colormanage cache", sizeof(ColormanageCacheKey), colormanage_hashhash, colormanage_hashcmp);
ibuf->colormanage_cache->moviecache = moviecache;
}
return ibuf->colormanage_cache->moviecache;
}
static void colormanage_cache_init(void)
static void colormanage_cachedata_set(ImBuf *ibuf, ColormnaageCacheData *data)
{
colormanage_cache = IMB_moviecache_create(sizeof(ColormanageCacheKey), colormanage_hashhash, colormanage_hashcmp);
if (!ibuf->colormanage_cache) {
ibuf->colormanage_cache = MEM_callocN(sizeof(ColormanageCache), "imbuf colormanage ca cache");
}
IMB_moviecache_set_key_deleter_callback(colormanage_cache, colormanage_keydeleter);
IMB_moviecache_set_check_unused_callback(colormanage_cache, colormanage_checkkeyunused);
ibuf->colormanage_cache->data = data;
}
static void colormanage_cache_exit(void)
{
IMB_moviecache_free(colormanage_cache);
}
#ifdef WITH_OCIO
static void colormanage_view_settings_to_cache(ColormanageCacheViewSettings *cache_view_settings,
const ColorManagedViewSettings *view_settings)
{
@@ -240,22 +261,28 @@ static void colormanage_display_settings_to_cache(ColormanageCacheDisplaySetting
cache_display_settings->display = display;
}
static void colormanage_settings_to_key(ColormanageCacheKey *key, ImBuf *ibuf,
static void colormanage_settings_to_key(ColormanageCacheKey *key,
const ColormanageCacheViewSettings *view_settings,
const ColormanageCacheDisplaySettings *display_settings)
{
key->ibuf = ibuf;
key->view = view_settings->view;
key->display = display_settings->display;
}
static ImBuf *colormanage_cache_get_ibuf(ColormanageCacheKey *key, void **cache_handle)
static ImBuf *colormanage_cache_get_ibuf(ImBuf *ibuf, ColormanageCacheKey *key, void **cache_handle)
{
ImBuf *cache_ibuf;
struct MovieCache *moviecache = colormanage_moviecache_get(ibuf);
if (!moviecache) {
/* if there's no moviecache it means no color management was applied before */
return NULL;
}
*cache_handle = NULL;
cache_ibuf = IMB_moviecache_get(colormanage_cache, key);
cache_ibuf = IMB_moviecache_get(moviecache, key);
*cache_handle = cache_ibuf;
@@ -270,17 +297,17 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV
ImBuf *cache_ibuf;
int view_flag = 1 << (view_settings->view - 1);
colormanage_settings_to_key(&key, ibuf, view_settings, display_settings);
colormanage_settings_to_key(&key, view_settings, display_settings);
/* check whether image was marked as dirty for requested transform */
if ((ibuf->display_buffer_flags[display_settings->display - 1] & view_flag) == 0) {
return NULL;
}
cache_ibuf = colormanage_cache_get_ibuf(&key, cache_handle);
cache_ibuf = colormanage_cache_get_ibuf(ibuf, &key, cache_handle);
if (cache_ibuf) {
ColormnaageCacheImBufData *cache_data;
ColormnaageCacheData *cache_data;
/* only buffers with different color space conversions are being stored
* in cache separately. buffer which were used only different exposure/gamma
@@ -289,7 +316,7 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV
* check here which exposure/gamma was used for cached buffer and if they're
* different from requested buffer should be re-generated
*/
cache_data = (ColormnaageCacheImBufData *) cache_ibuf->colormanage_cache_data;
cache_data = colormanage_cachedata_get(cache_ibuf);
if (cache_data->exposure != view_settings->exposure ||
cache_data->gamma != view_settings->gamma)
@@ -311,10 +338,11 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting
{
ColormanageCacheKey key;
ImBuf *cache_ibuf;
ColormnaageCacheImBufData *cache_data;
ColormnaageCacheData *cache_data;
int view_flag = 1 << (view_settings->view - 1);
struct MovieCache *moviecache = colormanage_moviecache_ensure(ibuf);
colormanage_settings_to_key(&key, ibuf, view_settings, display_settings);
colormanage_settings_to_key(&key, view_settings, display_settings);
/* mark display buffer as valid */
ibuf->display_buffer_flags[display_settings->display - 1] |= view_flag;
@@ -327,24 +355,15 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting
cache_ibuf->flags |= IB_rect;
/* store data which is needed to check whether cached buffer could be used for color managed display settings */
cache_data = MEM_callocN(sizeof(ColormnaageCacheImBufData), "color manage cache imbuf data");
cache_data = MEM_callocN(sizeof(ColormnaageCacheData), "color manage cache imbuf data");
cache_data->exposure = view_settings->exposure;
cache_data->gamma = view_settings->gamma;
cache_ibuf->colormanage_cache_data = cache_data;
colormanage_cachedata_set(cache_ibuf, cache_data);
*cache_handle = cache_ibuf;
/* mark source buffer as having color managed buffer and increment color managed buffers count for it */
if ((ibuf->colormanage_flags & IMB_COLORMANAGED) == 0) {
ibuf->colormanage_flags |= IMB_COLORMANAGED;
IMB_refImBuf(ibuf);
}
ibuf->colormanage_refcounter++;
IMB_moviecache_put(colormanage_cache, &key, cache_ibuf);
IMB_moviecache_put(moviecache, &key, cache_ibuf);
}
/* validation function checks whether there's buffer with given display transform
@@ -363,19 +382,19 @@ static unsigned char *colormanage_cache_get_validated(ImBuf *ibuf, const Colorma
ColormanageCacheKey key;
ImBuf *cache_ibuf;
colormanage_settings_to_key(&key, ibuf, view_settings, display_settings);
colormanage_settings_to_key(&key, view_settings, display_settings);
cache_ibuf = colormanage_cache_get_ibuf(&key, cache_handle);
cache_ibuf = colormanage_cache_get_ibuf(ibuf, &key, cache_handle);
if (cache_ibuf) {
if (cache_ibuf->x != ibuf->x || cache_ibuf->y != ibuf->y) {
ColormanageCacheViewSettings new_view_settings = *view_settings;
ColormnaageCacheImBufData *cache_data;
ColormnaageCacheData *cache_data;
unsigned char *display_buffer;
int buffer_size;
/* use the same settings as original cached buffer */
cache_data = (ColormnaageCacheImBufData *) cache_ibuf->colormanage_cache_data;
cache_data = colormanage_cachedata_get(cache_ibuf);
new_view_settings.exposure = cache_data->exposure;
new_view_settings.gamma = cache_data->gamma;
@@ -399,9 +418,9 @@ static unsigned char *colormanage_cache_get_validated(ImBuf *ibuf, const Colorma
static void colormanage_cache_get_cache_data(void *cache_handle, float *exposure, float *gamma)
{
ImBuf *cache_ibuf = (ImBuf *) cache_handle;
ColormnaageCacheImBufData *cache_data;
ColormnaageCacheData *cache_data;
cache_data = (ColormnaageCacheImBufData *) cache_ibuf->colormanage_cache_data;
cache_data = colormanage_cachedata_get(cache_ibuf);
*exposure = cache_data->exposure;
*gamma = cache_data->gamma;
@@ -581,8 +600,6 @@ void IMB_colormanagement_init(void)
/* special views, which does not depend on OCIO */
colormanage_view_add("ACES ODT Tonecurve");
#endif
colormanage_cache_init();
}
void IMB_colormanagement_exit(void)
@@ -590,8 +607,6 @@ void IMB_colormanagement_exit(void)
#ifdef WITH_OCIO
colormanage_free_config();
#endif
colormanage_cache_exit();
}
/*********************** Public display buffers interfaces *************************/
@@ -812,31 +827,39 @@ static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *displ
}
}
#endif
void IMB_colormanage_flags_allocate(ImBuf *ibuf)
static void colormanage_flags_allocate(ImBuf *ibuf)
{
if (global_tot_display == 0)
return;
ibuf->display_buffer_flags = MEM_callocN(sizeof(unsigned int) * global_tot_display, "imbuf display_buffer_flags");
}
#endif
void IMB_colormanage_flags_free(ImBuf *ibuf)
void IMB_colormanage_cache_free(ImBuf *ibuf)
{
if (ibuf->display_buffer_flags) {
MEM_freeN(ibuf->display_buffer_flags);
ibuf->display_buffer_flags = NULL;
}
}
void IMB_colormanage_cache_data_free(ImBuf *ibuf)
{
if (ibuf->colormanage_cache_data) {
MEM_freeN(ibuf->colormanage_cache_data);
if (ibuf->colormanage_cache) {
ColormnaageCacheData *cache_data = colormanage_cachedata_get(ibuf);
struct MovieCache *moviecache = colormanage_moviecache_get(ibuf);
ibuf->colormanage_cache_data = NULL;
if (cache_data) {
MEM_freeN(cache_data);
}
if (moviecache) {
IMB_moviecache_free(moviecache);
}
MEM_freeN(ibuf->colormanage_cache);
ibuf->colormanage_cache = NULL;
}
}
@@ -879,7 +902,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet
/* ensure color management bit fields exists */
if (!ibuf->display_buffer_flags)
IMB_colormanage_flags_allocate(ibuf);
colormanage_flags_allocate(ibuf);
display_buffer = colormanage_cache_get(ibuf, &cache_view_settings, &cache_display_settings, cache_handle);

View File

@@ -29,12 +29,15 @@
* \ingroup bke
*/
#undef DEBUG_MESSAGES
#include <stdlib.h> /* for qsort */
#include <memory.h>
#include "MEM_guardedalloc.h"
#include "MEM_CacheLimiterC-Api.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLI_mempool.h"
@@ -44,9 +47,21 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#ifdef DEBUG_MESSAGES
# if defined __GNUC__ || defined __sun
# define PRINT(format, args ...) printf(format, ##args)
# else
# define PRINT(format, ...) printf(__VA_ARGS__)
# endif
#else
# define PRINT(format, ...)
#endif
static MEM_CacheLimiterC *limitor = NULL;
typedef struct MovieCache {
char name[64];
GHash *hash;
MovieCacheKeyDeleterFP keydeleterfp;
GHashHashFP hashfp;
@@ -115,6 +130,8 @@ static void moviecache_valfree(void *val)
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->ibuf) {
MEM_CacheLimiter_unmanage(item->c_handle);
IMB_freeImBuf(item->ibuf);
@@ -141,9 +158,16 @@ static void check_unused_keys(MovieCache *cache)
remove = !item->ibuf;
if (!remove && cache->checkkeyunusedfp)
if (remove)
PRINT("%s: cache '%s' remove item %p without buffer\n", __func__, cache->name, item);
if (!remove && cache->checkkeyunusedfp) {
remove = cache->checkkeyunusedfp(key->userkey);
if (remove)
PRINT("%s: cache '%s' remove unused item %p\n", __func__, cache->name, item);
}
if (remove)
BLI_ghash_remove(cache->hash, key, moviecache_keyfree, moviecache_valfree);
}
@@ -161,12 +185,21 @@ static int compare_int(const void *av, const void *bv)
static void IMB_moviecache_destructor(void *p)
{
MovieCacheItem *item = (MovieCacheItem *) p;
MovieCache *cache = item->cache_owner;
PRINT("%s: cache '%s' destroy item %p buffer %p\n", __func__, cache->name, item, item->ibuf);
if (item && item->ibuf) {
IMB_freeImBuf(item->ibuf);
item->ibuf = NULL;
item->c_handle = NULL;
/* force cached segments to be updated */
if (cache->points) {
MEM_freeN(cache->points);
cache->points = NULL;
}
}
}
@@ -215,19 +248,19 @@ 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)
return default_priority;
if (!cache->last_userkey) {
/* happens when cache was overflow when adding element to one cache
* and elements from other cache are being measured as well
*/
if (!cache->getitempriorityfp) {
PRINT("%s: cache '%s' item %p use default priority %d\n", __func__, cache-> name, item, default_priority);
return default_priority;
}
return cache->getitempriorityfp(cache->last_userkey, item->priority_data);
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;
}
void IMB_moviecache_init(void)
@@ -243,12 +276,16 @@ void IMB_moviecache_destruct(void)
delete_MEM_CacheLimiter(limitor);
}
MovieCache *IMB_moviecache_create(int keysize, GHashHashFP hashfp, GHashCmpFP cmpfp)
MovieCache *IMB_moviecache_create(const char *name, int keysize, GHashHashFP hashfp, GHashCmpFP cmpfp)
{
MovieCache *cache;
PRINT("%s: cache '%s' create\n", __func__, name);
cache = MEM_callocN(sizeof(MovieCache), "MovieCache");
BLI_strncpy(cache->name, name, sizeof(cache->name));
cache->keys_pool = BLI_mempool_create(sizeof(MovieCacheKey), 64, 64, 0);
cache->items_pool = BLI_mempool_create(sizeof(MovieCacheItem), 64, 64, 0);
cache->userkeys_pool = BLI_mempool_create(keysize, 64, 64, 0);
@@ -281,6 +318,8 @@ void IMB_moviecache_set_priority_callback(struct MovieCache *cache, MovieCacheGe
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;
@@ -302,6 +341,9 @@ void IMB_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf)
memcpy(key->userkey, userkey, cache->keysize);
item = BLI_mempool_alloc(cache->items_pool);
PRINT("%s: cache '%s' put %p, item %p\n", __func__, cache-> name, ibuf, item);
item->ibuf = ibuf;
item->cache_owner = cache;
item->c_handle = NULL;
@@ -316,14 +358,14 @@ void IMB_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf)
item->c_handle = MEM_CacheLimiter_insert(limitor, item);
cache->last_userkey = userkey;
if (cache->last_userkey) {
memcpy(cache->last_userkey, userkey, cache->keysize);
}
MEM_CacheLimiter_ref(item->c_handle);
MEM_CacheLimiter_enforce_limits(limitor);
MEM_CacheLimiter_unref(item->c_handle);
cache->last_userkey = NULL;
/* cache limiter can't remove unused keys which points to destoryed values */
check_unused_keys(cache);
@@ -356,6 +398,8 @@ ImBuf *IMB_moviecache_get(MovieCache *cache, void *userkey)
void IMB_moviecache_free(MovieCache *cache)
{
PRINT("%s: create '%s' free\n", __func__, cache->name);
BLI_ghash_free(cache->hash, moviecache_keyfree, moviecache_valfree);
BLI_mempool_destroy(cache->keys_pool);
@@ -365,6 +409,9 @@ void IMB_moviecache_free(MovieCache *cache)
if (cache->points)
MEM_freeN(cache->points);
if (cache->last_userkey)
MEM_freeN(cache->last_userkey);
MEM_freeN(cache);
}