[Bf-blender-cvs] [a8f610a7e5a] asset-browser: Support dynamically showing local previews as they get finished

Julian Eisel noreply at git.blender.org
Sat Nov 14 00:35:24 CET 2020


Commit: a8f610a7e5a9114f53ed3857012a0ac9f4d65570
Author: Julian Eisel
Date:   Sat Nov 14 00:09:34 2020 +0100
Branches: asset-browser
https://developer.blender.org/rBa8f610a7e5a9114f53ed3857012a0ac9f4d65570

Support dynamically showing local previews as they get finished

The local asset previews can be created on a separate thread now, and the Asset
Browser can start showing them as they get done.

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

M	source/blender/blenkernel/BKE_icons.h
M	source/blender/blenkernel/intern/icons.c
M	source/blender/blenloader/intern/readblenentry.c
M	source/blender/editors/interface/interface_icons.c
M	source/blender/editors/render/render_preview.c
M	source/blender/editors/space_file/filelist.c
M	source/blender/makesdna/DNA_ID.h

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

diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h
index 7b418dc288a..f975e308570 100644
--- a/source/blender/blenkernel/BKE_icons.h
+++ b/source/blender/blenkernel/BKE_icons.h
@@ -151,6 +151,9 @@ void BKE_previewimg_ensure(struct PreviewImage *prv, const int size);
 
 struct ImBuf *BKE_previewimg_to_imbuf(struct PreviewImage *prv, const int size);
 
+void BKE_previewimg_finish(struct PreviewImage *prv, const int size);
+bool BKE_previewimg_is_finished(const struct PreviewImage *prv, const int size);
+
 struct PreviewImage *BKE_previewimg_cached_get(const char *name);
 
 struct PreviewImage *BKE_previewimg_cached_ensure(const char *name);
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index aa03b22b443..692312d33b1 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -61,6 +61,8 @@
 
 #include "BLO_read_write.h"
 
