Commit: e7c7b00fe0426f8d8ee0ffc2db670ac1ff8376e6
Author: Bastien Montagne
Date:   Mon Mar 30 21:13:04 2015 +0200
Branches: asset-experiments
https://developer.blender.org/rBe7c7b00fe0426f8d8ee0ffc2db670ac1ff8376e6

WIP FileBrowser thumbnails: get rid of job here, use lighter threaded tasks.

Fully WIP, compiles but not yet working!

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

M       source/blender/editors/space_file/filelist.c
M       source/blender/editors/space_file/filelist.h
M       source/blender/editors/space_file/space_file.c

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

diff --git a/source/blender/editors/space_file/filelist.c 
b/source/blender/editors/space_file/filelist.c
index bfc5fbe..cbe1d01 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -51,6 +51,7 @@
 #include "BLI_linklist.h"
 #include "BLI_math.h"
 #include "BLI_stack.h"
+#include "BLI_task.h"
 #include "BLI_threads.h"
 #include "BLI_utildefines.h"
 #include "BLI_fileops_types.h"
@@ -218,6 +219,11 @@ typedef struct FileListEntryCache {
        int misc_cursor;
        int misc_entries_indices[FILELIST_ENTRYCACHESIZE];
        GHash *misc_entries;
+
+       /* Previews handling. */
+       TaskPool *previews_pool;
+       ThreadQueue *previews_todo;
+       ThreadQueue *previews_done;
 } FileListEntryCache;
 
 typedef struct FileListEntryCacheIter {
@@ -227,6 +233,13 @@ typedef struct FileListEntryCacheIter {
        GHashIterator *misc_iter;
 } FileListEntryCacheIter;
 
+typedef struct FileListEntryPreview {
+       char path[FILE_MAX];
+       unsigned int flags;
+       int index;
+       ImBuf *img;
+} FileListEntryPreview;
+
 typedef struct FileListFilter {
        bool hide_dot;
        bool hide_parent;
@@ -260,8 +273,6 @@ typedef struct FileList {
 
        struct FileListEntryCache filelist_cache;
 
-       bool need_thumbnails;
-
        short max_recursion;
        short recursion_level;
 
@@ -1057,6 +1068,76 @@ static void filelist_intern_release_entry(FileList 
*UNUSED(filelist), FileDirEnt
        /* We do nothing here actually, later we'll give back the mem to the 
mempool... */
 }
 
+static void filelist_cache_previewf(TaskPool *pool, void *taskdata, int 
UNUSED(threadid))
+{
+       FileListEntryCache *cache = taskdata;
+       FileListEntryPreview *preview;
+
+       /* Note we wait on queue here. */
+       while (!BLI_task_pool_canceled(pool) && (preview = 
BLI_thread_queue_pop(cache->previews_todo))) {
+               if (preview->flags & FILE_TYPE_IMAGE) {
+                       preview->img = IMB_thumb_manage(preview->path, 
THB_NORMAL, THB_SOURCE_IMAGE);
+               }
+               else if (preview->flags & (FILE_TYPE_BLENDER | 
FILE_TYPE_BLENDER_BACKUP)) {
+                       preview->img = IMB_thumb_manage(preview->path, 
THB_NORMAL, THB_SOURCE_BLEND);
+               }
+               else if (preview->flags & FILE_TYPE_MOVIE) {
+                       preview->img = IMB_thumb_manage(preview->path, 
THB_NORMAL, THB_SOURCE_MOVIE);
+                       if (!preview->img) {
+                               /* remember that file can't be loaded via 
IMB_open_anim */
+                               preview->flags &= ~FILE_TYPE_MOVIE;
+                               preview->flags |= FILE_TYPE_MOVIE_ICON;
+                       }
+               }
+               BLI_thread_queue_push(cache->previews_done, preview);
+       }
+}
+
+static void filelist_cache_previews_clear(FileListEntryCache *cache)
+{
+       FileListEntryPreview *preview;
+
+       if (cache->previews_pool) {
+               BLI_task_pool_cancel(cache->previews_pool);
+
+               while (BLI_thread_queue_size(cache->previews_todo) > 0) {
+                       preview = BLI_thread_queue_pop(cache->previews_todo);
+                       MEM_freeN(preview);
+               }
+               while (BLI_thread_queue_size(cache->previews_done) > 0) {
+                       preview = BLI_thread_queue_pop(cache->previews_done);
+                       if (preview->img) {
+                               IMB_freeImBuf(preview->img);
+                       }
+                       MEM_freeN(preview);
+               }
+
+               BLI_thread_queue_free(cache->previews_done);
+               BLI_thread_queue_free(cache->previews_todo);
+               BLI_task_pool_free(cache->previews_pool);
+               cache->previews_pool = NULL;
+               cache->previews_todo = NULL;
+               cache->previews_done = NULL;
+       }
+}
+
+static void filelist_cache_previews_push(FileList *filelist, FileDirEntry 
*entry, const int index)
+{
+       FileListEntryCache *cache = &filelist->filelist_cache;
+
+       if (!entry->image &&
+               (entry->typeflag & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | 
FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)))
+       {
+               FileListEntryPreview *preview = MEM_mallocN(sizeof(*preview), 
__func__);
+               BLI_join_dirfile(preview->path, sizeof(preview->path), 
filelist->filelist.root, entry->relpath);
+               preview->index = index;
+               preview->flags = entry->typeflag;
+               preview->img = NULL;
+               BLI_thread_queue_push(cache->previews_todo, preview);
+       }
+
+}
+
 static void filelist_cache_init(FileListEntryCache *cache)
 {
        cache->block_cursor = cache->block_start_index = cache->block_end_index 
= 0;
@@ -1067,6 +1148,8 @@ static void filelist_cache_init(FileListEntryCache *cache)
 
 static void filelist_cache_free(FileListEntryCache *cache)
 {
+       filelist_cache_previews_clear(cache);
+
        /* Note we nearly have nothing to do here, entries are just 'borrowed', 
not owned by cache... */
        if (cache->misc_entries) {
                BLI_ghash_free(cache->misc_entries, NULL, NULL);
@@ -1075,6 +1158,8 @@ static void filelist_cache_free(FileListEntryCache *cache)
 
 static void filelist_cache_clear(FileListEntryCache *cache)
 {
+       filelist_cache_previews_clear(cache);
+
        /* Note we nearly have nothing to do here, entries are just 'borrowed', 
not owned by cache... */
        cache->block_cursor = cache->block_start_index = cache->block_end_index 
= 0;
 
@@ -1143,8 +1228,6 @@ void filelist_free(struct FileList *filelist)
        filelist->need_sorting = false;
        filelist->sort = FILE_SORT_NONE;
        filelist->need_filtering = false;
-
-       filelist->need_thumbnails = false;
 }
 
 void filelist_freelib(struct FileList *filelist)
@@ -1282,7 +1365,9 @@ static FileDirEntry *filelist_file_ex(struct FileList 
*filelist, const int index
        cache->misc_entries_indices[cache->misc_cursor] = index;
        cache->misc_cursor = (cache->misc_cursor + 1) % FILELIST_ENTRYCACHESIZE;
 
-       filelist->need_thumbnails = true;
+       if (cache->previews_pool) {
+               filelist_cache_previews_push(filelist, ret, index);
+       }
 
        return ret;
 }
@@ -1321,6 +1406,7 @@ bool filelist_file_cache_block(struct FileList *filelist, 
const int index)
        int start_index = max_ii(0, index - (FILELIST_ENTRYCACHESIZE / 2));
        int end_index = min_ii(nbr_entries, index + (FILELIST_ENTRYCACHESIZE / 
2));
        const int curr_block_size = cache->block_end_index - 
cache->block_start_index;
+       int i;
 
        if ((index < 0) || (index >= nbr_entries)) {
                return false;
@@ -1345,8 +1431,6 @@ bool filelist_file_cache_block(struct FileList *filelist, 
const int index)
                return true;
        }
 
-       filelist->need_thumbnails = true;
-
        if ((start_index >= cache->block_end_index) || (end_index <= 
cache->block_start_index)) {
                /* New cached block does not overlap existing one, simple. */
                memcpy(cache->block_entries, 
&filelist->filelist_intern.filtered[start_index],
@@ -1354,6 +1438,17 @@ bool filelist_file_cache_block(struct FileList 
*filelist, const int index)
                cache->block_start_index = start_index;
                cache->block_end_index = end_index;
                cache->block_cursor = 0;
+
+               if (cache->previews_pool) {
+                       i = -(cache->block_end_index - 
cache->block_start_index);
+                       while (i++) {
+                               const int idx = (cache->block_cursor - i) % 
FILELIST_ENTRYCACHESIZE;
+                               FileDirEntry *entry = cache->block_entries[idx];
+
+                               filelist_cache_previews_push(filelist, entry, 
start_index - i);
+                       }
+               }
+
                return true;
        }
 
@@ -1378,6 +1473,16 @@ bool filelist_file_cache_block(struct FileList 
*filelist, const int index)
                }
                memcpy(&cache->block_entries[idx1], 
&filelist->filelist_intern.filtered[end_index - size1 - size2],
                       sizeof(cache->block_entries[0]) * size1);
+
+               if (cache->previews_pool) {
+                       i = size1 + size2;
+                       while (i--) {
+                               const int idx = (cache->block_cursor + 
end_index - start_index - i - 1) % FILELIST_ENTRYCACHESIZE;
+                               FileDirEntry *entry = cache->block_entries[idx];
+
+                               filelist_cache_previews_push(filelist, entry, 
end_index - i);
+                       }
+               }
        }
        cache->block_end_index = end_index;
 
@@ -1408,6 +1513,16 @@ bool filelist_file_cache_block(struct FileList 
*filelist, const int index)
                       sizeof(cache->block_entries[0]) * size1);
 
                cache->block_cursor = idx1;
+
+               if (cache->previews_pool) {
+                       i = -(size1 + size2);
+                       while (i++) {
+                               const int idx = (cache->block_cursor - i) % 
FILELIST_ENTRYCACHESIZE;
+                               FileDirEntry *entry = cache->block_entries[idx];
+
+                               filelist_cache_previews_push(filelist, entry, 
start_index - i);
+                       }
+               }
        }
        else if (start_index > cache->block_start_index) {
                /* We do not free anything, just update start index and cursor. 
*/
@@ -1418,6 +1533,72 @@ bool filelist_file_cache_block(struct FileList 
*filelist, const int index)
        return true;
 }
 
+void filelist_cache_previews_set(FileList *filelist, const bool use_previews)
+{
+       FileListEntryCache *cache = &filelist->filelist_cache;
+       if (use_previews == (cache->previews_pool != NULL)) {
+               return;
+       }
+       else if (use_previews) {
+               TaskScheduler *scheduler = BLI_task_scheduler_get();
+               TaskPool *pool;
+               int num_tasks = 4;
+               int i;
+
+               BLI_assert((cache->previews_pool == NULL) && 
(cache->previews_todo = NULL) && (cache->previews_done == NULL));
+
+               pool = cache->previews_pool = BLI_task_pool_create(scheduler, 
NULL);
+               cache->previews_todo = BLI_thread_queue_init();
+               cache->previews_done = BLI_thread_queue_init();
+
+               while (num_tasks--) {
+                       BLI_task_pool_push(pool, filelist_cache_previewf, 
cache, false, TASK_PRIORITY_HIGH);
+               }
+
+               i = -(cache->block_end_index - cache->block_start_index);
+               while (i++) {
+                       const int idx = (cache->block_cursor - i) % 
FILELIST_ENTRYCACHESIZE;
+                       FileListEntryPreview *preview = 
MEM_mallocN(sizeof(*preview), __func__);
+                       FileDirEntry *entry = cache->block_entries[idx];
+
+                       filelist_cache_previews_push(filelist, entry, 
cache->block_start_index - i);
+               }
+       }
+       else {
+               filelist_cache_previews_clear(cache);
+       }
+}
+
+void filelist_cache_previews_update(FileList *filelist)
+{
+       FileListEntryCache *cache = &filelist->filelist_cache;
+       TaskPool *pool = cache->previews_pool;
+
+       if (!pool) {
+               return;
+       }
+
+       while (!(BLI_task_pool_canceled(pool) || 
(BLI_thread_queue_size(cache->previews_done) > 0))) {
+               FileListEntryPreview *preview = 
BLI_thread_queue_pop(cache->previews_done);
+               if (preview->img) {
+                       /* entry might have been removed from cache in the mean 
while, we do not want to cache it again here. */
+                       FileDirEntry *entry = filelist_file_ex(filelist, 
preview->index, false);
+                       if (entry) {
+                               entry->image = preview->img;
+                               /* update flag for movie files where thumbnail 
can't be created */
+                               if (preview->flags & FILE_TYPE_MOVIE_ICON) {
+                                       entry->typeflag &= ~FILE_TYPE_MOVIE;
+                                       entry->typeflag |= FILE_TYPE_MOVIE_ICON;
+                               }
+                       }
+                       else {
+                               IMB_freeImBuf(preview->img);
+                       }
+               }
+               MEM_freeN(preview);
+       }
+}
+
 /* Note: Iterating over a c

@@ Diff output truncated at 10240 characters. @@

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

Reply via email to