ID: Sanitize handling of 'USER_ONE' (ensure_user) case.
Note that this has little impact on current master - yet it allows to fix the 'Image Editor' bug (open image in editor, use same image in texture, delete image from texture, image us is 0 and red in image editor...) and probably a few other similar cases. But that change is mandatory to get a proper handling of ID deletion/reamapping/reloading/etc. as done in id-remap branch. Instead of just adding a user if none already present, new code use two new ID tags to get a three-states status: - Normal: nothing changes. - Needs extra user: we know that ID needs an extra user, so we take of never going down to 0 in 'real' usercount handling. - Has extra user: we do have increased that ID usercount to get our needed extrauser. Reviewers: sergey, campbellbarton Differential Revision: https://developer.blender.org/D1696
This commit is contained in:
parent
c35ad8d4a3
commit
2ac555fe47
|
@ -162,20 +162,38 @@ void id_lib_extern(ID *id)
|
|||
}
|
||||
|
||||
/* ensure we have a real user */
|
||||
/* Note: Now that we have flags, we could get rid of the 'fake_user' special case, flags are enough to ensure
|
||||
* we always have a real user.
|
||||
* However, ID_REAL_USERS is used in several places outside of core library.c, so think we can wait later
|
||||
* to make this change... */
|
||||
void id_us_ensure_real(ID *id)
|
||||
{
|
||||
if (id) {
|
||||
const int limit = ID_FAKE_USERS(id);
|
||||
id->tag |= LIB_TAG_EXTRAUSER;
|
||||
if (id->us <= limit) {
|
||||
if (id->us < limit) {
|
||||
if (id->us < limit || ((id->us == limit) && (id->tag & LIB_TAG_EXTRAUSER_SET))) {
|
||||
printf("ID user count error: %s (from '%s')\n", id->name, id->lib ? id->lib->filepath : "[Main]");
|
||||
BLI_assert(0);
|
||||
}
|
||||
id->us = limit + 1;
|
||||
id->tag |= LIB_TAG_EXTRAUSER_SET;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Unused currently... */
|
||||
static void UNUSED_FUNCTION(id_us_clear_real)(ID *id)
|
||||
{
|
||||
if (id && (id->tag & LIB_TAG_EXTRAUSER)) {
|
||||
if (id->tag & LIB_TAG_EXTRAUSER_SET) {
|
||||
id->us--;
|
||||
BLI_assert(id->us >= ID_FAKE_USERS(id));
|
||||
}
|
||||
id->tag &= ~(LIB_TAG_EXTRAUSER | LIB_TAG_EXTRAUSER_SET);
|
||||
}
|
||||
}
|
||||
|
||||
void id_us_plus(ID *id)
|
||||
{
|
||||
if (id) {
|
||||
|
@ -190,8 +208,15 @@ void id_us_min(ID *id)
|
|||
{
|
||||
if (id) {
|
||||
const int limit = ID_FAKE_USERS(id);
|
||||
|
||||
if ((id->us == limit) && (id->tag & LIB_TAG_EXTRAUSER) && !(id->tag & LIB_TAG_EXTRAUSER_SET)) {
|
||||
/* We need an extra user here, but never actually incremented user count for it so far, do it now. */
|
||||
id_us_ensure_real(id);
|
||||
}
|
||||
|
||||
if (id->us <= limit) {
|
||||
printf("ID user decrement error: %s (from '%s')\n", id->name, id->lib ? id->lib->filepath : "[Main]");
|
||||
printf("ID user decrement error: %s (from '%s'): %d <= %d\n",
|
||||
id->name, id->lib ? id->lib->filepath : "[Main]", id->us, limit);
|
||||
/* We cannot assert here, because of how we 'delete' datablocks currently (setting their usercount to zero),
|
||||
* this is weak but it's how it works for now. */
|
||||
/* BLI_assert(0); */
|
||||
|
|
|
@ -313,6 +313,11 @@ enum {
|
|||
/* RESET_NEVER tag datablock as a place-holder (because the real one could not be linked from its library e.g.). */
|
||||
LIB_TAG_MISSING = 1 << 6,
|
||||
|
||||
/* tag datablock has having an extra user. */
|
||||
LIB_TAG_EXTRAUSER = 1 << 2,
|
||||
/* tag datablock has having actually increased usercount for the extra virtual user. */
|
||||
LIB_TAG_EXTRAUSER_SET = 1 << 7,
|
||||
|
||||
/* RESET_AFTER_USE tag newly duplicated/copied IDs. */
|
||||
LIB_TAG_NEW = 1 << 8,
|
||||
/* RESET_BEFORE_USE free test flag.
|
||||
|
|
Loading…
Reference in New Issue