+#include "atomic_ops.h"
+
 /**
  * Only allow non-managed icons to be removed (by Python for eg).
  * Previews & ID's have their own functions to remove icons.
@@ -224,7 +226,7 @@ static PreviewImage *previewimg_create_ex(size_t deferred_data_size)
   }
 
   for (int i = 0; i < NUM_ICON_SIZES; i++) {
-    prv_img->flag[i] |= PRV_CHANGED;
+    prv_img->flag[i] |= (PRV_CHANGED | PRV_UNFINISHED);
     prv_img->changed_timestamp[i] = 0;
   }
   return prv_img;
@@ -267,7 +269,7 @@ void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size)
     GPU_texture_free(prv->gputexture[size]);
   }
   prv->h[size] = prv->w[size] = 0;
-  prv->flag[size] |= PRV_CHANGED;
+  prv->flag[size] |= (PRV_CHANGED | PRV_UNFINISHED);
   prv->flag[size] &= ~PRV_USER_EDITED;
   prv->changed_timestamp[size] = 0;
 }
@@ -501,7 +503,7 @@ void BKE_previewimg_ensure(PreviewImage *prv, const int size)
           prv->w[ICON_SIZE_PREVIEW] = thumb->x;
           prv->h[ICON_SIZE_PREVIEW] = thumb->y;
           prv->rect[ICON_SIZE_PREVIEW] = MEM_dupallocN(thumb->rect);
-          prv->flag[ICON_SIZE_PREVIEW] &= ~(PRV_CHANGED | PRV_USER_EDITED);
+          prv->flag[ICON_SIZE_PREVIEW] &= ~(PRV_CHANGED | PRV_USER_EDITED | PRV_UNFINISHED);
         }
         if (do_icon) {
           if (thumb->x > thumb->y) {
@@ -520,7 +522,7 @@ void BKE_previewimg_ensure(PreviewImage *prv, const int size)
           prv->w[ICON_SIZE_ICON] = icon_w;
           prv->h[ICON_SIZE_ICON] = icon_h;
           prv->rect[ICON_SIZE_ICON] = MEM_dupallocN(thumb->rect);
-          prv->flag[ICON_SIZE_ICON] &= ~(PRV_CHANGED | PRV_USER_EDITED);
+          prv->flag[ICON_SIZE_ICON] &= ~(PRV_CHANGED | PRV_USER_EDITED | PRV_UNFINISHED);
         }
         IMB_freeImBuf(thumb);
       }
@@ -549,6 +551,17 @@ ImBuf *BKE_previewimg_to_imbuf(PreviewImage *prv, const int size)
   return ima;
 }
 
+void BKE_previewimg_finish(PreviewImage *prv, const int size)
+{
+  /* Previews may be calculated on a thread. */
+  atomic_fetch_and_or_int32(&prv->flag[size], ~PRV_UNFINISHED);
+}
+
+bool BKE_previewimg_is_finished(const PreviewImage *prv, const int size)
+{
+  return (prv->flag[size] & PRV_UNFINISHED) == 0;
+}
+
 void BKE_previewimg_blend_write(BlendWriter *writer, const PreviewImage *prv)
 {
   /* Note we write previews also for undo steps. It takes up some memory,
@@ -586,6 +599,7 @@ void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv)
       BLO_read_data_address(reader, &prv->rect[i]);
     }
     prv->gputexture[i] = NULL;
+    prv->flag[i] |= PRV_UNFINISHED;
   }
   prv->icon_id = 0;
   prv->tag = 0;
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index d28c24950d3..011d509f9eb 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -242,6 +242,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to
       if (looking) {
         if (bhead->SDNAnr == DNA_struct_find_nr(fd->filesdna, "PreviewImage")) {
           prv = BLO_library_read_struct(fd, bhead, "PreviewImage");
+
           if (prv) {
             memcpy(new_prv, prv, sizeof(PreviewImage));
             if (prv->rect[0] && prv->w[0] && prv->h[0]) {
@@ -256,6 +257,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to
               new_prv->rect[0] = NULL;
               new_prv->w[0] = new_prv->h[0] = 0;
             }
+            prv->flag[0] &= ~PRV_UNFINISHED;
 
             if (prv->rect[1] && prv->w[1] && prv->h[1]) {
               bhead = blo_bhead_next(fd, bhead);
@@ -269,6 +271,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to
               new_prv->rect[1] = NULL;
               new_prv->w[1] = new_prv->h[1] = 0;
             }
+            prv->flag[1] &= ~PRV_UNFINISHED;
             MEM_freeN(prv);
           }
         }
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 8220e1b17a0..32928603b12 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -1262,7 +1262,7 @@ static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size)
   else if (!prv_img->rect[size]) {
     prv_img->w[size] = render_size;
     prv_img->h[size] = render_size;
-    prv_img->flag[size] |= PRV_CHANGED;
+    prv_img->flag[size] |= (PRV_CHANGED | PRV_UNFINISHED);
     prv_img->changed_timestamp[size] = 0;
     prv_img->rect[size] = MEM_callocN(render_size * render_size * sizeof(uint), "prv_rect");
   }
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 64194a5ddd2..9089b2e00e0 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -1347,6 +1347,22 @@ static void icon_preview_add_size(IconPreview *ip, uint *rect, int sizex, int si
   BLI_addtail(&ip->sizes, new_size);
 }
 
+/**
+ * Find the index to map \a ip to data in \a preview_image.
+ */
+static int icon_previewimg_size_index_get(const IconPreviewSize *icon_size,
+                                          const PreviewImage *prv_img)
+{
+  for (int i = 0; i < NUM_ICON_SIZES; i++) {
+    if ((prv_img->w[i] == icon_size->sizex) && (prv_img->h[i] == icon_size->sizey)) {
+      return i;
+    }
+  }
+
+  BLI_assert(false);
+  return -1;
+}
+
 static void icon_preview_startjob_all_sizes(void *customdata,
                                             short *stop,
                                             short *do_update,
@@ -1371,6 +1387,13 @@ static void icon_preview_startjob_all_sizes(void *customdata,
       continue;
     }
 
+#ifndef NDEBUG
+    {
+      int size_index = icon_previewimg_size_index_get(cur_size, prv);
+      BLI_assert(!BKE_previewimg_is_finished(prv, size_index));
+    }
+#endif
+
     if (ELEM(GS(ip->id->name), ID_OB)) {
       object_preview_render(ip, cur_size);
       continue;
@@ -1443,6 +1466,12 @@ static void icon_preview_endjob(void *customdata)
   if (ip->owner) {
     PreviewImage *prv_img = ip->owner;
     prv_img->tag &= ~PRV_TAG_DEFFERED_RENDERING;
+
+    LISTBASE_FOREACH (IconPreviewSize *, icon_size, &ip->sizes) {
+      int size_index = icon_previewimg_size_index_get(icon_size, prv_img);
+      BKE_previewimg_finish(prv_img, size_index);
+    }
+
     if (prv_img->tag & PRV_TAG_DEFFERED_DELETE) {
       BLI_assert(prv_img->tag & PRV_TAG_DEFFERED);
       BKE_previewimg_cached_release_pointer(prv_img);
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 12287f25270..8fc7b799e75 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -279,6 +279,10 @@ typedef struct FileListEntryPreview {
   char path[FILE_MAX];
   uint64_t flags;
   int index;
+  /* Some file types load the memory from runtime data, not from disk. We just wait until it's done
+   * generating (BKE_previewimg_is_finished()). */
+  PreviewImage *in_memory_preview;
+
   ImBuf *img;
 } FileListEntryPreview;
 
@@ -1340,37 +1344,50 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdat
   FileListEntryPreview *preview = preview_taskdata->preview;
 
   ThumbSource source = 0;
+  bool done = false;
 
   //  printf("%s: Start (%d)...\n", __func__, threadid);
 
-  //  printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
-  BLI_assert(preview->flags &
-             (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT | FILE_TYPE_BLENDER |
-              FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB));
-
-  if (preview->flags & FILE_TYPE_IMAGE) {
-    source = THB_SOURCE_IMAGE;
-  }
-  else if (preview->flags &
-           (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB)) {
-    source = THB_SOURCE_BLEND;
-  }
-  else if (preview->flags & FILE_TYPE_MOVIE) {
-    source = THB_SOURCE_MOVIE;
-  }
-  else if (preview->flags & FILE_TYPE_FTFONT) {
-    source = THB_SOURCE_FONT;
+  if (preview->in_memory_preview) {
+    if (BKE_previewimg_is_finished(preview->in_memory_preview, ICON_SIZE_PREVIEW)) {
+      preview->img = BKE_previewimg_to_imbuf(preview->in_memory_preview, ICON_SIZE_PREVIEW);
+      done = true;
+    }
   }
+  else {
+    //  printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
+    BLI_assert(preview->flags &
+               (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT | FILE_TYPE_BLENDER |
+                FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB));
 
-  IMB_thumb_path_lock(preview->path);
-  /* Always generate biggest preview size for now, it's simpler and avoids having to re-generate in
-   * case user switch to a bigger preview size. */
-  preview->img = IMB_thumb_manage(preview->path, THB_LARGE, source);
-  IMB_thumb_path_unlock(preview->path);
+    if (preview->flags & FILE_TYPE_IMAGE) {
+      source = THB_SOURCE_IMAGE;
+    }
+    else if (preview->flags &
+             (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB)) {
+      source = THB_SOURCE_BLEND;
+ 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list