Color management: refactor of cache to deal better with movie clip cache
authorSergey Sharybin <sergey.vfx@gmail.com>
Thu, 5 Jul 2012 09:41:00 +0000 (09:41 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Thu, 5 Jul 2012 09:41:00 +0000 (09:41 +0000)
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.

intern/memutil/MEM_CacheLimiter.h
source/blender/blenkernel/intern/movieclip.c
source/blender/blenkernel/intern/seqcache.c
source/blender/imbuf/IMB_colormanagement.h
source/blender/imbuf/IMB_imbuf_types.h
source/blender/imbuf/IMB_moviecache.h
source/blender/imbuf/intern/allocimbuf.c
source/blender/imbuf/intern/colormanagement.c
source/blender/imbuf/intern/moviecache.c

index bc92f9b5af85ef57a8425074d723d408949cfe8f..801ee154d401c9395264a26c71f2a0cfe0193103 100644 (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);
index 5a4919da65d331c7a6dae3f74605e0cb1312d7bd..488b590107101cbc7fa6134c7392629f64e5b947 100644 (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,
index c169a4a822322ce64f8e412ce178dd22dc35af96..0d91dcb7faad0dc0490f6ddf626c591ee4a98a20 100644 (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;
index e653d90f4d75045012a8fa7c62973ef2b3e3f2ef..2c31c2c6dcfe6c340c4930a73b8426fc4fb9b330 100644 (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);
index 58b9d3742cc06f2ab0b35055a42647615093dce1..4303b514ea7490b3b44eb93a4a92d042f4ea45ba 100644 (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
index 8beb7e0f7e2b37433924bc5c1453155daf367a19..0c37ab0adf3ad1c4a2fd9bafd6c609cd4fd89203 100644 (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);
index 0545bb33cb3d209589a7db30003e0ddb5cd91be6..0c36ecdda7e3447c21b76fe2de70f340ae181d8f 100644 (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);
 }
index cc9bff5affe8e81f7bd187048364956951fabaed..49f25c274b886b024b8183f8fc11006d86087738 100644 (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;
+
+typedef struct ColormanageCache {
+       struct MovieCache *moviecache;
+
+       ColormnaageCacheData *data;
+} ColormanageCache;
+
+static struct MovieCache *colormanage_moviecache_get(const ImBuf *ibuf)
+{
+       if (!ibuf->colormanage_cache)
+               return NULL;
 
-static struct MovieCache *colormanage_cache = 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;
+       if (!ibuf->colormanage_cache) {
+               ibuf->colormanage_cache = MEM_callocN(sizeof(ColormanageCache), "imbuf colormanage ca cache");
+       }
 
-       return key->ibuf->refcounter == 0;
-}
+       if (!ibuf->colormanage_cache->moviecache) {
+               struct MovieCache *moviecache;
 
-static void colormanage_keydeleter(void *key_v)
-{
-       ColormanageCacheKey *key = (ColormanageCacheKey *)key_v;
-       ImBuf *cache_ibuf = key->ibuf;
-
-       cache_ibuf->colormanage_refcounter--;
+               moviecache = IMB_moviecache_create("colormanage cache", sizeof(ColormanageCacheKey), colormanage_hashhash, colormanage_hashcmp);
 
-       if (cache_ibuf->colormanage_refcounter == 0) {
-               IMB_freeImBuf(key->ibuf);
+               ibuf->colormanage_cache->moviecache = moviecache;
        }
-}
 
-static void colormanage_cache_init(void)
-{
-       colormanage_cache = IMB_moviecache_create(sizeof(ColormanageCacheKey), colormanage_hashhash, colormanage_hashcmp);
-
-       IMB_moviecache_set_key_deleter_callback(colormanage_cache, colormanage_keydeleter);
-       IMB_moviecache_set_check_unused_callback(colormanage_cache, colormanage_checkkeyunused);
+       return ibuf->colormanage_cache->moviecache;
 }
 
-static void colormanage_cache_exit(void)
+static void colormanage_cachedata_set(ImBuf *ibuf, ColormnaageCacheData *data)
 {
-       IMB_moviecache_free(colormanage_cache);
+       if (!ibuf->colormanage_cache) {
+               ibuf->colormanage_cache = MEM_callocN(sizeof(ColormanageCache), "imbuf colormanage ca cache");
+       }
+
+       ibuf->colormanage_cache->data = data;
 }
 
-#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);
+
+               if (cache_data) {
+                       MEM_freeN(cache_data);
+               }
+
+               if (moviecache) {
+                       IMB_moviecache_free(moviecache);
+               }
+
+               MEM_freeN(ibuf->colormanage_cache);
 
-               ibuf->colormanage_cache_data = NULL;
+               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);
 
index f3442eb4147375779dbbf2a890d295fbc1d9fd0a..43e681591aa69531c14f9e503b6f6c7515817be7 100644 (file)
  *  \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"
 #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);
 }