[Bf-blender-cvs] [edc7666bd2e] asset-browser: Fix invalid memory use of "Current File" after undo & deleting data-blocks

Julian Eisel noreply at git.blender.org
Thu Dec 10 20:30:49 CET 2020


Commit: edc7666bd2e054b3697638642b1df4c9fce52906
Author: Julian Eisel
Date:   Thu Dec 10 17:12:56 2020 +0100
Branches: asset-browser
https://developer.blender.org/rBedc7666bd2e054b3697638642b1df4c9fce52906

Fix invalid memory use of "Current File" after undo & deleting data-blocks

Implement proper mechanisms to ensure the file list is recreated after undo,
data-blocks are removed, assets created/removed or file loading without UI.
This could be further improved (e.g. don't recreate it if no asset data-block
is affected by undo or deletion).

Addresses T82886 & T83242.

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

M	source/blender/blenkernel/intern/screen.c
M	source/blender/blenloader/intern/readfile.c
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
M	source/blender/makesdna/DNA_space_types.h

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

diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 59d61debd6c..6df6376219c 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -1670,6 +1670,7 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area)
       sfile->layout = NULL;
       sfile->op = NULL;
       sfile->previews_timer = NULL;
+      sfile->rebuild_flag = 0;
       BLO_read_data_address(reader, &sfile->params);
       BLO_read_data_address(reader, &sfile->asset_params);
     }
@@ -1755,8 +1756,11 @@ void BKE_screen_area_blend_read_lib(BlendLibReader *reader, ID *parent_id, ScrAr
         }
         break;
       }
