Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2013-12-10 12:40:09 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2013-12-22 12:44:56 +0400
commit78698a2ecf9d17340ce337ecf73ce6e355299f89 (patch)
treeb25d5e7a6b53a3c51733b5319b0b9535e037bf6a
parentc7a970a78eab2dea902b202d583fa98f70b54ba3 (diff)
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.
-rw-r--r--intern/memutil/MEM_CacheLimiter.h23
-rw-r--r--intern/memutil/MEM_CacheLimiterC-Api.h6
-rw-r--r--intern/memutil/intern/MEM_CacheLimiterC-Api.cpp6
-rw-r--r--source/blender/imbuf/intern/moviecache.c15
4 files changed, 48 insertions, 2 deletions
diff --git a/intern/memutil/MEM_CacheLimiter.h b/intern/memutil/MEM_CacheLimiter.h
index 32f97a21815..88e06833b4a 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 7579dbdd4d1..a6a3ec85777 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 0e11fbed4e7..6156b511f01 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 c042831a93f..3718cb270c9 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)