[Bf-blender-cvs] [e7c7b00] asset-experiments: WIP FileBrowser thumbnails: get rid of job here, use lighter threaded tasks.

Bastien Montagne noreply at git.blender.org
Mon Mar 30 21:36:15 CEST 2015


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. @@




More information about the Bf-blender-cvs mailing list