-      case SPACE_FILE:
+      case SPACE_FILE: {
+        SpaceFile *sfile = (SpaceFile *)sl;
+        sfile->rebuild_flag |= FILE_REBUILD_MAIN_FILES;
         break;
+      }
       case SPACE_ACTION: {
         SpaceAction *saction = (SpaceAction *)sl;
         bDopeSheet *ads = &saction->ads;
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 3979cfb2b4f..f43cb690a67 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2749,6 +2749,7 @@ static void lib_link_workspace_layout_restore(struct IDNameLib_Map *id_map,
           SpaceFile *sfile = (SpaceFile *)sl;
           sfile->op = NULL;
           sfile->previews_timer = NULL;
+          sfile->rebuild_flag = FILE_REBUILD_MAIN_FILES;
         }
         else if (sl->spacetype == SPACE_ACTION) {
           SpaceAction *saction = (SpaceAction *)sl;
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 8a1e0daf93b..8cf7fff2b6c 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -413,6 +413,9 @@ typedef struct FileList {
 
   /* Filter an entry of current filelist. */
   bool (*filterf)(struct FileListInternEntry *, const char *, FileListFilter *);
+
+  /* Flags for the list-type, only set/changed when the type changes (#filelist_settype()). */
+  short type_flags; /* FileList.type_flags */
 } FileList;
 
 /* FileList.flags */
@@ -425,6 +428,11 @@ enum {
   FL_SORT_INVERT = 1 << 5,
 };
 
+/* FileList.type_flags */
+enum FileListTypeFlags {
+  FL_USES_MAIN_DATA = (1 << 0),
+};
+
 #define SPECIAL_IMG_SIZE 256
 #define SPECIAL_IMG_ROWS 1
 #define SPECIAL_IMG_COLS 7
@@ -1712,6 +1720,7 @@ void filelist_settype(FileList *filelist, short type)
   }
 
   filelist->type = type;
+  filelist->type_flags = 0;
   switch (filelist->type) {
     case FILE_MAIN:
       filelist->checkdirf = filelist_checkdir_main;
@@ -1728,6 +1737,7 @@ void filelist_settype(FileList *filelist, short type)
       filelist->checkdirf = filelist_checkdir_main_assets;
       filelist->read_jobf = filelist_readjob_main_assets;
       filelist->filterf = is_filtered_main_assets;
+      filelist->type_flags |= FL_USES_MAIN_DATA;
       break;
     default:
       filelist->checkdirf = filelist_checkdir_dir;
@@ -1897,6 +1907,11 @@ bool filelist_pending(struct FileList *filelist)
   return (filelist->flags & FL_IS_PENDING) != 0;
 }
 
+bool filelist_needs_reset_on_main_changes(const FileList *filelist)
+{
+  return (filelist->type_flags & FL_USES_MAIN_DATA) != 0;
+}
+
 /**
  * Limited version of full update done by space_file's file_refresh(),
  * to be used by operators and such.
@@ -2872,6 +2887,7 @@ static int filelist_readjob_list_lib(const char *root, ListBase *entries, const
     entry->typeflag |= FILE_TYPE_BLENDERLIB;
     if (info && info->asset_data) {
       entry->typeflag |= FILE_TYPE_ASSET | FILE_TYPE_ASSET_EXTERNAL;
+      /* Moves ownership! */
       entry->asset_data = info->asset_data;
     }
     if (!(group && idcode)) {
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
index d35a77e7816..563e35da352 100644
--- a/source/blender/editors/space_file/filelist.h
+++ b/source/blender/editors/space_file/filelist.h
@@ -105,6 +105,7 @@ bool filelist_file_cache_block(struct FileList *filelist, const int index);
 bool filelist_needs_force_reset(struct FileList *filelist);
 void filelist_tag_force_reset(struct FileList *filelist);
 bool filelist_pending(struct FileList *filelist);
+bool filelist_needs_reset_on_main_changes(const struct FileList *filelist);
 bool filelist_is_ready(struct FileList *filelist);
 
 unsigned int filelist_entry_select_set(const struct FileList *filelist,
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 6284f5ffe13..df37419b10c 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -318,6 +318,12 @@ static void file_refresh(const bContext *C, ScrArea *area)
   fileselect_refresh_params(sfile);
   folder_history_list_ensure_for_active_browse_mode(sfile);
 
+  if (sfile->files && (sfile->rebuild_flag & FILE_REBUILD_MAIN_FILES) &&
+      filelist_needs_reset_on_main_changes(sfile->files)) {
+    filelist_tag_force_reset(sfile->files);
+  }
+  sfile->rebuild_flag &= ~FILE_REBUILD_MAIN_FILES;
+
   if (!sfile->files) {
     sfile->files = filelist_new(params->type);
     params->highlight_file = -1; /* added this so it opens nicer (ton) */
@@ -411,8 +417,7 @@ static void file_listener(wmWindow *UNUSED(win),
       }
       break;
     case NC_ASSET: {
-      FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile);
-      if (asset_params && (asset_params->asset_library.type == FILE_ASSET_LIBRARY_LOCAL)) {
+      if (sfile->files && filelist_needs_reset_on_main_changes(sfile->files)) {
         /* Full refresh of the file list if local asset data was changed. Refreshing this view is
          * cheap and users expect this to be updated immediately. */
         file_tag_reset_list(area, sfile);
@@ -496,6 +501,22 @@ static void file_main_region_message_subscribe(const struct bContext *UNUSED(C),
   }
 }
 
+static bool file_main_region_needs_refresh_before_draw(SpaceFile *sfile)
+{
+  /* Needed, because filelist is not initialized on loading */
+  if (!sfile->files || filelist_needs_reading(sfile->files)) {
+    return true;
+  }
+
+  /* File reading tagged the space because main data changed that may require a filelist reset. */
+  if (filelist_needs_reset_on_main_changes(sfile->files) &&
+      (sfile->rebuild_flag & FILE_REBUILD_MAIN_FILES)) {
+    return true;
+  }
+
+  return false;
+}
+
 static void file_main_region_draw(const bContext *C, ARegion *region)
 {
   /* draw entirely, view changes should be handled here */
@@ -504,8 +525,7 @@ static void file_main_region_draw(const bContext *C, ARegion *region)
 
   View2D *v2d = &region->v2d;
 
-  /* Needed, because filelist is not initialized on loading */
-  if (!sfile->files || filelist_needs_reading(sfile->files)) {
+  if (file_main_region_needs_refresh_before_draw(sfile)) {
     file_refresh(C, NULL);
   }
 
@@ -789,6 +809,19 @@ static int /*eContextResult*/ file_context(const bContext *C,
   return CTX_RESULT_MEMBER_NOT_FOUND;
 }
 
+static void file_id_remap(ScrArea *area, SpaceLink *sl, ID *UNUSED(old_id), ID *UNUSED(new_id))
+{
+  SpaceFile *sfile = (SpaceFile *)sl;
+
+  /* If the file shows main data (IDs), tag it for reset. */
+  if (sfile->files && filelist_needs_reset_on_main_changes(sfile->files)) {
+    /* Full refresh of the file list if main data was changed, don't even attempt remap pointers.
+     * We could give file list types a id-remap callback, but it's probably not worth it.
+     * Refreshing local file lists is relatively cheap. */
+    file_tag_reset_list(area, sfile);
+  }
+}
+
 /* only called once, from space/spacetypes.c */
 void ED_spacetype_file(void)
 {
@@ -812,6 +845,7 @@ void ED_spacetype_file(void)
   st->space_subtype_get = file_space_subtype_get;
   st->space_subtype_set = file_space_subtype_set;
   st->context = file_context;
+  st->id_remap = file_id_remap;
 
   /* regions: main window */
   art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index dd24195e648..cf037118cd7 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -777,10 +777,13 @@ typedef struct SpaceFile {
   char _pad0[6];
   /* End 'SpaceLink' header. */
 
-  /* Is this a File Browser or an Asset Browser? */
+  /** Is this a File Browser or an Asset Browser? */
   char browse_mode; /* eFileBrowse_Mode */
 
-  char _pad1[3];
+  /** Runtime flags to notify about changed data that may require rebuilding. */
+  char rebuild_flag;
+  char _pad1[2];
+
   int scroll_offset;
 
   /** Config and input for file select. One for each browse-mode, to keep them independent. */
@@ -880,6 +883,13 @@ enum eFileSortType {
   FILE_SORT_SIZE = 4,
 };
 
+/* SpaceFile.rebuild_flag */
+enum eFileRebuildFlags {
+  /** Tag the space as having to update files representing or containing main data. Must be set
+   * after file read and undo/redo. */
+  FILE_REBUILD_MAIN_FILES = (1 << 0),
+};
+
 /* FileSelectParams.details_flags */
 enum eFileDetails {
   FILE_DETAILS_SIZE = (1 << 0),
@@ -1073,8 +1083,6 @@ typedef struct FileDirEntry {
   /** ID type, in case typeflag has FILE_TYPE_BLENDERLIB set. */
   int blentype;
 
-  struct AssetMetaData *asset_data;
-
   /* Path to item that is relative to current folder root. */
   char *relpath;
   /** Optional argument for shortcuts, aliases etc. */
@@ -1082,6 +1090,10 @@ typedef struct FileDirEntry {
 
   /** When showing local IDs (FILE_MAIN, FILE_MAIN_ASSET), UUID of the ID this file represents. */
   uint id_session_uuid;
+  /** If this file represents an asset, its asset data is here. Note that we may show assets of
+   * external files (#FILE_TYPE_ASSET_EXTERNAL) in which case this is set but not the id above. */
+  struct AssetMetaData *asset_data;
+
   /* The icon_id for the preview image. */
   int preview_icon_id;



More information about the Bf-blender-cvs mailing list