Commit: 78698a2ecf9d17340ce337ecf73ce6e355299f89
Author: Sergey Sharybin
Date:   Tue Dec 10 14:40:09 2013 +0600
http://developer.blender.org/rB78698a2ecf9d17340ce337ecf73ce6e355299f89

Add ItemDestroyable to the cache limitor

This callback is used when cache limiter needs to remove
some cached objects when running out of limit.

>From blender side it's used to keep painted images always
in memory.

This fixes issue when painted images were removing from
the memory after image cache rewrite.

===================================================================

M       intern/memutil/MEM_CacheLimiter.h
M       intern/memutil/MEM_CacheLimiterC-Api.h
M       intern/memutil/intern/MEM_CacheLimiterC-Api.cpp
M       source/blender/imbuf/intern/moviecache.c

===================================================================

diff --git a/intern/memutil/MEM_CacheLimiter.h 
b/intern/memutil/MEM_CacheLimiter.h
index 32f97a2..88e0683 100644
--- a/intern/memutil/MEM_CacheLimiter.h
+++ b/intern/memutil/MEM_CacheLimiter.h
@@ -137,6 +137,7 @@ class MEM_CacheLimiter {
 public:
        typedef size_t (*MEM_CacheLimiter_DataSize_Func) (void *data);
        typedef int    (*MEM_CacheLimiter_ItemPriority_Func) (void *item, int 
default_priority);
+       typedef bool   (*MEM_CacheLimiter_ItemDestroyable_Func) (void *item);
 
        MEM_CacheLimiter(MEM_CacheLimiter_DataSize_Func data_size_func)
                : data_size_func(data_size_func) {
@@ -230,11 +231,28 @@ public:
                this->item_priority_func = item_priority_func;
        }
 
+       void set_item_destroyable_func(MEM_CacheLimiter_ItemDestroyable_Func 
item_destroyable_func) {
+               this->item_destroyable_func = item_destroyable_func;
+       }
+
 private:
        typedef MEM_CacheLimiterHandle<T> *MEM_CacheElementPtr;
        typedef std::list<MEM_CacheElementPtr, 
MEM_Allocator<MEM_CacheElementPtr> > MEM_CacheQueue;
        typedef typename MEM_CacheQueue::iterator iterator;
 
+       /* Check whether element can be destroyed when enforcing cache limits */
+       bool can_destroy_element(MEM_CacheElementPtr &elem) {
+               if (!elem->can_destroy()) {
+                       /* Element is referenced */
+                       return false;
+               }
+               if (item_destroyable_func) {
+                       if (!item_destroyable_func(elem->get()->get_data()))
+                               return false;
+               }
+               return true;
+       }
+
        MEM_CacheElementPtr get_least_priority_destroyable_element(void) {
                if (queue.empty())
                        return NULL;
@@ -244,7 +262,7 @@ private:
                if (!item_priority_func) {
                        for (iterator it = queue.begin(); it != queue.end(); 
it++) {
                                MEM_CacheElementPtr elem = *it;
-                               if (!elem->can_destroy())
+                               if (!can_destroy_element(elem))
                                        continue;
                                best_match_elem = elem;
                                break;
@@ -258,7 +276,7 @@ private:
                        for (it = queue.begin(), i = 0; it != queue.end(); 
it++, i++) {
                                MEM_CacheElementPtr elem = *it;
 
-                               if (!elem->can_destroy())
+                               if (!can_destroy_element(elem))
                                        continue;
 
                                /* by default 0 means highest priority element 
*/
@@ -280,6 +298,7 @@ private:
        MEM_CacheQueue queue;
        MEM_CacheLimiter_DataSize_Func data_size_func;
        MEM_CacheLimiter_ItemPriority_Func item_priority_func;
+       MEM_CacheLimiter_ItemDestroyable_Func item_destroyable_func;
 };
 
 #endif  // __MEM_CACHELIMITER_H__
diff --git a/intern/memutil/MEM_CacheLimiterC-Api.h 
b/intern/memutil/MEM_CacheLimiterC-Api.h
index 7579dbd..a6a3ec8 100644
--- a/intern/memutil/MEM_CacheLimiterC-Api.h
+++ b/intern/memutil/MEM_CacheLimiterC-Api.h
@@ -47,6 +47,9 @@ typedef size_t (*MEM_CacheLimiter_DataSize_Func) (void*);
 /* function used to measure priority of item when freeing memory */
 typedef int (*MEM_CacheLimiter_ItemPriority_Func) (void*, int);
 
+/* function to check whether item could be destroyed */
+typedef bool (*MEM_CacheLimiter_ItemDestroyable_Func) (void*);
+
 #ifndef __MEM_CACHELIMITER_H__
 void MEM_CacheLimiter_set_maximum(size_t m);
 size_t MEM_CacheLimiter_get_maximum(void);
@@ -145,6 +148,9 @@ void *MEM_CacheLimiter_get(MEM_CacheLimiterHandleC *handle);
 void MEM_CacheLimiter_ItemPriority_Func_set(MEM_CacheLimiterC *This,
                                             MEM_CacheLimiter_ItemPriority_Func 
item_priority_func);
 
+void MEM_CacheLimiter_ItemDestroyable_Func_set(MEM_CacheLimiterC *This,
+                                               
MEM_CacheLimiter_ItemDestroyable_Func item_destroyable_func);
+
 size_t MEM_CacheLimiter_get_memory_in_use(MEM_CacheLimiterC *This);
 
 #ifdef __cplusplus
diff --git a/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp 
b/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp
index 0e11fbe..6156b51 100644
--- a/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp
+++ b/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp
@@ -203,6 +203,12 @@ void 
MEM_CacheLimiter_ItemPriority_Func_set(MEM_CacheLimiterC *This,
        cast(This)->get_cache()->set_item_priority_func(item_priority_func);
 }
 
+void MEM_CacheLimiter_ItemDestroyable_Func_set(MEM_CacheLimiterC *This,
+                                               
MEM_CacheLimiter_ItemDestroyable_Func item_destroyable_func)
+{
+       
cast(This)->get_cache()->set_item_destroyable_func(item_destroyable_func);
+}
+
 size_t MEM_CacheLimiter_get_memory_in_use(MEM_CacheLimiterC *This)
 {
        return cast(This)->get_cache()->get_memory_in_use();
diff --git a/source/blender/imbuf/intern/moviecache.c 
b/source/blender/imbuf/intern/moviecache.c
index c042831..3718cb2 100644
--- a/source/blender/imbuf/intern/moviecache.c
+++ b/source/blender/imbuf/intern/moviecache.c
@@ -254,11 +254,26 @@ static int get_item_priority(void *item_v, int 
default_priority)
        return priority;
 }
 
+static bool get_item_destroyable(void *item_v)
+{
+       MovieCacheItem *item = (MovieCacheItem *) item_v;
+       /* 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) {
+               return false;
+       }
+       return true;
+}
+
 void IMB_moviecache_init(void)
 {
        limitor = new_MEM_CacheLimiter(IMB_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(void)

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to