Page MenuHome
Paste P1103

Example T61263 fix
ActivePublic

Authored by Campbell Barton (campbellbarton) on Sep 18 2019, 12:41 PM.
commit 323ad68790ce76c088b15e4cac9078a80d587b1a
Author: Campbell Barton <ideasman42@gmail.com>
Date: Wed Sep 18 18:41:07 2019 +1000
Initial fix
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 170cc230332..b338afd10a3 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -118,6 +118,8 @@ static void image_add_view(Image *ima, const char *viewname, const char *filepat
# define IMA_INDEX_PASS(index) (index & ~1023)
#endif
+MovieClipFromImageFn image_undo_system_lookup_cb;
+
/* ******** IMAGE CACHE ************* */
typedef struct ImageCacheKey {
@@ -155,9 +157,17 @@ static void imagecache_put(Image *image, int index, ImBuf *ibuf)
// char cache_name[64];
// SNPRINTF(cache_name, "Image Datablock %s", image->id.name);
- image->cache = IMB_moviecache_create(
- "Image Datablock Cache", sizeof(ImageCacheKey), imagecache_hashhash, imagecache_hashcmp);
- IMB_moviecache_set_getdata_callback(image->cache, imagecache_keydata);
+ struct MovieCache *cache = image_undo_system_lookup_cb ? image_undo_system_lookup_cb(image) :
+ NULL;
+ if (cache == NULL) {
+ cache = IMB_moviecache_create(
+ "Image Datablock Cache", sizeof(ImageCacheKey), imagecache_hashhash, imagecache_hashcmp);
+ IMB_moviecache_set_getdata_callback(cache, imagecache_keydata);
+ }
+ else {
+ printf("FOUND CACHE\n");
+ }
+ IMB_moviecache_assign_id_user(&image->cache, cache);
}
key.index = index;
@@ -191,8 +201,7 @@ void BKE_images_exit(void)
static void image_free_cached_frames(Image *image)
{
if (image->cache) {
- IMB_moviecache_free(image->cache);
- image->cache = NULL;
+ IMB_moviecache_assign_id_user(&image->cache, NULL);
}
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_undo.c b/source/blender/editors/sculpt_paint/paint_image_undo.c
index 72001d8ee4c..457c4fafcc6 100644
--- a/source/blender/editors/sculpt_paint/paint_image_undo.c
+++ b/source/blender/editors/sculpt_paint/paint_image_undo.c
@@ -33,6 +33,7 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "IMB_moviecache.h"
#include "BKE_context.h"
#include "BKE_image.h"
@@ -74,6 +75,7 @@ typedef struct UndoImageTile {
/* TODO(campbell): avoid storing the ID per tile,
* adds unnecessary overhead restoring undo steps when most tiles share the same image. */
UndoRefID_Image image_ref;
+ struct MovieCache *image_cache;
short source;
bool use_float;
@@ -263,6 +265,10 @@ void *image_undo_push_tile(ListBase *undo_tiles,
}
BLI_addtail(undo_tiles, tile);
+ if (ima->cache) {
+ IMB_moviecache_assign_undo_user(&tile->image_cache, ima->cache);
+ }
+
if (proj) {
BLI_spin_unlock(&undolock);
}
@@ -284,6 +290,11 @@ static void image_undo_restore_runtime(ListBase *lb)
for (UndoImageTile *tile = lb->first; tile; tile = tile->next) {
Image *ima = tile->image_ref.ptr;
+
+ if (tile->image_cache && ima->cache != tile->image_cache) {
+ IMB_moviecache_assign_id_user(&ima->cache, tile->image_cache);
+ }
+
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
undo_copy_tile(tile, tmpibuf, ibuf, RESTORE);
@@ -310,6 +321,10 @@ static void image_undo_restore_list(ListBase *lb)
for (UndoImageTile *tile = lb->first; tile; tile = tile->next) {
Image *ima = tile->image_ref.ptr;
+ if (tile->image_cache && ima->cache != tile->image_cache) {
+ IMB_moviecache_assign_id_user(&ima->cache, tile->image_cache);
+ }
+
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
if (ima && ibuf && !STREQ(tile->ibufname, ibuf->name)) {
@@ -363,6 +378,9 @@ static void image_undo_restore_list(ListBase *lb)
static void image_undo_free_tile(UndoImageTile *tile)
{
+ if (tile->image_cache) {
+ IMB_moviecache_assign_undo_user(&tile->image_cache, NULL);
+ }
MEM_freeN(tile->rect.pt);
MEM_freeN(tile);
}
@@ -547,6 +565,24 @@ static void image_undosys_foreach_ID_ref(UndoStep *us_p,
}
}
+static struct MovieCache *image_cache_lookup(Image *image)
+{
+ UndoStack *ustack = ED_undo_stack_get();
+ if (ustack == NULL) {
+ return NULL;
+ }
+ for (UndoStep *us = ustack->steps.first; us; us = us->next) {
+ if (us->type == BKE_UNDOSYS_TYPE_IMAGE) {
+ for (UndoImageTile *tile = ((ImageUndoStep *)us)->tiles.first; tile; tile = tile->next) {
+ if (tile->image_ref.ptr == image) {
+ return tile->image_cache;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
/* Export for ED_undo_sys. */
void ED_image_undosys_type(UndoType *ut)
{
@@ -562,6 +598,8 @@ void ED_image_undosys_type(UndoType *ut)
ut->use_context = true;
ut->step_size = sizeof(ImageUndoStep);
+
+ image_undo_system_lookup_cb = image_cache_lookup;
}
/** \} */
diff --git a/source/blender/imbuf/IMB_moviecache.h b/source/blender/imbuf/IMB_moviecache.h
index 25494df9c00..f8291889004 100644
--- a/source/blender/imbuf/IMB_moviecache.h
+++ b/source/blender/imbuf/IMB_moviecache.h
@@ -77,4 +77,11 @@ void IMB_moviecacheIter_step(struct MovieCacheIter *iter);
struct ImBuf *IMB_moviecacheIter_getImBuf(struct MovieCacheIter *iter);
void *IMB_moviecacheIter_getUserKey(struct MovieCacheIter *iter);
+struct Image;
+typedef struct MovieCache *(*MovieClipFromImageFn)(struct Image *image);
+extern MovieClipFromImageFn image_undo_system_lookup_cb;
+
+void IMB_moviecache_assign_id_user(struct MovieCache **cache_p, struct MovieCache *cache);
+void IMB_moviecache_assign_undo_user(struct MovieCache **cache_p, struct MovieCache *cache);
+
#endif
diff --git a/source/blender/imbuf/intern/moviecache.c b/source/blender/imbuf/intern/moviecache.c
index 3cb976a6d9f..187e8c2d150 100644
--- a/source/blender/imbuf/intern/moviecache.c
+++ b/source/blender/imbuf/intern/moviecache.c
@@ -50,6 +50,8 @@
# define PRINT(format, ...)
#endif
+static int total_cache = 0; /* only for printf's - can remove. */
+
static MEM_CacheLimiterC *limitor = NULL;
static pthread_mutex_t limitor_lock = BLI_MUTEX_INITIALIZER;
@@ -74,7 +76,12 @@ typedef struct MovieCache {
void *last_userkey;
int totseg, *points, proxy, render_flags; /* for visual statistics optimization */
- int pad;
+
+ /** Only ever one ID user. */
+ bool has_id_user;
+
+ /** How many undo steps use this. */
+ int users_undo;
} MovieCache;
typedef struct MovieCacheKey {
@@ -284,6 +291,9 @@ MovieCache *IMB_moviecache_create(const char *name,
cache->cmpfp = cmpfp;
cache->proxy = -1;
+ total_cache++;
+ printf("%s: allocated %d\n", __func__, total_cache);
+
return cache;
}
@@ -443,6 +453,8 @@ void IMB_moviecache_free(MovieCache *cache)
}
MEM_freeN(cache);
+ printf("%s: de-allocated %d\n", __func__, total_cache);
+ total_cache--;
}
void IMB_moviecache_cleanup(MovieCache *cache,
@@ -596,3 +608,41 @@ void *IMB_moviecacheIter_getUserKey(struct MovieCacheIter *iter)
MovieCacheKey *key = BLI_ghashIterator_getKey((GHashIterator *)iter);
return key->userkey;
}
+
+void IMB_moviecache_assign_id_user(MovieCache **cache_p, MovieCache *cache)
+{
+ if (*cache_p != NULL) {
+ BLI_assert((*cache_p)->has_id_user == true);
+ (*cache_p)->has_id_user = false;
+ BLI_assert((*cache_p)->users_undo >= 0);
+ if ((*cache_p)->users_undo == 0) {
+ IMB_moviecache_free(*cache_p);
+ }
+ }
+ if (cache) {
+ BLI_assert(cache->has_id_user == false);
+ cache->has_id_user = true;
+ }
+ *cache_p = cache;
+}
+
+void IMB_moviecache_assign_undo_user(MovieCache **cache_p, MovieCache *cache)
+{
+ if (cache != NULL) {
+ BLI_assert(*cache_p == NULL); /* unsupported (and not needed for now). */
+ cache->users_undo += 1;
+ }
+ else {
+ if (*cache_p != NULL) {
+ (*cache_p)->users_undo -= 1;
+
+ BLI_assert((*cache_p)->users_undo >= 0);
+ if ((*cache_p)->users_undo == 0) {
+ if ((*cache_p)->has_id_user == false) {
+ IMB_moviecache_free(*cache_p);
+ }
+ }
+ }
+ }
+ *cache_p = cache;
+}