[Bf-blender-cvs] [0e3ad1ccf4b] asset-browser: Asset Browser: Various changes for previews
Julian Eisel
noreply at git.blender.org
Thu Dec 3 01:58:54 CET 2020
Commit: 0e3ad1ccf4b1df1c6426e6c5a49c2bfda9d9ffcd
Author: Julian Eisel
Date: Wed Dec 2 18:11:11 2020 +0100
Branches: asset-browser
https://developer.blender.org/rB0e3ad1ccf4b1df1c6426e6c5a49c2bfda9d9ffcd
Asset Browser: Various changes for previews
* Operator to set a custom data-block preview. Copies an image from a selected path to the ID's preview buffer.
* Object preview support (threaded). Creates a localized copy of the object, creates a temporary main, scene, view-layer and depsgraph, uses the "Frame Selected" logic to place a camera in front of the object, and renders that offscreen.
* Support defining (not necessarily rendering) icons in threads. Needed so the File Browser can expose file previews with an icon-id to scripts.
** For that, ported the C++ to be able to use scope based mutex locks.
** Also support ImBuf icons.
* Tag previews as "unfinished" while they render in a thread, for the File Browser to dynamically load previews as they get finished.
* Better handle cases where threaded preview generation is requested, but the ID type doesn't support it (fallback to single threaded).
Differential Revision: https://developer.blender.org/D9719
===================================================================
M source/blender/blenkernel/BKE_icons.h
M source/blender/blenkernel/CMakeLists.txt
R074 source/blender/blenkernel/intern/icons.c source/blender/blenkernel/intern/icons.cc
M source/blender/blenkernel/intern/object.c
M source/blender/blenloader/intern/readblenentry.c
M source/blender/editors/include/ED_util.h
M source/blender/editors/include/ED_view3d.h
M source/blender/editors/interface/interface_icons.c
M source/blender/editors/render/render_preview.c
M source/blender/editors/screen/screen_ops.c
M source/blender/editors/space_view3d/view3d_utils.c
M source/blender/editors/space_view3d/view3d_view.c
M source/blender/editors/util/ed_util.c
M source/blender/imbuf/intern/thumbs_blend.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 9452717539c..820de84a4aa 100644
--- a/source/blender/blenkernel/BKE_icons.h
+++ b/source/blender/blenkernel/BKE_icons.h
@@ -23,17 +23,26 @@
* \ingroup bke
*
* Resizable Icons for Blender
+ *
+ * There is some thread safety for this API but it is rather weak. Registering or unregistering
+ * icons is thread safe, changing data of icons from multiple threads is not. Practically this
+ * should be fine since only the main thread modifies icons. Should that change, more locks or a
+ * different design need to be introduced.
*/
#ifdef __cplusplus
extern "C" {
#endif
+#include "BLI_compiler_attrs.h"
+
typedef void (*DrawInfoFreeFP)(void *drawinfo);
enum {
/** ID preview: obj is #ID. */
ICON_DATA_ID = 0,
+ /** Arbitrary Image buffer: obj is #ImBuf */
+ ICON_DATA_IMBUF,
/** Preview: obj is #PreviewImage */
ICON_DATA_PREVIEW,
/** 2D triangles: obj is #Icon_Geom */
@@ -44,6 +53,9 @@ enum {
ICON_DATA_GPLAYER,
};
+/**
+ * \note See comment at the top regarding thread safety.
+ */
struct Icon {
void *drawinfo;
/**
@@ -93,6 +105,9 @@ int BKE_icon_gplayer_color_ensure(struct bGPDlayer *gpl);
int BKE_icon_preview_ensure(struct ID *id, struct PreviewImage *preview);
+int BKE_icon_imbuf_create(struct ImBuf *ibuf) ATTR_WARN_UNUSED_RESULT;
+struct ImBuf *BKE_icon_imbuf_get_buffer(int icon_id) ATTR_WARN_UNUSED_RESULT;
+
/* retrieve icon for id */
struct Icon *BKE_icon_get(const int icon_id);
@@ -131,6 +146,9 @@ void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size)
struct PreviewImage **BKE_previewimg_id_get_p(const struct ID *id);
struct PreviewImage *BKE_previewimg_id_get(const struct ID *id);
+void BKE_previewimg_id_custom_set(struct ID *id, const char *path);
+
+bool BKE_previewimg_id_supports_jobs(const struct ID *id);
/* free the preview image belonging to the id */
void BKE_previewimg_id_free(struct ID *id);
@@ -148,6 +166,11 @@ struct PreviewImage *BKE_previewimg_id_ensure(struct ID *id);
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);
@@ -158,7 +181,8 @@ struct PreviewImage *BKE_previewimg_cached_thumbnail_read(const char *name,
bool force_update);
void BKE_previewimg_cached_release(const char *name);
-void BKE_previewimg_cached_release_pointer(struct PreviewImage *prv);
+
+void BKE_previewimg_deferred_release(struct PreviewImage *prv);
void BKE_previewimg_blend_write(struct BlendWriter *writer, const struct PreviewImage *prv);
void BKE_previewimg_blend_read(struct BlendDataReader *reader, struct PreviewImage *prv);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index ae79bf43a55..150da8a368a 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -130,7 +130,7 @@ set(SRC
intern/gpencil_geom.c
intern/gpencil_modifier.c
intern/hair.c
- intern/icons.c
+ intern/icons.cc
intern/icons_rasterize.c
intern/idprop.c
intern/idprop_utils.c
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.cc
similarity index 74%
rename from source/blender/blenkernel/intern/icons.c
rename to source/blender/blenkernel/intern/icons.cc
index 26a113b8b96..c5ca567ba46 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.cc
@@ -1,4 +1,4 @@
-/*
+/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -21,9 +21,10 @@
* \ingroup bke
*/
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
+#include <mutex>
#include "CLG_log.h"
@@ -46,6 +47,7 @@
#include "BLI_string.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLI_vector.hh"
#include "BKE_global.h" /* only for G.background test */
#include "BKE_icons.h"
@@ -61,6 +63,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.
@@ -73,12 +77,18 @@ enum {
static CLG_LogRef LOG = {"bke.icons"};
+/* Protected by gIconMutex. */
static GHash *gIcons = NULL;
+/* Protected by gIconMutex. */
static int gNextIconId = 1;
+/* Protected by gIconMutex. */
static int gFirstIconId = 1;
+std::mutex gIconMutex;
+
+/* Not mutex-protected! */
static GHash *gCachedPreviews = NULL;
/* Queue of icons for deferred deletion. */
@@ -86,15 +96,16 @@ typedef struct DeferredIconDeleteNode {
struct DeferredIconDeleteNode *next;
int icon_id;
} DeferredIconDeleteNode;
+/* Protected by gIconMutex. */
static LockfreeLinkList g_icon_delete_queue;
static void icon_free(void *val)
{
- Icon *icon = val;
+ Icon *icon = (Icon *)val;
if (icon) {
if (icon->obj_type == ICON_DATA_GEOM) {
- struct Icon_Geom *obj = icon->obj;
+ struct Icon_Geom *obj = (struct Icon_Geom *)icon->obj;
if (obj->mem) {
/* coords & colors are part of this memory. */
MEM_freeN((void *)obj->mem);
@@ -121,6 +132,12 @@ static void icon_free_data(int icon_id, Icon *icon)
if (icon->obj_type == ICON_DATA_ID) {
((ID *)(icon->obj))->icon_id = 0;
}
+ else if (icon->obj_type == ICON_DATA_IMBUF) {
+ ImBuf *imbuf = (ImBuf *)icon->obj;
+ if (imbuf) {
+ IMB_freeImBuf(imbuf);
+ }
+ }
else if (icon->obj_type == ICON_DATA_PREVIEW) {
((PreviewImage *)(icon->obj))->icon_id = 0;
}
@@ -131,7 +148,7 @@ static void icon_free_data(int icon_id, Icon *icon)
((struct Icon_Geom *)(icon->obj))->icon_id = 0;
}
else if (icon->obj_type == ICON_DATA_STUDIOLIGHT) {
- StudioLight *sl = icon->obj;
+ StudioLight *sl = (StudioLight *)icon->obj;
if (sl != NULL) {
BKE_studiolight_unset_icon_id(sl, icon_id);
}
@@ -141,19 +158,27 @@ static void icon_free_data(int icon_id, Icon *icon)
}
}
+static Icon *icon_ghash_lookup(int icon_id)
+{
+ std::scoped_lock lock(gIconMutex);
+ return (Icon *)BLI_ghash_lookup(gIcons, POINTER_FROM_INT(icon_id));
+}
+
/* create an id for a new icon and make sure that ids from deleted icons get reused
* after the integer number range is used up */
static int get_next_free_id(void)
{
- BLI_assert(BLI_thread_is_main());
+ std::scoped_lock lock(gIconMutex);
int startId = gFirstIconId;
/* if we haven't used up the int number range, we just return the next int */
if (gNextIconId >= gFirstIconId) {
- return gNextIconId++;
+ int next_id = gNextIconId++;
+ return next_id;
}
- /* now we try to find the smallest icon id not stored in the gIcons hash */
+ /* Now we try to find the smallest icon id not stored in the gIcons hash.
+ * Don't use icon_ghash_lookup here, it would lock recursively (dead-lock). */
while (BLI_ghash_lookup(gIcons, POINTER_FROM_INT(startId)) && startId >= gFirstIconId) {
startId++;
}
@@ -203,7 +228,7 @@ void BKE_icons_free(void)
void BKE_icons_deferred_free(void)
{
- BLI_assert(BLI_thread_is_main());
+ std::scoped_lock lock(gIconMutex);
for (DeferredIconDeleteNode *node =
(DeferredIconDeleteNode *)BLI_linklist_lockfree_begin(&g_icon_delete_queue);
@@ -216,7 +241,8 @@ void BKE_icons_deferred_free(void)
static PreviewImage *previewimg_create_ex(size_t deferred_data_size)
{
- PreviewImage *prv_img = MEM_mallocN(sizeof(PreviewImage) + deferred_data_size, "img_prv");
+ PreviewImage *prv_img = (PreviewImage *)MEM_mallocN(sizeof(PreviewImage) + deferred_data_size,
+ "img_prv");
memset(prv_img, 0, sizeof(*prv_img)); /* leave deferred data dirty */
if (deferred_data_size) {
@@ -224,12 +250,26 @@ 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;
}
+static PreviewImage *previewimg_defered_create(const char *path, int source)
+{
+ /* We pack needed data for lazy loading (source type, in a single char, and path). */
+ const size_t deferred_data_size = strlen(path) + 2;
+ char *deferred_data;
+
+ PreviewImage *prv = previewimg_create_ex(deferred_data_size);
+ deferred_data = (char *)PRV_DEFERRED_DATA(prv);
+ deferred_data[0] = source;
+ memcpy(&deferred_data[1], path, deferred_data_size - 1);
+
+ return prv;
+}
+
PreviewImage *BKE_previewimg_create(void)
{
return previewimg_create_ex(0);
@@ -267,7 +307,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;
}
@@ -275,7 +315,7 @@ void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size)
void BKE_previewimg_clear(struct PreviewImage *prv)
{
for (int i = 0; i < NUM_ICON_SIZES; i++) {
- BKE_previewimg_clear_single(prv, i);
+ BKE_previewimg_clear_single(prv, (eIconSizes)i);
}
}
@@ -284,10 +324,10 @@ PreviewImage *BKE_previewimg_copy(const PreviewImage *prv)
PreviewImage *prv_img = NULL;
if (prv) {
- prv_img = MEM_dupallocN(prv);
+ prv_img = (PreviewImage *)MEM_dupallocN(prv);
for (int i = 0; i < NUM_ICON_SIZES; i++) {
if (prv->rect[i]) {
- prv_img->rect[i] = MEM_dupal
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list