From d83a72ec104ce941b8f5a4c4cb63c805917b7efd Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Sat, 4 May 2019 15:12:55 +0200 Subject: Fix crash activating a fullscreened screen Steps to reproduce were: * Duplicate some area into new window (shift-click corner triangle) * Make it fullscreen * Close the window again * Activate the added screen from the menu (the one without the -nonnormal prefix) -> Crash (you may have to press "Back to Previous" first though) When activating a screen, code should check if there's a fullscreen variant of it and activate that instead. From what I can tell that's what the code tried to do, but incorrectly. Same issue as T64045, but things are a bit different for 2.7. --- source/blender/editors/screen/screen_edit.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index f777b42c5bd..3d2a3e395b9 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1195,10 +1195,9 @@ bool ED_screen_set(bContext *C, bScreen *sc) return true; } - if (ELEM(sc->state, SCREENMAXIMIZED, SCREENFULL)) { - /* find associated full */ - bScreen *sc1; - for (sc1 = bmain->screen.first; sc1; sc1 = sc1->id.next) { + /* find associated full */ + for (bScreen *sc1 = bmain->screen.first; sc1; sc1 = sc1->id.next) { + if ((sc1 != sc) && ELEM(sc1->state, SCREENMAXIMIZED, SCREENFULL)) { ScrArea *sa = sc1->areabase.first; if (sa->full == sc) { sc = sc1; -- cgit v1.2.3 From 3600e94ebac0d411042c54ed0970099a7a9cb932 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 22 May 2019 21:08:51 +0200 Subject: BKE Library handling: add function to recompute usercounts of IDs. This will be needed in undo/redo case, since we do not re-read linked IDs, their usercounts become total garbage (especially in 'used by local ID' cases)... --- source/blender/blenkernel/BKE_library.h | 2 ++ source/blender/blenkernel/intern/library.c | 56 ++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 493873bc840..0b781f95811 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -180,6 +180,8 @@ void BKE_main_id_flag_all(struct Main *bmain, const int flag, const bool value); void BKE_main_id_clear_newpoins(struct Main *bmain); +void BLE_main_id_refcount_recompute(struct Main *bmain, const bool do_linked_only); + void BKE_main_lib_objects_recalc_all(struct Main *bmain); /* (MAX_ID_NAME - 2) + 3 */ diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 16f0fc080eb..aa6ce744afd 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -1883,6 +1883,62 @@ void BKE_main_id_clear_newpoins(Main *bmain) } +static int id_refcount_recompute_callback( + void *user_data, struct ID *UNUSED(id_self), struct ID **id_pointer, int cb_flag) +{ + const bool do_linked_only = (bool)POINTER_AS_INT(user_data); + + if (*id_pointer == NULL) { + return IDWALK_RET_NOP; + } + if (do_linked_only && !ID_IS_LINKED(*id_pointer)) { + return IDWALK_RET_NOP; + } + + if (cb_flag & IDWALK_CB_USER) { + /* Do not touch to direct/indirect linked status here... */ + id_us_plus_no_lib(*id_pointer); + } + if (cb_flag & IDWALK_CB_USER_ONE) { + id_us_ensure_real(*id_pointer); + } + + return IDWALK_RET_NOP; +} + +void BLE_main_id_refcount_recompute(struct Main *bmain, const bool do_linked_only) +{ + ListBase *lbarray[MAX_LIBARRAY]; + ID *id; + int a; + + /* Reset usercount of all affected IDs. */ + const int nbr_lb = a = set_listbasepointers(bmain, lbarray); + while (a--) { + for(id = lbarray[a]->first; id != NULL; id = id->next) { + if (!ID_IS_LINKED(id) && do_linked_only) { + continue; + } + id->us = ID_FAKE_USERS(id); + /* Note that we keep EXTRAUSER tag here, since some UI users may define it too... */ + if (id->tag & LIB_TAG_EXTRAUSER) { + id->tag &= ~(LIB_TAG_EXTRAUSER | LIB_TAG_EXTRAUSER_SET); + id_us_ensure_real(id); + } + } + } + + /* Go over whole Main database to re-generate proper usercounts... */ + a = nbr_lb; + while (a--) { + for(id = lbarray[a]->first; id != NULL; id = id->next) { + BKE_library_foreach_ID_link( + bmain, id, id_refcount_recompute_callback, POINTER_FROM_INT((int)do_linked_only), IDWALK_READONLY); + } + } +} + + static void library_make_local_copying_check(ID *id, GSet *loop_tags, MainIDRelations *id_relations, GSet *done_ids) { if (BLI_gset_haskey(done_ids, id)) { -- cgit v1.2.3 From 3a702ec028231e7deb012edac3eee5ed7f2436d4 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 22 May 2019 21:10:36 +0200 Subject: Fix (unreported) usercount of linked IDs becoming garbage after undo/redo. Not re-reading linked data-blocks in undo/redo case also means that we do not touch to their usercounts. Even worse, lib_link process in readfile will increase those (for cases where local data uses linked one). Whole data management code is now heavily relying on valid consistent refcount of all IDs, so we cannot allow that anymore. Simple solution here could have been to then not increase that one for linked IDs in `newlibadr_us()`, but unfortunately that would not be totally bullet-proof, as some local users of linked data may be added or removed by an undo step... So I cannot think of any other solution than the ugly brute force one, i.e. going over the whole Main database and recompute linked IDs users count... Should not be a big issue performance wise though, this is fairly cheap process. --- source/blender/blenloader/intern/readfile.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source/blender') diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index c5a8aaca11c..9b393d3881f 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -8790,6 +8790,15 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) BKE_main_id_tag_all(bfd->main, LIB_TAG_NEW, false); + if (fd->memfile != NULL) { + /* In undo/redo case, we do a whole lot of magic tricks to avoid having to re-read linked datablocks from + * libraries (since those are not supposed to change). + * Unfortunately, that means that we do not reset their user count, however we do increase that one when + * doing lib_link on local IDs using linked ones. + * There is no real way to predict amount of changes here, so we have to fully redo refcounting . */ + BLE_main_id_refcount_recompute(bfd->main, true); + } + lib_verify_nodetree(bfd->main, true); fix_relpaths_library(fd->relabase, bfd->main); /* make all relative paths, relative to the open blend file */ -- cgit v1.2.3