diff options
author | Howard Trickey <howard.trickey@gmail.com> | 2020-08-21 00:03:51 +0300 |
---|---|---|
committer | Howard Trickey <howard.trickey@gmail.com> | 2020-08-21 00:03:51 +0300 |
commit | 3b36e2b7817dee8a800f3c4f4b89b7f64da8155b (patch) | |
tree | 62786e141de120bb7765a240ebe7321dfb4007cd /source | |
parent | 57c3718447a4b3db92475ecc86a6d793bd839aef (diff) | |
parent | ce0bcd5fbf40b44c515773434bc7187b093fdb53 (diff) |
Merge branch 'master' into newboolean
Diffstat (limited to 'source')
159 files changed, 2620 insertions, 1996 deletions
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 231cd0e53c5..5ad903a0119 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -39,7 +39,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 0 +#define BLENDER_FILE_SUBVERSION 1 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h index 5843992b25c..9a5700d2fbd 100644 --- a/source/blender/blenkernel/BKE_lib_override.h +++ b/source/blender/blenkernel/BKE_lib_override.h @@ -68,11 +68,20 @@ void BKE_lib_override_library_dependencies_tag(struct Main *bmain, struct ID *id_root, const uint tag, const bool do_create_main_relashionships); +void BKE_lib_override_library_override_group_tag(struct Main *bmain, + struct ID *id_root, + const uint tag, + const bool do_create_main_relashionships); bool BKE_lib_override_library_create(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct ID *id_root, struct ID *id_reference); +bool BKE_lib_override_library_resync(struct Main *bmain, + struct Scene *scene, + struct ViewLayer *view_layer, + struct ID *id_root); +void BKE_lib_override_library_delete(struct Main *bmain, struct ID *id_root); struct IDOverrideLibraryProperty *BKE_lib_override_library_property_find( struct IDOverrideLibrary *override, const char *rna_path); diff --git a/source/blender/blenkernel/BKE_mesh_runtime.h b/source/blender/blenkernel/BKE_mesh_runtime.h index 267be4f44fd..87b55c581a2 100644 --- a/source/blender/blenkernel/BKE_mesh_runtime.h +++ b/source/blender/blenkernel/BKE_mesh_runtime.h @@ -72,9 +72,9 @@ struct Mesh *mesh_get_eval_deform(struct Depsgraph *depsgraph, const struct CustomData_MeshMasks *dataMask); struct Mesh *mesh_create_eval_final(struct Depsgraph *depsgraph, - struct Scene *scene, - struct Object *ob, - const struct CustomData_MeshMasks *dataMask); + struct Scene *scene, + struct Object *ob, + const struct CustomData_MeshMasks *dataMask); struct Mesh *mesh_create_eval_final_index_render(struct Depsgraph *depsgraph, struct Scene *scene, diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 8b3231e5302..06e9e58d6d7 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -102,6 +102,7 @@ void BKE_nlastrip_set_active(struct AnimData *adt, struct NlaStrip *strip); bool BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); void BKE_nlastrip_recalculate_bounds(struct NlaStrip *strip); +void BKE_nlastrip_recalculate_bounds_sync_action(struct NlaStrip *strip); void BKE_nlastrip_validate_name(struct AnimData *adt, struct NlaStrip *strip); diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index e3bd57e75e3..3ab923f05f6 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -110,6 +110,8 @@ void BKE_toolsettings_free(struct ToolSettings *toolsettings); struct Scene *BKE_scene_duplicate(struct Main *bmain, struct Scene *sce, eSceneCopyMethod type); void BKE_scene_groups_relink(struct Scene *sce); +struct Scene *BKE_scene_find_from_view_layer(const struct Main *bmain, + const struct ViewLayer *layer); struct Scene *BKE_scene_find_from_collection(const struct Main *bmain, const struct Collection *collection); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 4f587abd9f0..263f63cb6da 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1991,9 +1991,9 @@ Mesh *mesh_get_eval_deform(struct Depsgraph *depsgraph, } Mesh *mesh_create_eval_final(Depsgraph *depsgraph, - Scene *scene, - Object *ob, - const CustomData_MeshMasks *dataMask) + Scene *scene, + Object *ob, + const CustomData_MeshMasks *dataMask) { Mesh *final; diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 5b5e32f1d81..8fe57f1bfa0 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -2192,7 +2192,15 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels, if (is_inplace_tweak) { /* edit active action in-place according to its active strip, so copy the data */ memcpy(dummy_strip, adt->actstrip, sizeof(NlaStrip)); + /* Prevents nla eval from considering active strip's adj strips. + * For user, this means entering tweak mode on a strip ignores evaluating adjacent strips + * in the same track. */ dummy_strip->next = dummy_strip->prev = NULL; + + /* If tweaked strip is syncing action length, then evaluate using action length. */ + if (dummy_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH) { + BKE_nlastrip_recalculate_bounds_sync_action(dummy_strip); + } } else { /* set settings of dummy NLA strip from AnimData settings */ @@ -2237,9 +2245,11 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels, /* If computing the context for keyframing, store data there instead of the list. */ else { /* The extend mode here effectively controls - * whether it is possible to key-frame beyond the ends. */ - dummy_strip->extendmode = is_inplace_tweak ? NLASTRIP_EXTEND_NOTHING : - NLASTRIP_EXTEND_HOLD; + * whether it is possible to key-frame beyond the ends.*/ + dummy_strip->extendmode = (is_inplace_tweak && + !(dummy_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH)) ? + NLASTRIP_EXTEND_NOTHING : + NLASTRIP_EXTEND_HOLD; r_context->eval_strip = nes = nlastrips_ctime_get_strip( NULL, &dummy_trackslist, -1, anim_eval_context, flush_to_original); diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 0d65ee5faa3..88037a8dad0 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -408,18 +408,28 @@ static Collection *collection_duplicate_recursive(Main *bmain, } if (do_objects) { + /* We need to first duplicate the objects in a separate loop, to support the master collection + * case, where both old and new collections are the same. + * Otherwise, depending on naming scheme and sorting, we may end up duplicating the new objects + * we just added, in some infinite loop. */ + LISTBASE_FOREACH (CollectionObject *, cob, &collection_old->gobject) { + Object *ob_old = cob->ob; + + if (ob_old->id.newid == NULL) { + BKE_object_duplicate( + bmain, ob_old, duplicate_flags, duplicate_options | LIB_ID_DUPLICATE_IS_SUBPROCESS); + } + } + /* We can loop on collection_old's objects, but have to consider it mutable because with master * collections collection_old and collection_new are the same data here. */ LISTBASE_FOREACH_MUTABLE (CollectionObject *, cob, &collection_old->gobject) { Object *ob_old = cob->ob; Object *ob_new = (Object *)ob_old->id.newid; - if (ob_new == NULL) { - ob_new = BKE_object_duplicate( - bmain, ob_old, duplicate_flags, duplicate_options | LIB_ID_DUPLICATE_IS_SUBPROCESS); - } - - if (ob_new == ob_old) { + /* New object can be NULL in master collection case, since new and old objects are in same + * collection. */ + if (ELEM(ob_new, ob_old, NULL)) { continue; } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 05c521e3b94..115980d577e 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -647,9 +647,9 @@ DO_INLINE void collision_interpolateOnTriangle(float to[3], VECADDMUL(to, v3, w3); } -static void cloth_selfcollision_impulse_vert(const float clamp_sq, - const float impulse[3], - struct ClothVertex *vert) +static void cloth_collision_impulse_vert(const float clamp_sq, + const float impulse[3], + struct ClothVertex *vert) { float impulse_len_sq = len_squared_v3(impulse); @@ -681,7 +681,7 @@ static int cloth_collision_response_static(ClothModifierData *clmd, { int result = 0; Cloth *cloth = clmd->clothObject; - const float clamp_sq = square_f(clmd->coll_parms->self_clamp * dt); + const float clamp_sq = square_f(clmd->coll_parms->clamp * dt); const float time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale); const float epsilon2 = BLI_bvhtree_get_epsilon(collmd->bvhtree); const float min_distance = (clmd->coll_parms->epsilon + epsilon2) * (8.0f / 9.0f); @@ -828,10 +828,10 @@ static int cloth_collision_response_static(ClothModifierData *clmd, } if (result) { - cloth_selfcollision_impulse_vert(clamp_sq, i1, &cloth->verts[collpair->ap1]); - cloth_selfcollision_impulse_vert(clamp_sq, i2, &cloth->verts[collpair->ap2]); + cloth_collision_impulse_vert(clamp_sq, i1, &cloth->verts[collpair->ap1]); + cloth_collision_impulse_vert(clamp_sq, i2, &cloth->verts[collpair->ap2]); if (!is_hair) { - cloth_selfcollision_impulse_vert(clamp_sq, i3, &cloth->verts[collpair->ap3]); + cloth_collision_impulse_vert(clamp_sq, i3, &cloth->verts[collpair->ap3]); } } } @@ -987,13 +987,13 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd, } if (result) { - cloth_selfcollision_impulse_vert(clamp_sq, ia[0], &cloth->verts[collpair->ap1]); - cloth_selfcollision_impulse_vert(clamp_sq, ia[1], &cloth->verts[collpair->ap2]); - cloth_selfcollision_impulse_vert(clamp_sq, ia[2], &cloth->verts[collpair->ap3]); + cloth_collision_impulse_vert(clamp_sq, ia[0], &cloth->verts[collpair->ap1]); + cloth_collision_impulse_vert(clamp_sq, ia[1], &cloth->verts[collpair->ap2]); + cloth_collision_impulse_vert(clamp_sq, ia[2], &cloth->verts[collpair->ap3]); - cloth_selfcollision_impulse_vert(clamp_sq, ib[0], &cloth->verts[collpair->bp1]); - cloth_selfcollision_impulse_vert(clamp_sq, ib[1], &cloth->verts[collpair->bp2]); - cloth_selfcollision_impulse_vert(clamp_sq, ib[2], &cloth->verts[collpair->bp3]); + cloth_collision_impulse_vert(clamp_sq, ib[0], &cloth->verts[collpair->bp1]); + cloth_collision_impulse_vert(clamp_sq, ib[1], &cloth->verts[collpair->bp2]); + cloth_collision_impulse_vert(clamp_sq, ib[2], &cloth->verts[collpair->bp3]); } } diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 09305434289..4f65f8a57ab 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -532,6 +532,7 @@ bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[]) gpd->grid.lines = GP_DEFAULT_GRID_LINES; /* Number of lines */ /* Onion-skinning settings (data-block level) */ + gpd->onion_keytype = -1; /* All by default. */ gpd->onion_flag |= (GP_ONION_GHOST_PREVCOL | GP_ONION_GHOST_NEXTCOL); gpd->onion_flag |= GP_ONION_FADE; gpd->onion_mode = GP_ONION_MODE_RELATIVE; diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 5b45148ed63..cca312270bc 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -361,7 +361,10 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain) return success; } -static bool lib_override_hierarchy_recursive_tag(Main *bmain, ID *id, const uint tag) +static bool lib_override_hierarchy_recursive_tag(Main *bmain, + ID *id, + const uint tag, + Library *override_group_lib_reference) { void **entry_vp = BLI_ghash_lookup_p(bmain->relations->id_user_to_used, id); if (entry_vp == NULL) { @@ -369,6 +372,11 @@ static bool lib_override_hierarchy_recursive_tag(Main *bmain, ID *id, const uint return (id->tag & tag) != 0; } + if (override_group_lib_reference != NULL && ID_IS_OVERRIDE_LIBRARY_REAL(id) && + id->override_library->reference->lib == override_group_lib_reference) { + id->tag |= tag; + } + /* This way we won't process again that ID should we encounter it again through another * relationship hierarchy. * Note that this does not free any memory from relations, so we can still use the entries. @@ -383,7 +391,9 @@ static bool lib_override_hierarchy_recursive_tag(Main *bmain, ID *id, const uint } /* We only consider IDs from the same library. */ if (entry->id_pointer != NULL && (*entry->id_pointer)->lib == id->lib) { - if (lib_override_hierarchy_recursive_tag(bmain, *entry->id_pointer, tag)) { + if (lib_override_hierarchy_recursive_tag( + bmain, *entry->id_pointer, tag, override_group_lib_reference) && + override_group_lib_reference == NULL) { id->tag |= tag; } } @@ -395,6 +405,7 @@ static bool lib_override_hierarchy_recursive_tag(Main *bmain, ID *id, const uint /** * Tag all IDs in given \a bmain that are being used by given \a id_root ID or its dependencies, * recursively. + * It detects and tag only chains of dependencies marked at both ends by given tag. * * This will include all local IDs, and all IDs from the same library as the \a id_root. * @@ -402,8 +413,8 @@ static bool lib_override_hierarchy_recursive_tag(Main *bmain, ID *id, const uint * \param do_create_main_relashionships Whether main relations needs to be created or already exist * (in any case, they will be freed by this function). */ -void BKE_lib_override_library_dependencies_tag(struct Main *bmain, - struct ID *id_root, +void BKE_lib_override_library_dependencies_tag(Main *bmain, + ID *id_root, const uint tag, const bool do_create_main_relashionships) { @@ -411,10 +422,36 @@ void BKE_lib_override_library_dependencies_tag(struct Main *bmain, BKE_main_relations_create(bmain, 0); } - /* Then we tag all intermediary data-blocks in-between two overridden ones (e.g. if a shapekey + /* We tag all intermediary data-blocks in-between two overridden ones (e.g. if a shapekey * has a driver using an armature object's bone, we need to override the shapekey/obdata, the * objects using them, etc.) */ - lib_override_hierarchy_recursive_tag(bmain, id_root, tag); + lib_override_hierarchy_recursive_tag(bmain, id_root, tag, NULL); + + BKE_main_relations_free(bmain); +} + +/** + * Tag all IDs in given \a bmain that are part of the same \a id_root liboverride ID group. + * That is, all other liboverrides IDs (in)directly used by \a is_root one, sharing the same + * library for their reference IDs. + * + * \param id_root The root of the hierarchy of liboverride dependencies to be tagged. + * \param do_create_main_relashionships Whether main relations needs to be created or already exist + * (in any case, they will be freed by this function). + */ +void BKE_lib_override_library_override_group_tag(Main *bmain, + ID *id_root, + const uint tag, + const bool do_create_main_relashionships) +{ + if (do_create_main_relashionships) { + BKE_main_relations_create(bmain, 0); + } + + /* We tag all liboverride data-blocks from the same library as reference one, + * being used by the root ID. */ + lib_override_hierarchy_recursive_tag( + bmain, id_root, tag, id_root->override_library->reference->lib); BKE_main_relations_free(bmain); } @@ -459,26 +496,7 @@ static int lib_override_library_make_tag_ids_cb(LibraryIDLinkCallbackData *cb_da return IDWALK_RET_NOP; } -/** - * Advanced 'smart' function to create fully functional overrides. - * - * \note Currently it only does special things if given \a id_root is an object of collection, more - * specific behaviors may be added in the future for other ID types. - * - * \note It will overrides all IDs tagged with \a LIB_TAG_DOIT, and it does not clear that tag at - * its beginning, so caller code can add extra data-blocks to be overridden as well. - * - * \note In the future that same function may be extended to support 'refresh' of overrides - * (rebuilding overrides from linked data, trying to preserve local overrides already defined). - * - * \param id_root The root ID to create an override from. - * \param id_reference some reference ID used to do some post-processing after overrides have been - * created, may be NULL. Typically, the Empty object instantiating the linked - * collection we override, currently. - * \return true if override was successfully created. - */ -bool BKE_lib_override_library_create( - Main *bmain, Scene *scene, ViewLayer *view_layer, ID *id_root, ID *id_reference) +static bool lib_override_library_create_do(Main *bmain, ID *id_root) { /* Tag all collections and objects, as well as other IDs using them. */ id_root->tag |= LIB_TAG_DOIT; @@ -508,115 +526,308 @@ bool BKE_lib_override_library_create( /* Note that this call will also free the main relations data we created above. */ BKE_lib_override_library_dependencies_tag(bmain, id_root, LIB_TAG_DOIT, false); - const bool success = BKE_lib_override_library_create_from_tag(bmain); - - if (success) { - BKE_main_collection_sync(bmain); - - switch (GS(id_root->name)) { - case ID_GR: { - Object *ob_reference = id_reference != NULL && GS(id_reference->name) == ID_OB ? - (Object *)id_reference : - NULL; - Collection *collection_new = ((Collection *)id_root->newid); - if (ob_reference != NULL) { - BKE_collection_add_from_object(bmain, scene, ob_reference, collection_new); - } - else { - BKE_collection_add_from_collection( - bmain, scene, ((Collection *)id_root), collection_new); - } + return BKE_lib_override_library_create_from_tag(bmain); +} - FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection_new, ob_new) { - if (ob_new != NULL && ob_new->id.override_library != NULL) { - if (ob_reference != NULL) { - Base *base; - if ((base = BKE_view_layer_base_find(view_layer, ob_new)) == NULL) { - BKE_collection_object_add_from(bmain, scene, ob_reference, ob_new); - base = BKE_view_layer_base_find(view_layer, ob_new); - DEG_id_tag_update_ex( - bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); - } +static void lib_override_library_create_post_process( + Main *bmain, Scene *scene, ViewLayer *view_layer, ID *id_root, ID *id_reference) +{ + BKE_main_collection_sync(bmain); + + switch (GS(id_root->name)) { + case ID_GR: { + Object *ob_reference = id_reference != NULL && GS(id_reference->name) == ID_OB ? + (Object *)id_reference : + NULL; + Collection *collection_new = ((Collection *)id_root->newid); + if (ob_reference != NULL) { + BKE_collection_add_from_object(bmain, scene, ob_reference, collection_new); + } + else { + BKE_collection_add_from_collection(bmain, scene, ((Collection *)id_root), collection_new); + } - if (ob_new == (Object *)ob_reference->id.newid) { - /* TODO: is setting active needed? */ - BKE_view_layer_base_select_and_set_active(view_layer, base); - } - } - else if (BKE_view_layer_base_find(view_layer, ob_new) == NULL) { - BKE_collection_object_add(bmain, collection_new, ob_new); + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection_new, ob_new) { + if (ob_new != NULL && ob_new->id.override_library != NULL) { + if (ob_reference != NULL) { + Base *base; + if ((base = BKE_view_layer_base_find(view_layer, ob_new)) == NULL) { + BKE_collection_object_add_from(bmain, scene, ob_reference, ob_new); + base = BKE_view_layer_base_find(view_layer, ob_new); DEG_id_tag_update_ex(bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); } + + if (ob_new == (Object *)ob_reference->id.newid) { + /* TODO: is setting active needed? */ + BKE_view_layer_base_select_and_set_active(view_layer, base); + } + } + else if (BKE_view_layer_base_find(view_layer, ob_new) == NULL) { + BKE_collection_object_add(bmain, collection_new, ob_new); + DEG_id_tag_update_ex(bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); } } - FOREACH_COLLECTION_OBJECT_RECURSIVE_END; - break; } - case ID_OB: { - BKE_collection_object_add_from( - bmain, scene, (Object *)id_root, ((Object *)id_root->newid)); - break; - } - default: - break; + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + break; } + case ID_OB: { + BKE_collection_object_add_from(bmain, scene, (Object *)id_root, ((Object *)id_root->newid)); + break; + } + default: + break; + } - /* We need to ensure all new overrides of objects are properly instantiated. */ - LISTBASE_FOREACH (Object *, ob, &bmain->objects) { - Object *ob_new = (Object *)ob->id.newid; - if (ob_new != NULL) { - BLI_assert(ob_new->id.override_library != NULL && - ob_new->id.override_library->reference == &ob->id); - - Collection *default_instantiating_collection = NULL; - if (BKE_view_layer_base_find(view_layer, ob_new) == NULL) { - if (default_instantiating_collection == NULL) { - switch (GS(id_root->name)) { - case ID_GR: { - default_instantiating_collection = BKE_collection_add( - bmain, (Collection *)id_root, "OVERRIDE_HIDDEN"); - break; - } - case ID_OB: { - /* Add the new container collection to one of the collections instantiating the - * root object, or scene's master collection if none found. */ - Object *ob_root = (Object *)id_root; - LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { - if (BKE_collection_has_object(collection, ob_root) && - BKE_view_layer_has_collection(view_layer, collection) && - !ID_IS_LINKED(collection) && !ID_IS_OVERRIDE_LIBRARY(collection)) { - default_instantiating_collection = BKE_collection_add( - bmain, collection, "OVERRIDE_HIDDEN"); - } - } - if (default_instantiating_collection == NULL) { + /* We need to ensure all new overrides of objects are properly instantiated. */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + Object *ob_new = (Object *)ob->id.newid; + if (ob_new != NULL) { + BLI_assert(ob_new->id.override_library != NULL && + ob_new->id.override_library->reference == &ob->id); + + Collection *default_instantiating_collection = NULL; + if (BKE_view_layer_base_find(view_layer, ob_new) == NULL) { + if (default_instantiating_collection == NULL) { + switch (GS(id_root->name)) { + case ID_GR: { + default_instantiating_collection = BKE_collection_add( + bmain, (Collection *)id_root, "OVERRIDE_HIDDEN"); + break; + } + case ID_OB: { + /* Add the new container collection to one of the collections instantiating the + * root object, or scene's master collection if none found. */ + Object *ob_root = (Object *)id_root; + LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { + if (BKE_collection_has_object(collection, ob_root) && + BKE_view_layer_has_collection(view_layer, collection) && + !ID_IS_LINKED(collection) && !ID_IS_OVERRIDE_LIBRARY(collection)) { default_instantiating_collection = BKE_collection_add( - bmain, scene->master_collection, "OVERRIDE_HIDDEN"); + bmain, collection, "OVERRIDE_HIDDEN"); } - break; } - default: - BLI_assert(0); + if (default_instantiating_collection == NULL) { + default_instantiating_collection = BKE_collection_add( + bmain, scene->master_collection, "OVERRIDE_HIDDEN"); + } + break; } - /* Hide the collection from viewport and render. */ - default_instantiating_collection->flag |= COLLECTION_RESTRICT_VIEWPORT | - COLLECTION_RESTRICT_RENDER; + default: + BLI_assert(0); + } + /* Hide the collection from viewport and render. */ + default_instantiating_collection->flag |= COLLECTION_RESTRICT_VIEWPORT | + COLLECTION_RESTRICT_RENDER; + } + + BKE_collection_object_add(bmain, default_instantiating_collection, ob_new); + DEG_id_tag_update_ex(bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); + } + } + } +} + +/** + * Advanced 'smart' function to create fully functional overrides. + * + * \note Currently it only does special things if given \a id_root is an object of collection, more + * specific behaviors may be added in the future for other ID types. + * + * \note It will overrides all IDs tagged with \a LIB_TAG_DOIT, and it does not clear that tag at + * its beginning, so caller code can add extra data-blocks to be overridden as well. + * + * \note In the future that same function may be extended to support 'refresh' of overrides + * (rebuilding overrides from linked data, trying to preserve local overrides already defined). + * + * \param id_root The root ID to create an override from. + * \param id_reference some reference ID used to do some post-processing after overrides have been + * created, may be NULL. Typically, the Empty object instantiating the linked + * collection we override, currently. + * \return true if override was successfully created. + */ +bool BKE_lib_override_library_create( + Main *bmain, Scene *scene, ViewLayer *view_layer, ID *id_root, ID *id_reference) +{ + const bool success = lib_override_library_create_do(bmain, id_root); + + if (!success) { + return success; + } + + lib_override_library_create_post_process(bmain, scene, view_layer, id_root, id_reference); + + /* Cleanup. */ + BKE_main_id_clear_newpoins(bmain); + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + + return success; +} + +/** + * Advanced 'smart' function to resync, re-create fully functional overrides up-to-date with linked + * data, from an existing override hierarchy. + * + * \param id_root The root liboverride ID to resync from. + * \return true if override was successfully resynced. + */ +bool BKE_lib_override_library_resync(Main *bmain, Scene *scene, ViewLayer *view_layer, ID *id_root) +{ + BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root)); + + /* Tag all collections and objects, as well as other IDs using them. */ + id_root->tag |= LIB_TAG_DOIT; + ID *id_root_reference = id_root->override_library->reference; + + /* Make a mapping 'linked reference IDs' -> 'Local override IDs' of existing overrides, and tag + * linked reference ones to be overridden again. */ + BKE_lib_override_library_override_group_tag(bmain, id_root, LIB_TAG_DOIT, true); + + GHash *linkedref_to_old_override = BLI_ghash_new( + BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); + ID *id; + FOREACH_MAIN_ID_BEGIN (bmain, id) { + if (id->tag & LIB_TAG_DOIT && ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + /* While this should not happen in typical cases (and won't be properly supported here), user + * is free to do all kind of very bad things, including having different local overrides of a + * same linked ID in a same hierarchy... */ + if (!BLI_ghash_haskey(linkedref_to_old_override, id->override_library->reference)) { + BLI_ghash_insert(linkedref_to_old_override, id->override_library->reference, id); + id->override_library->reference->tag |= LIB_TAG_DOIT; + } + } + } + FOREACH_MAIN_ID_END; + + /* Make new override from linked data. */ + /* Note that this call also remap all pointers of tagged IDs from old override IDs to new + * override IDs (including within the old overrides themselves, since those are tagged too + * above). */ + const bool success = lib_override_library_create_do(bmain, id_root_reference); + + if (!success) { + return success; + } + + ListBase *lb; + FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) { + FOREACH_MAIN_LISTBASE_ID_BEGIN (lb, id) { + if (id->tag & LIB_TAG_DOIT && id->newid != NULL && ID_IS_LINKED(id)) { + ID *id_override_new = id->newid; + ID *id_override_old = BLI_ghash_lookup(linkedref_to_old_override, id); + + if (id_override_old != NULL) { + /* Swap the names between old override ID and new one. */ + char id_name_buf[MAX_ID_NAME]; + memcpy(id_name_buf, id_override_old->name, sizeof(id_name_buf)); + memcpy(id_override_old->name, id_override_new->name, sizeof(id_override_old->name)); + memcpy(id_override_new->name, id_name_buf, sizeof(id_override_new->name)); + /* Note that this is very efficient way to keep BMain IDs ordered as expected after + * swapping their names. + * However, one has to be very careful with this when iterating over the listbase at the + * same time. Here it works because we only execute this code when we are in the linked + * IDs, which are always *after* all local ones, and we only affect local IDs. */ + BLI_listbase_swaplinks(lb, id_override_old, id_override_new); + + /* Remap the whole local IDs to use the new override. */ + BKE_libblock_remap( + bmain, id_override_old, id_override_new, ID_REMAP_SKIP_INDIRECT_USAGE); + + /* Copy over overrides rules from old override ID to new one. */ + BLI_duplicatelist(&id_override_new->override_library->properties, + &id_override_old->override_library->properties); + for (IDOverrideLibraryProperty * + op_new = id_override_new->override_library->properties.first, + *op_old = id_override_old->override_library->properties.first; + op_new; + op_new = op_new->next, op_old = op_old->next) { + lib_override_library_property_copy(op_new, op_old); } - BKE_collection_object_add(bmain, default_instantiating_collection, ob_new); - DEG_id_tag_update_ex(bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); + /* Apply rules on new override ID using old one as 'source' data. */ + /* Note that since we already remapped ID pointers in old override IDs to new ones, we + * can also apply ID pointer override rules safely here. */ + PointerRNA rnaptr_src, rnaptr_dst; + RNA_id_pointer_create(id_override_old, &rnaptr_src); + RNA_id_pointer_create(id_override_new, &rnaptr_dst); + + RNA_struct_override_apply( + bmain, &rnaptr_dst, &rnaptr_src, NULL, id_override_new->override_library); } } } + FOREACH_MAIN_LISTBASE_ID_END; + } + FOREACH_MAIN_LISTBASE_END; + + /* Delete old override IDs. */ + FOREACH_MAIN_ID_BEGIN (bmain, id) { + if (id->tag & LIB_TAG_DOIT && id->newid != NULL && ID_IS_LINKED(id)) { + ID *id_override_old = BLI_ghash_lookup(linkedref_to_old_override, id); + + if (id_override_old != NULL) { + BKE_id_delete(bmain, id_override_old); + } + } } + FOREACH_MAIN_ID_END; + + /* Essentially ensures that potentially new overrides of new objects will be instantiated. */ + lib_override_library_create_post_process(bmain, scene, view_layer, id_root_reference, id_root); /* Cleanup. */ + BLI_ghash_free(linkedref_to_old_override, NULL, NULL); + BKE_main_id_clear_newpoins(bmain); BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); return success; } +/** + * Advanced 'smart' function to delete library overrides (including their existing override + * hierarchy) and remap their usages to their linked reference IDs. + * + * \note All IDs tagged with `LIB_TAG_DOIT` will be deleted. + * + * \param id_root The root liboverride ID to resync from. + */ +void BKE_lib_override_library_delete(Main *bmain, ID *id_root) +{ + BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root)); + + /* Tag all collections and objects, as well as other IDs using them. */ + id_root->tag |= LIB_TAG_DOIT; + + /* Make a mapping 'linked reference IDs' -> 'Local override IDs' of existing overrides, and tag + * linked reference ones to be overridden again. */ + BKE_lib_override_library_override_group_tag(bmain, id_root, LIB_TAG_DOIT, true); + + ID *id; + FOREACH_MAIN_ID_BEGIN (bmain, id) { + if (id->tag & LIB_TAG_DOIT) { + if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + ID *id_override_reference = id->override_library->reference; + + /* Remap the whole local IDs to use the linked data. */ + BKE_libblock_remap(bmain, id, id_override_reference, ID_REMAP_SKIP_INDIRECT_USAGE); + } + } + } + FOREACH_MAIN_ID_END; + + /* Delete the override IDs. */ + FOREACH_MAIN_ID_BEGIN (bmain, id) { + if (id->tag & LIB_TAG_DOIT) { + BKE_id_delete(bmain, id); + } + } + FOREACH_MAIN_ID_END; + + /* Should not actually be needed here... */ + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); +} + BLI_INLINE IDOverrideLibraryRuntime *override_library_rna_path_runtime_ensure( IDOverrideLibrary *override) { diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 1ba82b352d1..e5527ed987a 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -1361,6 +1361,25 @@ static void nlastrip_fix_resize_overlaps(NlaStrip *strip) } } +/** Recalculate the start and end frames for the strip to match the bounds of its action such that + * the overall NLA animation result is unchanged. */ +void BKE_nlastrip_recalculate_bounds_sync_action(NlaStrip *strip) +{ + float prev_actstart; + + if (strip == NULL || strip->type != NLASTRIP_TYPE_CLIP) { + return; + } + + prev_actstart = strip->actstart; + + calc_action_range(strip->act, &strip->actstart, &strip->actend, 0); + + /* Set start such that key's do not visually move, to preserve the overall animation result. */ + strip->start += (strip->actstart - prev_actstart) * strip->scale; + + BKE_nlastrip_recalculate_bounds(strip); +} /* Recalculate the start and end frames for the current strip, after changing * the extents of the action or the mapping (repeats or scale factor) info */ @@ -2133,11 +2152,7 @@ void BKE_nla_tweakmode_exit(AnimData *adt) /* must be action-clip only (transitions don't have scale) */ if ((strip->type == NLASTRIP_TYPE_CLIP) && (strip->act)) { - /* recalculate the length of the action */ - calc_action_range(strip->act, &strip->actstart, &strip->actend, 0); - - /* adjust the strip extents in response to this */ - BKE_nlastrip_recalculate_bounds(strip); + BKE_nlastrip_recalculate_bounds_sync_action(strip); } } @@ -2151,11 +2166,7 @@ void BKE_nla_tweakmode_exit(AnimData *adt) /* sync strip extents if this strip uses the same action */ if ((adt->actstrip) && (adt->actstrip->act == strip->act) && (strip->flag & NLASTRIP_FLAG_SYNC_LENGTH)) { - /* recalculate the length of the action */ - calc_action_range(strip->act, &strip->actstart, &strip->actend, 0); - - /* adjust the strip extents in response to this */ - BKE_nlastrip_recalculate_bounds(strip); + BKE_nlastrip_recalculate_bounds_sync_action(strip); } /* clear tweakuser flag */ diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 6f1cca619ff..1dc51c9ddae 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1129,6 +1129,17 @@ int BKE_scene_base_iter_next( return iter->phase; } +Scene *BKE_scene_find_from_view_layer(const Main *bmain, const ViewLayer *layer) +{ + for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { + if (BLI_findindex(&scene->view_layers, layer) != -1) { + return scene; + } + } + + return NULL; +} + Scene *BKE_scene_find_from_collection(const Main *bmain, const Collection *collection) { for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { @@ -2246,6 +2257,7 @@ static Depsgraph **scene_get_depsgraph_p(Main *bmain, { BLI_assert(scene != NULL); BLI_assert(view_layer != NULL); + BLI_assert(BKE_scene_find_from_view_layer(bmain, view_layer) == scene); /* Make sure hash itself exists. */ if (allocate_ghash_entry) { BKE_scene_ensure_depsgraph_hash(scene); diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index c6daecbcee6..aba9b255f40 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -2437,16 +2437,16 @@ static void transform_image(int x, } static void do_transform_effect(const SeqRenderData *context, - Sequence *seq, - float UNUSED(cfra), - float UNUSED(facf0), - float UNUSED(facf1), - ImBuf *ibuf1, - ImBuf *UNUSED(ibuf2), - ImBuf *UNUSED(ibuf3), - int start_line, - int total_lines, - ImBuf *out) + Sequence *seq, + float UNUSED(cfra), + float UNUSED(facf0), + float UNUSED(facf1), + ImBuf *ibuf1, + ImBuf *UNUSED(ibuf2), + ImBuf *UNUSED(ibuf3), + int start_line, + int total_lines, + ImBuf *out) { Scene *scene = context->scene; TransformVars *transform = (TransformVars *)seq->effectdata; diff --git a/source/blender/blenlib/BLI_array.hh b/source/blender/blenlib/BLI_array.hh index 9d09bb3559e..0ffe6b9a750 100644 --- a/source/blender/blenlib/BLI_array.hh +++ b/source/blender/blenlib/BLI_array.hh @@ -77,32 +77,39 @@ class Array { /** * By default an empty array is created. */ - Array() + Array(Allocator allocator = {}) noexcept : allocator_(allocator) { data_ = inline_buffer_; size_ = 0; } + Array(NoExceptConstructor, Allocator allocator = {}) noexcept : Array(allocator) + { + } + /** * Create a new array that contains copies of all values. */ template<typename U, typename std::enable_if_t<std::is_convertible_v<U, T>> * = nullptr> - Array(Span<U> values, Allocator allocator = {}) : allocator_(allocator) + Array(Span<U> values, Allocator allocator = {}) : Array(NoExceptConstructor(), allocator) { - size_ = values.size(); - data_ = this->get_buffer_for_size(values.size()); - uninitialized_convert_n<U, T>(values.data(), size_, data_); + const int64_t size = values.size(); + data_ = this->get_buffer_for_size(size); + uninitialized_convert_n<U, T>(values.data(), size, data_); + size_ = size; } /** * Create a new array that contains copies of all values. */ template<typename U, typename std::enable_if_t<std::is_convertible_v<U, T>> * = nullptr> - Array(const std::initializer_list<U> &values) : Array(Span<U>(values)) + Array(const std::initializer_list<U> &values, Allocator allocator = {}) + : Array(Span<U>(values), allocator) { } - Array(const std::initializer_list<T> &values) : Array(Span<T>(values)) + Array(const std::initializer_list<T> &values, Allocator allocator = {}) + : Array(Span<T>(values), allocator) { } @@ -114,23 +121,24 @@ class Array { * even for non-trivial types. This should not be the default though, because one can easily mess * up when dealing with uninitialized memory. */ - explicit Array(int64_t size) + explicit Array(int64_t size, Allocator allocator = {}) : Array(NoExceptConstructor(), allocator) { - size_ = size; data_ = this->get_buffer_for_size(size); default_construct_n(data_, size); + size_ = size; } /** * Create a new array with the given size. All values will be initialized by copying the given * default. */ - Array(int64_t size, const T &value) + Array(int64_t size, const T &value, Allocator allocator = {}) + : Array(NoExceptConstructor(), allocator) { BLI_assert(size >= 0); - size_ = size; data_ = this->get_buffer_for_size(size); - uninitialized_fill_n(data_, size_, value); + uninitialized_fill_n(data_, size, value); + size_ = size; } /** @@ -145,28 +153,28 @@ class Array { * Usage: * Array<std::string> my_strings(10, NoInitialization()); */ - Array(int64_t size, NoInitialization) + Array(int64_t size, NoInitialization, Allocator allocator = {}) + : Array(NoExceptConstructor(), allocator) { BLI_assert(size >= 0); - size_ = size; data_ = this->get_buffer_for_size(size); + size_ = size; } Array(const Array &other) : Array(other.as_span(), other.allocator_) { } - Array(Array &&other) noexcept : allocator_(other.allocator_) + Array(Array &&other) noexcept(std::is_nothrow_move_constructible_v<T>) + : Array(NoExceptConstructor(), other.allocator_) { - size_ = other.size_; - - if (!other.uses_inline_buffer()) { - data_ = other.data_; + if (other.uses_inline_buffer()) { + uninitialized_relocate_n(other.data_, other.size_, data_); } else { - data_ = this->get_buffer_for_size(size_); - uninitialized_relocate_n(other.data_, size_, data_); + data_ = other.data_; } + size_ = other.size_; other.data_ = other.inline_buffer_; other.size_ = 0; @@ -182,24 +190,12 @@ class Array { Array &operator=(const Array &other) { - if (this == &other) { - return *this; - } - - this->~Array(); - new (this) Array(other); - return *this; + return copy_assign_container(*this, other); } - Array &operator=(Array &&other) + Array &operator=(Array &&other) noexcept(std::is_nothrow_move_constructible_v<T>) { - if (this == &other) { - return *this; - } - - this->~Array(); - new (this) Array(std::move(other)); - return *this; + return move_assign_container(*this, std::move(other)); } T &operator[](int64_t index) diff --git a/source/blender/blenlib/BLI_memory_utils.hh b/source/blender/blenlib/BLI_memory_utils.hh index 7216536a884..49076bb1aae 100644 --- a/source/blender/blenlib/BLI_memory_utils.hh +++ b/source/blender/blenlib/BLI_memory_utils.hh @@ -162,7 +162,7 @@ void uninitialized_convert_n(const From *src, int64_t n, To *dst) int64_t current = 0; try { for (; current < n; current++) { - new (static_cast<void *>(dst + current)) To((To)src[current]); + new (static_cast<void *>(dst + current)) To(static_cast<To>(src[current])); } } catch (...) { @@ -410,6 +410,15 @@ class NoInitialization { }; /** + * This can be used to mark a constructor of an object that does not throw exceptions. Other + * constructors can delegate to this constructor to make sure that the object lifetime starts. + * With this, the destructor of the object will be called, even when the remaining constructor + * throws. + */ +class NoExceptConstructor { +}; + +/** * Helper variable that checks if a pointer type can be converted into another pointer type without * issues. Possible issues are casting away const and casting a pointer to a child class. * Adding const or casting to a parent class is fine. @@ -427,4 +436,49 @@ inline constexpr int64_t default_inline_buffer_capacity(size_t element_size) return (static_cast<int64_t>(element_size) < 100) ? 4 : 0; } +/** + * This can be used by containers to implement an exception-safe copy-assignment-operator. + * It assumes that the container has an exception safe copy constructor and an exception-safe + * move-assignment-operator. + */ +template<typename Container> Container ©_assign_container(Container &dst, const Container &src) +{ + if (&src == &dst) { + return dst; + } + + Container container_copy{src}; + dst = std::move(container_copy); + return dst; +} + +/** + * This can be used by containers to implement an exception-safe move-assignment-operator. + * It assumes that the container has an exception-safe move-constructor and a noexcept constructor + * tagged with the NoExceptConstructor tag. + */ +template<typename Container> +Container &move_assign_container(Container &dst, Container &&src) noexcept( + std::is_nothrow_move_constructible_v<Container>) +{ + if (&dst == &src) { + return dst; + } + + dst.~Container(); + if constexpr (std::is_nothrow_move_constructible_v<Container>) { + new (&dst) Container(std::move(src)); + } + else { + try { + new (&dst) Container(std::move(src)); + } + catch (...) { + new (&dst) Container(NoExceptConstructor()); + throw; + } + } + return dst; +} + } // namespace blender diff --git a/source/blender/blenlib/BLI_stack.hh b/source/blender/blenlib/BLI_stack.hh index 8eca356ec54..a463ac102f1 100644 --- a/source/blender/blenlib/BLI_stack.hh +++ b/source/blender/blenlib/BLI_stack.hh @@ -117,7 +117,7 @@ class Stack { /** * Initialize an empty stack. No heap allocation is done. */ - Stack(Allocator allocator = {}) : allocator_(allocator) + Stack(Allocator allocator = {}) noexcept : allocator_(allocator) { inline_chunk_.below = nullptr; inline_chunk_.above = nullptr; @@ -129,11 +129,15 @@ class Stack { size_ = 0; } + Stack(NoExceptConstructor, Allocator allocator = {}) noexcept : Stack(allocator) + { + } + /** * Create a new stack that contains the given elements. The values are pushed to the stack in * the order they are in the array. */ - Stack(Span<T> values) : Stack() + Stack(Span<T> values, Allocator allocator = {}) : Stack(NoExceptConstructor(), allocator) { this->push_multiple(values); } @@ -147,11 +151,12 @@ class Stack { * assert(stack.pop() == 6); * assert(stack.pop() == 5); */ - Stack(const std::initializer_list<T> &values) : Stack(Span<T>(values)) + Stack(const std::initializer_list<T> &values, Allocator allocator = {}) + : Stack(Span<T>(values), allocator) { } - Stack(const Stack &other) : Stack(other.allocator_) + Stack(const Stack &other) : Stack(NoExceptConstructor(), other.allocator_) { for (const Chunk *chunk = &other.inline_chunk_; chunk; chunk = chunk->above) { const T *begin = chunk->begin; @@ -160,7 +165,8 @@ class Stack { } } - Stack(Stack &&other) noexcept : Stack(other.allocator_) + Stack(Stack &&other) noexcept(std::is_nothrow_move_constructible_v<T>) + : Stack(NoExceptConstructor(), other.allocator_) { uninitialized_relocate_n<T>( other.inline_buffer_, std::min(other.size_, InlineBufferCapacity), inline_buffer_); @@ -197,28 +203,14 @@ class Stack { } } - Stack &operator=(const Stack &stack) + Stack &operator=(const Stack &other) { - if (this == &stack) { - return *this; - } - - this->~Stack(); - new (this) Stack(stack); - - return *this; + return copy_assign_container(*this, other); } - Stack &operator=(Stack &&stack) + Stack &operator=(Stack &&other) { - if (this == &stack) { - return *this; - } - - this->~Stack(); - new (this) Stack(std::move(stack)); - - return *this; + return move_assign_container(*this, std::move(other)); } /** @@ -226,21 +218,26 @@ class Stack { */ void push(const T &value) { - if (top_ == top_chunk_->capacity_end) { - this->activate_next_chunk(1); - } - new (top_) T(value); - top_++; - size_++; + this->push_as(value); } void push(T &&value) { + this->push_as(std::move(value)); + } + template<typename ForwardT> void push_as(ForwardT &&value) + { if (top_ == top_chunk_->capacity_end) { this->activate_next_chunk(1); } - new (top_) T(std::move(value)); - top_++; - size_++; + try { + new (top_) T(std::forward<ForwardT>(value)); + top_++; + size_++; + } + catch (...) { + this->move_top_pointer_back_to_below_chunk(); + throw; + } } /** @@ -250,8 +247,8 @@ class Stack { T pop() { BLI_assert(size_ > 0); + T value = std::move(*(top_ - 1)); top_--; - T value = std::move(*top_); top_->~T(); size_--; @@ -296,13 +293,18 @@ class Stack { const int64_t remaining_capacity = top_chunk_->capacity_end - top_; const int64_t amount = std::min(remaining_values.size(), remaining_capacity); - uninitialized_copy_n(remaining_values.data(), amount, top_); + try { + uninitialized_copy_n(remaining_values.data(), amount, top_); + } + catch (...) { + this->move_top_pointer_back_to_below_chunk(); + throw; + } top_ += amount; + size_ += amount; remaining_values = remaining_values.drop_front(amount); } - - size_ += values.size(); } /** @@ -332,6 +334,15 @@ class Stack { top_ = top_chunk_->begin; } + /* This should only be called by unit tests. */ + bool is_invariant_maintained() const + { + if (size_ == 0) { + return top_ == inline_chunk_.begin; + } + return top_ > top_chunk_->begin; + } + private: /** * Changes top_chunk_ to point to a new chunk that is above the current one. The new chunk might @@ -365,6 +376,18 @@ class Stack { top_ = top_chunk_->begin; } + void move_top_pointer_back_to_below_chunk() + { + /* This makes sure that the invariant stays intact after a failed push. */ + if (size_ == 0) { + top_ = inline_chunk_.begin; + } + else if (top_ == top_chunk_->begin) { + top_chunk_ = top_chunk_->below; + top_ = top_chunk_->capacity_end; + } + } + void destruct_all_elements() { for (T *value = top_chunk_->begin; value != top_; value++) { diff --git a/source/blender/blenlib/BLI_vector.hh b/source/blender/blenlib/BLI_vector.hh index 74ce8dd42e7..392b6cd9f47 100644 --- a/source/blender/blenlib/BLI_vector.hh +++ b/source/blender/blenlib/BLI_vector.hh @@ -118,7 +118,7 @@ class Vector { * Create an empty vector. * This does not do any memory allocation. */ - Vector(Allocator allocator = {}) : allocator_(allocator) + Vector(Allocator allocator = {}) noexcept : allocator_(allocator) { begin_ = inline_buffer_; end_ = begin_; @@ -126,12 +126,17 @@ class Vector { UPDATE_VECTOR_SIZE(this); } + Vector(NoExceptConstructor, Allocator allocator = {}) noexcept : Vector(allocator) + { + } + /** * Create a vector with a specific size. * The elements will be default constructed. * If T is trivially constructible, the elements in the vector are not touched. */ - explicit Vector(int64_t size) : Vector() + explicit Vector(int64_t size, Allocator allocator = {}) + : Vector(NoExceptConstructor(), allocator) { this->resize(size); } @@ -139,7 +144,8 @@ class Vector { /** * Create a vector filled with a specific value. */ - Vector(int64_t size, const T &value) : Vector() + Vector(int64_t size, const T &value, Allocator allocator = {}) + : Vector(NoExceptConstructor(), allocator) { this->resize(size, value); } @@ -148,12 +154,12 @@ class Vector { * Create a vector from an array ref. The values in the vector are copy constructed. */ template<typename U, typename std::enable_if_t<std::is_convertible_v<U, T>> * = nullptr> - Vector(Span<U> values, Allocator allocator = {}) : Vector(allocator) + Vector(Span<U> values, Allocator allocator = {}) : Vector(NoExceptConstructor(), allocator) { const int64_t size = values.size(); this->reserve(size); - this->increase_size_by_unchecked(size); uninitialized_convert_n<U, T>(values.data(), size, begin_); + this->increase_size_by_unchecked(size); } /** @@ -182,7 +188,8 @@ class Vector { /* This constructor should not be called with e.g. Vector(3, 10), because that is expected to produce the vector (10, 10, 10). */ typename std::enable_if_t<!std::is_convertible_v<InputIt, int>> * = nullptr> - Vector(InputIt first, InputIt last, Allocator allocator = {}) : Vector(std::move(allocator)) + Vector(InputIt first, InputIt last, Allocator allocator = {}) + : Vector(NoExceptConstructor(), allocator) { for (InputIt current = first; current != last; ++current) { this->append(*current); @@ -196,7 +203,7 @@ class Vector { * Example Usage: * Vector<ModifierData *> modifiers(ob->modifiers); */ - Vector(ListBase &values) : Vector() + Vector(ListBase &values, Allocator allocator = {}) : Vector(NoExceptConstructor(), allocator) { LISTBASE_FOREACH (T, value, &values) { this->append(value); @@ -226,27 +233,26 @@ class Vector { * have zero elements afterwards. */ template<int64_t OtherInlineBufferCapacity> - Vector(Vector<T, OtherInlineBufferCapacity, Allocator> &&other) noexcept - : allocator_(other.allocator_) + Vector(Vector<T, OtherInlineBufferCapacity, Allocator> &&other) noexcept( + std::is_nothrow_move_constructible_v<T>) + : Vector(NoExceptConstructor(), other.allocator_) { const int64_t size = other.size(); if (other.is_inline()) { if (size <= InlineBufferCapacity) { /* Copy between inline buffers. */ - begin_ = inline_buffer_; - end_ = begin_ + size; - capacity_end_ = begin_ + InlineBufferCapacity; uninitialized_relocate_n(other.begin_, size, begin_); + end_ = begin_ + size; } else { /* Copy from inline buffer to newly allocated buffer. */ const int64_t capacity = size; begin_ = static_cast<T *>( allocator_.allocate(sizeof(T) * static_cast<size_t>(capacity), alignof(T), AT)); - end_ = begin_ + size; capacity_end_ = begin_ + capacity; uninitialized_relocate_n(other.begin_, size, begin_); + end_ = begin_ + size; } } else { @@ -273,28 +279,12 @@ class Vector { Vector &operator=(const Vector &other) { - if (this == &other) { - return *this; - } - - this->~Vector(); - new (this) Vector(other); - - return *this; + return copy_assign_container(*this, other); } Vector &operator=(Vector &&other) { - if (this == &other) { - return *this; - } - - /* This can be incorrect, when the vector is used to build a recursive data structure. However, - we don't take care of it at this low level. See https://youtu.be/7Qgd9B1KuMQ?t=840. */ - this->~Vector(); - new (this) Vector(std::move(other)); - - return *this; + return move_assign_container(*this, std::move(other)); } /** @@ -474,17 +464,10 @@ class Vector { * behavior when not enough capacity has been reserved beforehand. Only use this in performance * critical code. */ - void append_unchecked(const T &value) - { - BLI_assert(end_ < capacity_end_); - new (end_) T(value); - end_++; - UPDATE_VECTOR_SIZE(this); - } - void append_unchecked(T &&value) + template<typename ForwardT> void append_unchecked(ForwardT &&value) { BLI_assert(end_ < capacity_end_); - new (end_) T(std::move(value)); + new (end_) T(std::forward<ForwardT>(value)); end_++; UPDATE_VECTOR_SIZE(this); } @@ -497,7 +480,7 @@ class Vector { { BLI_assert(n >= 0); this->reserve(this->size() + n); - blender::uninitialized_fill_n(end_, n, value); + uninitialized_fill_n(end_, n, value); this->increase_size_by_unchecked(n); } @@ -507,7 +490,7 @@ class Vector { * useful when you want to call constructors in the vector yourself. This should only be done in * very rare cases and has to be justified every time. */ - void increase_size_by_unchecked(const int64_t n) + void increase_size_by_unchecked(const int64_t n) noexcept { BLI_assert(end_ + n <= capacity_end_); end_ += n; @@ -553,7 +536,7 @@ class Vector { { BLI_assert(amount >= 0); BLI_assert(begin_ + amount <= capacity_end_); - blender::uninitialized_copy_n(start, amount, end_); + uninitialized_copy_n(start, amount, end_); end_ += amount; UPDATE_VECTOR_SIZE(this); } @@ -600,11 +583,29 @@ class Vector { for (int64_t i = 0; i < move_amount; i++) { const int64_t src_index = insert_index + move_amount - i - 1; const int64_t dst_index = new_size - i - 1; - new (static_cast<void *>(begin_ + dst_index)) T(std::move(begin_[src_index])); + try { + new (static_cast<void *>(begin_ + dst_index)) T(std::move(begin_[src_index])); + } + catch (...) { + /* Destruct all values that have been moved already. */ + destruct_n(begin_ + dst_index + 1, i); + end_ = begin_ + src_index + 1; + UPDATE_VECTOR_SIZE(this); + throw; + } begin_[src_index].~T(); } - std::uninitialized_copy_n(first, insert_amount, begin_ + insert_index); + try { + std::uninitialized_copy_n(first, insert_amount, begin_ + insert_index); + } + catch (...) { + /* Destruct all values that have been moved. */ + destruct_n(begin_ + new_size - move_amount, move_amount); + end_ = begin_ + insert_index; + UPDATE_VECTOR_SIZE(this); + throw; + } end_ = begin_ + new_size; UPDATE_VECTOR_SIZE(this); } @@ -686,8 +687,8 @@ class Vector { T pop_last() { BLI_assert(!this->is_empty()); + T value = std::move(*(end_ - 1)); end_--; - T value = std::move(*end_); end_->~T(); UPDATE_VECTOR_SIZE(this); return value; @@ -702,10 +703,10 @@ class Vector { BLI_assert(index >= 0); BLI_assert(index < this->size()); T *element_to_remove = begin_ + index; - end_--; if (element_to_remove < end_) { - *element_to_remove = std::move(*end_); + *element_to_remove = std::move(*(end_ - 1)); } + end_--; end_->~T(); UPDATE_VECTOR_SIZE(this); } @@ -901,7 +902,13 @@ class Vector { T *new_array = static_cast<T *>( allocator_.allocate(static_cast<size_t>(new_capacity) * sizeof(T), alignof(T), AT)); - uninitialized_relocate_n(begin_, size, new_array); + try { + uninitialized_relocate_n(begin_, size, new_array); + } + catch (...) { + allocator_.deallocate(new_array); + throw; + } if (!this->is_inline()) { allocator_.deallocate(begin_); diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 2ddc15fb894..1ad1ea1a307 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -415,6 +415,8 @@ if(WITH_GTESTS) tests/BLI_task_test.cc tests/BLI_vector_set_test.cc tests/BLI_vector_test.cc + + tests/BLI_exception_safety_test_utils.hh ) set(TEST_INC ../imbuf diff --git a/source/blender/blenlib/tests/BLI_array_test.cc b/source/blender/blenlib/tests/BLI_array_test.cc index 38ab695d238..251cff833f7 100644 --- a/source/blender/blenlib/tests/BLI_array_test.cc +++ b/source/blender/blenlib/tests/BLI_array_test.cc @@ -1,6 +1,7 @@ /* Apache License, Version 2.0 */ #include "BLI_array.hh" +#include "BLI_exception_safety_test_utils.hh" #include "BLI_strict_flags.h" #include "BLI_vector.hh" #include "testing/testing.h" @@ -188,4 +189,42 @@ TEST(array, ReverseIterator) EXPECT_EQ_ARRAY(array.data(), Span({13, 14, 15, 16}).data(), 4); } +TEST(array, SpanConstructorExceptions) +{ + std::array<ExceptionThrower, 4> values; + values[2].throw_during_copy = true; + Span<ExceptionThrower> span{values}; + EXPECT_ANY_THROW({ Array<ExceptionThrower> array(span); }); +} + +TEST(array, SizeValueConstructorExceptions) +{ + ExceptionThrower value; + value.throw_during_copy = true; + EXPECT_ANY_THROW({ Array<ExceptionThrower> array(5, value); }); +} + +TEST(array, MoveConstructorExceptions) +{ + Array<ExceptionThrower, 4> array(3); + array[1].throw_during_move = true; + EXPECT_ANY_THROW({ Array<ExceptionThrower> array_copy(std::move(array)); }); +} + +TEST(array, CopyAssignmentExceptions) +{ + Array<ExceptionThrower> array(5); + array[3].throw_during_copy = true; + Array<ExceptionThrower> array_copy(10); + EXPECT_ANY_THROW({ array_copy = array; }); +} + +TEST(array, MoveAssignmentExceptions) +{ + Array<ExceptionThrower, 4> array(4); + array[2].throw_during_move = true; + Array<ExceptionThrower> array_moved(10); + EXPECT_ANY_THROW({ array_moved = std::move(array); }); +} + } // namespace blender::tests diff --git a/source/blender/blenlib/tests/BLI_exception_safety_test_utils.hh b/source/blender/blenlib/tests/BLI_exception_safety_test_utils.hh new file mode 100644 index 00000000000..5ad7674396b --- /dev/null +++ b/source/blender/blenlib/tests/BLI_exception_safety_test_utils.hh @@ -0,0 +1,72 @@ +#include "BLI_utildefines.h" +#include "MEM_guardedalloc.h" +#include "testing/testing.h" + +namespace blender::tests { + +class ExceptionThrower { + private: + /* Use some random values that are unlikely to exist at the memory location already. */ + static constexpr uint32_t is_alive_state = 0x21254634; + static constexpr uint32_t is_destructed_state = 0xFA4BC327; + + uint32_t state_; + + /* Make use of leak detector to check if this value has been destructed. */ + void *my_memory_; + + public: + bool throw_during_copy; + bool throw_during_move; + + ExceptionThrower() + : state_(is_alive_state), + my_memory_(MEM_mallocN(1, AT)), + throw_during_copy(false), + throw_during_move(false) + { + } + + ExceptionThrower(const ExceptionThrower &other) : ExceptionThrower() + { + EXPECT_EQ(other.state_, is_alive_state); + if (other.throw_during_copy) { + throw std::runtime_error("throwing during copy, as requested"); + } + } + + ExceptionThrower(ExceptionThrower &&other) : ExceptionThrower() + { + EXPECT_EQ(other.state_, is_alive_state); + if (other.throw_during_move) { + throw std::runtime_error("throwing during move, as requested"); + } + } + + ExceptionThrower &operator=(const ExceptionThrower &other) + { + EXPECT_EQ(other.state_, is_alive_state); + if (throw_during_copy || other.throw_during_copy) { + throw std::runtime_error("throwing during copy, as requested"); + } + return *this; + } + + ExceptionThrower &operator=(ExceptionThrower &&other) + { + EXPECT_EQ(other.state_, is_alive_state); + if (throw_during_move || other.throw_during_move) { + throw std::runtime_error("throwing during move, as requested"); + } + return *this; + } + + ~ExceptionThrower() + { + EXPECT_EQ(state_, is_alive_state); + state_ = is_destructed_state; + MEM_freeN(my_memory_); + } +}; + +} // namespace blender::tests diff --git a/source/blender/blenlib/tests/BLI_memory_utils_test.cc b/source/blender/blenlib/tests/BLI_memory_utils_test.cc index f3cb02b63d7..fcef2f8688a 100644 --- a/source/blender/blenlib/tests/BLI_memory_utils_test.cc +++ b/source/blender/blenlib/tests/BLI_memory_utils_test.cc @@ -7,6 +7,7 @@ namespace blender::tests { +namespace { struct MyValue { static inline int alive = 0; @@ -33,6 +34,7 @@ struct MyValue { alive--; } }; +} // namespace TEST(memory_utils, DefaultConstructN_ActuallyCallsConstructor) { diff --git a/source/blender/blenlib/tests/BLI_stack_cxx_test.cc b/source/blender/blenlib/tests/BLI_stack_cxx_test.cc index 3572e751b88..c03893c5596 100644 --- a/source/blender/blenlib/tests/BLI_stack_cxx_test.cc +++ b/source/blender/blenlib/tests/BLI_stack_cxx_test.cc @@ -1,5 +1,6 @@ /* Apache License, Version 2.0 */ +#include "BLI_exception_safety_test_utils.hh" #include "BLI_stack.hh" #include "BLI_strict_flags.h" #include "BLI_vector.hh" @@ -185,4 +186,59 @@ TEST(stack, OveralignedValues) } } +TEST(stack, SpanConstructorExceptions) +{ + std::array<ExceptionThrower, 5> values; + values[3].throw_during_copy = true; + EXPECT_ANY_THROW({ Stack<ExceptionThrower> stack(values); }); +} + +TEST(stack, MoveConstructorExceptions) +{ + Stack<ExceptionThrower, 4> stack; + stack.push({}); + stack.push({}); + stack.peek().throw_during_move = true; + EXPECT_ANY_THROW({ Stack<ExceptionThrower> moved_stack{std::move(stack)}; }); +} + +TEST(stack, PushExceptions) +{ + Stack<ExceptionThrower, 2> stack; + stack.push({}); + stack.push({}); + ExceptionThrower *ptr1 = &stack.peek(); + ExceptionThrower value; + value.throw_during_copy = true; + EXPECT_ANY_THROW({ stack.push(value); }); + EXPECT_EQ(stack.size(), 2); + ExceptionThrower *ptr2 = &stack.peek(); + EXPECT_EQ(ptr1, ptr2); + EXPECT_TRUE(stack.is_invariant_maintained()); +} + +TEST(stack, PopExceptions) +{ + Stack<ExceptionThrower> stack; + stack.push({}); + stack.peek().throw_during_move = true; + stack.push({}); + stack.pop(); /* NOLINT: bugprone-throw-keyword-missing */ + EXPECT_ANY_THROW({ stack.pop(); }); /* NOLINT: bugprone-throw-keyword-missing */ + EXPECT_EQ(stack.size(), 1); + EXPECT_TRUE(stack.is_invariant_maintained()); +} + +TEST(stack, PushMultipleExceptions) +{ + Stack<ExceptionThrower> stack; + stack.push({}); + std::array<ExceptionThrower, 100> values; + values[6].throw_during_copy = true; + EXPECT_ANY_THROW({ stack.push_multiple(values); }); + EXPECT_TRUE(stack.is_invariant_maintained()); + EXPECT_ANY_THROW({ stack.push_multiple(values); }); + EXPECT_TRUE(stack.is_invariant_maintained()); +} + } // namespace blender::tests diff --git a/source/blender/blenlib/tests/BLI_vector_test.cc b/source/blender/blenlib/tests/BLI_vector_test.cc index 792e120d2c0..056a7aa3924 100644 --- a/source/blender/blenlib/tests/BLI_vector_test.cc +++ b/source/blender/blenlib/tests/BLI_vector_test.cc @@ -1,5 +1,6 @@ /* Apache License, Version 2.0 */ +#include "BLI_exception_safety_test_utils.hh" #include "BLI_strict_flags.h" #include "BLI_vector.hh" #include "testing/testing.h" @@ -709,4 +710,87 @@ TEST(vector, ReverseIterator) EXPECT_EQ_ARRAY(reversed_vec.data(), Span({7, 6, 5, 4}).data(), 4); } +TEST(vector, SizeValueConstructorExceptions) +{ + ExceptionThrower value; + value.throw_during_copy = true; + EXPECT_ANY_THROW({ Vector<ExceptionThrower> vec(5, value); }); +} + +TEST(vector, SpanConstructorExceptions) +{ + std::array<ExceptionThrower, 5> values; + values[3].throw_during_copy = true; + EXPECT_ANY_THROW({ Vector<ExceptionThrower> vec(values); }); +} + +TEST(vector, MoveConstructorExceptions) +{ + Vector<ExceptionThrower, 4> vec(3); + vec[2].throw_during_move = true; + EXPECT_ANY_THROW({ Vector<ExceptionThrower> moved_vector{std::move(vec)}; }); +} + +TEST(vector, AppendExceptions) +{ + Vector<ExceptionThrower, 4> vec(2); + ExceptionThrower *ptr1 = &vec.last(); + ExceptionThrower value; + value.throw_during_copy = true; + EXPECT_ANY_THROW({ vec.append(value); }); + EXPECT_EQ(vec.size(), 2); + ExceptionThrower *ptr2 = &vec.last(); + EXPECT_EQ(ptr1, ptr2); +} + +TEST(vector, ExtendExceptions) +{ + Vector<ExceptionThrower> vec(5); + std::array<ExceptionThrower, 10> values; + values[6].throw_during_copy = true; + EXPECT_ANY_THROW({ vec.extend(values); }); + EXPECT_EQ(vec.size(), 5); +} + +TEST(vector, Insert1Exceptions) +{ + Vector<ExceptionThrower> vec(10); + std::array<ExceptionThrower, 5> values; + values[3].throw_during_copy = true; + EXPECT_ANY_THROW({ vec.insert(7, values); }); +} + +TEST(vector, Insert2Exceptions) +{ + Vector<ExceptionThrower> vec(10); + vec.reserve(100); + vec[8].throw_during_move = true; + std::array<ExceptionThrower, 5> values; + EXPECT_ANY_THROW({ vec.insert(3, values); }); +} + +TEST(vector, PopLastExceptions) +{ + Vector<ExceptionThrower> vec(10); + vec.last().throw_during_move = true; + EXPECT_ANY_THROW({ vec.pop_last(); }); /* NOLINT: bugprone-throw-keyword-missing */ + EXPECT_EQ(vec.size(), 10); +} + +TEST(vector, RemoveAndReorderExceptions) +{ + Vector<ExceptionThrower> vec(10); + vec.last().throw_during_move = true; + EXPECT_ANY_THROW({ vec.remove_and_reorder(3); }); + EXPECT_EQ(vec.size(), 10); +} + +TEST(vector, RemoveExceptions) +{ + Vector<ExceptionThrower> vec(10); + vec[8].throw_during_move = true; + EXPECT_ANY_THROW({ vec.remove(2); }); + EXPECT_EQ(vec.size(), 10); +} + } // namespace blender::tests diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index bc13e3b3a39..00214c16eb0 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -208,6 +208,17 @@ void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports)) } } + if (!MAIN_VERSION_ATLEAST(bmain, 291, 1)) { + LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { + if (BKE_collection_cycles_fix(bmain, collection)) { + printf( + "WARNING: Cycle detected in collection '%s', fixed as best as possible.\n" + "You may have to reconstruct your View Layers...\n", + collection->id.name); + } + } + } + /** * Versioning code until next subversion bump goes here. * @@ -219,18 +230,26 @@ void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports)) * \note Keep this message at the bottom of the function. */ { - LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { - if (BKE_collection_cycles_fix(bmain, collection)) { - printf( - "WARNING: Cycle detected in collection '%s', fixed as best as possible.\n" - "You may have to reconstruct your View Layers...\n", - collection->id.name); - } - } + /* Keep this block, even when empty. */ } } +static void panels_remove_x_closed_flag_recursive(Panel *panel) +{ + const bool was_closed_x = panel->flag & PNL_UNUSED_1; + const bool was_closed_y = panel->flag & PNL_CLOSED; /* That value was the Y closed flag. */ + + SET_FLAG_FROM_TEST(panel->flag, was_closed_x || was_closed_y, PNL_CLOSED); + + /* Clear the old PNL_CLOSEDX flag. */ + panel->flag &= ~PNL_UNUSED_1; + + LISTBASE_FOREACH (Panel *, child_panel, &panel->children) { + panels_remove_x_closed_flag_recursive(child_panel); + } +} + void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) { UNUSED_VARS(fd); @@ -409,17 +428,7 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - /** - * Versioning code until next subversion bump goes here. - * - * \note Be sure to check when bumping the version: - * - "versioning_userdef.c", #BLO_version_defaults_userpref_blend - * - "versioning_userdef.c", #do_versions_theme - * - * \note Keep this message at the bottom of the function. - */ - { - /* Keep this block, even when empty. */ + if (!MAIN_VERSION_ATLEAST(bmain, 291, 1)) { /* Initialize additional parameter of the Nishita sky model and change altitude unit. */ if (!DNA_struct_elem_find(fd->filesdna, "NodeTexSky", "float", "sun_intensity")) { @@ -484,5 +493,29 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + /* Remove panel X axis collapsing, a remnant of horizontal panel alignment. */ + LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { + panels_remove_x_closed_flag_recursive(panel); + } + } + } + } + } + + /** + * Versioning code until next subversion bump goes here. + * + * \note Be sure to check when bumping the version: + * - "versioning_userdef.c", #BLO_version_defaults_userpref_blend + * - "versioning_userdef.c", #do_versions_theme + * + * \note Keep this message at the bottom of the function. + */ + { + /* Keep this block, even when empty. */ } } diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index 0b116804481..1437d46bd8d 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -758,6 +758,12 @@ void BLO_version_defaults_userpref_blend(Main *bmain, UserDef *userdef) userdef->statusbar_flag = STATUSBAR_SHOW_VERSION; } + if (!USER_VERSION_ATLEAST(291, 1)) { + if (userdef->collection_instance_empty_size == 0) { + userdef->collection_instance_empty_size = 1.0f; + } + } + /** * Versioning code until next subversion bump goes here. * @@ -769,10 +775,6 @@ void BLO_version_defaults_userpref_blend(Main *bmain, UserDef *userdef) */ { /* Keep this block, even when empty. */ - - if (userdef->collection_instance_empty_size == 0) { - userdef->collection_instance_empty_size = 1.0f; - } } if (userdef->pixelsize == 0.0f) { diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h index 8f33e9f480d..0ded511b8f8 100644 --- a/source/blender/depsgraph/DEG_depsgraph.h +++ b/source/blender/depsgraph/DEG_depsgraph.h @@ -127,6 +127,12 @@ void DEG_graph_id_tag_update(struct Main *bmain, struct ID *id, int flag); +/* Tag all dependency graphs when time has changed. */ +void DEG_time_tag_update(struct Main *bmain); + +/* Tag a dependency graph when time has changed. */ +void DEG_graph_time_tag_update(struct Depsgraph *depsgraph); + /* Mark a particular datablock type as having changing. This does * not cause any updates but is used by external render engines to detect if for * example a datablock was removed. */ @@ -155,8 +161,6 @@ void DEG_evaluate_on_framechange(Depsgraph *graph, float ctime); /* Data changed recalculation entry point. */ void DEG_evaluate_on_refresh(Depsgraph *graph); -bool DEG_needs_eval(Depsgraph *graph); - /* Editors Integration -------------------------- */ /* Mechanism to allow editors to be informed of depsgraph updates, diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc index 4a9c840dd9f..c0feab2262a 100644 --- a/source/blender/depsgraph/intern/depsgraph.cc +++ b/source/blender/depsgraph/intern/depsgraph.cc @@ -63,7 +63,6 @@ namespace deg { Depsgraph::Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode) : time_source(nullptr), need_update(true), - need_update_time(false), bmain(bmain), scene(scene), view_layer(view_layer), @@ -103,6 +102,11 @@ TimeSourceNode *Depsgraph::find_time_source() const return time_source; } +void Depsgraph::tag_time_source() +{ + time_source->tag_update(this, DEG_UPDATE_SOURCE_TIME); +} + IDNode *Depsgraph::find_id_node(const ID *id) const { return id_hash.lookup_default(id, nullptr); diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h index ea579a4958e..e03846f81e2 100644 --- a/source/blender/depsgraph/intern/depsgraph.h +++ b/source/blender/depsgraph/intern/depsgraph.h @@ -68,6 +68,7 @@ struct Depsgraph { TimeSourceNode *add_time_source(); TimeSourceNode *find_time_source() const; + void tag_time_source(); IDNode *find_id_node(const ID *id) const; IDNode *add_id_node(ID *id, ID *id_cow_hint = nullptr); @@ -121,10 +122,6 @@ struct Depsgraph { /* Nodes which have been tagged as "directly modified". */ Set<OperationNode *> entry_tags; - /* Special entry tag for time source. Allows to tag invisible dependency graphs for update when - * scene frame changes, so then when dependency graph becomes visible it is on a proper state. */ - bool need_update_time; - /* Convenience Data ................... */ /* XXX: should be collected after building (if actually needed?) */ diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc index 0c116f5863c..1ad3fdbc9da 100644 --- a/source/blender/depsgraph/intern/depsgraph_eval.cc +++ b/source/blender/depsgraph/intern/depsgraph_eval.cc @@ -47,38 +47,37 @@ namespace deg = blender::deg; -/* Evaluate all nodes tagged for updating. */ -void DEG_evaluate_on_refresh(Depsgraph *graph) +static void deg_flush_updates_and_refresh(deg::Depsgraph *deg_graph) { - deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(graph); - deg_graph->ctime = BKE_scene_frame_get(deg_graph->scene); - /* Update time in scene. */ + /* Update the time on the cow scene. */ if (deg_graph->scene_cow) { BKE_scene_frame_set(deg_graph->scene_cow, deg_graph->ctime); } + deg::deg_graph_flush_updates(deg_graph); deg::deg_evaluate_on_refresh(deg_graph); - deg_graph->need_update_time = false; } -/* Frame-change happened for root scene that graph belongs to. */ -void DEG_evaluate_on_framechange(Depsgraph *graph, float ctime) +/* Evaluate all nodes tagged for updating. */ +void DEG_evaluate_on_refresh(Depsgraph *graph) { deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(graph); - deg_graph->ctime = ctime; - deg_graph->need_update_time = true; - deg::deg_graph_flush_updates(deg_graph); - /* Update time in scene. */ - if (deg_graph->scene_cow) { - BKE_scene_frame_set(deg_graph->scene_cow, deg_graph->ctime); + const Scene *scene = DEG_get_input_scene(graph); + const float ctime = BKE_scene_frame_get(scene); + + if (ctime != deg_graph->ctime) { + deg_graph->tag_time_source(); + deg_graph->ctime = ctime; } - /* Perform recalculation updates. */ - deg::deg_evaluate_on_refresh(deg_graph); - deg_graph->need_update_time = false; + + deg_flush_updates_and_refresh(deg_graph); } -bool DEG_needs_eval(Depsgraph *graph) +/* Frame-change happened for root scene that graph belongs to. */ +void DEG_evaluate_on_framechange(Depsgraph *graph, float ctime) { deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(graph); - return !deg_graph->entry_tags.is_empty() || deg_graph->need_update_time; + deg_graph->tag_time_source(); + deg_graph->ctime = ctime; + deg_flush_updates_and_refresh(deg_graph); } diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index 4a2d47f9379..868f88d8fcd 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -66,6 +66,7 @@ #include "intern/node/deg_node_factory.h" #include "intern/node/deg_node_id.h" #include "intern/node/deg_node_operation.h" +#include "intern/node/deg_node_time.h" namespace deg = blender::deg; @@ -230,9 +231,6 @@ void depsgraph_tag_to_component_opcode(const ID *id, case ID_RECALC_SOURCE: *component_type = NodeType::PARAMETERS; break; - case ID_RECALC_TIME: - BLI_assert(!"Should be handled outside of this function"); - break; case ID_RECALC_ALL: case ID_RECALC_PSYS_ALL: BLI_assert(!"Should not happen"); @@ -372,12 +370,6 @@ void graph_id_tag_update_single_flag(Main *bmain, } return; } - if (tag == ID_RECALC_TIME) { - if (graph != nullptr) { - graph->need_update_time = true; - } - return; - } /* Get description of what is to be tagged. */ NodeType component_type; OperationCode operation_code; @@ -462,8 +454,8 @@ const char *update_source_as_string(eUpdateSource source) int deg_recalc_flags_for_legacy_zero() { - return ID_RECALC_ALL & ~(ID_RECALC_PSYS_ALL | ID_RECALC_ANIMATION | ID_RECALC_SOURCE | - ID_RECALC_TIME | ID_RECALC_EDITORS); + return ID_RECALC_ALL & + ~(ID_RECALC_PSYS_ALL | ID_RECALC_ANIMATION | ID_RECALC_SOURCE | ID_RECALC_EDITORS); } int deg_recalc_flags_effective(Depsgraph *graph, int flags) @@ -734,8 +726,6 @@ const char *DEG_update_tag_as_string(IDRecalcFlag flag) return "AUDIO"; case ID_RECALC_PARAMETERS: return "PARAMETERS"; - case ID_RECALC_TIME: - return "TIME"; case ID_RECALC_SOURCE: return "SOURCE"; case ID_RECALC_ALL: @@ -772,6 +762,19 @@ void DEG_graph_id_tag_update(struct Main *bmain, deg::graph_id_tag_update(bmain, graph, id, flag, deg::DEG_UPDATE_SOURCE_USER_EDIT); } +void DEG_time_tag_update(struct Main *bmain) +{ + for (deg::Depsgraph *depsgraph : deg::get_all_registered_graphs(bmain)) { + DEG_graph_time_tag_update(reinterpret_cast<::Depsgraph *>(depsgraph)); + } +} + +void DEG_graph_time_tag_update(struct Depsgraph *depsgraph) +{ + deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(depsgraph); + deg_graph->tag_time_source(); +} + /* Mark a particular datablock type as having changing. */ void DEG_graph_id_type_tag(Depsgraph *depsgraph, short id_type) { diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index dea23c9f96d..5ccdcbec858 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -357,14 +357,9 @@ void deg_graph_flush_updates(Depsgraph *graph) BLI_assert(graph != nullptr); Main *bmain = graph->bmain; + graph->time_source->flush_update_tag(graph); + /* Nothing to update, early out. */ - if (graph->need_update_time) { - const Scene *scene_orig = graph->scene; - const float ctime = BKE_scene_frame_get(scene_orig); - TimeSourceNode *time_source = graph->find_time_source(); - graph->ctime = ctime; - time_source->tag_update(graph, DEG_UPDATE_SOURCE_TIME); - } if (graph->entry_tags.is_empty()) { return; } @@ -412,6 +407,8 @@ void deg_graph_clear_tags(Depsgraph *graph) } /* Clear any entry tags which haven't been flushed. */ graph->entry_tags.clear(); + + graph->time_source->tagged_for_update = false; } } // namespace deg diff --git a/source/blender/depsgraph/intern/node/deg_node_time.cc b/source/blender/depsgraph/intern/node/deg_node_time.cc index af931fbae34..4f7f70fef33 100644 --- a/source/blender/depsgraph/intern/node/deg_node_time.cc +++ b/source/blender/depsgraph/intern/node/deg_node_time.cc @@ -31,8 +31,16 @@ namespace blender { namespace deg { -void TimeSourceNode::tag_update(Depsgraph *graph, eUpdateSource /*source*/) +void TimeSourceNode::tag_update(Depsgraph * /*graph*/, eUpdateSource /*source*/) { + tagged_for_update = true; +} + +void TimeSourceNode::flush_update_tag(Depsgraph *graph) +{ + if (!tagged_for_update) { + return; + } for (Relation *rel : outlinks) { Node *node = rel->to; node->tag_update(graph, DEG_UPDATE_SOURCE_TIME); diff --git a/source/blender/depsgraph/intern/node/deg_node_time.h b/source/blender/depsgraph/intern/node/deg_node_time.h index fe17684abb0..79ad92f336f 100644 --- a/source/blender/depsgraph/intern/node/deg_node_time.h +++ b/source/blender/depsgraph/intern/node/deg_node_time.h @@ -30,10 +30,14 @@ namespace deg { /* Time Source Node. */ struct TimeSourceNode : public Node { + bool tagged_for_update = false; + // TODO: evaluate() operation needed virtual void tag_update(Depsgraph *graph, eUpdateSource source) override; + void flush_update_tag(Depsgraph *graph); + DEG_DEPSNODE_DECLARE; }; diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c index 73e0ff7ef83..b93c782a5b9 100644 --- a/source/blender/draw/intern/draw_cache_impl_curve.c +++ b/source/blender/draw/intern/draw_cache_impl_curve.c @@ -307,7 +307,7 @@ static int curve_render_data_normal_len_get(const CurveRenderData *rdata) return rdata->normal.len; } -static void curve_cd_calc_used_gpu_layers(int *cd_layers, +static void curve_cd_calc_used_gpu_layers(CustomDataMask *cd_layers, struct GPUMaterial **gpumat_array, int gpumat_array_len) { @@ -334,16 +334,16 @@ static void curve_cd_calc_used_gpu_layers(int *cd_layers, switch (type) { case CD_MTFACE: - *cd_layers |= CD_MLOOPUV; + *cd_layers |= CD_MASK_MLOOPUV; break; case CD_TANGENT: - *cd_layers |= CD_TANGENT; + *cd_layers |= CD_MASK_TANGENT; break; case CD_MCOL: /* Curve object don't have Color data. */ break; case CD_ORCO: - *cd_layers |= CD_ORCO; + *cd_layers |= CD_MASK_ORCO; break; } } @@ -397,7 +397,7 @@ typedef struct CurveBatchCache { GPUIndexBuf **surf_per_mat_tris; GPUBatch **surf_per_mat; int mat_len; - int cd_used, cd_needed; + CustomDataMask cd_used, cd_needed; /* settings to determine if cache is invalid */ bool is_dirty; @@ -998,10 +998,10 @@ void DRW_curve_batch_cache_create_requested(Object *ob) if (cache->mat_len > 1) { DRW_ibo_request(cache->surf_per_mat[i], &cache->surf_per_mat_tris[i]); } - if (cache->cd_used & CD_MLOOPUV) { + if (cache->cd_used & CD_MASK_MLOOPUV) { DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_uv); } - if (cache->cd_used & CD_TANGENT) { + if (cache->cd_used & CD_MASK_TANGENT) { DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_tan); } DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_pos_nor); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index d90d7d36ebc..e17ec4f707e 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1314,15 +1314,15 @@ void DRW_draw_callbacks_post_scene(void) /* annotations - temporary drawing buffer (3d space) */ /* XXX: Or should we use a proper draw/overlay engine for this case? */ if (do_annotations) { - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); /* XXX: as scene->gpd is not copied for COW yet */ ED_annotation_draw_view3d(DEG_get_input_scene(depsgraph), depsgraph, v3d, region, true); - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } drw_debug_draw(); - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.region, REGION_DRAW_POST_VIEW); /* Callback can be nasty and do whatever they want with the state. @@ -1331,11 +1331,11 @@ void DRW_draw_callbacks_post_scene(void) /* needed so gizmo isn't obscured */ if ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) { - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); DRW_draw_gizmo_3d(); } - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); drw_engines_draw_text(); DRW_draw_region_info(); @@ -1343,7 +1343,7 @@ void DRW_draw_callbacks_post_scene(void) /* annotations - temporary drawing buffer (screenspace) */ /* XXX: Or should we use a proper draw/overlay engine for this case? */ if (((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && (do_annotations)) { - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); /* XXX: as scene->gpd is not copied for COW yet */ ED_annotation_draw_view3d(DEG_get_input_scene(depsgraph), depsgraph, v3d, region, false); } @@ -1351,18 +1351,18 @@ void DRW_draw_callbacks_post_scene(void) if ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) { /* Draw 2D after region info so we can draw on top of the camera passepartout overlay. * 'DRW_draw_region_info' sets the projection in pixel-space. */ - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); DRW_draw_gizmo_2d(); } if (G.debug_value > 20 && G.debug_value < 30) { - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); /* local coordinate visible rect inside region, to accommodate overlapping ui */ const rcti *rect = ED_region_visible_rect(DST.draw_ctx.region); DRW_stats_draw(rect); } - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } } @@ -1703,7 +1703,7 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph GPU_viewport_free(DST.viewport); DRW_state_reset(); - glDisable(GL_DEPTH_TEST); + GPU_depth_test(GPU_DEPTH_NONE); /* Restore Drawing area. */ GPU_framebuffer_restore(); @@ -2438,7 +2438,7 @@ void DRW_draw_depth_object( GPU_framebuffer_bind(fbl->depth_only_fb); GPU_framebuffer_clear_depth(fbl->depth_only_fb, 1.0f); - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); const float(*world_clip_planes)[4] = NULL; if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) { @@ -2485,7 +2485,7 @@ void DRW_draw_depth_object( } GPU_matrix_set(rv3d->viewmat); - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); GPU_framebuffer_restore(); DRW_opengl_context_disable(); } diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 47892b958d0..9902d3b0aeb 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -301,11 +301,8 @@ void DRW_state_reset(void) /* Should stay constant during the whole rendering. */ GPU_point_size(5); GPU_line_smooth(false); - /* Bypass U.pixelsize factor. */ - glLineWidth(1.0f); - - /* Reset blending function */ - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + /* Bypass U.pixelsize factor by using a factor of 0.0f. Will be clamped to 1.0f. */ + GPU_line_width(0.0f); } /** \} */ @@ -762,19 +759,14 @@ static void draw_call_resource_bind(DRWCommandsState *state, const DRWResourceHa /* Front face is not a resource but it is inside the resource handle. */ bool neg_scale = DRW_handle_negative_scale_get(handle); if (neg_scale != state->neg_scale) { - if (DST.view_active->is_inverted) { - glFrontFace(neg_scale ? GL_CCW : GL_CW); - } - else { - glFrontFace(neg_scale ? GL_CW : GL_CCW); - } state->neg_scale = neg_scale; + GPU_front_facing(neg_scale != DST.view_active->is_inverted); } int chunk = DRW_handle_chunk_get(handle); if (state->resource_chunk != chunk) { if (state->chunkid_loc != -1) { - GPU_shader_uniform_int(NULL, state->chunkid_loc, chunk); + GPU_shader_uniform_int(DST.shader, state->chunkid_loc, chunk); } if (state->obmats_loc != -1) { GPU_uniformbuffer_unbind(DST.vmempool->matrices_ubo[state->resource_chunk]); @@ -790,7 +782,7 @@ static void draw_call_resource_bind(DRWCommandsState *state, const DRWResourceHa if (state->resourceid_loc != -1) { int id = DRW_handle_id_get(handle); if (state->resource_id != id) { - GPU_shader_uniform_int(NULL, state->resourceid_loc, id); + GPU_shader_uniform_int(DST.shader, state->resourceid_loc, id); state->resource_id = id; } } @@ -898,7 +890,7 @@ static void draw_call_batching_finish(DRWShadingGroup *shgroup, DRWCommandsState /* Reset state */ if (state->neg_scale) { - glFrontFace(DST.view_active->is_inverted ? GL_CW : GL_CCW); + GPU_front_facing(DST.view_active->is_inverted); } if (state->obmats_loc != -1) { GPU_uniformbuffer_unbind(DST.vmempool->matrices_ubo[state->resource_chunk]); @@ -1110,7 +1102,7 @@ static void drw_draw_pass_ex(DRWPass *pass, drw_state_validate(); if (DST.view_active->is_inverted) { - glFrontFace(GL_CW); + GPU_front_facing(true); } DRW_stats_query_start(pass->name); @@ -1147,7 +1139,7 @@ static void drw_draw_pass_ex(DRWPass *pass, /* Reset default. */ if (DST.view_active->is_inverted) { - glFrontFace(GL_CCW); + GPU_front_facing(false); } DRW_stats_query_end(); diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c index 0dc35d44788..d01e1a51080 100644 --- a/source/blender/draw/intern/draw_view.c +++ b/source/blender/draw/intern/draw_view.c @@ -105,7 +105,7 @@ void DRW_draw_cursor(void) GPU_color_mask(true, true, true, true); GPU_depth_mask(false); - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); if (is_cursor_visible(draw_ctx, scene, view_layer)) { int co[2]; diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c index 2dac273501d..889041daacf 100644 --- a/source/blender/editors/curve/editcurve_paint.c +++ b/source/blender/editors/curve/editcurve_paint.c @@ -419,7 +419,7 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); GPU_blend(GPU_BLEND_ALPHA); GPU_line_smooth(true); GPU_line_width(3.0f); @@ -441,7 +441,7 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), immEnd(); /* Reset defaults */ - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); GPU_blend(GPU_BLEND_NONE); GPU_line_smooth(false); diff --git a/source/blender/editors/gizmo_library/gizmo_draw_utils.c b/source/blender/editors/gizmo_library/gizmo_draw_utils.c index 033673a99a8..2896aa25930 100644 --- a/source/blender/editors/gizmo_library/gizmo_draw_utils.c +++ b/source/blender/editors/gizmo_library/gizmo_draw_utils.c @@ -84,13 +84,13 @@ void wm_gizmo_geometryinfo_draw(const GizmoGeomInfo *info, * since it causes issues leaving the GL state modified. */ #if 0 GPU_face_culling(GPU_CULL_BACK); - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); #endif GPU_batch_draw(batch); #if 0 - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); GPU_face_culling(GPU_CULL_NONE); #endif diff --git a/source/blender/editors/gpencil/annotate_draw.c b/source/blender/editors/gpencil/annotate_draw.c index 654d1b87918..b6cbbe7712b 100644 --- a/source/blender/editors/gpencil/annotate_draw.c +++ b/source/blender/editors/gpencil/annotate_draw.c @@ -556,7 +556,7 @@ static void annotation_draw_strokes(const bGPDframe *gpf, const int no_xray = (dflag & GP_DRAWDATA_NO_XRAY); if (no_xray) { - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); /* first arg is normally rv3d->dist, but this isn't * available here and seems to work quite well without */ @@ -574,7 +574,7 @@ static void annotation_draw_strokes(const bGPDframe *gpf, } if (no_xray) { - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); GPU_polygon_offset(0.0f, 0.0f); } diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 9d11c1c2a25..93767127cc7 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -348,7 +348,7 @@ static void gpencil_draw_strokes(tGPDdraw *tgpw) const int no_xray = (tgpw->dflag & GP_DRAWDATA_NO_XRAY); if (no_xray) { - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); /* first arg is normally rv3d->dist, but this isn't * available here and seems to work quite well without */ @@ -393,7 +393,7 @@ static void gpencil_draw_strokes(tGPDdraw *tgpw) } } if (no_xray) { - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); GPU_polygon_offset(0.0f, 0.0f); } diff --git a/source/blender/editors/include/ED_info.h b/source/blender/editors/include/ED_info.h index df6b6a20ddc..e3ce494e09a 100644 --- a/source/blender/editors/include/ED_info.h +++ b/source/blender/editors/include/ED_info.h @@ -31,8 +31,13 @@ struct Main; /* info_stats.c */ void ED_info_stats_clear(struct ViewLayer *view_layer); const char *ED_info_statusbar_string(struct Main *bmain, - struct bScreen *screen, - struct bContext *C); + struct Scene *scene, + struct ViewLayer *view_layer); + +const char *ED_info_statistics_string(struct Main *bmain, + struct Scene *scene, + struct ViewLayer *view_layer); + void ED_info_draw_stats( struct Main *bmain, Scene *scene, ViewLayer *view_layer, int x, int *y, int height); diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index ad46dada0c9..dd7ca5c65a4 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -81,18 +81,12 @@ void ED_region_tag_refresh_ui(struct ARegion *region); void ED_region_tag_redraw_editor_overlays(struct ARegion *region); void ED_region_panels_init(struct wmWindowManager *wm, struct ARegion *region); -void ED_region_panels_ex(const struct bContext *C, - struct ARegion *region, - const char *contexts[], - int contextnr, - const bool vertical); +void ED_region_panels_ex(const struct bContext *C, struct ARegion *region, const char *contexts[]); void ED_region_panels(const struct bContext *C, struct ARegion *region); void ED_region_panels_layout_ex(const struct bContext *C, struct ARegion *region, struct ListBase *paneltypes, const char *contexts[], - int contextnr, - const bool vertical, const char *category_override); void ED_region_panels_layout(const struct bContext *C, struct ARegion *region); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 5d936cdfaa3..22e3fec172a 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -1667,19 +1667,13 @@ void UI_panels_end(const struct bContext *C, struct ARegion *region, int *r_x, i void UI_panels_draw(const struct bContext *C, struct ARegion *region); struct Panel *UI_panel_find_by_type(struct ListBase *lb, struct PanelType *pt); -struct Panel *UI_panel_begin(struct ScrArea *area, - struct ARegion *region, +struct Panel *UI_panel_begin(struct ARegion *region, struct ListBase *lb, uiBlock *block, struct PanelType *pt, struct Panel *panel, bool *r_open); -void UI_panel_end(const struct ScrArea *area, - const struct ARegion *region, - uiBlock *block, - int width, - int height, - bool open); +void UI_panel_end(const struct ARegion *region, uiBlock *block, int width, int height, bool open); void UI_panels_scale(struct ARegion *region, float new_width); void UI_panel_label_offset(struct uiBlock *block, int *r_x, int *r_y); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index a70bcd208ab..4982a27316c 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -134,43 +134,6 @@ static void panel_title_color_get(bool show_background, uchar color[4]) } } -/*********************** space specific code ************************/ -/* temporary code to remove all sbuts stuff from panel code */ - -/* SpaceProperties.align */ -typedef enum eSpaceButtons_Align { - BUT_HORIZONTAL = 0, - BUT_VERTICAL = 1, - BUT_AUTO = 2, -} eSpaceButtons_Align; - -static int panel_aligned(const ScrArea *area, const ARegion *region) -{ - if (area->spacetype == SPACE_PROPERTIES && region->regiontype == RGN_TYPE_WINDOW) { - return BUT_VERTICAL; - } - if (area->spacetype == SPACE_USERPREF && region->regiontype == RGN_TYPE_WINDOW) { - return BUT_VERTICAL; - } - if (area->spacetype == SPACE_FILE && region->regiontype == RGN_TYPE_CHANNELS) { - return BUT_VERTICAL; - } - if (area->spacetype == SPACE_IMAGE && region->regiontype == RGN_TYPE_PREVIEW) { - return BUT_VERTICAL; - } - if (ELEM(region->regiontype, - RGN_TYPE_UI, - RGN_TYPE_TOOLS, - RGN_TYPE_TOOL_PROPS, - RGN_TYPE_HUD, - RGN_TYPE_NAV_BAR, - RGN_TYPE_EXECUTE)) { - return BUT_VERTICAL; - } - - return 0; -} - static bool panel_active_animation_changed(ListBase *lb, Panel **pa_animation, bool *no_animation) { LISTBASE_FOREACH (Panel *, panel, lb) { @@ -530,13 +493,9 @@ static void reorder_instanced_panel_list(bContext *C, ARegion *region, Panel *dr static bool panel_set_expand_from_list_data_recursive(Panel *panel, short flag, short *flag_index) { bool open = (flag & (1 << *flag_index)); - bool changed = (open == (bool)(panel->flag & PNL_CLOSEDY)); - if (open) { - panel->flag &= ~PNL_CLOSEDY; - } - else { - panel->flag |= PNL_CLOSEDY; - } + bool changed = (open == (bool)(panel->flag & PNL_CLOSED)); + SET_FLAG_FROM_TEST(panel->flag, !open, PNL_CLOSED); + LISTBASE_FOREACH (Panel *, child, &panel->children) { *flag_index = *flag_index + 1; changed |= panel_set_expand_from_list_data_recursive(child, flag, flag_index); @@ -572,13 +531,9 @@ void UI_panel_set_expand_from_list_data(const bContext *C, Panel *panel) */ static void get_panel_expand_flag(Panel *panel, short *flag, short *flag_index) { - bool open = !(panel->flag & PNL_CLOSEDY); - if (open) { - *flag |= (1 << *flag_index); - } - else { - *flag &= ~(1 << *flag_index); - } + bool open = !(panel->flag & PNL_CLOSED); + SET_FLAG_FROM_TEST(*flag, open, (1 << *flag_index)); + LISTBASE_FOREACH (Panel *, child, &panel->children) { *flag_index = *flag_index + 1; get_panel_expand_flag(child, flag, flag_index); @@ -635,14 +590,10 @@ static bool panel_set_flag_recursive(Panel *panel, int flag, bool value) return changed; } -static void panels_collapse_all(const bContext *C, - ScrArea *area, - ARegion *region, - const Panel *from_panel) +static void panels_collapse_all(const bContext *C, ARegion *region, const Panel *from_panel) { const bool has_category_tabs = UI_panel_category_is_visible(region); const char *category = has_category_tabs ? UI_panel_category_active_get(region, false) : NULL; - const int flag = ((panel_aligned(area, region) == BUT_HORIZONTAL) ? PNL_CLOSEDX : PNL_CLOSEDY); const PanelType *from_pt = from_panel->type; LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { @@ -654,7 +605,6 @@ static void panels_collapse_all(const bContext *C, if ((panel->flag & PNL_PIN) || !category || !pt->category[0] || STREQ(pt->category, category)) { panel->flag &= ~PNL_CLOSED; - panel->flag |= flag; } } } @@ -692,19 +642,13 @@ Panel *UI_panel_find_by_type(ListBase *lb, PanelType *pt) /** * \note \a panel should be return value from #UI_panel_find_by_type and can be NULL. */ -Panel *UI_panel_begin(ScrArea *area, - ARegion *region, - ListBase *lb, - uiBlock *block, - PanelType *pt, - Panel *panel, - bool *r_open) +Panel *UI_panel_begin( + ARegion *region, ListBase *lb, uiBlock *block, PanelType *pt, Panel *panel, bool *r_open) { Panel *panel_last; const char *drawname = CTX_IFACE_(pt->translation_context, pt->label); const char *idname = pt->idname; const bool newpanel = (panel == NULL); - int align = panel_aligned(area, region); if (!newpanel) { panel->type = pt; @@ -716,12 +660,7 @@ Panel *UI_panel_begin(ScrArea *area, BLI_strncpy(panel->panelname, idname, sizeof(panel->panelname)); if (pt->flag & PNL_DEFAULT_CLOSED) { - if (align == BUT_VERTICAL) { - panel->flag |= PNL_CLOSEDY; - } - else { - panel->flag |= PNL_CLOSEDX; - } + panel->flag |= PNL_CLOSED; } panel->ofsx = 0; @@ -790,11 +729,10 @@ Panel *UI_panel_begin(ScrArea *area, return panel; } -static float panel_region_offset_x_get(const ARegion *region, int align) +static float panel_region_offset_x_get(const ARegion *region) { if (UI_panel_category_is_visible(region)) { - if (align == BUT_VERTICAL && - (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) != RGN_ALIGN_RIGHT)) { + if (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) != RGN_ALIGN_RIGHT) { return UI_PANEL_CATEGORY_MARGIN_WIDTH; } } @@ -802,8 +740,7 @@ static float panel_region_offset_x_get(const ARegion *region, int align) return 0; } -void UI_panel_end( - const ScrArea *area, const ARegion *region, uiBlock *block, int width, int height, bool open) +void UI_panel_end(const ARegion *region, uiBlock *block, int width, int height, bool open) { Panel *panel = block->panel; @@ -843,8 +780,7 @@ void UI_panel_end( panel->ofsy += old_sizey - panel->sizey; } - int align = panel_aligned(area, region); - panel->runtime.region_ofsx = panel_region_offset_x_get(region, align); + panel->runtime.region_ofsx = panel_region_offset_x_get(region); if (old_region_ofsx != panel->runtime.region_ofsx) { panel->runtime_flag |= PNL_ANIM_ALIGN; } @@ -955,8 +891,6 @@ void ui_draw_aligned_panel(uiStyle *style, Panel *panel = block->panel; rctf itemrect; float color[4]; - const bool is_closed_x = (panel->flag & PNL_CLOSEDX) ? true : false; - const bool is_closed_y = (panel->flag & PNL_CLOSEDY) ? true : false; const bool is_subpanel = (panel->type && panel->type->parent); const bool show_drag = (!is_subpanel && /* FIXME(campbell): currently no background means floating panel which @@ -993,12 +927,12 @@ void ui_draw_aligned_panel(uiStyle *style, /* Expand the top a tiny bit to give header buttons equal size above and below. */ rcti box_rect = {rect->xmin, rect->xmax, - (is_closed_x || is_closed_y) ? headrect.ymin : rect->ymin, + (panel->flag & PNL_CLOSED) ? headrect.ymin : rect->ymin, headrect.ymax + U.pixelsize}; ui_draw_box_opaque(&box_rect, UI_CNR_ALL); /* Mimick the border between aligned box widgets for the bottom of the header. */ - if (!(is_closed_x || is_closed_y)) { + if (!(panel->flag & PNL_CLOSED)) { immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); GPU_blend(GPU_BLEND_ALPHA); @@ -1021,7 +955,6 @@ void ui_draw_aligned_panel(uiStyle *style, /* Draw the header backdrop. */ if (show_background && !is_subpanel && !draw_box_style) { float minx = rect->xmin; - float maxx = is_closed_x ? (minx + PNL_HEADER / block->aspect) : rect->xmax; float y = headrect.ymax; immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); @@ -1029,15 +962,15 @@ void ui_draw_aligned_panel(uiStyle *style, /* draw with background color */ immUniformThemeColor(TH_PANEL_HEADER); - immRectf(pos, minx, headrect.ymin, maxx, y); + immRectf(pos, minx, headrect.ymin, rect->xmax, y); immBegin(GPU_PRIM_LINES, 4); immVertex2f(pos, minx, y); - immVertex2f(pos, maxx, y); + immVertex2f(pos, rect->xmax, y); immVertex2f(pos, minx, y); - immVertex2f(pos, maxx, y); + immVertex2f(pos, rect->xmax, y); immEnd(); @@ -1072,45 +1005,34 @@ void ui_draw_aligned_panel(uiStyle *style, if (is_subpanel) { titlerect.xmin += (0.7f * UI_UNIT_X) / block->aspect + 0.001f; } - if (is_closed_x == false) { - ui_draw_aligned_panel_header(style, block, &titlerect, 'h', show_background); + ui_draw_aligned_panel_header(style, block, &titlerect, 'h', show_background); - if (show_drag) { - /* itemrect smaller */ - const float scale = 0.7; - itemrect.xmax = headrect.xmax - (0.2f * UI_UNIT_X); - itemrect.xmin = itemrect.xmax - BLI_rcti_size_y(&headrect); - itemrect.ymin = headrect.ymin; - itemrect.ymax = headrect.ymax; - BLI_rctf_scale(&itemrect, scale); + if (show_drag) { + /* itemrect smaller */ + const float scale = 0.7; + itemrect.xmax = headrect.xmax - (0.2f * UI_UNIT_X); + itemrect.xmin = itemrect.xmax - BLI_rcti_size_y(&headrect); + itemrect.ymin = headrect.ymin; + itemrect.ymax = headrect.ymax; + BLI_rctf_scale(&itemrect, scale); - GPU_matrix_push(); - GPU_matrix_translate_2f(itemrect.xmin, itemrect.ymin); + GPU_matrix_push(); + GPU_matrix_translate_2f(itemrect.xmin, itemrect.ymin); - const int col_tint = 84; - float col_high[4], col_dark[4]; - UI_GetThemeColorShade4fv(TH_PANEL_HEADER, col_tint, col_high); - UI_GetThemeColorShade4fv(TH_PANEL_BACK, -col_tint, col_dark); + const int col_tint = 84; + float col_high[4], col_dark[4]; + UI_GetThemeColorShade4fv(TH_PANEL_HEADER, col_tint, col_high); + UI_GetThemeColorShade4fv(TH_PANEL_BACK, -col_tint, col_dark); - GPUBatch *batch = GPU_batch_preset_panel_drag_widget( - U.pixelsize, col_high, col_dark, BLI_rcti_size_y(&headrect) * scale); - GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_FLAT_COLOR); - GPU_batch_draw(batch); - GPU_matrix_pop(); - } + GPUBatch *batch = GPU_batch_preset_panel_drag_widget( + U.pixelsize, col_high, col_dark, BLI_rcti_size_y(&headrect) * scale); + GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_FLAT_COLOR); + GPU_batch_draw(batch); + GPU_matrix_pop(); } /* Draw panel backdrop. */ - if (is_closed_y) { - /* skip */ - } - else if (is_closed_x) { - /* draw vertical title */ - ui_draw_aligned_panel_header(style, block, &headrect, 'v', show_background); - pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - } - /* an open panel */ - else { + if (!(panel->flag & PNL_CLOSED)) { /* in some occasions, draw a border */ if (panel->flag & PNL_SELECT && !is_subpanel) { float radius; @@ -1186,10 +1108,7 @@ void ui_draw_aligned_panel(uiStyle *style, rgb_uchar_to_float(tria_color, col_title); tria_color[3] = 1.0f; - if (is_closed_y) { - ui_draw_anti_tria_rect(&itemrect, 'h', tria_color); - } - else if (is_closed_x) { + if (panel->flag & PNL_CLOSED) { ui_draw_anti_tria_rect(&itemrect, 'h', tria_color); } else { @@ -1200,15 +1119,6 @@ void ui_draw_aligned_panel(uiStyle *style, /************************** panel alignment *************************/ -static int get_panel_header(const Panel *panel) -{ - if (panel->type && (panel->type->flag & PNL_NO_HEADER)) { - return 0; - } - - return PNL_HEADER; -} - static int get_panel_size_y(const Panel *panel) { if (panel->type && (panel->type->flag & PNL_NO_HEADER)) { @@ -1238,20 +1148,12 @@ int UI_panel_size_y(const Panel *panel) * change sizey or location when closed */ static int get_panel_real_ofsy(Panel *panel) { - if (panel->flag & PNL_CLOSEDY) { + if (panel->flag & PNL_CLOSED) { return panel->ofsy + panel->sizey; } return panel->ofsy; } -static int get_panel_real_ofsx(Panel *panel) -{ - if (panel->flag & PNL_CLOSEDX) { - return panel->ofsx + get_panel_header(panel); - } - return panel->ofsx + panel->sizex; -} - bool UI_panel_is_dragging(const struct Panel *panel) { uiHandlePanelData *data = panel->activedata; @@ -1270,26 +1172,6 @@ bool UI_panel_is_dragging(const struct Panel *panel) * panels do not match for sorting */ -static int find_leftmost_panel(const void *a1, const void *a2) -{ - const PanelSort *ps1 = a1, *ps2 = a2; - - if (ps1->panel->ofsx > ps2->panel->ofsx) { - return 1; - } - if (ps1->panel->ofsx < ps2->panel->ofsx) { - return -1; - } - if (ps1->panel->sortorder > ps2->panel->sortorder) { - return 1; - } - if (ps1->panel->sortorder < ps2->panel->sortorder) { - return -1; - } - - return 0; -} - static int find_highest_panel(const void *a1, const void *a2) { const PanelSort *ps1 = a1, *ps2 = a2; @@ -1356,12 +1238,11 @@ static void align_sub_panels(Panel *panel) /* this doesn't draw */ /* returns 1 when it did something */ -static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, const bool drag) +static bool uiAlignPanelStep(ARegion *region, const float fac, const bool drag) { PanelSort *ps, *panelsort, *psnext; int a, tot = 0; bool done; - int align = panel_aligned(area, region); /* count active, not tabbed panels */ LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { @@ -1374,18 +1255,6 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co return 0; } - /* extra; change close direction? */ - LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { - if (panel->runtime_flag & PNL_ACTIVE) { - if ((panel->flag & PNL_CLOSEDX) && (align == BUT_VERTICAL)) { - panel->flag ^= PNL_CLOSED; - } - else if ((panel->flag & PNL_CLOSEDY) && (align == BUT_HORIZONTAL)) { - panel->flag ^= PNL_CLOSED; - } - } - } - /* sort panels */ panelsort = MEM_callocN(tot * sizeof(PanelSort), "panelsort"); @@ -1400,12 +1269,7 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co if (drag) { /* while we are dragging, we sort on location and update sortorder */ - if (align == BUT_VERTICAL) { - qsort(panelsort, tot, sizeof(PanelSort), find_highest_panel); - } - else { - qsort(panelsort, tot, sizeof(PanelSort), find_leftmost_panel); - } + qsort(panelsort, tot, sizeof(PanelSort), find_highest_panel); for (ps = panelsort, a = 0; a < tot; a++, ps++) { ps->orig->sortorder = a; @@ -1418,7 +1282,7 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co /* no smart other default start loc! this keeps switching f5/f6/etc compatible */ ps = panelsort; - ps->panel->runtime.region_ofsx = panel_region_offset_x_get(region, align); + ps->panel->runtime.region_ofsx = panel_region_offset_x_get(region); ps->panel->ofsx = 0; ps->panel->ofsy = -get_panel_size_y(ps->panel); ps->panel->ofsx += ps->panel->runtime.region_ofsx; @@ -1426,22 +1290,15 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co for (a = 0; a < tot - 1; a++, ps++) { psnext = ps + 1; - if (align == BUT_VERTICAL) { - bool use_box = ps->panel->type && ps->panel->type->flag & PNL_DRAW_BOX; - bool use_box_next = psnext->panel->type && psnext->panel->type->flag & PNL_DRAW_BOX; - psnext->panel->ofsx = ps->panel->ofsx; - psnext->panel->ofsy = get_panel_real_ofsy(ps->panel) - get_panel_size_y(psnext->panel); + bool use_box = ps->panel->type && ps->panel->type->flag & PNL_DRAW_BOX; + bool use_box_next = psnext->panel->type && psnext->panel->type->flag & PNL_DRAW_BOX; + psnext->panel->ofsx = ps->panel->ofsx; + psnext->panel->ofsy = get_panel_real_ofsy(ps->panel) - get_panel_size_y(psnext->panel); - /* Extra margin for box style panels. */ - ps->panel->ofsx += (use_box) ? UI_PANEL_BOX_STYLE_MARGIN : 0.0f; - if (use_box || use_box_next) { - psnext->panel->ofsy -= UI_PANEL_BOX_STYLE_MARGIN; - } - } - else { - psnext->panel->ofsx = get_panel_real_ofsx(ps->panel); - psnext->panel->ofsy = ps->panel->ofsy + get_panel_size_y(ps->panel) - - get_panel_size_y(psnext->panel); + /* Extra margin for box style panels. */ + ps->panel->ofsx += (use_box) ? UI_PANEL_BOX_STYLE_MARGIN : 0.0f; + if (use_box || use_box_next) { + psnext->panel->ofsy -= UI_PANEL_BOX_STYLE_MARGIN; } } /* Extra margin for the last panel if it's a box-style panel. */ @@ -1482,25 +1339,16 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co return done; } -static void ui_panels_size(ScrArea *area, ARegion *region, int *r_x, int *r_y) +static void ui_panels_size(ARegion *region, int *r_x, int *r_y) { - int align = panel_aligned(area, region); int sizex = 0; int sizey = 0; /* compute size taken up by panels, for setting in view2d */ LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { if (panel->runtime_flag & PNL_ACTIVE) { - int pa_sizex, pa_sizey; - - if (align == BUT_VERTICAL) { - pa_sizex = panel->ofsx + panel->sizex; - pa_sizey = get_panel_real_ofsy(panel); - } - else { - pa_sizex = get_panel_real_ofsx(panel) + panel->sizex; - pa_sizey = panel->ofsy + get_panel_size_y(panel); - } + int pa_sizex = panel->ofsx + panel->sizex; + int pa_sizey = get_panel_real_ofsy(panel); sizex = max_ii(sizex, pa_sizex); sizey = min_ii(sizey, pa_sizey); @@ -1521,7 +1369,6 @@ static void ui_panels_size(ScrArea *area, ARegion *region, int *r_x, int *r_y) static void ui_do_animate(bContext *C, Panel *panel) { uiHandlePanelData *data = panel->activedata; - ScrArea *area = CTX_wm_area(C); ARegion *region = CTX_wm_region(C); float fac; @@ -1529,7 +1376,7 @@ static void ui_do_animate(bContext *C, Panel *panel) fac = min_ff(sqrtf(fac), 1.0f); /* for max 1 second, interpolate positions */ - if (uiAlignPanelStep(area, region, fac, false)) { + if (uiAlignPanelStep(region, fac, false)) { ED_region_tag_redraw(region); } else { @@ -1590,7 +1437,7 @@ void UI_panels_end(const bContext *C, ARegion *region, int *r_x, int *r_y) panel_activate_state(C, panel, PANEL_STATE_ANIMATION); } else { - uiAlignPanelStep(area, region, 1.0, false); + uiAlignPanelStep(region, 1.0, false); } } @@ -1609,7 +1456,7 @@ void UI_panels_end(const bContext *C, ARegion *region, int *r_x, int *r_y) } /* compute size taken up by panel */ - ui_panels_size(area, region, r_x, r_y); + ui_panels_size(region, r_x, r_y); } void UI_panels_draw(const bContext *C, ARegion *region) @@ -1655,9 +1502,7 @@ void UI_panels_scale(ARegion *region, float new_width) static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel) { uiHandlePanelData *data = panel->activedata; - ScrArea *area = CTX_wm_area(C); ARegion *region = CTX_wm_region(C); - short align = panel_aligned(area, region); /* Keep the drag position in the region with a small pad to keep the panel visible. */ int x = clamp_i(event->x, region->winrct.xmin, region->winrct.xmax + DRAG_REGION_PAD); @@ -1690,9 +1535,7 @@ static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel) panel->ofsx = data->startofsx + round_fl_to_int(dx); panel->ofsy = data->startofsy + round_fl_to_int(dy); - if (align) { - uiAlignPanelStep(area, region, 0.2f, true); - } + uiAlignPanelStep(region, 0.2f, true); } ED_region_tag_redraw(region); @@ -1706,27 +1549,20 @@ static uiPanelMouseState ui_panel_mouse_state_get(const uiBlock *block, const int mx, const int my) { - /* open panel */ - if (panel->flag & PNL_CLOSEDX) { - if ((block->rect.xmin <= mx) && (block->rect.xmin + PNL_HEADER >= mx)) { - return PANEL_MOUSE_INSIDE_HEADER; - } - } - /* outside left/right side */ - else if ((block->rect.xmin > mx) || (block->rect.xmax < mx)) { - /* pass */ + if (!IN_RANGE((float)mx, block->rect.xmin, block->rect.xmax)) { + return PANEL_MOUSE_OUTSIDE; } - else if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) { + + if (IN_RANGE((float)my, block->rect.ymax, block->rect.ymax + PNL_HEADER)) { return PANEL_MOUSE_INSIDE_HEADER; } - /* open panel */ - else if (!(panel->flag & PNL_CLOSEDY)) { - if ((block->rect.xmin <= mx) && (block->rect.xmax >= mx)) { - if ((block->rect.ymin <= my) && (block->rect.ymax + PNL_HEADER >= my)) { - return PANEL_MOUSE_INSIDE_CONTENT; - } + + if (!(panel->flag & PNL_CLOSED)) { + if (IN_RANGE((float)my, block->rect.ymin, block->rect.ymax + PNL_HEADER)) { + return PANEL_MOUSE_INSIDE_CONTENT; } } + return PANEL_MOUSE_OUTSIDE; } @@ -1745,7 +1581,6 @@ static void ui_panel_drag_collapse(bContext *C, uiPanelDragCollapseHandle *dragcol_data, const int xy_dst[2]) { - ScrArea *area = CTX_wm_area(C); ARegion *region = CTX_wm_region(C); Panel *panel; @@ -1754,20 +1589,14 @@ static void ui_panel_drag_collapse(bContext *C, float xy_b_block[2] = {UNPACK2(xy_dst)}; rctf rect = block->rect; int oldflag; - const bool is_horizontal = (panel_aligned(area, region) == BUT_HORIZONTAL); if ((panel = block->panel) == 0 || (panel->type && (panel->type->flag & PNL_NO_HEADER))) { continue; } oldflag = panel->flag; - /* lock one axis */ - if (is_horizontal) { - xy_b_block[1] = dragcol_data->xy_init[1]; - } - else { - xy_b_block[0] = dragcol_data->xy_init[0]; - } + /* lock axis */ + xy_b_block[0] = dragcol_data->xy_init[0]; /* use cursor coords in block space */ ui_window_to_block_fl(region, block, &xy_a_block[0], &xy_a_block[1]); @@ -1776,20 +1605,11 @@ static void ui_panel_drag_collapse(bContext *C, /* set up rect to match header size */ rect.ymin = rect.ymax; rect.ymax = rect.ymin + PNL_HEADER; - if (panel->flag & PNL_CLOSEDX) { - rect.xmax = rect.xmin + PNL_HEADER; - } /* touch all panels between last mouse coord and the current one */ if (BLI_rctf_isect_segment(&rect, xy_a_block, xy_b_block)) { - /* force panel to close */ - if (dragcol_data->was_first_open == true) { - panel->flag |= (is_horizontal ? PNL_CLOSEDX : PNL_CLOSEDY); - } - /* force panel to open */ - else { - panel->flag &= ~PNL_CLOSED; - } + /* Force panel to open or close. */ + SET_FLAG_FROM_TEST(panel->flag, dragcol_data->was_first_open, PNL_CLOSED); /* if panel->flag has changed this means a panel was opened/closed here */ if (panel->flag != oldflag) { @@ -1856,9 +1676,8 @@ static void ui_panel_drag_collapse_handler_add(const bContext *C, const bool was /* this function is supposed to call general window drawing too */ /* also it supposes a block has panel, and isn't a menu */ static void ui_handle_panel_header( - const bContext *C, uiBlock *block, int mx, int my, int event, short ctrl, short shift) + const bContext *C, uiBlock *block, int mx, int event, short ctrl, short shift) { - ScrArea *area = CTX_wm_area(C); ARegion *region = CTX_wm_region(C); #ifdef USE_PIN_HIDDEN const bool show_pin = UI_panel_category_is_visible(region) && @@ -1870,7 +1689,7 @@ static void ui_handle_panel_header( const bool is_subpanel = (block->panel->type && block->panel->type->parent); const bool show_drag = !is_subpanel; - int align = panel_aligned(area, region), button = 0; + int button = 0; rctf rect_drag, rect_pin; float rect_leftmost; @@ -1901,11 +1720,6 @@ static void ui_handle_panel_header( button = 2; } } - else if (block->panel->flag & PNL_CLOSEDX) { - if (my >= block->rect.ymax) { - button = 1; - } - } else if (mx < rect_leftmost) { button = 1; } @@ -1921,20 +1735,18 @@ static void ui_handle_panel_header( /* For parent panels, collapse all other panels or toggle children. */ if (block->panel->type != NULL && block->panel->type->parent == NULL) { if (block->panel->flag & PNL_CLOSED || BLI_listbase_is_empty(&block->panel->children)) { - panels_collapse_all(C, area, region, block->panel); + panels_collapse_all(C, region, block->panel); /* Reset the view - we don't want to display a view without content. */ UI_view2d_offset(®ion->v2d, 0.0f, 1.0f); } else { - const int closed_flag = (align == BUT_HORIZONTAL) ? PNL_CLOSEDX : PNL_CLOSEDY; /* If a panel has sub-panels and it's open, toggle the expansion * of the sub-panels (based on the expansion of the first subpanel). */ Panel *first_child = block->panel->children.first; BLI_assert(first_child != NULL); - panel_set_flag_recursive( - block->panel, closed_flag, (first_child->flag & PNL_CLOSED) == 0); - block->panel->flag |= closed_flag; + panel_set_flag_recursive(block->panel, PNL_CLOSED, !(first_child->flag & PNL_CLOSED)); + block->panel->flag |= PNL_CLOSED; } } } @@ -1950,16 +1762,9 @@ static void ui_handle_panel_header( ui_panel_drag_collapse_handler_add(C, false); } } - else if (align == BUT_HORIZONTAL) { - block->panel->flag |= PNL_CLOSEDX; - - if (event == LEFTMOUSE) { - ui_panel_drag_collapse_handler_add(C, true); - } - } else { /* snap down to bottom screen edge */ - block->panel->flag |= PNL_CLOSEDY; + block->panel->flag |= PNL_CLOSED; if (block->panel->snap & PNL_SNAP_BOTTOM) { block->panel->ofsy = -block->panel->sizey; } @@ -1972,15 +1777,7 @@ static void ui_handle_panel_header( set_panels_list_data_expand_flag(C, region); } - if (align) { - panel_activate_state(C, block->panel, PANEL_STATE_ANIMATION); - } - else { - /* FIXME: this doesn't update the panel drawing, assert to avoid debugging why this is. - * We could fix this in the future if it's ever needed. */ - BLI_assert(0); - ED_region_tag_redraw(region); - } + panel_activate_state(C, block->panel, PANEL_STATE_ANIMATION); } else if (show_drag && BLI_rctf_isect_x(&rect_drag, mx)) { /* XXX, for now don't allow dragging in floating windows yet. */ @@ -2595,6 +2392,10 @@ int ui_handler_panel_region(bContext *C, retval = WM_UI_HANDLER_CONTINUE; + if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { + return retval; + } + /* Scrollbars can overlap panels now, they have handling priority. */ if (UI_view2d_mouse_in_scrollers(region, ®ion->v2d, event->x, event->y)) { return retval; @@ -2653,13 +2454,13 @@ int ui_handler_panel_region(bContext *C, if (event->type == EVT_AKEY && ((event->ctrl + event->oskey + event->shift + event->alt) == 0)) { - if (panel->flag & PNL_CLOSEDY) { + if (panel->flag & PNL_CLOSED) { if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) { - ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl, event->shift); + ui_handle_panel_header(C, block, mx, event->type, event->ctrl, event->shift); } } else { - ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl, event->shift); + ui_handle_panel_header(C, block, mx, event->type, event->ctrl, event->shift); } retval = WM_UI_HANDLER_BREAK; @@ -2679,7 +2480,7 @@ int ui_handler_panel_region(bContext *C, /* open close on header */ if (ELEM(event->type, EVT_RETKEY, EVT_PADENTER)) { if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) { - ui_handle_panel_header(C, block, mx, my, EVT_RETKEY, event->ctrl, event->shift); + ui_handle_panel_header(C, block, mx, EVT_RETKEY, event->ctrl, event->shift); retval = WM_UI_HANDLER_BREAK; break; } @@ -2689,7 +2490,7 @@ int ui_handler_panel_region(bContext *C, retval = WM_UI_HANDLER_BREAK; if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) { - ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl, event->shift); + ui_handle_panel_header(C, block, mx, event->type, event->ctrl, event->shift); retval = WM_UI_HANDLER_BREAK; break; } @@ -2773,16 +2574,7 @@ static int ui_handler_panel(bContext *C, const wmEvent *event, void *userdata) /* verify if we can stop */ if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { - ScrArea *area = CTX_wm_area(C); - ARegion *region = CTX_wm_region(C); - int align = panel_aligned(area, region); - - if (align) { - panel_activate_state(C, panel, PANEL_STATE_ANIMATION); - } - else { - panel_activate_state(C, panel, PANEL_STATE_EXIT); - } + panel_activate_state(C, panel, PANEL_STATE_ANIMATION); } else if (event->type == MOUSEMOVE) { if (data->state == PANEL_STATE_DRAG) { diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 0de1d64dcfe..0e801c8cee2 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -7361,6 +7361,10 @@ int uiTemplateRecentFiles(uiLayout *layout, int rows) { int i; LISTBASE_FOREACH_INDEX (RecentFile *, recent, &G.recent_files, i) { + if (i >= rows) { + break; + } + const char *filename = BLI_path_basename(recent->filepath); PointerRNA ptr; uiItemFullO(layout, @@ -7373,10 +7377,6 @@ int uiTemplateRecentFiles(uiLayout *layout, int rows) &ptr); RNA_string_set(&ptr, "filepath", recent->filepath); RNA_boolean_set(&ptr, "display_file_selector", false); - - if (i > rows) { - break; - } } return i; diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index c1801290152..bf64672fd81 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1096,7 +1096,8 @@ static void widgetbase_outline(uiWidgetBase *wtb, uint pos) float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */ widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip); - widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, wtb->totvert * 2 + 2); + widget_draw_vertex_buffer( + pos, 0, GPU_PRIM_TRI_STRIP, triangle_strip, NULL, wtb->totvert * 2 + 2); } static void widgetbase_set_uniform_alpha_discard(uiWidgetBase *wtb, @@ -2758,7 +2759,7 @@ static void widget_softshadow(const rcti *rect, int roundboxalign, const float r widget_verts_to_triangle_strip(&wtb, totvert, triangle_strip); - widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, totvert * 2); + widget_draw_vertex_buffer(pos, 0, GPU_PRIM_TRI_STRIP, triangle_strip, NULL, totvert * 2); } immUnbindProgram(); diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index dbaa335a9bf..8acbb328ab0 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -750,7 +750,7 @@ void ED_mask_draw_region( IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); GPU_shader_uniform_vector( state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red); - immDrawPixelsTex(&state, 0.0f, 0.0f, width, height, GL_R16F, false, buffer, 1.0f, 1.0f, NULL); + immDrawPixelsTex(&state, 0.0f, 0.0f, width, height, GPU_R16F, false, buffer, 1.0f, 1.0f, NULL); GPU_matrix_pop(); diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 94cd7650abe..6facee77c1e 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -1051,7 +1051,7 @@ static void knife_init_colors(KnifeColors *colors) static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void *arg) { const KnifeTool_OpData *kcd = arg; - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); GPU_matrix_push_projection(); GPU_polygon_offset(1.0f, 1.0f); @@ -1222,7 +1222,7 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), v GPU_matrix_pop_projection(); /* Reset default */ - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } /** diff --git a/source/blender/editors/mesh/editmesh_preselect_edgering.c b/source/blender/editors/mesh/editmesh_preselect_edgering.c index d9bd63ef35f..aa1df3d76fc 100644 --- a/source/blender/editors/mesh/editmesh_preselect_edgering.c +++ b/source/blender/editors/mesh/editmesh_preselect_edgering.c @@ -159,7 +159,7 @@ void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const fl return; } - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); GPU_matrix_push(); GPU_matrix_mul(matrix); @@ -197,7 +197,7 @@ void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const fl GPU_matrix_pop(); /* Reset default */ - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } static void view3d_preselect_mesh_edgering_update_verts_from_edge( diff --git a/source/blender/editors/mesh/editmesh_preselect_elem.c b/source/blender/editors/mesh/editmesh_preselect_elem.c index d53a1e2b55c..dfd646c767f 100644 --- a/source/blender/editors/mesh/editmesh_preselect_elem.c +++ b/source/blender/editors/mesh/editmesh_preselect_elem.c @@ -133,7 +133,7 @@ void EDBM_preselect_elem_draw(struct EditMesh_PreSelElem *psel, const float matr return; } - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); GPU_matrix_push(); GPU_matrix_mul(matrix); @@ -204,7 +204,7 @@ void EDBM_preselect_elem_draw(struct EditMesh_PreSelElem *psel, const float matr GPU_matrix_pop(); /* Reset default */ - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } static void view3d_preselect_mesh_elem_update_from_vert(struct EditMesh_PreSelElem *psel, diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 139900d0a4d..a59d8136f47 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1450,6 +1450,7 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); return OPERATOR_FINISHED; } @@ -2783,6 +2784,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); return OPERATOR_FINISHED; } @@ -3003,6 +3005,7 @@ static int duplicate_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); return OPERATOR_FINISHED; } @@ -3094,6 +3097,7 @@ static int object_add_named_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); ED_outliner_select_sync_from_object_tag(C); return OPERATOR_FINISHED; diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 5004b0132c2..27a641dc6d8 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2569,14 +2569,12 @@ BLI_INLINE bool streq_array_any(const char *s, const char *arr[]) * correct old \a uiBlock, and NULL otherwise. */ static void ed_panel_draw(const bContext *C, - ScrArea *area, ARegion *region, ListBase *lb, PanelType *pt, Panel *panel, int w, int em, - bool vertical, char *unique_panel_str) { const uiStyle *style = UI_style_get_dpi(); @@ -2592,13 +2590,13 @@ static void ed_panel_draw(const bContext *C, uiBlock *block = UI_block_begin(C, region, block_name, UI_EMBOSS); bool open; - panel = UI_panel_begin(area, region, lb, block, pt, panel, &open); + panel = UI_panel_begin(region, lb, block, pt, panel, &open); /* bad fixed values */ int xco, yco, h = 0; int headerend = w - UI_UNIT_X; - if (pt->draw_header_preset && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) { + if (pt->draw_header_preset && !(pt->flag & PNL_NO_HEADER)) { /* for preset menu */ panel->layout = UI_block_layout(block, UI_LAYOUT_HORIZONTAL, @@ -2617,7 +2615,7 @@ static void ed_panel_draw(const bContext *C, panel->layout = NULL; } - if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) { + if (pt->draw_header && !(pt->flag & PNL_NO_HEADER)) { int labelx, labely; UI_panel_label_offset(block, &labelx, &labely); @@ -2694,21 +2692,12 @@ static void ed_panel_draw(const bContext *C, Panel *child_panel = UI_panel_find_by_type(&panel->children, child_pt); if (child_pt->draw && (!child_pt->poll || child_pt->poll(C, child_pt))) { - ed_panel_draw(C, - area, - region, - &panel->children, - child_pt, - child_panel, - w, - em, - vertical, - unique_panel_str); + ed_panel_draw(C, region, &panel->children, child_pt, child_panel, w, em, unique_panel_str); } } } - UI_panel_end(area, region, block, w, h, open); + UI_panel_end(region, block, w, h, open); } /** @@ -2720,8 +2709,6 @@ void ED_region_panels_layout_ex(const bContext *C, ARegion *region, ListBase *paneltypes, const char *contexts[], - int contextnr, - const bool vertical, const char *category_override) { /* collect panels to draw */ @@ -2772,25 +2759,13 @@ void ED_region_panels_layout_ex(const bContext *C, const int category_tabs_width = UI_PANEL_CATEGORY_MARGIN_WIDTH; int margin_x = 0; const bool region_layout_based = region->flag & RGN_FLAG_DYNAMIC_SIZE; - const bool is_context_new = (contextnr != -1) ? UI_view2d_tab_set(v2d, contextnr) : false; bool update_tot_size = true; - /* before setting the view */ - if (vertical) { - /* only allow scrolling in vertical direction */ - v2d->keepofs |= V2D_LOCKOFS_X | V2D_KEEPOFS_Y; - v2d->keepofs &= ~(V2D_LOCKOFS_Y | V2D_KEEPOFS_X); - v2d->scroll &= ~V2D_SCROLL_BOTTOM; - v2d->scroll |= V2D_SCROLL_RIGHT; - } - else { - /* for now, allow scrolling in both directions (since layouts are optimized for vertical, - * they often don't fit in horizontal layout) - */ - v2d->keepofs &= ~(V2D_LOCKOFS_X | V2D_LOCKOFS_Y | V2D_KEEPOFS_X | V2D_KEEPOFS_Y); - v2d->scroll |= V2D_SCROLL_BOTTOM; - v2d->scroll &= ~V2D_SCROLL_RIGHT; - } + /* only allow scrolling in vertical direction */ + v2d->keepofs |= V2D_LOCKOFS_X | V2D_KEEPOFS_Y; + v2d->keepofs &= ~(V2D_LOCKOFS_Y | V2D_KEEPOFS_X); + v2d->scroll &= ~V2D_SCROLL_BOTTOM; + v2d->scroll |= V2D_SCROLL_RIGHT; /* collect categories */ if (use_category_tabs) { @@ -2815,14 +2790,8 @@ void ED_region_panels_layout_ex(const bContext *C, } } - if (vertical) { - w = BLI_rctf_size_x(&v2d->cur); - em = (region->type->prefsizex) ? 10 : 20; /* works out to 10*UI_UNIT_X or 20*UI_UNIT_X */ - } - else { - w = UI_PANEL_WIDTH; - em = (region->type->prefsizex) ? 10 : 20; - } + w = BLI_rctf_size_x(&v2d->cur); + em = (region->type->prefsizex) ? 10 : 20; /* works out to 10*UI_UNIT_X or 20*UI_UNIT_X */ w -= margin_x; int w_box_panel = w - UI_PANEL_BOX_STYLE_MARGIN * 2.0f; @@ -2855,14 +2824,12 @@ void ED_region_panels_layout_ex(const bContext *C, } ed_panel_draw(C, - area, region, ®ion->panels, pt, panel, (pt->flag & PNL_DRAW_BOX) ? w_box_panel : w, em, - vertical, NULL); } @@ -2890,14 +2857,12 @@ void ED_region_panels_layout_ex(const bContext *C, char unique_panel_str[8]; UI_list_panel_unique_str(panel, unique_panel_str); ed_panel_draw(C, - area, region, ®ion->panels, panel->type, panel, (panel->type->flag & PNL_DRAW_BOX) ? w_box_panel : w, em, - vertical, unique_panel_str); } } @@ -2925,7 +2890,7 @@ void ED_region_panels_layout_ex(const bContext *C, y = fabsf(region->sizey * UI_DPI_FAC - 1); } } - else if (vertical) { + else { /* We always keep the scroll offset - * so the total view gets increased with the scrolled away part. */ if (v2d->cur.ymax < -FLT_EPSILON) { @@ -2940,19 +2905,6 @@ void ED_region_panels_layout_ex(const bContext *C, y = -y; } - else { - /* don't jump back when panels close or hide */ - if (!is_context_new) { - if (v2d->tot.xmax > v2d->winx) { - x = max_ii(x, 0); - } - else { - x = max_ii(x, v2d->cur.xmax); - } - } - - y = -y; - } if (update_tot_size) { /* this also changes the 'cur' */ @@ -2966,8 +2918,7 @@ void ED_region_panels_layout_ex(const bContext *C, void ED_region_panels_layout(const bContext *C, ARegion *region) { - bool vertical = true; - ED_region_panels_layout_ex(C, region, ®ion->type->paneltypes, NULL, -1, vertical, NULL); + ED_region_panels_layout_ex(C, region, ®ion->type->paneltypes, NULL, NULL); } void ED_region_panels_draw(const bContext *C, ARegion *region) @@ -3011,12 +2962,10 @@ void ED_region_panels_draw(const bContext *C, ARegion *region) UI_view2d_scrollers_draw(v2d, mask); } -void ED_region_panels_ex( - const bContext *C, ARegion *region, const char *contexts[], int contextnr, const bool vertical) +void ED_region_panels_ex(const bContext *C, ARegion *region, const char *contexts[]) { /* TODO: remove? */ - ED_region_panels_layout_ex( - C, region, ®ion->type->paneltypes, contexts, contextnr, vertical, NULL); + ED_region_panels_layout_ex(C, region, ®ion->type->paneltypes, contexts, NULL); ED_region_panels_draw(C, region); } diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index dbf84cad80b..a2509c7a330 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1576,7 +1576,7 @@ void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph) { Scene *scene = DEG_get_input_scene(depsgraph); - DEG_id_tag_update_ex(bmain, &scene->id, ID_RECALC_TIME); + DEG_time_tag_update(bmain); #ifdef DURIAN_CAMERA_SWITCH void *camera = BKE_scene_camera_switch_find(scene); diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 0e38340d3bc..ee514fa745c 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -566,7 +566,7 @@ static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups, if (load_tex(brush, vc, zoom, col, primary)) { GPU_color_mask(true, true, true, true); - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { GPU_matrix_push(); @@ -693,7 +693,7 @@ static bool paint_draw_cursor_overlay( float center[2]; GPU_color_mask(true, true, true, true); - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); if (ups->draw_anchored) { copy_v2_v2(center, ups->anchored_initial_mouse); @@ -776,7 +776,7 @@ static bool paint_draw_alpha_overlay(UnifiedPaintSettings *ups, ePaintOverlayControlFlags flags = BKE_paint_get_overlay_flags(); eGPUBlend blend_state = GPU_blend_get(); - bool depth_test = GPU_depth_test_enabled(); + eGPUDepthTest depth_test = GPU_depth_test_get(); /* Translate to region. */ GPU_matrix_push(); @@ -1147,9 +1147,9 @@ static void sculpt_geometry_preview_lines_draw(const uint gpuattr, immUniformColor4f(1.0f, 1.0f, 1.0f, 0.6f); /* Cursor normally draws on top, but for this part we need depth tests. */ - const bool depth_test = GPU_depth_test_enabled(); + const eGPUDepthTest depth_test = GPU_depth_test_get(); if (!depth_test) { - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } GPU_line_width(1.0f); @@ -1163,7 +1163,7 @@ static void sculpt_geometry_preview_lines_draw(const uint gpuattr, /* Restore depth test value. */ if (!depth_test) { - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); } } diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 52cdebf3fd5..e709224f370 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -691,6 +691,14 @@ static float paint_space_stroke_spacing(bContext *C, spacing = spacing * (1.5f - spacing_pressure); } + if (SCULPT_is_cloth_deform_brush(brush)) { + /* The spacing in tools that use the cloth solver should not be affected by the brush radius to + * avoid affecting the simulation update rate when changing the radius of the brush. + With a value of 100 and the brush default of 10 for spacing, a simulation step runs every 2 + pixels movement of the cursor. */ + size_clamp = 100.0f; + } + /* stroke system is used for 2d paint too, so we need to account for * the fact that brush can be scaled there. */ spacing *= stroke->zoom_2d; @@ -1001,7 +1009,7 @@ bool paint_space_stroke_enabled(Brush *br, ePaintMode mode) return false; } - if (br->sculpt_tool == SCULPT_TOOL_CLOTH) { + if (br->sculpt_tool == SCULPT_TOOL_CLOTH || SCULPT_is_cloth_deform_brush(br)) { /* The Cloth Brush is a special case for stroke spacing. Even if it has grab modes which do * not support dynamic size, stroke spacing needs to be enabled so it is possible to control * whether the simulation runs constantly or only when the brush moves when using the cloth diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index 9a3fbe474b8..cf2ed0943eb 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -1071,6 +1071,25 @@ static EnumPropertyItem prop_cloth_filter_type[] = { {0, NULL, 0, NULL, NULL}, }; +static EnumPropertyItem prop_cloth_filter_orientation_items[] = { + {SCULPT_FILTER_ORIENTATION_LOCAL, + "LOCAL", + 0, + "Local", + "Use the local axis to limit the force and set the gravity direction"}, + {SCULPT_FILTER_ORIENTATION_WORLD, + "WORLD", + 0, + "World", + "Use the global axis to limit the force and set the gravity direction"}, + {SCULPT_FILTER_ORIENTATION_VIEW, + "VIEW", + 0, + "View", + "Use the view axis to limit the force and set the gravity direction"}, + {0, NULL, 0, NULL, NULL}, +}; + typedef enum eClothFilterForceAxis { CLOTH_FILTER_FORCE_X = 1 << 0, CLOTH_FILTER_FORCE_Y = 1 << 1, @@ -1120,7 +1139,15 @@ static void cloth_filter_apply_forces_task_cb(void *__restrict userdata, switch (filter_type) { case CLOTH_FILTER_GRAVITY: - force[2] = -data->filter_strength * fade; + if (ss->filter_cache->orientation == SCULPT_FILTER_ORIENTATION_VIEW) { + /* When using the view orientation apply gravity in the -Y axis, this way objects will + * fall down instead of backwards. */ + force[1] = -data->filter_strength * fade; + } + else { + force[2] = -data->filter_strength * fade; + } + SCULPT_filter_to_object_space(force, ss->filter_cache); break; case CLOTH_FILTER_INFLATE: { float normal[3]; @@ -1138,11 +1165,13 @@ static void cloth_filter_apply_forces_task_cb(void *__restrict userdata, break; } + SCULPT_filter_to_orientation_space(force, ss->filter_cache); for (int axis = 0; axis < 3; axis++) { if (!ss->filter_cache->enabled_force_axis[axis]) { force[axis] = 0.0f; } } + SCULPT_filter_to_object_space(force, ss->filter_cache); add_v3_v3(force, sculpt_gravity); @@ -1264,6 +1293,9 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent ss->filter_cache->enabled_force_axis[1] = force_axis & CLOTH_FILTER_FORCE_Y; ss->filter_cache->enabled_force_axis[2] = force_axis & CLOTH_FILTER_FORCE_Z; + SculptFilterOrientation orientation = RNA_enum_get(op->ptr, "orientation"); + ss->filter_cache->orientation = orientation; + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -1297,6 +1329,12 @@ void SCULPT_OT_cloth_filter(struct wmOperatorType *ot) CLOTH_FILTER_FORCE_X | CLOTH_FILTER_FORCE_Y | CLOTH_FILTER_FORCE_Z, "Force axis", "Apply the force in the selected axis"); + RNA_def_enum(ot->srna, + "orientation", + prop_cloth_filter_orientation_items, + SCULPT_FILTER_ORIENTATION_LOCAL, + "Orientation", + "Orientation of the axis to limit the filter force"); RNA_def_float(ot->srna, "cloth_mass", 1.0f, diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index abfbe035928..619a1b975b6 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -181,7 +181,7 @@ void SCULPT_filter_cache_free(SculptSession *ss) MEM_SAFE_FREE(ss->filter_cache); } -typedef enum eSculptMeshFilterTypes { +typedef enum eSculptMeshFilterType { MESH_FILTER_SMOOTH = 0, MESH_FILTER_SCALE = 1, MESH_FILTER_INFLATE = 2, @@ -193,7 +193,7 @@ typedef enum eSculptMeshFilterTypes { MESH_FILTER_SHARPEN = 8, MESH_FILTER_ENHANCE_DETAILS = 9, MESH_FILTER_ERASE_DISPLACEMENT = 10, -} eSculptMeshFilterTypes; +} eSculptMeshFilterType; static EnumPropertyItem prop_mesh_filter_types[] = { {MESH_FILTER_SMOOTH, "SMOOTH", 0, "Smooth", "Smooth mesh"}, @@ -258,7 +258,7 @@ static EnumPropertyItem prop_mesh_filter_orientation_items[] = { {0, NULL, 0, NULL, NULL}, }; -static bool sculpt_mesh_filter_needs_pmap(int filter_type, bool use_face_sets) +static bool sculpt_mesh_filter_needs_pmap(eSculptMeshFilterType filter_type, bool use_face_sets) { return use_face_sets || ELEM(filter_type, MESH_FILTER_SMOOTH, @@ -277,7 +277,7 @@ static void mesh_filter_task_cb(void *__restrict userdata, SculptSession *ss = data->ob->sculpt; PBVHNode *node = data->nodes[i]; - const int filter_type = data->filter_type; + const eSculptMeshFilterType filter_type = data->filter_type; SculptOrigVertData orig_data; SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[i]); @@ -383,7 +383,7 @@ static void mesh_filter_task_cb(void *__restrict userdata, const uint *hash_co = (const uint *)orig_co; const uint hash = BLI_hash_int_2d(hash_co[0], hash_co[1]) ^ BLI_hash_int_2d(hash_co[2], ss->filter_cache->random_seed); - mul_v3_fl(normal, hash * (1.0f / 0xFFFFFFFF) - 0.5f); + mul_v3_fl(normal, hash * (1.0f / (float)0xFFFFFFFF) - 0.5f); mul_v3_v3fl(disp, normal, fade); break; } @@ -486,49 +486,80 @@ static void mesh_filter_task_cb(void *__restrict userdata, static void mesh_filter_enhance_details_init_directions(SculptSession *ss) { const int totvert = SCULPT_vertex_count_get(ss); + FilterCache *filter_cache = ss->filter_cache; + + filter_cache->detail_directions = MEM_malloc_arrayN( + totvert, sizeof(float[3]), "detail directions"); for (int i = 0; i < totvert; i++) { float avg[3]; SCULPT_neighbor_coords_average(ss, avg, i); - sub_v3_v3v3(ss->filter_cache->detail_directions[i], avg, SCULPT_vertex_co_get(ss, i)); + sub_v3_v3v3(filter_cache->detail_directions[i], avg, SCULPT_vertex_co_get(ss, i)); } } +static void mesh_filter_surface_smooth_init(SculptSession *ss, + const float shape_preservation, + const float current_vertex_displacement) +{ + const int totvert = SCULPT_vertex_count_get(ss); + FilterCache *filter_cache = ss->filter_cache; + + filter_cache->surface_smooth_laplacian_disp = MEM_malloc_arrayN( + totvert, sizeof(float[3]), "surface smooth displacement"); + filter_cache->surface_smooth_shape_preservation = shape_preservation; + filter_cache->surface_smooth_current_vertex = current_vertex_displacement; +} + static void mesh_filter_init_limit_surface_co(SculptSession *ss) { const int totvert = SCULPT_vertex_count_get(ss); - ss->filter_cache->limit_surface_co = MEM_malloc_arrayN( - 3 * sizeof(float), totvert, "limit surface co"); + FilterCache *filter_cache = ss->filter_cache; + + filter_cache->limit_surface_co = MEM_malloc_arrayN( + sizeof(float[3]), totvert, "limit surface co"); for (int i = 0; i < totvert; i++) { - SCULPT_vertex_limit_surface_get(ss, i, ss->filter_cache->limit_surface_co[i]); + SCULPT_vertex_limit_surface_get(ss, i, filter_cache->limit_surface_co[i]); } } -static void mesh_filter_sharpen_init_factors(SculptSession *ss) +static void mesh_filter_sharpen_init(SculptSession *ss, + const float smooth_ratio, + const float intensify_detail_strength, + const int curvature_smooth_iterations) { const int totvert = SCULPT_vertex_count_get(ss); + FilterCache *filter_cache = ss->filter_cache; + + filter_cache->sharpen_smooth_ratio = smooth_ratio; + filter_cache->sharpen_intensify_detail_strength = intensify_detail_strength; + filter_cache->sharpen_curvature_smooth_iterations = curvature_smooth_iterations; + filter_cache->sharpen_factor = MEM_malloc_arrayN(sizeof(float), totvert, "sharpen factor"); + filter_cache->detail_directions = MEM_malloc_arrayN( + totvert, sizeof(float[3]), "sharpen detail direction"); + for (int i = 0; i < totvert; i++) { float avg[3]; SCULPT_neighbor_coords_average(ss, avg, i); - sub_v3_v3v3(ss->filter_cache->detail_directions[i], avg, SCULPT_vertex_co_get(ss, i)); - ss->filter_cache->sharpen_factor[i] = len_v3(ss->filter_cache->detail_directions[i]); + sub_v3_v3v3(filter_cache->detail_directions[i], avg, SCULPT_vertex_co_get(ss, i)); + filter_cache->sharpen_factor[i] = len_v3(filter_cache->detail_directions[i]); } float max_factor = 0.0f; for (int i = 0; i < totvert; i++) { - if (ss->filter_cache->sharpen_factor[i] > max_factor) { - max_factor = ss->filter_cache->sharpen_factor[i]; + if (filter_cache->sharpen_factor[i] > max_factor) { + max_factor = filter_cache->sharpen_factor[i]; } } max_factor = 1.0f / max_factor; for (int i = 0; i < totvert; i++) { - ss->filter_cache->sharpen_factor[i] *= max_factor; - ss->filter_cache->sharpen_factor[i] = 1.0f - pow2f(1.0f - ss->filter_cache->sharpen_factor[i]); + filter_cache->sharpen_factor[i] *= max_factor; + filter_cache->sharpen_factor[i] = 1.0f - pow2f(1.0f - filter_cache->sharpen_factor[i]); } /* Smooth the calculated factors and directions to remove high frecuency detail. */ for (int smooth_iterations = 0; - smooth_iterations < ss->filter_cache->sharpen_curvature_smooth_iterations; + smooth_iterations < filter_cache->sharpen_curvature_smooth_iterations; smooth_iterations++) { for (int i = 0; i < totvert; i++) { float direction_avg[3] = {0.0f, 0.0f, 0.0f}; @@ -537,15 +568,15 @@ static void mesh_filter_sharpen_init_factors(SculptSession *ss) SculptVertexNeighborIter ni; SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) { - add_v3_v3(direction_avg, ss->filter_cache->detail_directions[ni.index]); - sharpen_avg += ss->filter_cache->sharpen_factor[ni.index]; + add_v3_v3(direction_avg, filter_cache->detail_directions[ni.index]); + sharpen_avg += filter_cache->sharpen_factor[ni.index]; total++; } SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); if (total > 0) { - mul_v3_v3fl(ss->filter_cache->detail_directions[i], direction_avg, 1.0f / total); - ss->filter_cache->sharpen_factor[i] = sharpen_avg / total; + mul_v3_v3fl(filter_cache->detail_directions[i], direction_avg, 1.0f / total); + filter_cache->sharpen_factor[i] = sharpen_avg / total; } } } @@ -590,7 +621,7 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent * Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); SculptSession *ss = ob->sculpt; Sculpt *sd = CTX_data_tool_settings(C)->sculpt; - int filter_type = RNA_enum_get(op->ptr, "type"); + eSculptMeshFilterType filter_type = RNA_enum_get(op->ptr, "type"); float filter_strength = RNA_float_get(op->ptr, "strength"); const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets"); @@ -654,17 +685,21 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent Object *ob = CTX_data_active_object(C); Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); Sculpt *sd = CTX_data_tool_settings(C)->sculpt; - int filter_type = RNA_enum_get(op->ptr, "type"); SculptSession *ss = ob->sculpt; - PBVH *pbvh = ob->sculpt->pbvh; - int deform_axis = RNA_enum_get(op->ptr, "deform_axis"); + const eMeshFilterDeformAxis deform_axis = RNA_enum_get(op->ptr, "deform_axis"); + const eSculptMeshFilterType filter_type = RNA_enum_get(op->ptr, "type"); + const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets"); + const bool needs_topology_info = sculpt_mesh_filter_needs_pmap(filter_type, use_face_sets); + if (deform_axis == 0) { + /* All axis are disabled, so the filter is not going to produce any deformation. */ return OPERATOR_CANCELLED; } - if (RNA_boolean_get(op->ptr, "use_face_sets")) { - /* Update the active vertex */ + if (use_face_sets) { + /* Update the active face set manually as the paint cursor is not enabled when using the Mesh + * Filter Tool. */ float mouse[2]; SculptCursorGeometryInfo sgi; mouse[0] = event->mval[0]; @@ -672,67 +707,48 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); } - const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets"); - SCULPT_vertex_random_access_ensure(ss); - - const bool needs_topology_info = sculpt_mesh_filter_needs_pmap(filter_type, use_face_sets); BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_topology_info, false, false); if (needs_topology_info) { SCULPT_boundary_info_ensure(ob); } - const int totvert = SCULPT_vertex_count_get(ss); - if (BKE_pbvh_type(pbvh) == PBVH_FACES && needs_topology_info && !ob->sculpt->pmap) { - return OPERATOR_CANCELLED; - } - - SCULPT_undo_push_begin("Mesh filter"); - - if (ELEM(filter_type, MESH_FILTER_RELAX, MESH_FILTER_RELAX_FACE_SETS)) { - SCULPT_boundary_info_ensure(ob); - } + SCULPT_undo_push_begin("Mesh Filter"); SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COORDS); - if (use_face_sets) { - ss->filter_cache->active_face_set = SCULPT_active_face_set_get(ss); - } - else { - ss->filter_cache->active_face_set = SCULPT_FACE_SET_NONE; - } - - if (RNA_enum_get(op->ptr, "type") == MESH_FILTER_SURFACE_SMOOTH) { - ss->filter_cache->surface_smooth_laplacian_disp = MEM_mallocN(sizeof(float[3]) * totvert, - "surface smooth disp"); - ss->filter_cache->surface_smooth_shape_preservation = RNA_float_get( - op->ptr, "surface_smooth_shape_preservation"); - ss->filter_cache->surface_smooth_current_vertex = RNA_float_get( - op->ptr, "surface_smooth_current_vertex"); - } - - if (RNA_enum_get(op->ptr, "type") == MESH_FILTER_SHARPEN) { - ss->filter_cache->sharpen_smooth_ratio = RNA_float_get(op->ptr, "sharpen_smooth_ratio"); - ss->filter_cache->sharpen_intensify_detail_strength = RNA_float_get( - op->ptr, "sharpen_intensify_detail_strength"); - ss->filter_cache->sharpen_curvature_smooth_iterations = RNA_int_get( - op->ptr, "sharpen_curvature_smooth_iterations"); - - ss->filter_cache->sharpen_factor = MEM_mallocN(sizeof(float) * totvert, "sharpen factor"); - ss->filter_cache->detail_directions = MEM_malloc_arrayN( - totvert, sizeof(float[3]), "sharpen detail direction"); - - mesh_filter_sharpen_init_factors(ss); - } - - if (RNA_enum_get(op->ptr, "type") == MESH_FILTER_ENHANCE_DETAILS) { - ss->filter_cache->detail_directions = MEM_malloc_arrayN( - totvert, sizeof(float[3]), "detail direction"); - mesh_filter_enhance_details_init_directions(ss); - } + FilterCache *filter_cache = ss->filter_cache; + filter_cache->active_face_set = use_face_sets ? SCULPT_active_face_set_get(ss) : + SCULPT_FACE_SET_NONE; - if (RNA_enum_get(op->ptr, "type") == MESH_FILTER_ERASE_DISPLACEMENT) { - mesh_filter_init_limit_surface_co(ss); + switch (filter_type) { + case MESH_FILTER_SURFACE_SMOOTH: { + const float shape_preservation = RNA_float_get(op->ptr, "surface_smooth_shape_preservation"); + const float current_vertex_displacement = RNA_float_get(op->ptr, + "surface_smooth_current_vertex"); + mesh_filter_surface_smooth_init(ss, shape_preservation, current_vertex_displacement); + break; + } + case MESH_FILTER_SHARPEN: { + const float smooth_ratio = RNA_float_get(op->ptr, "sharpen_smooth_ratio"); + const float intensify_detail_strength = RNA_float_get(op->ptr, + "sharpen_intensify_detail_strength"); + const int curvature_smooth_iterations = RNA_int_get(op->ptr, + "sharpen_curvature_smooth_iterations"); + mesh_filter_sharpen_init( + ss, smooth_ratio, intensify_detail_strength, curvature_smooth_iterations); + break; + } + case MESH_FILTER_ENHANCE_DETAILS: { + mesh_filter_enhance_details_init_directions(ss); + break; + } + case MESH_FILTER_ERASE_DISPLACEMENT: { + mesh_filter_init_limit_surface_co(ss); + break; + } + default: + break; } ss->filter_cache->enabled_axis[0] = deform_axis & MESH_FILTER_DEFORM_X; diff --git a/source/blender/editors/sculpt_paint/sculpt_transform.c b/source/blender/editors/sculpt_paint/sculpt_transform.c index bdada4d2565..b52b04eba3a 100644 --- a/source/blender/editors/sculpt_paint/sculpt_transform.c +++ b/source/blender/editors/sculpt_paint/sculpt_transform.c @@ -326,6 +326,12 @@ static int sculpt_set_pivot_position_exec(bContext *C, wmOperator *op) MEM_SAFE_FREE(nodes); } + /* Update the viewport navigation rotation origin. */ + UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings; + copy_v3_v3(ups->average_stroke_accum, ss->pivot_pos); + ups->average_stroke_counter = 1; + ups->last_stroke_valid = true; + ED_region_tag_redraw(region); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index dc34e56dc92..d7cf2e4d544 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -292,9 +292,7 @@ static void buttons_main_region_layout_properties(const bContext *C, break; } - const bool vertical = true; - ED_region_panels_layout_ex( - C, region, ®ion->type->paneltypes, contexts, sbuts->mainb, vertical, NULL); + ED_region_panels_layout_ex(C, region, ®ion->type->paneltypes, contexts, NULL); } static void buttons_main_region_layout(const bContext *C, ARegion *region) diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index d58f5ede7d7..058436a46bf 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -523,7 +523,7 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, GPU_shader_uniform_vector( state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red); - immDrawPixelsTex(&state, x1, y1, rectx, recty, GL_R16F, false, rectf, zoomx, zoomy, NULL); + immDrawPixelsTex(&state, x1, y1, rectx, recty, GPU_R16F, false, rectf, zoomx, zoomy, NULL); MEM_freeN(rectf); } diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index a64d5505ebe..1f7929cea7b 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -662,7 +662,7 @@ static void image_main_region_draw(const bContext *C, ARegion *region) srgb_to_linearrgb_v3_v3(col, col); GPU_clear_color(col[0], col[1], col[2], 1.0f); GPU_clear(GPU_COLOR_BIT); - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); image_user_refresh_scene(C, sima); @@ -836,9 +836,7 @@ static void image_buttons_region_layout(const bContext *C, ARegion *region) break; } - const bool vertical = true; - ED_region_panels_layout_ex( - C, region, ®ion->type->paneltypes, contexts_base, -1, vertical, NULL); + ED_region_panels_layout_ex(C, region, ®ion->type->paneltypes, contexts_base, NULL); } static void image_buttons_region_draw(const bContext *C, ARegion *region) diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index 4e91da01cc9..e97031736ca 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -547,19 +547,20 @@ static void get_stats_string( info + *ofs, len - *ofs, TIP_(" | Objects:%s/%s"), stats_fmt->totobjsel, stats_fmt->totobj); } -const char *ED_info_statusbar_string(Main *bmain, bScreen *screen, bContext *C) +static const char *info_statusbar_string(Main *bmain, + Scene *scene, + ViewLayer *view_layer, + char statusbar_flag) { char formatted_mem[15]; size_t ofs = 0; - char *info = screen->statusbar_info; - int len = sizeof(screen->statusbar_info); + static char info[256]; + int len = sizeof(info); info[0] = '\0'; /* Scene statistics. */ - if (U.statusbar_flag & STATUSBAR_SHOW_STATS) { - ViewLayer *view_layer = CTX_data_view_layer(C); - Scene *scene = CTX_data_scene(C); + if (statusbar_flag & STATUSBAR_SHOW_STATS) { SceneStatsFmt stats_fmt; if (format_stats(bmain, scene, view_layer, &stats_fmt)) { get_stats_string(info + ofs, len, &ofs, view_layer, &stats_fmt); @@ -567,7 +568,7 @@ const char *ED_info_statusbar_string(Main *bmain, bScreen *screen, bContext *C) } /* Memory status. */ - if (U.statusbar_flag & STATUSBAR_SHOW_MEMORY) { + if (statusbar_flag & STATUSBAR_SHOW_MEMORY) { if (info[0]) { ofs += BLI_snprintf(info + ofs, len - ofs, " | "); } @@ -577,7 +578,7 @@ const char *ED_info_statusbar_string(Main *bmain, bScreen *screen, bContext *C) } /* GPU VRAM status. */ - if ((U.statusbar_flag & STATUSBAR_SHOW_VRAM) && (GPU_mem_stats_supported())) { + if ((statusbar_flag & STATUSBAR_SHOW_VRAM) && (GPU_mem_stats_supported())) { int gpu_free_mem_kb, gpu_tot_mem_kb; GPU_mem_stats_get(&gpu_tot_mem_kb, &gpu_free_mem_kb); float gpu_total_gb = gpu_tot_mem_kb / 1048576.0f; @@ -599,7 +600,7 @@ const char *ED_info_statusbar_string(Main *bmain, bScreen *screen, bContext *C) } /* Blender version. */ - if (U.statusbar_flag & STATUSBAR_SHOW_VERSION) { + if (statusbar_flag & STATUSBAR_SHOW_VERSION) { if (info[0]) { ofs += BLI_snprintf(info + ofs, len - ofs, " | "); } @@ -609,6 +610,20 @@ const char *ED_info_statusbar_string(Main *bmain, bScreen *screen, bContext *C) return info; } +const char *ED_info_statusbar_string(Main *bmain, Scene *scene, ViewLayer *view_layer) +{ + return info_statusbar_string(bmain, scene, view_layer, U.statusbar_flag); +} + +const char *ED_info_statistics_string(Main *bmain, Scene *scene, ViewLayer *view_layer) +{ + const eUserpref_StatusBar_Flag statistics_status_bar_flag = STATUSBAR_SHOW_STATS | + STATUSBAR_SHOW_MEMORY | + STATUSBAR_SHOW_VERSION; + + return info_statusbar_string(bmain, scene, view_layer, statistics_status_bar_flag); +} + static void stats_row(int col1, const char *key, int col2, diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index bc9bd0e18f2..dc8f616c5e6 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -1847,11 +1847,7 @@ static int nlaedit_sync_actlen_exec(bContext *C, wmOperator *op) continue; } - /* recalculate the length of the action */ - calc_action_range(strip->act, &strip->actstart, &strip->actend, 0); - - /* adjust the strip extents in response to this */ - BKE_nlastrip_recalculate_bounds(strip); + BKE_nlastrip_recalculate_bounds_sync_action(strip); ale->update |= ANIM_UPDATE_DEPS; } diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 814473b0e9a..917bb8e75fd 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -1738,7 +1738,7 @@ void drawnodespace(const bContext *C, ARegion *region) UI_view2d_view_ortho(v2d); UI_ThemeClearColor(TH_BACK); GPU_clear(GPU_COLOR_BIT); - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); /* XXX snode->cursor set in coordspace for placing new nodes, used for drawing noodles too */ UI_view2d_region_to_view(®ion->v2d, diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 1705b9dd606..cf6a86ba6d7 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -2743,6 +2743,23 @@ static void outliner_icon_background_colors(float icon_color[4], float icon_bord icon_border[3] = 0.2f; } +/* Draw a rounded rectangle behind icons of active elements. */ +static void outliner_draw_active_indicator(const float minx, + const float miny, + const float maxx, + const float maxy, + const float icon_color[4], + const float icon_border[4]) +{ + const float ufac = UI_UNIT_X / 20.0f; + const float radius = UI_UNIT_Y / 4.0f; + + UI_draw_roundbox_corner_set(UI_CNR_ALL); + UI_draw_roundbox_aa(true, minx, miny + ufac, maxx, maxy - ufac, radius, icon_color); + UI_draw_roundbox_aa(false, minx, miny + ufac, maxx, maxy - ufac, radius, icon_border); + GPU_blend(GPU_BLEND_ALPHA); /* Roundbox disables. */ +} + static void outliner_draw_iconrow_doit(uiBlock *block, TreeElement *te, const uiFontStyle *fstyle, @@ -2756,31 +2773,19 @@ static void outliner_draw_iconrow_doit(uiBlock *block, TreeStoreElem *tselem = TREESTORE(te); if (active != OL_DRAWSEL_NONE) { - float ufac = UI_UNIT_X / 20.0f; float icon_color[4], icon_border[4]; outliner_icon_background_colors(icon_color, icon_border); if (active == OL_DRAWSEL_ACTIVE) { UI_GetThemeColor4fv(TH_EDITED_OBJECT, icon_color); icon_border[3] = 0.3f; } - UI_draw_roundbox_corner_set(UI_CNR_ALL); - - UI_draw_roundbox_aa(true, - (float)*offsx, - (float)ys + ufac, - (float)*offsx + UI_UNIT_X, - (float)ys + UI_UNIT_Y - ufac, - (float)UI_UNIT_Y / 4.0f, - icon_color); - /* border around it */ - UI_draw_roundbox_aa(false, - (float)*offsx, - (float)ys + ufac, - (float)*offsx + UI_UNIT_X, - (float)ys + UI_UNIT_Y - ufac, - (float)UI_UNIT_Y / 4.0f, - icon_border); - GPU_blend(GPU_BLEND_ALPHA); /* Roundbox disables. */ + + outliner_draw_active_indicator((float)*offsx, + (float)ys, + (float)*offsx + UI_UNIT_X, + (float)ys + UI_UNIT_Y, + icon_color, + icon_border); } if (tselem->flag & TSE_HIGHLIGHTED) { @@ -3052,23 +3057,12 @@ static void outliner_draw_tree_element(bContext *C, /* active circle */ if (active != OL_DRAWSEL_NONE) { - UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_aa(true, - (float)startx + offsx + UI_UNIT_X, - (float)*starty + ufac, - (float)startx + offsx + 2.0f * UI_UNIT_X, - (float)*starty + UI_UNIT_Y - ufac, - UI_UNIT_Y / 4.0f, - icon_bgcolor); - /* border around it */ - UI_draw_roundbox_aa(false, - (float)startx + offsx + UI_UNIT_X, - (float)*starty + ufac, - (float)startx + offsx + 2.0f * UI_UNIT_X, - (float)*starty + UI_UNIT_Y - ufac, - UI_UNIT_Y / 4.0f, - icon_border); - GPU_blend(GPU_BLEND_ALPHA); /* roundbox disables it */ + outliner_draw_active_indicator((float)startx + offsx + UI_UNIT_X, + (float)*starty, + (float)startx + offsx + 2.0f * UI_UNIT_X, + (float)*starty + UI_UNIT_Y, + icon_bgcolor, + icon_border); te->flag |= TE_ACTIVE; /* For lookup in display hierarchies. */ } diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index cd2fcd8e2cf..8567dd4da13 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -193,13 +193,7 @@ static int outliner_item_openclose_modal(bContext *C, wmOperator *op, const wmEv if (te->xs == data->x_location) { outliner_item_openclose(te, data->open, false); - /* Avoid rebuild if possible. */ - if (outliner_element_needs_rebuild_on_open_change(TREESTORE(te))) { - ED_region_tag_redraw(region); - } - else { - ED_region_tag_redraw_no_rebuild(region); - } + outliner_tag_redraw_avoid_rebuild_on_open_change(space_outliner, region); } } @@ -239,13 +233,7 @@ static int outliner_item_openclose_invoke(bContext *C, wmOperator *op, const wmE (toggle_all && (outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1))); outliner_item_openclose(te, open, toggle_all); - /* Avoid rebuild if possible. */ - if (outliner_element_needs_rebuild_on_open_change(TREESTORE(te))) { - ED_region_tag_redraw(region); - } - else { - ED_region_tag_redraw_no_rebuild(region); - } + outliner_tag_redraw_avoid_rebuild_on_open_change(space_outliner, region); /* Only toggle once for single click toggling */ if (event->type == LEFTMOUSE) { diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 33dbbb274c0..9795bb73efe 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -237,7 +237,7 @@ void outliner_build_tree(struct Main *mainvar, struct SpaceOutliner *space_outliner, struct ARegion *region); -bool outliner_element_needs_rebuild_on_open_change(const TreeStoreElem *tselem); +bool outliner_mode_requires_always_rebuild(const struct SpaceOutliner *space_outliner); typedef struct IDsSelectedData { struct ListBase selected_array; @@ -515,6 +515,8 @@ float outliner_restrict_columns_width(const struct SpaceOutliner *space_outliner TreeElement *outliner_find_element_with_flag(const ListBase *lb, short flag); bool outliner_is_element_visible(const TreeElement *te); void outliner_scroll_view(struct ARegion *region, int delta_y); +void outliner_tag_redraw_avoid_rebuild_on_open_change(const struct SpaceOutliner *space_outliner, + struct ARegion *region); /* outliner_sync.c ---------------------------------------------- */ diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 1ac1b46f0d1..d720747e953 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -1000,7 +1000,9 @@ static eOLDrawState tree_element_active_master_collection(bContext *C, ViewLayer *view_layer = CTX_data_view_layer(C); LayerCollection *layer_collection = view_layer->layer_collections.first; BKE_layer_collection_activate(view_layer, layer_collection); - WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + /* A very precise notifier - ND_LAYER alone is quite vague, we want to avoid unnecessary work + * when only the active collection changes. */ + WM_main_add_notifier(NC_SCENE | ND_LAYER | NS_LAYER_COLLECTION | NA_ACTIVATED, NULL); } return OL_DRAWSEL_NONE; @@ -1022,7 +1024,9 @@ static eOLDrawState tree_element_active_layer_collection(bContext *C, LayerCollection *layer_collection = te->directdata; ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, layer_collection); BKE_layer_collection_activate(view_layer, layer_collection); - WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + /* A very precise notifier - ND_LAYER alone is quite vague, we want to avoid unnecessary work + * when only the active collection changes. */ + WM_main_add_notifier(NC_SCENE | ND_LAYER | NS_LAYER_COLLECTION | NA_ACTIVATED, NULL); } return OL_DRAWSEL_NONE; @@ -1507,7 +1511,7 @@ static int outliner_box_select_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - ED_region_tag_redraw(region); + ED_region_tag_redraw_no_rebuild(region); ED_outliner_select_sync_from_outliner(C, space_outliner); @@ -1729,7 +1733,7 @@ static int outliner_walk_select_invoke(bContext *C, wmOperator *op, const wmEven outliner_walk_scroll(region, active_te); ED_outliner_select_sync_from_outliner(C, space_outliner); - ED_region_tag_redraw(region); + outliner_tag_redraw_avoid_rebuild_on_open_change(space_outliner, region); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 6532ff189b5..2a13f9d6a66 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -792,10 +792,11 @@ static void id_override_library_create_fn(bContext *C, } else if (ID_IS_OVERRIDABLE_LIBRARY(id_root)) { BKE_lib_override_library_create_from_id(bmain, id_root, true); - } - BKE_main_id_clear_newpoins(bmain); - BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + /* Cleanup. */ + BKE_main_id_clear_newpoins(bmain); + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + } } } @@ -827,6 +828,68 @@ static void id_override_library_reset_fn(bContext *C, } } +static void id_override_library_resync_fn(bContext *C, + ReportList *UNUSED(reports), + Scene *scene, + TreeElement *te, + TreeStoreElem *UNUSED(tsep), + TreeStoreElem *tselem, + void *UNUSED(user_data)) +{ + BLI_assert(TSE_IS_REAL_ID(tselem)); + ID *id_root = tselem->id; + + if (ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) { + Main *bmain = CTX_data_main(C); + + id_root->tag |= LIB_TAG_DOIT; + + /* Tag all linked parents in tree hierarchy to be also overridden. */ + while ((te = te->parent) != NULL) { + if (!TSE_IS_REAL_ID(te->store_elem)) { + continue; + } + if (!ID_IS_OVERRIDE_LIBRARY_REAL(te->store_elem->id)) { + break; + } + te->store_elem->id->tag |= LIB_TAG_DOIT; + } + + BKE_lib_override_library_resync(bmain, scene, CTX_data_view_layer(C), id_root); + } +} + +static void id_override_library_delete_fn(bContext *C, + ReportList *UNUSED(reports), + Scene *UNUSED(scene), + TreeElement *te, + TreeStoreElem *UNUSED(tsep), + TreeStoreElem *tselem, + void *UNUSED(user_data)) +{ + BLI_assert(TSE_IS_REAL_ID(tselem)); + ID *id_root = tselem->id; + + if (ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) { + Main *bmain = CTX_data_main(C); + + id_root->tag |= LIB_TAG_DOIT; + + /* Tag all linked parents in tree hierarchy to be also overridden. */ + while ((te = te->parent) != NULL) { + if (!TSE_IS_REAL_ID(te->store_elem)) { + continue; + } + if (!ID_IS_OVERRIDE_LIBRARY_REAL(te->store_elem->id)) { + break; + } + te->store_elem->id->tag |= LIB_TAG_DOIT; + } + + BKE_lib_override_library_delete(bmain, id_root); + } +} + static void id_fake_user_set_fn(bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *UNUSED(scene), @@ -1567,6 +1630,7 @@ static int outliner_delete_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); ED_outliner_select_sync_from_object_tag(C); return OPERATOR_FINISHED; @@ -1607,6 +1671,8 @@ typedef enum eOutlinerIdOpTypes { OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY, OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET, OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY, + OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY, + OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY, OUTLINER_IDOP_SINGLE, OUTLINER_IDOP_DELETE, OUTLINER_IDOP_REMAP, @@ -1653,6 +1719,18 @@ static const EnumPropertyItem prop_id_op_types[] = { 0, "Reset Library Override Hierarchy", "Reset this local override to its linked values, as well as its hierarchy of dependencies"}, + {OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY, + "OVERRIDE_LIBRARY_RESYNC_HIERARCHY", + 0, + "Resync Library Override Hierarchy", + "Rebuild this local override from its linked reference, as well as its hierarchy of " + "dependencies"}, + {OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY, + "OVERRIDE_LIBRARY_DELETE_HIERARCHY", + 0, + "Delete Library Override Hierarchy", + "Delete this local override (including its hierarchy of override dependencies) and relink " + "its usages to the linked data-blocks"}, {0, "", 0, NULL, NULL}, {OUTLINER_IDOP_COPY, "COPY", ICON_COPYDOWN, "Copy", ""}, {OUTLINER_IDOP_PASTE, "PASTE", ICON_PASTEDOWN, "Paste", ""}, @@ -1683,6 +1761,10 @@ static bool outliner_id_operation_item_poll(bContext *C, case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET: case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY: return true; + case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY: + return true; + case OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY: + return true; case OUTLINER_IDOP_SINGLE: if (!space_outliner || ELEM(space_outliner->outlinevis, SO_SCENES, SO_VIEW_LAYER)) { return true; @@ -1818,7 +1900,6 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op) break; } case OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE: { - /* make local */ outliner_do_libdata_operation(C, op->reports, scene, @@ -1830,7 +1911,6 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op) break; } case OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY: { - /* make local */ outliner_do_libdata_operation(C, op->reports, scene, @@ -1842,7 +1922,6 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op) break; } case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET: { - /* make local */ outliner_do_libdata_operation(C, op->reports, scene, @@ -1854,7 +1933,6 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op) break; } case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY: { - /* make local */ outliner_do_libdata_operation(C, op->reports, scene, @@ -1865,6 +1943,28 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op) ED_undo_push(C, "Reset Overridden Data Hierarchy"); break; } + case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY: { + outliner_do_libdata_operation(C, + op->reports, + scene, + space_outliner, + &space_outliner->tree, + id_override_library_resync_fn, + &(OutlinerLibOverrideData){.do_hierarchy = true}); + ED_undo_push(C, "Resync Overridden Data Hierarchy"); + break; + } + case OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY: { + outliner_do_libdata_operation(C, + op->reports, + scene, + space_outliner, + &space_outliner->tree, + id_override_library_delete_fn, + &(OutlinerLibOverrideData){.do_hierarchy = true}); + ED_undo_push(C, "Delete Overridden Data Hierarchy"); + break; + } case OUTLINER_IDOP_SINGLE: { /* make single user */ switch (idlevel) { diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 60058c82283..9e3cbabf283 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -244,14 +244,12 @@ static TreeElement *outliner_add_element(SpaceOutliner *space_outliner, /* -------------------------------------------------------- */ /** - * Check if an element type needs a full rebuild if the open/collapsed state changes. - * These element types don't add children if collapsed. - * - * This current check isn't great really. A per element-type flag would be preferable. + * Check if a display mode needs a full rebuild if the open/collapsed state changes. + * Element types in these modes don't actually add children if collapsed, so the rebuild is needed. */ -bool outliner_element_needs_rebuild_on_open_change(const TreeStoreElem *tselem) +bool outliner_mode_requires_always_rebuild(const SpaceOutliner *space_outliner) { - return ELEM(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_KEYMAP); + return ELEM(space_outliner->outlinevis, SO_DATA_API); } /* special handling of hierarchical non-lib data */ diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c index 1da44b5e51e..25dc7bc271e 100644 --- a/source/blender/editors/space_outliner/outliner_utils.c +++ b/source/blender/editors/space_outliner/outliner_utils.c @@ -37,6 +37,7 @@ #include "ED_armature.h" #include "ED_outliner.h" +#include "ED_screen.h" #include "UI_interface.h" #include "UI_view2d.h" @@ -455,6 +456,23 @@ void outliner_scroll_view(ARegion *region, int delta_y) } } +/** + * The outliner should generally use #ED_region_tag_redraw_no_rebuild() to avoid unnecessary tree + * rebuilds. If elements are open or closed, we may still have to rebuild. + * Upon changing the open/closed state, call this to avoid rebuilds if possible. + */ +void outliner_tag_redraw_avoid_rebuild_on_open_change(const SpaceOutliner *space_outliner, + ARegion *region) +{ + /* Avoid rebuild if possible. */ + if (outliner_mode_requires_always_rebuild(space_outliner)) { + ED_region_tag_redraw(region); + } + else { + ED_region_tag_redraw_no_rebuild(region); + } +} + /* Get base of object under cursor. Used for eyedropper tool */ Base *ED_outliner_give_base_under_cursor(bContext *C, const int mval[2]) { diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index b14afed81dd..6854367d975 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -114,6 +114,8 @@ static void outliner_main_region_listener(wmWindow *UNUSED(win), switch (wmn->data) { case ND_OB_ACTIVE: case ND_OB_SELECT: + ED_region_tag_redraw_no_rebuild(region); + break; case ND_OB_VISIBLE: case ND_OB_RENDER: case ND_MODE: @@ -121,15 +123,23 @@ static void outliner_main_region_listener(wmWindow *UNUSED(win), case ND_FRAME: case ND_RENDER_OPTIONS: case ND_SEQUENCER: - case ND_LAYER: case ND_LAYER_CONTENT: case ND_WORLD: case ND_SCENEBROWSE: ED_region_tag_redraw(region); break; + case ND_LAYER: + /* Avoid rebuild if only the active collection changes */ + if ((wmn->subtype == NS_LAYER_COLLECTION) && (wmn->action == NA_ACTIVATED)) { + ED_region_tag_redraw_no_rebuild(region); + break; + } + + ED_region_tag_redraw(region); + break; } - if (wmn->action & NA_EDITED) { - ED_region_tag_redraw(region); + if (wmn->action == NA_EDITED) { + ED_region_tag_redraw_no_rebuild(region); } break; case NC_OBJECT: @@ -181,7 +191,7 @@ static void outliner_main_region_listener(wmWindow *UNUSED(win), case NC_MATERIAL: switch (wmn->data) { case ND_SHADING_LINKS: - ED_region_tag_redraw(region); + ED_region_tag_redraw_no_rebuild(region); break; } break; diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 8a6b97b3834..eb066f6afea 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1772,7 +1772,7 @@ void sequencer_draw_preview(const bContext *C, GPUFrameBuffer *framebuffer_overlay = GPU_viewport_framebuffer_overlay_get(viewport); GPU_framebuffer_bind_no_srgb(framebuffer_overlay); - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); if (sseq->render_size == SEQ_PROXY_RENDER_SIZE_NONE) { sequencer_preview_clear(); diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c index 0242bb4fe24..3efdee9cec9 100644 --- a/source/blender/editors/space_userpref/space_userpref.c +++ b/source/blender/editors/space_userpref/space_userpref.c @@ -141,8 +141,7 @@ static void userpref_main_region_layout(const bContext *C, ARegion *region) BLI_str_tolower_ascii(id_lower, strlen(id_lower)); } - ED_region_panels_layout_ex( - C, region, ®ion->type->paneltypes, contexts, U.space_data.section_active, true, NULL); + ED_region_panels_layout_ex(C, region, ®ion->type->paneltypes, contexts, NULL); } static void userpref_operatortypes(void) diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index e5ba27cef07..de0b420a3b5 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -1323,9 +1323,7 @@ void ED_view3d_buttons_region_layout_ex(const bContext *C, paneltypes = &art->paneltypes; } - const bool vertical = true; - ED_region_panels_layout_ex( - C, region, paneltypes, contexts_base, -1, vertical, category_override); + ED_region_panels_layout_ex(C, region, paneltypes, contexts_base, category_override); } static void view3d_buttons_region_layout(const bContext *C, ARegion *region) @@ -1453,7 +1451,7 @@ static void view3d_tools_region_init(wmWindowManager *wm, ARegion *region) static void view3d_tools_region_draw(const bContext *C, ARegion *region) { - ED_region_panels_ex(C, region, (const char *[]){CTX_data_mode_string(C), NULL}, -1, true); + ED_region_panels_ex(C, region, (const char *[]){CTX_data_mode_string(C), NULL}); } /* area (not region) level listener */ diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 33b365b45aa..4cc48dfd175 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1618,7 +1618,7 @@ void view3d_main_region_draw(const bContext *C, ARegion *region) GPU_pass_cache_garbage_collect(); /* No depth test for drawing action zones afterwards. */ - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); v3d->flag |= V3D_INVALID_BACKBUF; } @@ -2321,12 +2321,12 @@ void ED_view3d_draw_depth_gpencil(Depsgraph *depsgraph, Scene *scene, ARegion *r GPU_clear(GPU_DEPTH_BIT); - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); GPUViewport *viewport = WM_draw_region_get_viewport(region); DRW_draw_depth_loop_gpencil(depsgraph, region, v3d, viewport); - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); } /* *********************** customdata **************** */ diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c index 6c61c83731d..6c2f4df7004 100644 --- a/source/blender/editors/space_view3d/view3d_placement.c +++ b/source/blender/editors/space_view3d/view3d_placement.c @@ -586,23 +586,23 @@ static void draw_primitive_view(const struct bContext *C, ARegion *UNUSED(region UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, color); const bool use_depth = !XRAY_ENABLED(ipd->v3d); - const bool depth_test_enabled = GPU_depth_test_enabled(); + const eGPUDepthTest depth_test_enabled = GPU_depth_test_get(); if (use_depth) { - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); color[3] = 0.15f; draw_primitive_view_impl(C, ipd, color); } if (use_depth) { - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } color[3] = 1.0f; draw_primitive_view_impl(C, ipd, color); if (use_depth) { if (depth_test_enabled == false) { - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); } } } diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index b986ebb75b6..d015b5dcc89 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -1100,7 +1100,7 @@ int view3d_opengl_select(ViewContext *vc, wm, vc->win, depsgraph, scene, region, v3d, vc->rv3d->viewmat, NULL, &rect); if (!XRAY_ACTIVE(v3d)) { - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } /* If in xray mode, we select the wires in priority. */ @@ -1165,7 +1165,7 @@ int view3d_opengl_select(ViewContext *vc, wm, vc->win, depsgraph, scene, region, v3d, vc->rv3d->viewmat, NULL, NULL); if (!XRAY_ACTIVE(v3d)) { - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); } DRW_opengl_context_disable(); diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 0aa6b4f6131..4e5eaf4bf51 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -785,7 +785,6 @@ void drawConstraint(TransInfo *t) else { if (tc->mode & CON_SELECT) { float vec[3]; - int depth_test_enabled; convertViewVec(t, vec, (t->mval[0] - t->con.imval[0]), (t->mval[1] - t->con.imval[1])); add_v3_v3(vec, t->center_global); @@ -794,9 +793,9 @@ void drawConstraint(TransInfo *t) drawLine(t, t->center_global, t->spacemtx[1], 'Y', 0); drawLine(t, t->center_global, t->spacemtx[2], 'Z', 0); - depth_test_enabled = GPU_depth_test_enabled(); + eGPUDepthTest depth_test_enabled = GPU_depth_test_get(); if (depth_test_enabled) { - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); } const uint shdr_pos = GPU_vertformat_attr_add( @@ -821,7 +820,7 @@ void drawConstraint(TransInfo *t) immUnbindProgram(); if (depth_test_enabled) { - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } } @@ -843,7 +842,6 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) if (t->flag & T_PROP_EDIT) { RegionView3D *rv3d = CTX_wm_region_view3d(C); float tmat[4][4], imat[4][4]; - int depth_test_enabled; if (t->spacetype == SPACE_VIEW3D && rv3d != NULL) { copy_m4_m4(tmat, rv3d->viewmat); @@ -873,9 +871,9 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) GPU_matrix_scale_2f(1.0f, (ysize / xsize) * (xmask / ymask)); } - depth_test_enabled = GPU_depth_test_enabled(); + eGPUDepthTest depth_test_enabled = GPU_depth_test_get(); if (depth_test_enabled) { - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); } uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); @@ -899,7 +897,7 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) immUnbindProgram(); if (depth_test_enabled) { - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } GPU_matrix_pop(); diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index dffee72205b..14ef5e87534 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -1343,7 +1343,7 @@ void drawDial3d(const TransInfo *t) BLI_assert(axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END); gizmo_get_axis_color(axis_idx, NULL, color, color); - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); GPU_blend(GPU_BLEND_ALPHA); GPU_line_smooth(true); @@ -1359,7 +1359,7 @@ void drawDial3d(const TransInfo *t) }); GPU_line_smooth(false); - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); GPU_blend(GPU_BLEND_NONE); } } diff --git a/source/blender/editors/transform/transform_mode_edge_slide.c b/source/blender/editors/transform/transform_mode_edge_slide.c index 45debe964f4..fe97a9fba87 100644 --- a/source/blender/editors/transform/transform_mode_edge_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_slide.c @@ -1147,7 +1147,7 @@ void drawEdgeSlide(TransInfo *t) const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); GPU_blend(GPU_BLEND_ALPHA); @@ -1266,7 +1266,7 @@ void drawEdgeSlide(TransInfo *t) GPU_blend(GPU_BLEND_NONE); - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } static void edge_slide_snap_apply(TransInfo *t, float *value) diff --git a/source/blender/editors/transform/transform_mode_vert_slide.c b/source/blender/editors/transform/transform_mode_vert_slide.c index 11d0b375e6f..4367dd5ee92 100644 --- a/source/blender/editors/transform/transform_mode_vert_slide.c +++ b/source/blender/editors/transform/transform_mode_vert_slide.c @@ -390,7 +390,7 @@ void drawVertSlide(TransInfo *t) const int alpha_shade = -160; int i; - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); GPU_blend(GPU_BLEND_ALPHA); @@ -485,7 +485,7 @@ void drawVertSlide(TransInfo *t) GPU_matrix_pop(); - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } } } diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 09b5df82c2b..5db41570e00 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -184,7 +184,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t) const float *loc_prev = NULL; const float *normal = NULL; - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); RegionView3D *rv3d = CTX_wm_region_view3d(C); if (!BLI_listbase_is_empty(&t->tsnap.points)) { @@ -228,7 +228,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t) ED_gizmotypes_snap_3d_draw_util( rv3d, loc_prev, loc_cur, normal, col, activeCol, t->tsnap.snapElem); - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } } else if (t->spacetype == SPACE_IMAGE) { diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index faeefcb989e..d80e7f3c754 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -451,13 +451,13 @@ static void draw_uvs(SpaceImage *sima, GPU_batch_program_set_builtin(batch->edges, shader); /* Inner Line. Use depth test to insure selection is drawn on top. */ - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); GPU_line_width(1.0f); GPU_batch_uniform_4fv(batch->edges, "edgeColor", col1); GPU_batch_uniform_4fv(batch->edges, "selectColor", col2); GPU_batch_uniform_1f(batch->edges, "dashWidth", dash_width); GPU_batch_draw(batch->edges); - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); GPU_provoking_vertex(GPU_VERTEX_LAST); } diff --git a/source/blender/functions/tests/FN_array_spans_test.cc b/source/blender/functions/tests/FN_array_spans_test.cc index 9a632b58be8..af2bc0aad91 100644 --- a/source/blender/functions/tests/FN_array_spans_test.cc +++ b/source/blender/functions/tests/FN_array_spans_test.cc @@ -50,7 +50,9 @@ TEST(virtual_array_span, MultipleArrayConstructor) std::array<int, 2> values1 = {6, 7}; std::array<int, 1> values2 = {8}; std::array<const int *, 3> starts = {values0.data(), values1.data(), values2.data()}; - std::array<int64_t, 3> sizes{values0.size(), values1.size(), values2.size()}; + std::array<int64_t, 3> sizes{static_cast<int64_t>(values0.size()), + static_cast<int64_t>(values1.size()), + static_cast<int64_t>(values2.size())}; VArraySpan<int> span{starts, sizes}; EXPECT_EQ(span.size(), 3); diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 45b379c5e0a..50a5a0243f8 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -93,6 +93,7 @@ set(SRC opengl/gl_context.cc opengl/gl_drawlist.cc opengl/gl_shader.cc + opengl/gl_shader_interface.cc opengl/gl_state.cc opengl/gl_vertex_array.cc @@ -119,7 +120,6 @@ set(SRC GPU_primitive.h GPU_select.h GPU_shader.h - GPU_shader_interface.h GPU_state.h GPU_texture.h GPU_uniformbuffer.h @@ -140,6 +140,7 @@ set(SRC intern/gpu_private.h intern/gpu_select_private.h intern/gpu_shader_private.hh + intern/gpu_shader_interface.hh intern/gpu_state_private.hh intern/gpu_vertex_format_private.h @@ -148,6 +149,7 @@ set(SRC opengl/gl_context.hh opengl/gl_drawlist.hh opengl/gl_shader.hh + opengl/gl_shader_interface.hh opengl/gl_state.hh opengl/gl_vertex_array.hh ) diff --git a/source/blender/gpu/GPU_context.h b/source/blender/gpu/GPU_context.h index e3d47cfe084..be7e604fb96 100644 --- a/source/blender/gpu/GPU_context.h +++ b/source/blender/gpu/GPU_context.h @@ -27,7 +27,6 @@ #include "GPU_batch.h" #include "GPU_common.h" -#include "GPU_shader_interface.h" #ifdef __cplusplus extern "C" { diff --git a/source/blender/gpu/GPU_immediate.h b/source/blender/gpu/GPU_immediate.h index 41d4f5d28d3..6057770d2d9 100644 --- a/source/blender/gpu/GPU_immediate.h +++ b/source/blender/gpu/GPU_immediate.h @@ -29,7 +29,6 @@ #include "GPU_immediate_util.h" #include "GPU_primitive.h" #include "GPU_shader.h" -#include "GPU_shader_interface.h" #include "GPU_texture.h" #include "GPU_vertex_format.h" @@ -103,13 +102,11 @@ void immVertex2iv(uint attr_id, const int data[2]); /* Provide uniform values that don't change for the entire draw call. */ void immUniform1i(const char *name, int x); -void immUniform4iv(const char *name, const int data[4]); void immUniform1f(const char *name, float x); void immUniform2f(const char *name, float x, float y); void immUniform2fv(const char *name, const float data[2]); void immUniform3f(const char *name, float x, float y, float z); void immUniform3fv(const char *name, const float data[3]); -void immUniformArray3fv(const char *name, const float *data, int count); void immUniform4f(const char *name, float x, float y, float z, float w); void immUniform4fv(const char *name, const float data[4]); void immUniformArray4fv(const char *bare_name, const float *data, int count); diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index 99fcae19984..b38cc1f3244 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -27,7 +27,6 @@ extern "C" { #endif -struct GPUShaderInterface; struct GPUTexture; struct GPUUniformBuffer; struct GPUVertBuf; @@ -35,8 +34,6 @@ struct GPUVertBuf; /* TODO(fclem) These members should be private and the * whole struct should just be an opaque pointer. */ typedef struct GPUShader { - /** Uniform & attribute locations for shader. */ - struct GPUShaderInterface *interface; /** For debugging purpose. */ char name[64]; } GPUShader; @@ -90,6 +87,41 @@ void GPU_shader_transform_feedback_disable(GPUShader *shader); int GPU_shader_get_program(GPUShader *shader); +typedef enum { + GPU_UNIFORM_MODEL = 0, /* mat4 ModelMatrix */ + GPU_UNIFORM_VIEW, /* mat4 ViewMatrix */ + GPU_UNIFORM_MODELVIEW, /* mat4 ModelViewMatrix */ + GPU_UNIFORM_PROJECTION, /* mat4 ProjectionMatrix */ + GPU_UNIFORM_VIEWPROJECTION, /* mat4 ViewProjectionMatrix */ + GPU_UNIFORM_MVP, /* mat4 ModelViewProjectionMatrix */ + + GPU_UNIFORM_MODEL_INV, /* mat4 ModelMatrixInverse */ + GPU_UNIFORM_VIEW_INV, /* mat4 ViewMatrixInverse */ + GPU_UNIFORM_MODELVIEW_INV, /* mat4 ModelViewMatrixInverse */ + GPU_UNIFORM_PROJECTION_INV, /* mat4 ProjectionMatrixInverse */ + GPU_UNIFORM_VIEWPROJECTION_INV, /* mat4 ViewProjectionMatrixInverse */ + + GPU_UNIFORM_NORMAL, /* mat3 NormalMatrix */ + GPU_UNIFORM_ORCO, /* vec4 OrcoTexCoFactors[] */ + GPU_UNIFORM_CLIPPLANES, /* vec4 WorldClipPlanes[] */ + + GPU_UNIFORM_COLOR, /* vec4 color */ + GPU_UNIFORM_BASE_INSTANCE, /* int baseInstance */ + GPU_UNIFORM_RESOURCE_CHUNK, /* int resourceChunk */ + GPU_UNIFORM_RESOURCE_ID, /* int resourceId */ + GPU_UNIFORM_SRGB_TRANSFORM, /* bool srgbTarget */ + + GPU_NUM_UNIFORMS, /* Special value, denotes number of builtin uniforms. */ +} GPUUniformBuiltin; + +typedef enum { + GPU_UNIFORM_BLOCK_VIEW = 0, /* viewBlock */ + GPU_UNIFORM_BLOCK_MODEL, /* modelBlock */ + GPU_UNIFORM_BLOCK_INFO, /* infoBlock */ + + GPU_NUM_UNIFORM_BLOCKS, /* Special value, denotes number of builtin uniforms block. */ +} GPUUniformBlockBuiltin; + void GPU_shader_set_srgb_uniform(GPUShader *shader); int GPU_shader_get_uniform(GPUShader *shader, const char *name); @@ -123,8 +155,6 @@ void GPU_shader_uniform_4fv_array(GPUShader *sh, const char *name, int len, cons int GPU_shader_get_attribute(GPUShader *shader, const char *name); -char *GPU_shader_get_binary(GPUShader *shader, uint *r_binary_format, int *r_binary_len); - void GPU_shader_set_framebuffer_srgb_target(int use_srgb_to_linear); /* Builtin/Non-generated shaders */ diff --git a/source/blender/gpu/GPU_shader_interface.h b/source/blender/gpu/GPU_shader_interface.h deleted file mode 100644 index 47e4e432d66..00000000000 --- a/source/blender/gpu/GPU_shader_interface.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2016 by Mike Erwin. - * All rights reserved. - */ - -/** \file - * \ingroup gpu - * - * GPU shader interface (C --> GLSL) - */ - -#pragma once - -#include "GPU_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - GPU_UNIFORM_MODEL = 0, /* mat4 ModelMatrix */ - GPU_UNIFORM_VIEW, /* mat4 ViewMatrix */ - GPU_UNIFORM_MODELVIEW, /* mat4 ModelViewMatrix */ - GPU_UNIFORM_PROJECTION, /* mat4 ProjectionMatrix */ - GPU_UNIFORM_VIEWPROJECTION, /* mat4 ViewProjectionMatrix */ - GPU_UNIFORM_MVP, /* mat4 ModelViewProjectionMatrix */ - - GPU_UNIFORM_MODEL_INV, /* mat4 ModelMatrixInverse */ - GPU_UNIFORM_VIEW_INV, /* mat4 ViewMatrixInverse */ - GPU_UNIFORM_MODELVIEW_INV, /* mat4 ModelViewMatrixInverse */ - GPU_UNIFORM_PROJECTION_INV, /* mat4 ProjectionMatrixInverse */ - GPU_UNIFORM_VIEWPROJECTION_INV, /* mat4 ViewProjectionMatrixInverse */ - - GPU_UNIFORM_NORMAL, /* mat3 NormalMatrix */ - GPU_UNIFORM_ORCO, /* vec4 OrcoTexCoFactors[] */ - GPU_UNIFORM_CLIPPLANES, /* vec4 WorldClipPlanes[] */ - - GPU_UNIFORM_COLOR, /* vec4 color */ - GPU_UNIFORM_BASE_INSTANCE, /* int baseInstance */ - GPU_UNIFORM_RESOURCE_CHUNK, /* int resourceChunk */ - GPU_UNIFORM_RESOURCE_ID, /* int resourceId */ - GPU_UNIFORM_SRGB_TRANSFORM, /* bool srgbTarget */ - - GPU_NUM_UNIFORMS, /* Special value, denotes number of builtin uniforms. */ -} GPUUniformBuiltin; - -typedef enum { - GPU_UNIFORM_BLOCK_VIEW = 0, /* viewBlock */ - GPU_UNIFORM_BLOCK_MODEL, /* modelBlock */ - GPU_UNIFORM_BLOCK_INFO, /* infoBlock */ - - GPU_NUM_UNIFORM_BLOCKS, /* Special value, denotes number of builtin uniforms block. */ -} GPUUniformBlockBuiltin; - -typedef struct GPUShaderInput { - uint32_t name_offset; - uint32_t name_hash; - int32_t location; - /** Defined at interface creation or in shader. Only for Samplers, UBOs and Vertex Attribs. */ - int32_t binding; -} GPUShaderInput; - -#define GPU_SHADERINTERFACE_REF_ALLOC_COUNT 16 - -typedef struct GPUShaderInterface { - /** Buffer containing all inputs names separated by '\0'. */ - char *name_buffer; - /** Reference to GPUBatches using this interface */ - void **batches; - uint batches_len; - /** Input counts. */ - uint attribute_len; - uint ubo_len; - uint uniform_len; - /** Enabled bindpoints that needs to be fed with data. */ - uint16_t enabled_attr_mask; - uint16_t enabled_ubo_mask; - uint64_t enabled_tex_mask; - /** Opengl Location of builtin uniforms. Fast access, no lookup needed. */ - int32_t builtins[GPU_NUM_UNIFORMS]; - int32_t builtin_blocks[GPU_NUM_UNIFORM_BLOCKS]; - /** Flat array. In this order: Attributes, Ubos, Uniforms. */ - GPUShaderInput inputs[0]; -} GPUShaderInterface; - -GPUShaderInterface *GPU_shaderinterface_create(int32_t program_id); -void GPU_shaderinterface_discard(GPUShaderInterface *); - -const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *, const char *name); -int32_t GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *shaderface, - GPUUniformBuiltin builtin); -int32_t GPU_shaderinterface_block_builtin(const GPUShaderInterface *shaderface, - GPUUniformBlockBuiltin builtin); -const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *, const char *name); -const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *, const char *name); - -/* keep track of batches using this interface */ -void GPU_shaderinterface_add_batch_ref(GPUShaderInterface *interface, void *cache); -void GPU_shaderinterface_remove_batch_ref(GPUShaderInterface *interface, void *cache); - -#ifdef __cplusplus -} -#endif diff --git a/source/blender/gpu/GPU_state.h b/source/blender/gpu/GPU_state.h index be3250f6654..6a59baa38f0 100644 --- a/source/blender/gpu/GPU_state.h +++ b/source/blender/gpu/GPU_state.h @@ -66,9 +66,9 @@ typedef enum eGPUBlend { typedef enum eGPUDepthTest { GPU_DEPTH_NONE = 0, - GPU_DEPTH_ALWAYS, + GPU_DEPTH_ALWAYS, /* Used to draw to the depth buffer without really testing. */ GPU_DEPTH_LESS, - GPU_DEPTH_LESS_EQUAL, + GPU_DEPTH_LESS_EQUAL, /* Default. */ GPU_DEPTH_EQUAL, GPU_DEPTH_GREATER, GPU_DEPTH_GREATER_EQUAL, @@ -106,11 +106,10 @@ extern "C" { void GPU_blend(eGPUBlend blend); void GPU_face_culling(eGPUFaceCullTest culling); -void GPU_front_facing(bool invert); +void GPU_depth_test(eGPUDepthTest test); void GPU_provoking_vertex(eGPUProvokingVertex vert); +void GPU_front_facing(bool invert); void GPU_depth_range(float near, float far); -void GPU_depth_test(bool enable); -bool GPU_depth_test_enabled(void); void GPU_scissor_test(bool enable); void GPU_line_smooth(bool enable); void GPU_line_width(float width); @@ -144,6 +143,7 @@ void GPU_stencil_write_mask_set(uint write_mask); void GPU_stencil_compare_mask_set(uint compare_mask); eGPUBlend GPU_blend_get(void); +eGPUDepthTest GPU_depth_test_get(void); eGPUWriteMask GPU_write_mask_get(void); void GPU_flush(void); diff --git a/source/blender/gpu/intern/gpu_attr_binding.cc b/source/blender/gpu/intern/gpu_attr_binding.cc index 6cb60884620..2a48107e190 100644 --- a/source/blender/gpu/intern/gpu_attr_binding.cc +++ b/source/blender/gpu/intern/gpu_attr_binding.cc @@ -61,9 +61,7 @@ static void write_attr_location(GPUAttrBinding *binding, uint a_idx, uint locati binding->enabled_bits |= 1 << a_idx; } -void get_attr_locations(const GPUVertFormat *format, - GPUAttrBinding *binding, - const GPUShaderInterface *shaderface) +void get_attr_locations(const GPUVertFormat *format, GPUAttrBinding *binding, GPUShader *shader) { AttrBinding_clear(binding); @@ -71,13 +69,12 @@ void get_attr_locations(const GPUVertFormat *format, const GPUVertAttr *a = &format->attrs[a_idx]; for (uint n_idx = 0; n_idx < a->name_len; n_idx++) { const char *name = GPU_vertformat_attr_name_get(format, a, n_idx); - const GPUShaderInput *input = GPU_shaderinterface_attr(shaderface, name); -#if TRUST_NO_ONE - assert(input != NULL); + int loc = GPU_shader_get_attribute(shader, name); /* TODO: make this a recoverable runtime error? * indicates mismatch between vertex format and program. */ -#endif - write_attr_location(binding, a_idx, input->location); + BLI_assert(loc != -1); + + write_attr_location(binding, a_idx, loc); } } } diff --git a/source/blender/gpu/intern/gpu_attr_binding_private.h b/source/blender/gpu/intern/gpu_attr_binding_private.h index 4d359343c38..cd67a51a822 100644 --- a/source/blender/gpu/intern/gpu_attr_binding_private.h +++ b/source/blender/gpu/intern/gpu_attr_binding_private.h @@ -25,8 +25,8 @@ #pragma once -#include "GPU_shader_interface.h" #include "GPU_vertex_format.h" +#include "gpu_shader_interface.hh" #ifdef __cplusplus extern "C" { @@ -35,9 +35,7 @@ extern "C" { /* TODO(fclem) remove, use shaderface directly. */ void AttrBinding_clear(GPUAttrBinding *binding); -void get_attr_locations(const GPUVertFormat *format, - GPUAttrBinding *binding, - const GPUShaderInterface *shaderface); +void get_attr_locations(const GPUVertFormat *format, GPUAttrBinding *binding, GPUShader *shader); uint read_attr_location(const GPUAttrBinding *binding, uint a_idx); #ifdef __cplusplus diff --git a/source/blender/gpu/intern/gpu_batch_private.hh b/source/blender/gpu/intern/gpu_batch_private.hh index 3a8044efc1d..11efd784238 100644 --- a/source/blender/gpu/intern/gpu_batch_private.hh +++ b/source/blender/gpu/intern/gpu_batch_private.hh @@ -28,7 +28,6 @@ #include "GPU_batch.h" #include "GPU_context.h" -#include "GPU_shader_interface.h" namespace blender { namespace gpu { diff --git a/source/blender/gpu/intern/gpu_immediate.cc b/source/blender/gpu/intern/gpu_immediate.cc index dd05689d69a..431dbe848f7 100644 --- a/source/blender/gpu/intern/gpu_immediate.cc +++ b/source/blender/gpu/intern/gpu_immediate.cc @@ -73,7 +73,6 @@ typedef struct { GLuint vao_id; GPUShader *bound_program; - const GPUShaderInterface *shader_interface; GPUAttrBinding attr_binding; uint16_t prev_enabled_attr_bits; /* <-- only affects this VAO, so we're ok */ } Immediate; @@ -148,14 +147,13 @@ void immBindShader(GPUShader *shader) BLI_assert(imm.bound_program == NULL); imm.bound_program = shader; - imm.shader_interface = shader->interface; if (!imm.vertex_format.packed) { VertexFormat_pack(&imm.vertex_format); } GPU_shader_bind(shader); - get_attr_locations(&imm.vertex_format, &imm.attr_binding, imm.shader_interface); + get_attr_locations(&imm.vertex_format, &imm.attr_binding, shader); GPU_matrix_bind(shader); GPU_shader_set_srgb_uniform(shader); } @@ -749,123 +747,77 @@ void immVertex2iv(uint attr_id, const int data[2]) /* --- generic uniform functions --- */ -#if 0 -# if TRUST_NO_ONE -# define GET_UNIFORM \ - const GPUShaderInput *uniform = GPU_shaderinterface_uniform(imm.shader_interface, name); \ - assert(uniform); -# else -# define GET_UNIFORM \ - const GPUShaderInput *uniform = GPU_shaderinterface_uniform(imm.shader_interface, name); -# endif -#else -/* NOTE: It is possible to have uniform fully optimized out from the shader. - * In this case we can't assert failure or allow NULL-pointer dereference. - * TODO(sergey): How can we detect existing-but-optimized-out uniform but still - * catch typos in uniform names passed to immUniform*() functions? */ -# define GET_UNIFORM \ - const GPUShaderInput *uniform = GPU_shaderinterface_uniform(imm.shader_interface, name); \ - if (uniform == NULL) \ - return; -#endif - void immUniform1f(const char *name, float x) { - GET_UNIFORM - glUniform1f(uniform->location, x); + GPU_shader_uniform_1f(imm.bound_program, name, x); } void immUniform2f(const char *name, float x, float y) { - GET_UNIFORM - glUniform2f(uniform->location, x, y); + GPU_shader_uniform_2f(imm.bound_program, name, x, y); } void immUniform2fv(const char *name, const float data[2]) { - GET_UNIFORM - glUniform2fv(uniform->location, 1, data); + GPU_shader_uniform_2fv(imm.bound_program, name, data); } void immUniform3f(const char *name, float x, float y, float z) { - GET_UNIFORM - glUniform3f(uniform->location, x, y, z); + GPU_shader_uniform_3f(imm.bound_program, name, x, y, z); } void immUniform3fv(const char *name, const float data[3]) { - GET_UNIFORM - glUniform3fv(uniform->location, 1, data); -} - -/* can increase this limit or move to another file */ -#define MAX_UNIFORM_NAME_LEN 60 - -/* Note array index is not supported for name (i.e: "array[0]"). */ -void immUniformArray3fv(const char *name, const float *data, int count) -{ - GET_UNIFORM - glUniform3fv(uniform->location, count, data); + GPU_shader_uniform_3fv(imm.bound_program, name, data); } void immUniform4f(const char *name, float x, float y, float z, float w) { - GET_UNIFORM - glUniform4f(uniform->location, x, y, z, w); + GPU_shader_uniform_4f(imm.bound_program, name, x, y, z, w); } void immUniform4fv(const char *name, const float data[4]) { - GET_UNIFORM - glUniform4fv(uniform->location, 1, data); + GPU_shader_uniform_4fv(imm.bound_program, name, data); } /* Note array index is not supported for name (i.e: "array[0]"). */ void immUniformArray4fv(const char *name, const float *data, int count) { - GET_UNIFORM - glUniform4fv(uniform->location, count, data); + GPU_shader_uniform_4fv_array(imm.bound_program, name, count, (float(*)[4])data); } void immUniformMatrix4fv(const char *name, const float data[4][4]) { - GET_UNIFORM - glUniformMatrix4fv(uniform->location, 1, GL_FALSE, (float *)data); + GPU_shader_uniform_mat4(imm.bound_program, name, data); } void immUniform1i(const char *name, int x) { - GET_UNIFORM - glUniform1i(uniform->location, x); -} - -void immUniform4iv(const char *name, const int data[4]) -{ - GET_UNIFORM - glUniform4iv(uniform->location, 1, data); + GPU_shader_uniform_1i(imm.bound_program, name, x); } void immBindTexture(const char *name, GPUTexture *tex) { - GET_UNIFORM - GPU_texture_bind(tex, uniform->binding); + int binding = GPU_shader_get_texture_binding(imm.bound_program, name); + GPU_texture_bind(tex, binding); } void immBindTextureSampler(const char *name, GPUTexture *tex, eGPUSamplerState state) { - GET_UNIFORM - GPU_texture_bind_ex(tex, state, uniform->binding, true); + int binding = GPU_shader_get_texture_binding(imm.bound_program, name); + GPU_texture_bind_ex(tex, state, binding, true); } /* --- convenience functions for setting "uniform vec4 color" --- */ void immUniformColor4f(float r, float g, float b, float a) { - int32_t uniform_loc = GPU_shaderinterface_uniform_builtin(imm.shader_interface, - GPU_UNIFORM_COLOR); + int32_t uniform_loc = GPU_shader_get_builtin_uniform(imm.bound_program, GPU_UNIFORM_COLOR); BLI_assert(uniform_loc != -1); - glUniform4f(uniform_loc, r, g, b, a); + float data[4] = {r, g, b, a}; + GPU_shader_uniform_vector(imm.bound_program, uniform_loc, 4, 1, data); } void immUniformColor4fv(const float rgba[4]) diff --git a/source/blender/gpu/intern/gpu_matrix.cc b/source/blender/gpu/intern/gpu_matrix.cc index 951652b9393..cdb6d303588 100644 --- a/source/blender/gpu/intern/gpu_matrix.cc +++ b/source/blender/gpu/intern/gpu_matrix.cc @@ -21,8 +21,6 @@ * \ingroup gpu */ -#include "GPU_shader_interface.h" - #include "gpu_context_private.hh" #include "gpu_matrix_private.h" @@ -649,14 +647,13 @@ void GPU_matrix_bind(GPUShader *shader) * call this before a draw call if desired matrices are dirty * call glUseProgram before this, as glUniform expects program to be bound */ - const GPUShaderInterface *shaderface = shader->interface; - int32_t MV = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_MODELVIEW); - int32_t P = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_PROJECTION); - int32_t MVP = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_MVP); - - int32_t N = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_NORMAL); - int32_t MV_inv = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_MODELVIEW_INV); - int32_t P_inv = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_PROJECTION_INV); + int32_t MV = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW); + int32_t P = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_PROJECTION); + int32_t MVP = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP); + + int32_t N = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_NORMAL); + int32_t MV_inv = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW_INV); + int32_t P_inv = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_PROJECTION_INV); if (MV != -1) { GPU_shader_uniform_vector(shader, MV, 16, 1, (const float *)GPU_matrix_model_view_get(NULL)); diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c index 29e2615345c..f7fd1faeb1e 100644 --- a/source/blender/gpu/intern/gpu_select_pick.c +++ b/source/blender/gpu/intern/gpu_select_pick.c @@ -27,6 +27,7 @@ #include <stdlib.h> #include <string.h> +#include "GPU_framebuffer.h" #include "GPU_glew.h" #include "GPU_immediate.h" #include "GPU_select.h" @@ -287,7 +288,7 @@ typedef struct GPUPickState { int viewport[4]; int scissor[4]; eGPUWriteMask write_mask; - bool depth_test; + eGPUDepthTest depth_test; } GPUPickState; static GPUPickState g_pick_state = {0}; @@ -311,18 +312,17 @@ void gpu_select_pick_begin(uint (*buffer)[4], uint bufsize, const rcti *input, c /* Restrict OpenGL operations for when we don't have cache */ if (ps->is_cached == false) { ps->write_mask = GPU_write_mask_get(); - ps->depth_test = GPU_depth_test_enabled(); + ps->depth_test = GPU_depth_test_get(); GPU_scissor_get(ps->scissor); /* disable writing to the framebuffer */ GPU_color_mask(false, false, false, false); - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_TRUE); + GPU_depth_mask(true); /* Always use #GL_LEQUAL even though GPU_SELECT_PICK_ALL always clears the buffer. This is * because individual objects themselves might have sections that overlap and we need these * to have the correct distance information. */ - glDepthFunc(GL_LEQUAL); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); float viewport[4]; GPU_viewport_size_get_f(viewport); @@ -339,7 +339,7 @@ void gpu_select_pick_begin(uint (*buffer)[4], uint bufsize, const rcti *input, c /* It's possible we don't want to clear depth buffer, * so existing elements are masked by current z-buffer. */ - glClear(GL_DEPTH_BUFFER_BIT); + GPU_clear(GPU_DEPTH_BIT); /* scratch buffer (read new values here) */ ps->gl.rect_depth_test = depth_buf_malloc(rect_len); @@ -519,7 +519,7 @@ bool gpu_select_pick_load_id(uint id, bool end) if (g_pick_state.mode == GPU_SELECT_PICK_ALL) { /* we want new depths every time */ - glClear(GL_DEPTH_BUFFER_BIT); + GPU_clear(GPU_DEPTH_BIT); } } } diff --git a/source/blender/gpu/intern/gpu_select_sample_query.c b/source/blender/gpu/intern/gpu_select_sample_query.c index 62414febb44..7e41faf8678 100644 --- a/source/blender/gpu/intern/gpu_select_sample_query.c +++ b/source/blender/gpu/intern/gpu_select_sample_query.c @@ -26,6 +26,7 @@ #include <stdlib.h> +#include "GPU_framebuffer.h" #include "GPU_glew.h" #include "GPU_select.h" #include "GPU_state.h" @@ -65,7 +66,7 @@ typedef struct GPUQueryState { int viewport[4]; int scissor[4]; eGPUWriteMask write_mask; - bool depth_test; + eGPUDepthTest depth_test; } GPUQueryState; static GPUQueryState g_query_state = {0}; @@ -91,7 +92,7 @@ void gpu_select_query_begin( glGenQueries(g_query_state.num_of_queries, g_query_state.queries); g_query_state.write_mask = GPU_write_mask_get(); - g_query_state.depth_test = GPU_depth_test_enabled(); + g_query_state.depth_test = GPU_depth_test_get(); GPU_scissor_get(g_query_state.scissor); /* disable writing to the framebuffer */ @@ -112,20 +113,17 @@ void gpu_select_query_begin( if (mode == GPU_SELECT_ALL) { /* glQueries on Windows+Intel drivers only works with depth testing turned on. * See T62947 for details */ - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_ALWAYS); - glDepthMask(GL_TRUE); + GPU_depth_test(GPU_DEPTH_ALWAYS); + GPU_depth_mask(true); } else if (mode == GPU_SELECT_NEAREST_FIRST_PASS) { - glClear(GL_DEPTH_BUFFER_BIT); - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_TRUE); - glDepthFunc(GL_LEQUAL); + GPU_clear(GPU_DEPTH_BIT); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); + GPU_depth_mask(true); } else if (mode == GPU_SELECT_NEAREST_SECOND_PASS) { - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); - glDepthFunc(GL_EQUAL); + GPU_depth_test(GPU_DEPTH_EQUAL); + GPU_depth_mask(false); } } diff --git a/source/blender/gpu/intern/gpu_shader.cc b/source/blender/gpu/intern/gpu_shader.cc index 4e74e1f69e7..21678548b13 100644 --- a/source/blender/gpu/intern/gpu_shader.cc +++ b/source/blender/gpu/intern/gpu_shader.cc @@ -95,7 +95,7 @@ void Shader::print_errors(Span<const char *> sources, char *log) error_char = (int)strtol(error_line_number_end + 1, NULL, 10); } } - if ((error_line == -1)) { + if (error_line == -1) { found_line_id = false; } const char *src_line = sources_combined; @@ -196,9 +196,7 @@ Shader::Shader(const char *sh_name) Shader::~Shader() { - if (this->interface) { - GPU_shaderinterface_discard(this->interface); - } + delete interface; } static void standard_defines(Vector<const char *> &sources) @@ -484,43 +482,49 @@ void GPU_shader_transform_feedback_disable(GPUShader *shader) int GPU_shader_get_uniform(GPUShader *shader, const char *name) { - const GPUShaderInput *uniform = GPU_shaderinterface_uniform(shader->interface, name); + ShaderInterface *interface = static_cast<Shader *>(shader)->interface; + const ShaderInput *uniform = interface->uniform_get(name); return uniform ? uniform->location : -1; } int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin) { - return GPU_shaderinterface_uniform_builtin(shader->interface, - static_cast<GPUUniformBuiltin>(builtin)); + ShaderInterface *interface = static_cast<Shader *>(shader)->interface; + return interface->uniform_builtin((GPUUniformBuiltin)builtin); } int GPU_shader_get_builtin_block(GPUShader *shader, int builtin) { - return GPU_shaderinterface_block_builtin(shader->interface, - static_cast<GPUUniformBlockBuiltin>(builtin)); + ShaderInterface *interface = static_cast<Shader *>(shader)->interface; + return interface->ubo_builtin((GPUUniformBlockBuiltin)builtin); } +/* DEPRECATED. */ int GPU_shader_get_uniform_block(GPUShader *shader, const char *name) { - const GPUShaderInput *ubo = GPU_shaderinterface_ubo(shader->interface, name); + ShaderInterface *interface = static_cast<Shader *>(shader)->interface; + const ShaderInput *ubo = interface->ubo_get(name); return ubo ? ubo->location : -1; } int GPU_shader_get_uniform_block_binding(GPUShader *shader, const char *name) { - const GPUShaderInput *ubo = GPU_shaderinterface_ubo(shader->interface, name); + ShaderInterface *interface = static_cast<Shader *>(shader)->interface; + const ShaderInput *ubo = interface->ubo_get(name); return ubo ? ubo->binding : -1; } int GPU_shader_get_texture_binding(GPUShader *shader, const char *name) { - const GPUShaderInput *tex = GPU_shaderinterface_uniform(shader->interface, name); + ShaderInterface *interface = static_cast<Shader *>(shader)->interface; + const ShaderInput *tex = interface->uniform_get(name); return tex ? tex->binding : -1; } int GPU_shader_get_attribute(GPUShader *shader, const char *name) { - const GPUShaderInput *attr = GPU_shaderinterface_attr(shader->interface, name); + ShaderInterface *interface = static_cast<Shader *>(shader)->interface; + const ShaderInput *attr = interface->attr_get(name); return attr ? attr->location : -1; } @@ -565,14 +569,10 @@ void GPU_shader_uniform_float(GPUShader *shader, int location, float value) GPU_shader_uniform_vector(shader, location, 1, 1, &value); } -#define GET_UNIFORM \ - const GPUShaderInput *uniform = GPU_shaderinterface_uniform(sh->interface, name); \ - BLI_assert(uniform); - void GPU_shader_uniform_1i(GPUShader *sh, const char *name, int value) { - GET_UNIFORM - GPU_shader_uniform_int(sh, uniform->location, value); + const int loc = GPU_shader_get_uniform(sh, name); + GPU_shader_uniform_int(sh, loc, value); } void GPU_shader_uniform_1b(GPUShader *sh, const char *name, bool value) @@ -600,44 +600,44 @@ void GPU_shader_uniform_4f(GPUShader *sh, const char *name, float x, float y, fl void GPU_shader_uniform_1f(GPUShader *sh, const char *name, float x) { - GET_UNIFORM - GPU_shader_uniform_float(sh, uniform->location, x); + const int loc = GPU_shader_get_uniform(sh, name); + GPU_shader_uniform_float(sh, loc, x); } void GPU_shader_uniform_2fv(GPUShader *sh, const char *name, const float data[2]) { - GET_UNIFORM - GPU_shader_uniform_vector(sh, uniform->location, 2, 1, data); + const int loc = GPU_shader_get_uniform(sh, name); + GPU_shader_uniform_vector(sh, loc, 2, 1, data); } void GPU_shader_uniform_3fv(GPUShader *sh, const char *name, const float data[3]) { - GET_UNIFORM - GPU_shader_uniform_vector(sh, uniform->location, 3, 1, data); + const int loc = GPU_shader_get_uniform(sh, name); + GPU_shader_uniform_vector(sh, loc, 3, 1, data); } void GPU_shader_uniform_4fv(GPUShader *sh, const char *name, const float data[4]) { - GET_UNIFORM - GPU_shader_uniform_vector(sh, uniform->location, 4, 1, data); + const int loc = GPU_shader_get_uniform(sh, name); + GPU_shader_uniform_vector(sh, loc, 4, 1, data); } void GPU_shader_uniform_mat4(GPUShader *sh, const char *name, const float data[4][4]) { - GET_UNIFORM - GPU_shader_uniform_vector(sh, uniform->location, 16, 1, (const float *)data); + const int loc = GPU_shader_get_uniform(sh, name); + GPU_shader_uniform_vector(sh, loc, 16, 1, (const float *)data); } void GPU_shader_uniform_2fv_array(GPUShader *sh, const char *name, int len, const float (*val)[2]) { - GET_UNIFORM - GPU_shader_uniform_vector(sh, uniform->location, 2, len, (const float *)val); + const int loc = GPU_shader_get_uniform(sh, name); + GPU_shader_uniform_vector(sh, loc, 2, len, (const float *)val); } void GPU_shader_uniform_4fv_array(GPUShader *sh, const char *name, int len, const float (*val)[4]) { - GET_UNIFORM - GPU_shader_uniform_vector(sh, uniform->location, 4, len, (const float *)val); + const int loc = GPU_shader_get_uniform(sh, name); + GPU_shader_uniform_vector(sh, loc, 4, len, (const float *)val); } /** \} */ @@ -657,7 +657,7 @@ static int g_shader_builtin_srgb_transform = 0; void GPU_shader_set_srgb_uniform(GPUShader *shader) { - int32_t loc = GPU_shaderinterface_uniform_builtin(shader->interface, GPU_UNIFORM_SRGB_TRANSFORM); + int32_t loc = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_SRGB_TRANSFORM); if (loc != -1) { GPU_shader_uniform_vector_int(shader, loc, 1, 1, &g_shader_builtin_srgb_transform); } diff --git a/source/blender/gpu/intern/gpu_shader_interface.cc b/source/blender/gpu/intern/gpu_shader_interface.cc index ef90dde1877..dc59dca9f78 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.cc +++ b/source/blender/gpu/intern/gpu_shader_interface.cc @@ -23,161 +23,41 @@ * GPU shader interface (C --> GLSL) */ -#include "BKE_global.h" - -#include "BLI_bitmap.h" -#include "BLI_math_base.h" - #include "MEM_guardedalloc.h" -#include "GPU_shader_interface.h" - -#include "gpu_batch_private.hh" -#include "gpu_context_private.hh" - -#include "gl_batch.hh" - -#include <stddef.h> -#include <stdlib.h> -#include <string.h> - -#define DEBUG_SHADER_INTERFACE 0 - -#if DEBUG_SHADER_INTERFACE -# include <stdio.h> -#endif - -using namespace blender::gpu; - -static const char *BuiltinUniform_name(GPUUniformBuiltin u) -{ - switch (u) { - case GPU_UNIFORM_MODEL: - return "ModelMatrix"; - case GPU_UNIFORM_VIEW: - return "ViewMatrix"; - case GPU_UNIFORM_MODELVIEW: - return "ModelViewMatrix"; - case GPU_UNIFORM_PROJECTION: - return "ProjectionMatrix"; - case GPU_UNIFORM_VIEWPROJECTION: - return "ViewProjectionMatrix"; - case GPU_UNIFORM_MVP: - return "ModelViewProjectionMatrix"; - - case GPU_UNIFORM_MODEL_INV: - return "ModelMatrixInverse"; - case GPU_UNIFORM_VIEW_INV: - return "ViewMatrixInverse"; - case GPU_UNIFORM_MODELVIEW_INV: - return "ModelViewMatrixInverse"; - case GPU_UNIFORM_PROJECTION_INV: - return "ProjectionMatrixInverse"; - case GPU_UNIFORM_VIEWPROJECTION_INV: - return "ViewProjectionMatrixInverse"; - - case GPU_UNIFORM_NORMAL: - return "NormalMatrix"; - case GPU_UNIFORM_ORCO: - return "OrcoTexCoFactors"; - case GPU_UNIFORM_CLIPPLANES: - return "WorldClipPlanes"; - - case GPU_UNIFORM_COLOR: - return "color"; - case GPU_UNIFORM_BASE_INSTANCE: - return "baseInstance"; - case GPU_UNIFORM_RESOURCE_CHUNK: - return "resourceChunk"; - case GPU_UNIFORM_RESOURCE_ID: - return "resourceId"; - case GPU_UNIFORM_SRGB_TRANSFORM: - return "srgbTarget"; +#include "BLI_span.hh" +#include "BLI_vector.hh" - default: - return NULL; - } -} +#include "gpu_shader_interface.hh" -static const char *BuiltinUniformBlock_name(GPUUniformBlockBuiltin u) -{ - switch (u) { - case GPU_UNIFORM_BLOCK_VIEW: - return "viewBlock"; - case GPU_UNIFORM_BLOCK_MODEL: - return "modelBlock"; - case GPU_UNIFORM_BLOCK_INFO: - return "infoBlock"; - default: - return NULL; - } -} +namespace blender::gpu { -GPU_INLINE bool match(const char *a, const char *b) +ShaderInterface::ShaderInterface(void) { - return STREQ(a, b); + /* TODO(fclem) add unique ID for debugging. */ } -GPU_INLINE uint hash_string(const char *str) +ShaderInterface::~ShaderInterface(void) { - uint i = 0, c; - while ((c = *str++)) { - i = i * 37 + c; - } - return i; + /* Free memory used by name_buffer. */ + MEM_freeN(name_buffer_); + MEM_freeN(inputs_); } -GPU_INLINE uint32_t set_input_name(GPUShaderInterface *shaderface, - GPUShaderInput *input, - char *name, - uint32_t name_len) +static void sort_input_list(MutableSpan<ShaderInput> dst) { - /* remove "[0]" from array name */ - if (name[name_len - 1] == ']') { - name[name_len - 3] = '\0'; - name_len -= 3; + if (dst.size() == 0) { + return; } - input->name_offset = (uint32_t)(name - shaderface->name_buffer); - input->name_hash = hash_string(name); - return name_len + 1; /* include NULL terminator */ -} - -GPU_INLINE const GPUShaderInput *input_lookup(const GPUShaderInterface *shaderface, - const GPUShaderInput *const inputs, - const uint inputs_len, - const char *name) -{ - const uint name_hash = hash_string(name); - /* Simple linear search for now. */ - for (int i = inputs_len - 1; i >= 0; i--) { - if (inputs[i].name_hash == name_hash) { - if ((i > 0) && UNLIKELY(inputs[i - 1].name_hash == name_hash)) { - /* Hash colision resolve. */ - for (; i >= 0 && inputs[i].name_hash == name_hash; i--) { - if (match(name, shaderface->name_buffer + inputs[i].name_offset)) { - return inputs + i; /* not found */ - } - } - return NULL; /* not found */ - } - - /* This is a bit dangerous since we could have a hash collision. - * where the asked uniform that does not exist has the same hash - * as a real uniform. */ - BLI_assert(match(name, shaderface->name_buffer + inputs[i].name_offset)); - return inputs + i; - } - } - return NULL; /* not found */ -} + Vector<ShaderInput> inputs_vec = Vector<ShaderInput>(dst.size()); + MutableSpan<ShaderInput> src = inputs_vec.as_mutable_span(); + src.copy_from(dst); -/* Note that this modify the src array. */ -GPU_INLINE void sort_input_list(GPUShaderInput *dst, GPUShaderInput *src, const uint input_len) -{ - for (uint i = 0; i < input_len; i++) { - GPUShaderInput *input_src = &src[0]; - for (uint j = 1; j < input_len; j++) { + /* Simple sorting by going through the array and selecting the biggest element each time. */ + for (uint i = 0; i < dst.size(); i++) { + ShaderInput *input_src = &src[0]; + for (uint j = 1; j < src.size(); j++) { if (src[j].name_hash > input_src->name_hash) { input_src = &src[j]; } @@ -187,360 +67,60 @@ GPU_INLINE void sort_input_list(GPUShaderInput *dst, GPUShaderInput *src, const } } -static int block_binding(int32_t program, uint32_t block_index) +/* Sorts all inputs inside their respective array. + * This is to allow fast hash collision detection. + * See ShaderInterface::input_lookup for more details. */ +void ShaderInterface::sort_inputs(void) { - /* For now just assign a consecutive index. In the future, we should set it in - * the shader using layout(binding = i) and query its value. */ - glUniformBlockBinding(program, block_index, block_index); - return block_index; + sort_input_list(MutableSpan<ShaderInput>(inputs_, attr_len_)); + sort_input_list(MutableSpan<ShaderInput>(inputs_ + attr_len_, ubo_len_)); + sort_input_list(MutableSpan<ShaderInput>(inputs_ + attr_len_ + ubo_len_, uniform_len_)); } -static int sampler_binding(int32_t program, - uint32_t uniform_index, - int32_t uniform_location, - int *sampler_len) +void ShaderInterface::debug_print(void) { - /* Identify sampler uniforms and asign sampler units to them. */ - GLint type; - glGetActiveUniformsiv(program, 1, &uniform_index, GL_UNIFORM_TYPE, &type); - - switch (type) { - case GL_SAMPLER_1D: - case GL_SAMPLER_2D: - case GL_SAMPLER_3D: - case GL_SAMPLER_CUBE: - case GL_SAMPLER_CUBE_MAP_ARRAY_ARB: /* OpenGL 4.0 */ - case GL_SAMPLER_1D_SHADOW: - case GL_SAMPLER_2D_SHADOW: - case GL_SAMPLER_1D_ARRAY: - case GL_SAMPLER_2D_ARRAY: - case GL_SAMPLER_1D_ARRAY_SHADOW: - case GL_SAMPLER_2D_ARRAY_SHADOW: - case GL_SAMPLER_2D_MULTISAMPLE: - case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_SAMPLER_CUBE_SHADOW: - case GL_SAMPLER_BUFFER: - case GL_INT_SAMPLER_1D: - case GL_INT_SAMPLER_2D: - case GL_INT_SAMPLER_3D: - case GL_INT_SAMPLER_CUBE: - case GL_INT_SAMPLER_1D_ARRAY: - case GL_INT_SAMPLER_2D_ARRAY: - case GL_INT_SAMPLER_2D_MULTISAMPLE: - case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_INT_SAMPLER_BUFFER: - case GL_UNSIGNED_INT_SAMPLER_1D: - case GL_UNSIGNED_INT_SAMPLER_2D: - case GL_UNSIGNED_INT_SAMPLER_3D: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_BUFFER: { - /* For now just assign a consecutive index. In the future, we should set it in - * the shader using layout(binding = i) and query its value. */ - int binding = *sampler_len; - glUniform1i(uniform_location, binding); - (*sampler_len)++; - return binding; - } - default: - return -1; - } -} + Span<ShaderInput> attrs = Span<ShaderInput>(inputs_, attr_len_); + Span<ShaderInput> ubos = Span<ShaderInput>(inputs_ + attr_len_, ubo_len_); + Span<ShaderInput> uniforms = Span<ShaderInput>(inputs_ + attr_len_ + ubo_len_, uniform_len_); + char *name_buf = name_buffer_; + const char format[] = " | %.8x : %4d : %s\n"; -GPUShaderInterface *GPU_shaderinterface_create(int32_t program) -{ -#ifndef NDEBUG - GLint curr_program; - glGetIntegerv(GL_CURRENT_PROGRAM, &curr_program); - BLI_assert(curr_program == program); -#endif - - GLint max_attr_name_len = 0, attr_len = 0; - glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_attr_name_len); - glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &attr_len); - - GLint max_ubo_name_len = 0, ubo_len = 0; - glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_ubo_name_len); - glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &ubo_len); - - GLint max_uniform_name_len = 0, active_uniform_len = 0, uniform_len = 0; - glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_uniform_name_len); - glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniform_len); - uniform_len = active_uniform_len; - - /* Work around driver bug with Intel HD 4600 on Windows 7/8, where - * GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH does not work. */ - if (attr_len > 0 && max_attr_name_len == 0) { - max_attr_name_len = 256; - } - if (ubo_len > 0 && max_ubo_name_len == 0) { - max_ubo_name_len = 256; + printf(" \033[1mGPUShaderInterface : \033[0m\n"); + if (attrs.size() > 0) { + printf("\n Attributes :\n"); } - if (uniform_len > 0 && max_uniform_name_len == 0) { - max_uniform_name_len = 256; + for (const ShaderInput &attr : attrs) { + printf(format, attr.name_hash, attr.location, name_buf + attr.name_offset); } - /* GL_ACTIVE_UNIFORMS lied to us! Remove the UBO uniforms from the total before - * allocating the uniform array. */ - GLint max_ubo_uni_len = 0; - for (int i = 0; i < ubo_len; i++) { - GLint ubo_uni_len; - glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &ubo_uni_len); - max_ubo_uni_len = max_ii(max_ubo_uni_len, ubo_uni_len); - uniform_len -= ubo_uni_len; + if (uniforms.size() > 0) { + printf("\n Uniforms :\n"); } - /* Bit set to true if uniform comes from a uniform block. */ - BLI_bitmap *uniforms_from_blocks = BLI_BITMAP_NEW(active_uniform_len, __func__); - /* Set uniforms from block for exclusion. */ - GLint *ubo_uni_ids = (GLint *)MEM_mallocN(sizeof(GLint) * max_ubo_uni_len, __func__); - for (int i = 0; i < ubo_len; i++) { - GLint ubo_uni_len; - glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &ubo_uni_len); - glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, ubo_uni_ids); - for (int u = 0; u < ubo_uni_len; u++) { - BLI_BITMAP_ENABLE(uniforms_from_blocks, ubo_uni_ids[u]); + for (const ShaderInput &uni : uniforms) { + /* Bypass samplers. */ + if (uni.binding == -1) { + printf(format, uni.name_hash, uni.location, name_buf + uni.name_offset); } } - MEM_freeN(ubo_uni_ids); - uint32_t name_buffer_offset = 0; - const uint32_t name_buffer_len = attr_len * max_attr_name_len + ubo_len * max_ubo_name_len + - uniform_len * max_uniform_name_len; - - int input_tot_len = attr_len + ubo_len + uniform_len; - size_t interface_size = sizeof(GPUShaderInterface) + sizeof(GPUShaderInput) * input_tot_len; - - GPUShaderInterface *shaderface = (GPUShaderInterface *)MEM_callocN(interface_size, - "GPUShaderInterface"); - shaderface->attribute_len = attr_len; - shaderface->ubo_len = ubo_len; - shaderface->uniform_len = uniform_len; - shaderface->name_buffer = (char *)MEM_mallocN(name_buffer_len, "name_buffer"); - GPUShaderInput *inputs = shaderface->inputs; - - /* Temp buffer. */ - int input_tmp_len = max_iii(attr_len, ubo_len, uniform_len); - GPUShaderInput *inputs_tmp = (GPUShaderInput *)MEM_mallocN( - sizeof(GPUShaderInput) * input_tmp_len, "name_buffer"); - - /* Attributes */ - shaderface->enabled_attr_mask = 0; - for (int i = 0, idx = 0; i < attr_len; i++) { - char *name = shaderface->name_buffer + name_buffer_offset; - GLsizei remaining_buffer = name_buffer_len - name_buffer_offset; - GLsizei name_len = 0; - GLenum type; - GLint size; - - glGetActiveAttrib(program, i, remaining_buffer, &name_len, &size, &type, name); - GLint location = glGetAttribLocation(program, name); - /* Ignore OpenGL names like `gl_BaseInstanceARB`, `gl_InstanceID` and `gl_VertexID`. */ - if (location == -1) { - shaderface->attribute_len--; - continue; - } - - GPUShaderInput *input = &inputs_tmp[idx++]; - input->location = input->binding = location; - - name_buffer_offset += set_input_name(shaderface, input, name, name_len); - shaderface->enabled_attr_mask |= (1 << input->location); + if (ubos.size() > 0) { + printf("\n Uniform Buffer Objects :\n"); } - sort_input_list(inputs, inputs_tmp, shaderface->attribute_len); - inputs += shaderface->attribute_len; - - /* Uniform Blocks */ - for (int i = 0, idx = 0; i < ubo_len; i++) { - char *name = shaderface->name_buffer + name_buffer_offset; - GLsizei remaining_buffer = name_buffer_len - name_buffer_offset; - GLsizei name_len = 0; - - glGetActiveUniformBlockName(program, i, remaining_buffer, &name_len, name); - - GPUShaderInput *input = &inputs_tmp[idx++]; - input->binding = input->location = block_binding(program, i); - - name_buffer_offset += set_input_name(shaderface, input, name, name_len); - shaderface->enabled_ubo_mask |= (1 << input->binding); + for (const ShaderInput &ubo : ubos) { + printf(format, ubo.name_hash, ubo.binding, name_buf + ubo.name_offset); } - sort_input_list(inputs, inputs_tmp, shaderface->ubo_len); - inputs += shaderface->ubo_len; - /* Uniforms */ - for (int i = 0, idx = 0, sampler = 0; i < active_uniform_len; i++) { - if (BLI_BITMAP_TEST(uniforms_from_blocks, i)) { - continue; - } - char *name = shaderface->name_buffer + name_buffer_offset; - GLsizei remaining_buffer = name_buffer_len - name_buffer_offset; - GLsizei name_len = 0; - - glGetActiveUniformName(program, i, remaining_buffer, &name_len, name); - - GPUShaderInput *input = &inputs_tmp[idx++]; - input->location = glGetUniformLocation(program, name); - input->binding = sampler_binding(program, i, input->location, &sampler); - - name_buffer_offset += set_input_name(shaderface, input, name, name_len); - shaderface->enabled_tex_mask |= (input->binding != -1) ? (1lu << input->binding) : 0lu; - } - sort_input_list(inputs, inputs_tmp, shaderface->uniform_len); - - /* Builtin Uniforms */ - for (int32_t u_int = 0; u_int < GPU_NUM_UNIFORMS; u_int++) { - GPUUniformBuiltin u = static_cast<GPUUniformBuiltin>(u_int); - shaderface->builtins[u] = glGetUniformLocation(program, BuiltinUniform_name(u)); - } - - /* Builtin Uniforms Blocks */ - for (int32_t u_int = 0; u_int < GPU_NUM_UNIFORM_BLOCKS; u_int++) { - GPUUniformBlockBuiltin u = static_cast<GPUUniformBlockBuiltin>(u_int); - const GPUShaderInput *block = GPU_shaderinterface_ubo(shaderface, BuiltinUniformBlock_name(u)); - shaderface->builtin_blocks[u] = (block != NULL) ? block->binding : -1; - } - - /* Batches ref buffer */ - shaderface->batches_len = GPU_SHADERINTERFACE_REF_ALLOC_COUNT; - shaderface->batches = (void **)MEM_callocN(shaderface->batches_len * sizeof(GPUBatch *), - "GPUShaderInterface batches"); - - MEM_freeN(uniforms_from_blocks); - MEM_freeN(inputs_tmp); - - /* Resize name buffer to save some memory. */ - if (name_buffer_offset < name_buffer_len) { - shaderface->name_buffer = (char *)MEM_reallocN(shaderface->name_buffer, name_buffer_offset); - } - -#if DEBUG_SHADER_INTERFACE - char *name_buf = shaderface->name_buffer; - printf("--- GPUShaderInterface %p, program %d ---\n", shaderface, program); - if (shaderface->attribute_len > 0) { - printf("Attributes {\n"); - for (int i = 0; i < shaderface->attribute_len; i++) { - GPUShaderInput *input = shaderface->inputs + i; - printf("\t(location = %d) %s;\n", input->location, name_buf + input->name_offset); - } - printf("};\n"); - } - if (shaderface->ubo_len > 0) { - printf("Uniform Buffer Objects {\n"); - for (int i = 0; i < shaderface->ubo_len; i++) { - GPUShaderInput *input = shaderface->inputs + shaderface->attribute_len + i; - printf("\t(binding = %d) %s;\n", input->binding, name_buf + input->name_offset); - } - printf("};\n"); + if (enabled_tex_mask_ > 0) { + printf("\n Samplers :\n"); } - if (shaderface->enabled_tex_mask > 0) { - printf("Samplers {\n"); - for (int i = 0; i < shaderface->uniform_len; i++) { - GPUShaderInput *input = shaderface->inputs + shaderface->attribute_len + - shaderface->ubo_len + i; - if (input->binding != -1) { - printf("\t(location = %d, binding = %d) %s;\n", - input->location, - input->binding, - name_buf + input->name_offset); - } - } - printf("};\n"); - } - if (shaderface->uniform_len > 0) { - printf("Uniforms {\n"); - for (int i = 0; i < shaderface->uniform_len; i++) { - GPUShaderInput *input = shaderface->inputs + shaderface->attribute_len + - shaderface->ubo_len + i; - if (input->binding == -1) { - printf("\t(location = %d) %s;\n", input->location, name_buf + input->name_offset); - } + for (const ShaderInput &samp : uniforms) { + /* Bypass uniforms. */ + if (samp.binding != -1) { + printf(format, samp.name_hash, samp.binding, name_buf + samp.name_offset); } - printf("};\n"); } - printf("--- GPUShaderInterface end ---\n\n"); -#endif - return shaderface; -} - -void GPU_shaderinterface_discard(GPUShaderInterface *shaderface) -{ - /* Free memory used by name_buffer. */ - MEM_freeN(shaderface->name_buffer); - /* Remove this interface from all linked Batches vao cache. */ - for (int i = 0; i < shaderface->batches_len; i++) { - if (shaderface->batches[i] != NULL) { - /* XXX GL specific. to be removed during refactor. */ - reinterpret_cast<GLVaoCache *>(shaderface->batches[i])->remove(shaderface); - } - } - MEM_freeN(shaderface->batches); - /* Free memory used by shader interface by its self. */ - MEM_freeN(shaderface); + printf("\n"); } -const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *shaderface, - const char *name) -{ - uint ofs = 0; - return input_lookup(shaderface, shaderface->inputs + ofs, shaderface->attribute_len, name); -} - -const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *shaderface, - const char *name) -{ - uint ofs = shaderface->attribute_len; - return input_lookup(shaderface, shaderface->inputs + ofs, shaderface->ubo_len, name); -} - -const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *shaderface, - const char *name) -{ - uint ofs = shaderface->attribute_len + shaderface->ubo_len; - return input_lookup(shaderface, shaderface->inputs + ofs, shaderface->uniform_len, name); -} - -int32_t GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *shaderface, - GPUUniformBuiltin builtin) -{ - BLI_assert(builtin >= 0 && builtin < GPU_NUM_UNIFORMS); - return shaderface->builtins[builtin]; -} - -int32_t GPU_shaderinterface_block_builtin(const GPUShaderInterface *shaderface, - GPUUniformBlockBuiltin builtin) -{ - BLI_assert(builtin >= 0 && builtin < GPU_NUM_UNIFORM_BLOCKS); - return shaderface->builtin_blocks[builtin]; -} - -void GPU_shaderinterface_add_batch_ref(GPUShaderInterface *shaderface, void *batch) -{ - int i; /* find first unused slot */ - for (i = 0; i < shaderface->batches_len; i++) { - if (shaderface->batches[i] == NULL) { - break; - } - } - if (i == shaderface->batches_len) { - /* Not enough place, realloc the array. */ - i = shaderface->batches_len; - shaderface->batches_len += GPU_SHADERINTERFACE_REF_ALLOC_COUNT; - shaderface->batches = (void **)MEM_recallocN(shaderface->batches, - sizeof(void *) * shaderface->batches_len); - } - /** XXX todo cleanup. */ - shaderface->batches[i] = reinterpret_cast<void *>(batch); -} - -void GPU_shaderinterface_remove_batch_ref(GPUShaderInterface *shaderface, void *batch) -{ - for (int i = 0; i < shaderface->batches_len; i++) { - if (shaderface->batches[i] == batch) { - shaderface->batches[i] = NULL; - break; /* cannot have duplicates */ - } - } -} +} // namespace blender::gpu diff --git a/source/blender/gpu/intern/gpu_shader_interface.hh b/source/blender/gpu/intern/gpu_shader_interface.hh new file mode 100644 index 00000000000..76925f4fddb --- /dev/null +++ b/source/blender/gpu/intern/gpu_shader_interface.hh @@ -0,0 +1,225 @@ +/* + * 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 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + */ + +/** \file + * \ingroup gpu + * + * GPU shader interface (C --> GLSL) + * + * Structure detailling needed vertex inputs and resources for a specific shader. + * A shader interface can be shared between two similar shaders. + */ + +#pragma once + +#include <cstring> /* required for STREQ later on. */ + +#include "BLI_hash.h" +#include "BLI_utildefines.h" + +#include "GPU_shader.h" + +namespace blender::gpu { + +typedef struct ShaderInput { + uint32_t name_offset; + uint32_t name_hash; + int32_t location; + /** Defined at interface creation or in shader. Only for Samplers, UBOs and Vertex Attribs. */ + int32_t binding; +} ShaderInput; + +class ShaderInterface { + /* TODO(fclem) should be protected. */ + public: + /** Flat array. In this order: Attributes, Ubos, Uniforms. */ + ShaderInput *inputs_ = NULL; + /** Buffer containing all inputs names separated by '\0'. */ + char *name_buffer_ = NULL; + /** Input counts inside input array. */ + uint attr_len_ = 0; + uint ubo_len_ = 0; + uint uniform_len_ = 0; + /** Enabled bindpoints that needs to be fed with data. */ + uint16_t enabled_attr_mask_ = 0; + uint16_t enabled_ubo_mask_ = 0; + uint64_t enabled_tex_mask_ = 0; + /** Location of builtin uniforms. Fast access, no lookup needed. */ + int32_t builtins_[GPU_NUM_UNIFORMS]; + int32_t builtin_blocks_[GPU_NUM_UNIFORM_BLOCKS]; + + public: + ShaderInterface(); + virtual ~ShaderInterface(); + + void debug_print(void); + + inline const ShaderInput *attr_get(const char *name) const + { + return input_lookup(inputs_, attr_len_, name); + } + + inline const ShaderInput *ubo_get(const char *name) const + { + return input_lookup(inputs_ + attr_len_, ubo_len_, name); + } + + inline const ShaderInput *uniform_get(const char *name) const + { + return input_lookup(inputs_ + attr_len_ + ubo_len_, uniform_len_, name); + } + + /* Returns uniform location. */ + inline int32_t uniform_builtin(const GPUUniformBuiltin builtin) const + { + BLI_assert(builtin >= 0 && builtin < GPU_NUM_UNIFORMS); + return builtins_[builtin]; + } + + /* Returns binding position. */ + inline int32_t ubo_builtin(const GPUUniformBlockBuiltin builtin) const + { + BLI_assert(builtin >= 0 && builtin < GPU_NUM_UNIFORM_BLOCKS); + return builtin_blocks_[builtin]; + } + + protected: + static inline const char *builtin_uniform_name(GPUUniformBuiltin u); + static inline const char *builtin_uniform_block_name(GPUUniformBlockBuiltin u); + + inline uint32_t set_input_name(ShaderInput *input, char *name, uint32_t name_len) const; + + /* Finalize interface construction by sorting the ShaderInputs for faster lookups. */ + void sort_inputs(void); + + private: + inline const ShaderInput *input_lookup(const ShaderInput *const inputs, + const uint inputs_len, + const char *name) const; +}; + +inline const char *ShaderInterface::builtin_uniform_name(GPUUniformBuiltin u) +{ + switch (u) { + case GPU_UNIFORM_MODEL: + return "ModelMatrix"; + case GPU_UNIFORM_VIEW: + return "ViewMatrix"; + case GPU_UNIFORM_MODELVIEW: + return "ModelViewMatrix"; + case GPU_UNIFORM_PROJECTION: + return "ProjectionMatrix"; + case GPU_UNIFORM_VIEWPROJECTION: + return "ViewProjectionMatrix"; + case GPU_UNIFORM_MVP: + return "ModelViewProjectionMatrix"; + + case GPU_UNIFORM_MODEL_INV: + return "ModelMatrixInverse"; + case GPU_UNIFORM_VIEW_INV: + return "ViewMatrixInverse"; + case GPU_UNIFORM_MODELVIEW_INV: + return "ModelViewMatrixInverse"; + case GPU_UNIFORM_PROJECTION_INV: + return "ProjectionMatrixInverse"; + case GPU_UNIFORM_VIEWPROJECTION_INV: + return "ViewProjectionMatrixInverse"; + + case GPU_UNIFORM_NORMAL: + return "NormalMatrix"; + case GPU_UNIFORM_ORCO: + return "OrcoTexCoFactors"; + case GPU_UNIFORM_CLIPPLANES: + return "WorldClipPlanes"; + + case GPU_UNIFORM_COLOR: + return "color"; + case GPU_UNIFORM_BASE_INSTANCE: + return "baseInstance"; + case GPU_UNIFORM_RESOURCE_CHUNK: + return "resourceChunk"; + case GPU_UNIFORM_RESOURCE_ID: + return "resourceId"; + case GPU_UNIFORM_SRGB_TRANSFORM: + return "srgbTarget"; + + default: + return NULL; + } +} + +inline const char *ShaderInterface::builtin_uniform_block_name(GPUUniformBlockBuiltin u) +{ + switch (u) { + case GPU_UNIFORM_BLOCK_VIEW: + return "viewBlock"; + case GPU_UNIFORM_BLOCK_MODEL: + return "modelBlock"; + case GPU_UNIFORM_BLOCK_INFO: + return "infoBlock"; + default: + return NULL; + } +} + +/* Returns string length including '\0' terminator. */ +inline uint32_t ShaderInterface::set_input_name(ShaderInput *input, + char *name, + uint32_t name_len) const +{ + /* remove "[0]" from array name */ + if (name[name_len - 1] == ']') { + name[name_len - 3] = '\0'; + name_len -= 3; + } + + input->name_offset = (uint32_t)(name - name_buffer_); + input->name_hash = BLI_hash_string(name); + return name_len + 1; /* include NULL terminator */ +} + +inline const ShaderInput *ShaderInterface::input_lookup(const ShaderInput *const inputs, + const uint inputs_len, + const char *name) const +{ + const uint name_hash = BLI_hash_string(name); + /* Simple linear search for now. */ + for (int i = inputs_len - 1; i >= 0; i--) { + if (inputs[i].name_hash == name_hash) { + if ((i > 0) && UNLIKELY(inputs[i - 1].name_hash == name_hash)) { + /* Hash colision resolve. */ + for (; i >= 0 && inputs[i].name_hash == name_hash; i--) { + if (STREQ(name, name_buffer_ + inputs[i].name_offset)) { + return inputs + i; /* not found */ + } + } + return NULL; /* not found */ + } + + /* This is a bit dangerous since we could have a hash collision. + * where the asked uniform that does not exist has the same hash + * as a real uniform. */ + BLI_assert(STREQ(name, name_buffer_ + inputs[i].name_offset)); + return inputs + i; + } + } + return NULL; /* not found */ +} + +} // namespace blender::gpu diff --git a/source/blender/gpu/intern/gpu_shader_private.hh b/source/blender/gpu/intern/gpu_shader_private.hh index 1f667fb4cf9..d51c3b03ecb 100644 --- a/source/blender/gpu/intern/gpu_shader_private.hh +++ b/source/blender/gpu/intern/gpu_shader_private.hh @@ -23,14 +23,18 @@ #include "BLI_span.hh" #include "GPU_shader.h" -#include "GPU_shader_interface.h" #include "GPU_vertex_buffer.h" +#include "gpu_shader_interface.hh" namespace blender { namespace gpu { class Shader : public GPUShader { public: + /** Uniform & attribute locations for shader. */ + ShaderInterface *interface; + + public: Shader(const char *name); virtual ~Shader(); diff --git a/source/blender/gpu/intern/gpu_state.cc b/source/blender/gpu/intern/gpu_state.cc index f02ec9c5cd4..1be3b06fa34 100644 --- a/source/blender/gpu/intern/gpu_state.cc +++ b/source/blender/gpu/intern/gpu_state.cc @@ -44,7 +44,7 @@ using namespace blender::gpu; do { \ GPUStateManager *stack = GPU_context_active_get()->state_manager; \ auto &state_object = stack->_prefix##state; \ - state_object._state = _value; \ + state_object._state = (_value); \ } while (0) #define SET_IMMUTABLE_STATE(_state, _value) SET_STATE(, _state, _value) @@ -74,10 +74,9 @@ void GPU_provoking_vertex(eGPUProvokingVertex vert) SET_IMMUTABLE_STATE(provoking_vert, vert); } -/* TODO explicit depth test. */ -void GPU_depth_test(bool enable) +void GPU_depth_test(eGPUDepthTest test) { - SET_IMMUTABLE_STATE(depth_test, (enable) ? GPU_DEPTH_LESS_EQUAL : GPU_DEPTH_NONE); + SET_IMMUTABLE_STATE(depth_test, test); } void GPU_line_smooth(bool enable) @@ -104,11 +103,11 @@ void GPU_color_mask(bool r, bool g, bool b, bool a) { GPUStateManager *stack = GPU_context_active_get()->state_manager; auto &state = stack->state; - eGPUWriteMask write_mask = state.write_mask; - SET_FLAG_FROM_TEST(write_mask, r, GPU_WRITE_RED); - SET_FLAG_FROM_TEST(write_mask, g, GPU_WRITE_GREEN); - SET_FLAG_FROM_TEST(write_mask, b, GPU_WRITE_BLUE); - SET_FLAG_FROM_TEST(write_mask, a, GPU_WRITE_ALPHA); + uint32_t write_mask = state.write_mask; + SET_FLAG_FROM_TEST(write_mask, r, (uint32_t)GPU_WRITE_RED); + SET_FLAG_FROM_TEST(write_mask, g, (uint32_t)GPU_WRITE_GREEN); + SET_FLAG_FROM_TEST(write_mask, b, (uint32_t)GPU_WRITE_BLUE); + SET_FLAG_FROM_TEST(write_mask, a, (uint32_t)GPU_WRITE_ALPHA); state.write_mask = write_mask; } @@ -116,8 +115,8 @@ void GPU_depth_mask(bool depth) { GPUStateManager *stack = GPU_context_active_get()->state_manager; auto &state = stack->state; - eGPUWriteMask write_mask = state.write_mask; - SET_FLAG_FROM_TEST(write_mask, depth, GPU_WRITE_DEPTH); + uint32_t write_mask = state.write_mask; + SET_FLAG_FROM_TEST(write_mask, depth, (uint32_t)GPU_WRITE_DEPTH); state.write_mask = write_mask; } @@ -141,13 +140,13 @@ void GPU_state_set(eGPUWriteMask write_mask, { GPUStateManager *stack = GPU_context_active_get()->state_manager; auto &state = stack->state; - state.write_mask = write_mask; - state.blend = blend; - state.culling_test = culling_test; - state.depth_test = depth_test; - state.stencil_test = stencil_test; - state.stencil_op = stencil_op; - state.provoking_vert = provoking_vert; + state.write_mask = (uint32_t)write_mask; + state.blend = (uint32_t)blend; + state.culling_test = (uint32_t)culling_test; + state.depth_test = (uint32_t)depth_test; + state.stencil_test = (uint32_t)stencil_test; + state.stencil_op = (uint32_t)stencil_op; + state.provoking_vert = (uint32_t)provoking_vert; } /** \} */ @@ -231,19 +230,19 @@ void GPU_stencil_compare_mask_set(uint compare_mask) eGPUBlend GPU_blend_get() { GPUState &state = GPU_context_active_get()->state_manager->state; - return state.blend; + return (eGPUBlend)state.blend; } eGPUWriteMask GPU_write_mask_get() { GPUState &state = GPU_context_active_get()->state_manager->state; - return state.write_mask; + return (eGPUWriteMask)state.write_mask; } -bool GPU_depth_test_enabled() +eGPUDepthTest GPU_depth_test_get() { GPUState &state = GPU_context_active_get()->state_manager->state; - return state.depth_test != GPU_DEPTH_NONE; + return (eGPUDepthTest)state.depth_test; } void GPU_scissor_get(int coords[4]) diff --git a/source/blender/gpu/intern/gpu_state_private.hh b/source/blender/gpu/intern/gpu_state_private.hh index 1ba79c7c048..f325f035f28 100644 --- a/source/blender/gpu/intern/gpu_state_private.hh +++ b/source/blender/gpu/intern/gpu_state_private.hh @@ -35,13 +35,20 @@ namespace gpu { * Try to keep small to reduce validation time. */ union GPUState { struct { - eGPUWriteMask write_mask : 13; - eGPUBlend blend : 4; - eGPUFaceCullTest culling_test : 2; - eGPUDepthTest depth_test : 3; - eGPUStencilTest stencil_test : 3; - eGPUStencilOp stencil_op : 3; - eGPUProvokingVertex provoking_vert : 1; + /** eGPUWriteMask */ + uint32_t write_mask : 13; + /** eGPUBlend */ + uint32_t blend : 4; + /** eGPUFaceCullTest */ + uint32_t culling_test : 2; + /** eGPUDepthTest */ + uint32_t depth_test : 3; + /** eGPUStencilTest */ + uint32_t stencil_test : 3; + /** eGPUStencilOp */ + uint32_t stencil_op : 3; + /** eGPUProvokingVertex */ + uint32_t provoking_vert : 1; /** Enable bits. */ uint32_t logic_op_xor : 1; uint32_t invert_facing : 1; diff --git a/source/blender/gpu/opengl/gl_batch.cc b/source/blender/gpu/opengl/gl_batch.cc index fade8763065..9ca0a9f71db 100644 --- a/source/blender/gpu/opengl/gl_batch.cc +++ b/source/blender/gpu/opengl/gl_batch.cc @@ -33,6 +33,7 @@ #include "gpu_batch_private.hh" #include "gpu_primitive_private.h" +#include "gpu_shader_private.hh" #include "gl_batch.hh" #include "gl_context.hh" @@ -71,7 +72,7 @@ void GLVaoCache::init(void) } /* Create a new VAO object and store it in the cache. */ -void GLVaoCache::insert(const GPUShaderInterface *interface, GLuint vao) +void GLVaoCache::insert(const GLShaderInterface *interface, GLuint vao) { /* Now insert the cache. */ if (!is_dynamic_vao_count) { @@ -90,8 +91,7 @@ void GLVaoCache::insert(const GPUShaderInterface *interface, GLuint vao) /* Erase previous entries, they will be added back if drawn again. */ for (int i = 0; i < GPU_VAO_STATIC_LEN; i++) { if (static_vaos.interfaces[i] != NULL) { - GPU_shaderinterface_remove_batch_ref( - const_cast<GPUShaderInterface *>(static_vaos.interfaces[i]), this); + const_cast<GLShaderInterface *>(static_vaos.interfaces[i])->ref_remove(this); context_->vao_free(static_vaos.vao_ids[i]); } } @@ -99,8 +99,8 @@ void GLVaoCache::insert(const GPUShaderInterface *interface, GLuint vao) is_dynamic_vao_count = true; /* Init dynamic arrays and let the branch below set the values. */ dynamic_vaos.count = GPU_BATCH_VAO_DYN_ALLOC_COUNT; - dynamic_vaos.interfaces = (const GPUShaderInterface **)MEM_callocN( - dynamic_vaos.count * sizeof(GPUShaderInterface *), "dyn vaos interfaces"); + dynamic_vaos.interfaces = (const GLShaderInterface **)MEM_callocN( + dynamic_vaos.count * sizeof(GLShaderInterface *), "dyn vaos interfaces"); dynamic_vaos.vao_ids = (GLuint *)MEM_callocN(dynamic_vaos.count * sizeof(GLuint), "dyn vaos ids"); } @@ -118,8 +118,8 @@ void GLVaoCache::insert(const GPUShaderInterface *interface, GLuint vao) /* Not enough place, realloc the array. */ i = dynamic_vaos.count; dynamic_vaos.count += GPU_BATCH_VAO_DYN_ALLOC_COUNT; - dynamic_vaos.interfaces = (const GPUShaderInterface **)MEM_recallocN( - (void *)dynamic_vaos.interfaces, sizeof(GPUShaderInterface *) * dynamic_vaos.count); + dynamic_vaos.interfaces = (const GLShaderInterface **)MEM_recallocN( + (void *)dynamic_vaos.interfaces, sizeof(GLShaderInterface *) * dynamic_vaos.count); dynamic_vaos.vao_ids = (GLuint *)MEM_recallocN(dynamic_vaos.vao_ids, sizeof(GLuint) * dynamic_vaos.count); } @@ -127,15 +127,15 @@ void GLVaoCache::insert(const GPUShaderInterface *interface, GLuint vao) dynamic_vaos.vao_ids[i] = vao; } - GPU_shaderinterface_add_batch_ref(const_cast<GPUShaderInterface *>(interface), this); + const_cast<GLShaderInterface *>(interface)->ref_add(this); } -void GLVaoCache::remove(const GPUShaderInterface *interface) +void GLVaoCache::remove(const GLShaderInterface *interface) { const int count = (is_dynamic_vao_count) ? dynamic_vaos.count : GPU_VAO_STATIC_LEN; GLuint *vaos = (is_dynamic_vao_count) ? dynamic_vaos.vao_ids : static_vaos.vao_ids; - const GPUShaderInterface **interfaces = (is_dynamic_vao_count) ? dynamic_vaos.interfaces : - static_vaos.interfaces; + const GLShaderInterface **interfaces = (is_dynamic_vao_count) ? dynamic_vaos.interfaces : + static_vaos.interfaces; for (int i = 0; i < count; i++) { if (interfaces[i] == interface) { context_->vao_free(vaos[i]); @@ -151,8 +151,8 @@ void GLVaoCache::clear(void) GLContext *ctx = static_cast<GLContext *>(GPU_context_active_get()); const int count = (is_dynamic_vao_count) ? dynamic_vaos.count : GPU_VAO_STATIC_LEN; GLuint *vaos = (is_dynamic_vao_count) ? dynamic_vaos.vao_ids : static_vaos.vao_ids; - const GPUShaderInterface **interfaces = (is_dynamic_vao_count) ? dynamic_vaos.interfaces : - static_vaos.interfaces; + const GLShaderInterface **interfaces = (is_dynamic_vao_count) ? dynamic_vaos.interfaces : + static_vaos.interfaces; /* Early out, nothing to free. */ if (context_ == NULL) { return; @@ -171,10 +171,9 @@ void GLVaoCache::clear(void) } for (int i = 0; i < count; i++) { - if (interfaces[i] == NULL) { - continue; + if (interfaces[i] != NULL) { + const_cast<GLShaderInterface *>(interfaces[i])->ref_remove(this); } - GPU_shaderinterface_remove_batch_ref(const_cast<GPUShaderInterface *>(interfaces[i]), this); } if (is_dynamic_vao_count) { @@ -190,11 +189,11 @@ void GLVaoCache::clear(void) } /* Return 0 on cache miss (invalid VAO) */ -GLuint GLVaoCache::lookup(const GPUShaderInterface *interface) +GLuint GLVaoCache::lookup(const GLShaderInterface *interface) { const int count = (is_dynamic_vao_count) ? dynamic_vaos.count : GPU_VAO_STATIC_LEN; - const GPUShaderInterface **interfaces = (is_dynamic_vao_count) ? dynamic_vaos.interfaces : - static_vaos.interfaces; + const GLShaderInterface **interfaces = (is_dynamic_vao_count) ? dynamic_vaos.interfaces : + static_vaos.interfaces; for (int i = 0; i < count; i++) { if (interfaces[i] == interface) { return (is_dynamic_vao_count) ? dynamic_vaos.vao_ids[i] : static_vaos.vao_ids[i]; @@ -226,7 +225,9 @@ GLuint GLVaoCache::base_instance_vao_get(GPUBatch *batch, int i_first) { this->context_check(); /* Make sure the interface is up to date. */ - if (interface_ != GPU_context_active_get()->shader->interface) { + Shader *shader = static_cast<Shader *>(GPU_context_active_get()->shader); + GLShaderInterface *interface = static_cast<GLShaderInterface *>(shader->interface); + if (interface_ != interface) { vao_get(batch); /* Trigger update. */ base_instance_ = 0; @@ -255,9 +256,10 @@ GLuint GLVaoCache::vao_get(GPUBatch *batch) { this->context_check(); - GPUContext *ctx = GPU_context_active_get(); - if (interface_ != ctx->shader->interface) { - interface_ = ctx->shader->interface; + Shader *shader = static_cast<Shader *>(GPU_context_active_get()->shader); + GLShaderInterface *interface = static_cast<GLShaderInterface *>(shader->interface); + if (interface_ != interface) { + interface_ = interface; vao_id_ = this->lookup(interface_); if (vao_id_ == 0) { diff --git a/source/blender/gpu/opengl/gl_batch.hh b/source/blender/gpu/opengl/gl_batch.hh index d70f43aed2a..9a7767d679d 100644 --- a/source/blender/gpu/opengl/gl_batch.hh +++ b/source/blender/gpu/opengl/gl_batch.hh @@ -32,11 +32,11 @@ #include "glew-mx.h" -#include "GPU_shader_interface.h" - namespace blender { namespace gpu { +class GLShaderInterface; + #define GPU_VAO_STATIC_LEN 3 /* Vao management: remembers all geometry state (vertex attribute bindings & element buffer) @@ -47,7 +47,7 @@ class GLVaoCache { /** Context for which the vao_cache_ was generated. */ struct GLContext *context_ = NULL; /** Last interface this batch was drawn with. */ - GPUShaderInterface *interface_ = NULL; + GLShaderInterface *interface_ = NULL; /** Cached vao for the last interface. */ GLuint vao_id_ = 0; /** Used whend arb_base_instance is not supported. */ @@ -58,13 +58,13 @@ class GLVaoCache { union { /** Static handle count */ struct { - const GPUShaderInterface *interfaces[GPU_VAO_STATIC_LEN]; + const GLShaderInterface *interfaces[GPU_VAO_STATIC_LEN]; GLuint vao_ids[GPU_VAO_STATIC_LEN]; } static_vaos; /** Dynamic handle count */ struct { uint count; - const GPUShaderInterface **interfaces; + const GLShaderInterface **interfaces; GLuint *vao_ids; } dynamic_vaos; }; @@ -76,9 +76,9 @@ class GLVaoCache { GLuint vao_get(GPUBatch *batch); GLuint base_instance_vao_get(GPUBatch *batch, int i_first); - GLuint lookup(const GPUShaderInterface *interface); - void insert(const GPUShaderInterface *interface, GLuint vao_id); - void remove(const GPUShaderInterface *interface); + GLuint lookup(const GLShaderInterface *interface); + void insert(const GLShaderInterface *interface, GLuint vao_id); + void remove(const GLShaderInterface *interface); void clear(void); private: diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index ea33ff00d69..93ed7a408c6 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -29,6 +29,7 @@ #include "GPU_platform.h" #include "gl_shader.hh" +#include "gl_shader_interface.hh" using namespace blender; using namespace blender::gpu; @@ -203,10 +204,7 @@ bool GLShader::finalize(void) return false; } - /* TODO(fclem) We need this to modify the image binding points using glUniform. - * This could be avoided using glProgramUniform in GL 4.1. */ - glUseProgram(shader_program_); - interface = GPU_shaderinterface_create(shader_program_); + interface = new GLShaderInterface(shader_program_); return true; } diff --git a/source/blender/gpu/opengl/gl_shader.hh b/source/blender/gpu/opengl/gl_shader.hh index 0e37ea18d23..b432a04abaa 100644 --- a/source/blender/gpu/opengl/gl_shader.hh +++ b/source/blender/gpu/opengl/gl_shader.hh @@ -57,7 +57,7 @@ class GLShader : public Shader { bool finalize(void) override; void transform_feedback_names_set(Span<const char *> name_list, - const eGPUShaderTFBType geom_type); + const eGPUShaderTFBType geom_type) override; bool transform_feedback_enable(GPUVertBuf *buf) override; void transform_feedback_disable(void) override; diff --git a/source/blender/gpu/opengl/gl_shader_interface.cc b/source/blender/gpu/opengl/gl_shader_interface.cc new file mode 100644 index 00000000000..423db5c8c97 --- /dev/null +++ b/source/blender/gpu/opengl/gl_shader_interface.cc @@ -0,0 +1,297 @@ +/* + * 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 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + */ + +/** \file + * \ingroup gpu + * + * GPU shader interface (C --> GLSL) + */ + +#include "BLI_bitmap.h" + +#include "gl_batch.hh" + +#include "gl_shader_interface.hh" + +namespace blender::gpu { + +/* -------------------------------------------------------------------- */ +/** \name Binding assignment + * + * To mimic vulkan, we assign binding at shader creation to avoid shader recompilation. + * In the future, we should set it in the shader using layout(binding = i) and query its value. + * \{ */ + +static inline int block_binding(int32_t program, uint32_t block_index) +{ + /* For now just assign a consecutive index. In the future, we should set it in + * the shader using layout(binding = i) and query its value. */ + glUniformBlockBinding(program, block_index, block_index); + return block_index; +} + +static inline int sampler_binding(int32_t program, + uint32_t uniform_index, + int32_t uniform_location, + int *sampler_len) +{ + /* Identify sampler uniforms and asign sampler units to them. */ + GLint type; + glGetActiveUniformsiv(program, 1, &uniform_index, GL_UNIFORM_TYPE, &type); + + switch (type) { + case GL_SAMPLER_1D: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_CUBE_MAP_ARRAY_ARB: /* OpenGL 4.0 */ + case GL_SAMPLER_1D_SHADOW: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_1D_ARRAY: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_1D_ARRAY_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_BUFFER: + case GL_INT_SAMPLER_1D: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_1D_ARRAY: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_1D: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: { + /* For now just assign a consecutive index. In the future, we should set it in + * the shader using layout(binding = i) and query its value. */ + int binding = *sampler_len; + glUniform1i(uniform_location, binding); + (*sampler_len)++; + return binding; + } + default: + return -1; + } +} +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Creation / Destruction + * \{ */ + +GLShaderInterface::GLShaderInterface(GLuint program) +{ + /* Necessary to make glUniform works. */ + glUseProgram(program); + + GLint max_attr_name_len = 0, attr_len = 0; + glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_attr_name_len); + glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &attr_len); + + GLint max_ubo_name_len = 0, ubo_len = 0; + glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_ubo_name_len); + glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &ubo_len); + + GLint max_uniform_name_len = 0, active_uniform_len = 0, uniform_len = 0; + glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_uniform_name_len); + glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniform_len); + uniform_len = active_uniform_len; + + /* Work around driver bug with Intel HD 4600 on Windows 7/8, where + * GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH does not work. */ + if (attr_len > 0 && max_attr_name_len == 0) { + max_attr_name_len = 256; + } + if (ubo_len > 0 && max_ubo_name_len == 0) { + max_ubo_name_len = 256; + } + if (uniform_len > 0 && max_uniform_name_len == 0) { + max_uniform_name_len = 256; + } + + /* GL_ACTIVE_UNIFORMS lied to us! Remove the UBO uniforms from the total before + * allocating the uniform array. */ + GLint max_ubo_uni_len = 0; + for (int i = 0; i < ubo_len; i++) { + GLint ubo_uni_len; + glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &ubo_uni_len); + max_ubo_uni_len = max_ii(max_ubo_uni_len, ubo_uni_len); + uniform_len -= ubo_uni_len; + } + /* Bit set to true if uniform comes from a uniform block. */ + BLI_bitmap *uniforms_from_blocks = BLI_BITMAP_NEW(active_uniform_len, __func__); + /* Set uniforms from block for exclusion. */ + GLint *ubo_uni_ids = (GLint *)MEM_mallocN(sizeof(GLint) * max_ubo_uni_len, __func__); + for (int i = 0; i < ubo_len; i++) { + GLint ubo_uni_len; + glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &ubo_uni_len); + glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, ubo_uni_ids); + for (int u = 0; u < ubo_uni_len; u++) { + BLI_BITMAP_ENABLE(uniforms_from_blocks, ubo_uni_ids[u]); + } + } + MEM_freeN(ubo_uni_ids); + + int input_tot_len = attr_len + ubo_len + uniform_len; + inputs_ = (ShaderInput *)MEM_callocN(sizeof(ShaderInput) * input_tot_len, __func__); + + const uint32_t name_buffer_len = attr_len * max_attr_name_len + ubo_len * max_ubo_name_len + + uniform_len * max_uniform_name_len; + name_buffer_ = (char *)MEM_mallocN(name_buffer_len, "name_buffer"); + uint32_t name_buffer_offset = 0; + + /* Attributes */ + enabled_attr_mask_ = 0; + for (int i = 0; i < attr_len; i++) { + char *name = name_buffer_ + name_buffer_offset; + GLsizei remaining_buffer = name_buffer_len - name_buffer_offset; + GLsizei name_len = 0; + GLenum type; + GLint size; + + glGetActiveAttrib(program, i, remaining_buffer, &name_len, &size, &type, name); + GLint location = glGetAttribLocation(program, name); + /* Ignore OpenGL names like `gl_BaseInstanceARB`, `gl_InstanceID` and `gl_VertexID`. */ + if (location == -1) { + continue; + } + + ShaderInput *input = &inputs_[attr_len_++]; + input->location = input->binding = location; + + name_buffer_offset += set_input_name(input, name, name_len); + enabled_attr_mask_ |= (1 << input->location); + } + + /* Uniform Blocks */ + for (int i = 0; i < ubo_len; i++) { + char *name = name_buffer_ + name_buffer_offset; + GLsizei remaining_buffer = name_buffer_len - name_buffer_offset; + GLsizei name_len = 0; + + glGetActiveUniformBlockName(program, i, remaining_buffer, &name_len, name); + + ShaderInput *input = &inputs_[attr_len_ + ubo_len_++]; + input->binding = input->location = block_binding(program, i); + + name_buffer_offset += this->set_input_name(input, name, name_len); + enabled_ubo_mask_ |= (1 << input->binding); + } + + /* Uniforms */ + for (int i = 0, sampler = 0; i < active_uniform_len; i++) { + if (BLI_BITMAP_TEST(uniforms_from_blocks, i)) { + continue; + } + char *name = name_buffer_ + name_buffer_offset; + GLsizei remaining_buffer = name_buffer_len - name_buffer_offset; + GLsizei name_len = 0; + + glGetActiveUniformName(program, i, remaining_buffer, &name_len, name); + + ShaderInput *input = &inputs_[attr_len_ + ubo_len_ + uniform_len_++]; + input->location = glGetUniformLocation(program, name); + input->binding = sampler_binding(program, i, input->location, &sampler); + + name_buffer_offset += this->set_input_name(input, name, name_len); + enabled_tex_mask_ |= (input->binding != -1) ? (1lu << input->binding) : 0lu; + } + + /* Builtin Uniforms */ + for (int32_t u_int = 0; u_int < GPU_NUM_UNIFORMS; u_int++) { + GPUUniformBuiltin u = static_cast<GPUUniformBuiltin>(u_int); + builtins_[u] = glGetUniformLocation(program, builtin_uniform_name(u)); + } + + /* Builtin Uniforms Blocks */ + for (int32_t u_int = 0; u_int < GPU_NUM_UNIFORM_BLOCKS; u_int++) { + GPUUniformBlockBuiltin u = static_cast<GPUUniformBlockBuiltin>(u_int); + const ShaderInput *block = this->ubo_get(builtin_uniform_block_name(u)); + builtin_blocks_[u] = (block != NULL) ? block->binding : -1; + } + + MEM_freeN(uniforms_from_blocks); + + /* Resize name buffer to save some memory. */ + if (name_buffer_offset < name_buffer_len) { + name_buffer_ = (char *)MEM_reallocN(name_buffer_, name_buffer_offset); + } + + // this->debug_print(); + + this->sort_inputs(); +} + +GLShaderInterface::~GLShaderInterface() +{ + for (auto *ref : refs_) { + if (ref != NULL) { + ref->remove(this); + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Batch Reference + * \{ */ + +void GLShaderInterface::ref_add(GLVaoCache *ref) +{ + for (int i = 0; i < refs_.size(); i++) { + if (refs_[i] == NULL) { + refs_[i] = ref; + return; + } + } + refs_.append(ref); +} + +void GLShaderInterface::ref_remove(GLVaoCache *ref) +{ + for (int i = 0; i < refs_.size(); i++) { + if (refs_[i] == ref) { + refs_[i] = NULL; + break; /* cannot have duplicates */ + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Validation + * TODO + * \{ */ + +/** \} */ + +} // namespace blender::gpu
\ No newline at end of file diff --git a/source/blender/gpu/opengl/gl_shader_interface.hh b/source/blender/gpu/opengl/gl_shader_interface.hh new file mode 100644 index 00000000000..fdf9512ef79 --- /dev/null +++ b/source/blender/gpu/opengl/gl_shader_interface.hh @@ -0,0 +1,60 @@ +/* + * 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 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup gpu + * + * GPU shader interface (C --> GLSL) + * + * Structure detailling needed vertex inputs and resources for a specific shader. + * A shader interface can be shared between two similar shaders. + */ + +#pragma once + +#include "MEM_guardedalloc.h" + +#include "BLI_vector.hh" + +#include "glew-mx.h" + +#include "gpu_shader_interface.hh" + +namespace blender::gpu { + +class GLVaoCache; + +class GLShaderInterface : public ShaderInterface { + private: + /** Reference to VaoCaches using this interface */ + Vector<GLVaoCache *> refs_; + + public: + GLShaderInterface(GLuint program); + ~GLShaderInterface(); + + void ref_add(GLVaoCache *ref); + void ref_remove(GLVaoCache *ref); + + // bool resource_binding_validate(); + + MEM_CXX_CLASS_ALLOC_FUNCS("GLShaderInterface"); +}; + +} // namespace blender::gpu diff --git a/source/blender/gpu/opengl/gl_state.cc b/source/blender/gpu/opengl/gl_state.cc index 3e3695e0b48..4e21ab43b45 100644 --- a/source/blender/gpu/opengl/gl_state.cc +++ b/source/blender/gpu/opengl/gl_state.cc @@ -65,23 +65,23 @@ void GLStateManager::set_state(const GPUState &state) GPUState changed = state ^ current_; if (changed.blend != 0) { - set_blend(state.blend); + set_blend((eGPUBlend)state.blend); } if (changed.write_mask != 0) { - set_write_mask(state.write_mask); + set_write_mask((eGPUWriteMask)state.write_mask); } if (changed.depth_test != 0) { - set_depth_test(state.depth_test); + set_depth_test((eGPUDepthTest)state.depth_test); } if (changed.stencil_test != 0 || changed.stencil_op != 0) { - set_stencil_test(state.stencil_test, state.stencil_op); - set_stencil_mask(state.stencil_test, mutable_state); + set_stencil_test((eGPUStencilTest)state.stencil_test, (eGPUStencilOp)state.stencil_op); + set_stencil_mask((eGPUStencilTest)state.stencil_test, mutable_state); } if (changed.clip_distances != 0) { set_clip_distances(state.clip_distances, current_.clip_distances); } if (changed.culling_test != 0) { - set_backface_culling(state.culling_test); + set_backface_culling((eGPUFaceCullTest)state.culling_test); } if (changed.logic_op_xor != 0) { set_logic_op(state.logic_op_xor); @@ -90,7 +90,7 @@ void GLStateManager::set_state(const GPUState &state) set_facing(state.invert_facing); } if (changed.provoking_vert != 0) { - set_provoking_vert(state.provoking_vert); + set_provoking_vert((eGPUProvokingVertex)state.provoking_vert); } if (changed.shadow_bias != 0) { set_shadow_bias(state.shadow_bias); @@ -160,7 +160,7 @@ void GLStateManager::set_mutable_state(const GPUStateMutable &state) if (changed.stencil_compare_mask != 0 || changed.stencil_reference != 0 || changed.stencil_write_mask != 0) { - set_stencil_mask(current_.stencil_test, state); + set_stencil_mask((eGPUStencilTest)current_.stencil_test, state); } current_mutable_ = state; diff --git a/source/blender/gpu/opengl/gl_vertex_array.cc b/source/blender/gpu/opengl/gl_vertex_array.cc index 907dc37e46f..b2d2445f113 100644 --- a/source/blender/gpu/opengl/gl_vertex_array.cc +++ b/source/blender/gpu/opengl/gl_vertex_array.cc @@ -23,9 +23,9 @@ #include "GPU_glew.h" -#include "GPU_shader_interface.h" #include "GPU_vertex_buffer.h" +#include "gpu_shader_interface.hh" #include "gpu_vertex_format_private.h" #include "gl_batch.hh" @@ -33,14 +33,14 @@ #include "gl_vertex_array.hh" -using namespace blender::gpu; +namespace blender::gpu { /* -------------------------------------------------------------------- */ /** \name Vertex Array Bindings * \{ */ /* Returns enabled vertex pointers as a bitflag (one bit per attrib). */ -static uint16_t vbo_bind(const GPUShaderInterface *interface, +static uint16_t vbo_bind(const ShaderInterface *interface, const GPUVertFormat *format, uint v_first, uint v_len, @@ -68,7 +68,7 @@ static uint16_t vbo_bind(const GPUShaderInterface *interface, for (uint n_idx = 0; n_idx < a->name_len; n_idx++) { const char *name = GPU_vertformat_attr_name_get(format, a, n_idx); - const GPUShaderInput *input = GPU_shaderinterface_attr(interface, name); + const ShaderInput *input = interface->attr_get(name); if (input == NULL) { continue; @@ -111,10 +111,10 @@ static uint16_t vbo_bind(const GPUShaderInterface *interface, /* Update the Attrib Binding of the currently bound VAO. */ void GLVertArray::update_bindings(const GLuint vao, const GPUBatch *batch, - const GPUShaderInterface *interface, + const ShaderInterface *interface, const int base_instance) { - uint16_t attr_mask = interface->enabled_attr_mask; + uint16_t attr_mask = interface->enabled_attr_mask_; glBindVertexArray(vao); @@ -156,3 +156,5 @@ void GLVertArray::update_bindings(const GLuint vao, } /** \} */ + +} // namespace blender::gpu
\ No newline at end of file diff --git a/source/blender/gpu/opengl/gl_vertex_array.hh b/source/blender/gpu/opengl/gl_vertex_array.hh index 6da414d7e62..59cd50ad7b8 100644 --- a/source/blender/gpu/opengl/gl_vertex_array.hh +++ b/source/blender/gpu/opengl/gl_vertex_array.hh @@ -26,7 +26,7 @@ #include "glew-mx.h" #include "GPU_batch.h" -#include "GPU_shader_interface.h" +#include "gl_shader_interface.hh" namespace blender { namespace gpu { @@ -35,7 +35,7 @@ namespace GLVertArray { void update_bindings(const GLuint vao, const GPUBatch *batch, - const GPUShaderInterface *interface, + const ShaderInterface *interface, const int base_instance); } // namespace GLVertArray diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index feda4ba43eb..e16a22f5459 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -686,10 +686,6 @@ typedef enum IDRecalcFlag { ID_RECALC_PARAMETERS = (1 << 21), - /* Makes it so everything what depends on time. - * Basically, the same what changing frame in a timeline will do. */ - ID_RECALC_TIME = (1 << 22), - /* Input has changed and datablock is to be reload from disk. * Applies to movie clips to inform that copy-on-written version is to be refreshed for the new * input file or for color space changes. */ diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 7ff96c5a908..8e4063b36eb 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -68,8 +68,6 @@ typedef struct bScreen { /** User-setting for which editors get redrawn during anim playback. */ short redraws_flag; - char statusbar_info[256]; - /** Temp screen in a temp window, don't save (like user prefs). */ char temp; /** Temp screen for image render display or fileselect. */ @@ -536,9 +534,8 @@ typedef enum eScreen_Redraws_Flag { /** #Panel.flag */ enum { PNL_SELECT = (1 << 0), - PNL_CLOSEDX = (1 << 1), - PNL_CLOSEDY = (1 << 2), - PNL_CLOSED = (PNL_CLOSEDX | PNL_CLOSEDY), + PNL_UNUSED_1 = (1 << 1), /* Cleared */ + PNL_CLOSED = (1 << 2), /* PNL_TABBED = (1 << 3), */ /*UNUSED*/ /* PNL_OVERLAP = (1 << 4), */ /*UNUSED*/ PNL_PIN = (1 << 5), diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index d34f431c848..2b1e5b3c702 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -599,7 +599,7 @@ static void rna_float_print(FILE *f, float num) else if (num == FLT_MAX) { fprintf(f, "FLT_MAX"); } - else if ((fabsf(num) < INT64_MAX) && ((int64_t)num == num)) { + else if ((fabsf(num) < (float)INT64_MAX) && ((int64_t)num == num)) { fprintf(f, "%.1ff", num); } else { diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index c8d16ab65cc..9bcf2b81557 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -106,7 +106,7 @@ static const EnumPropertyItem rna_enum_keyframe_type_items[] = { }; static const EnumPropertyItem rna_enum_onion_keyframe_type_items[] = { - {-1, "ALL", ICON_ACTION, "All Types", "Include all Keyframe types"}, + {-1, "ALL", 0, "All", "Include all Keyframe types"}, {BEZT_KEYTYPE_KEYFRAME, "KEYFRAME", ICON_KEYTYPE_KEYFRAME_VEC, diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 5d266e910ad..ec1a77c9520 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -924,6 +924,23 @@ static void rna_Scene_volume_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_VOLUME | ID_RECALC_SEQUENCER_STRIPS); } +static const char *rna_Scene_statistics_string_get(Scene *scene, + Main *bmain, + ReportList *reports, + ViewLayer *view_layer) +{ + if (BKE_scene_find_from_view_layer(bmain, view_layer) != scene) { + BKE_reportf(reports, + RPT_ERROR, + "View Layer '%s' not found in scene '%s'", + view_layer->name, + scene->id.name + 2); + return ""; + } + + return ED_info_statistics_string(bmain, scene, view_layer); +} + static void rna_Scene_framelen_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) { scene->r.framelen = (float)scene->r.framapto / (float)scene->r.images; @@ -1866,11 +1883,10 @@ static void object_simplify_update(Object *ob) } if (ob->instance_collection) { - CollectionObject *cob; - - for (cob = ob->instance_collection->gobject.first; cob; cob = cob->next) { - object_simplify_update(cob->ob); + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (ob->instance_collection, ob_collection) { + object_simplify_update(ob_collection); } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } } @@ -7277,6 +7293,9 @@ void RNA_def_scene(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; + FunctionRNA *func; + PropertyRNA *parm; + static const EnumPropertyItem audio_distance_model_items[] = { {0, "NONE", 0, "None", "No distance attenuation"}, {1, "INVERSE", 0, "Inverse", "Inverse distance model"}, @@ -7668,6 +7687,14 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_update(prop, NC_SCENE, NULL); RNA_def_property_update(prop, NC_SCENE, "rna_Scene_volume_update"); + /* Statistics */ + func = RNA_def_function(srna, "statistics", "rna_Scene_statistics_string_get"); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "view_layer", "ViewLayer", "View Layer", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "statistics", NULL, 0, "Statistics", ""); + RNA_def_function_return(func, parm); + /* Grease Pencil */ prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "gpd"); diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c index fb2a60db0fd..ab84dcb0aba 100644 --- a/source/blender/makesrna/intern/rna_screen.c +++ b/source/blender/makesrna/intern/rna_screen.c @@ -288,9 +288,11 @@ static void rna_View2D_view_to_region( } } -static const char *rna_Screen_statusbar_info_get(struct bScreen *screen, Main *bmain, bContext *C) +static const char *rna_Screen_statusbar_info_get(struct bScreen *UNUSED(screen), + Main *bmain, + bContext *C) { - return ED_info_statusbar_string(bmain, screen, C); + return ED_info_statusbar_string(bmain, CTX_data_scene(C), CTX_data_view_layer(C)); } #else diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c index a387ba31c84..d0676ec1947 100644 --- a/source/blender/python/bmesh/bmesh_py_ops_call.c +++ b/source/blender/python/bmesh/bmesh_py_ops_call.c @@ -228,7 +228,7 @@ static int bpy_slot_from_py(BMesh *bm, break; } case BMO_OP_SLOT_FLT: { - float param = PyFloat_AsDouble(value); + const float param = PyFloat_AsDouble(value); if (param == -1 && PyErr_Occurred()) { PyErr_Format(PyExc_TypeError, "%.200s: keyword \"%.200s\" expected a float, not %.200s", @@ -840,7 +840,7 @@ PyObject *BPy_BMO_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw) { char slot_name_strip[MAX_SLOTNAME]; const char *ch = strchr(slot->slot_name, '.'); /* can't fail! */ - int tot = ch - slot->slot_name; + const int tot = ch - slot->slot_name; BLI_assert(ch != NULL); memcpy(slot_name_strip, slot->slot_name, tot); slot_name_strip[tot] = '\0'; diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 04bceb17c20..2b174de7136 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -1093,7 +1093,7 @@ static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args, PyObject bool use_deform = true; bool use_cage = false; bool use_fnorm = true; - CustomData_MeshMasks data_masks = CD_MASK_BMESH; + const CustomData_MeshMasks data_masks = CD_MASK_BMESH; BPY_BM_CHECK_OBJ(self); @@ -1346,7 +1346,7 @@ static PyObject *bpy_bmesh_transform(BPy_BMElem *self, PyObject *args, PyObject } } else { - char filter_flags_ch = (char)filter_flags; + const char filter_flags_ch = (char)filter_flags; BM_ITER_MESH (eve, &iter, self->bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(eve, filter_flags_ch)) { mul_m4_v3((float(*)[4])mat_ptr, eve->co); @@ -3222,7 +3222,7 @@ static PyObject *bpy_bmelemseq_subscript(BPy_BMElemSeq *self, PyObject *key) { /* don't need error check here */ if (PyIndex_Check(key)) { - Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); + const Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) { return NULL; } @@ -3255,7 +3255,7 @@ static PyObject *bpy_bmelemseq_subscript(BPy_BMElemSeq *self, PyObject *key) if (start < 0 || stop < 0) { /* only get the length for negative values */ - Py_ssize_t len = bpy_bmelemseq_length(self); + const Py_ssize_t len = bpy_bmelemseq_length(self); if (start < 0) { start += len; } diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c index 51616030d30..a9a9a3ad5d9 100644 --- a/source/blender/python/bmesh/bmesh_py_types_customdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c @@ -714,7 +714,7 @@ static PyObject *bpy_bmlayercollection_subscript_slice(BPy_BMLayerCollection *se Py_ssize_t start, Py_ssize_t stop) { - Py_ssize_t len = bpy_bmlayercollection_length(self); + const Py_ssize_t len = bpy_bmlayercollection_length(self); int count = 0; PyObject *tuple; @@ -746,7 +746,7 @@ static PyObject *bpy_bmlayercollection_subscript(BPy_BMLayerCollection *self, Py return bpy_bmlayercollection_subscript_str(self, _PyUnicode_AsString(key)); } if (PyIndex_Check(key)) { - Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); + const Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) { return NULL; } @@ -779,7 +779,7 @@ static PyObject *bpy_bmlayercollection_subscript(BPy_BMLayerCollection *self, Py if (start < 0 || stop < 0) { /* only get the length for negative values */ - Py_ssize_t len = bpy_bmlayercollection_length(self); + const Py_ssize_t len = bpy_bmlayercollection_length(self); if (start < 0) { start += len; } @@ -1127,7 +1127,7 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj } case CD_PROP_FLOAT: case CD_PAINT_MASK: { - float tmp_val = PyFloat_AsDouble(py_value); + const float tmp_val = PyFloat_AsDouble(py_value); if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) { PyErr_Format( PyExc_TypeError, "expected a float, not a %.200s", Py_TYPE(py_value)->tp_name); @@ -1140,7 +1140,7 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj } case CD_PROP_INT32: case CD_FACEMAP: { - int tmp_val = PyC_Long_AsI32(py_value); + const int tmp_val = PyC_Long_AsI32(py_value); if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) { /* error is set */ ret = -1; @@ -1187,7 +1187,7 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj break; } case CD_BWEIGHT: { - float tmp_val = PyFloat_AsDouble(py_value); + const float tmp_val = PyFloat_AsDouble(py_value); if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) { PyErr_Format( PyExc_TypeError, "expected a float, not a %.200s", Py_TYPE(py_value)->tp_name); @@ -1199,7 +1199,7 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj break; } case CD_CREASE: { - float tmp_val = PyFloat_AsDouble(py_value); + const float tmp_val = PyFloat_AsDouble(py_value); if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) { PyErr_Format( PyExc_TypeError, "expected a float, not a %.200s", Py_TYPE(py_value)->tp_name); diff --git a/source/blender/python/bmesh/bmesh_py_types_select.c b/source/blender/python/bmesh/bmesh_py_types_select.c index d69668341ff..9bb9815f731 100644 --- a/source/blender/python/bmesh/bmesh_py_types_select.c +++ b/source/blender/python/bmesh/bmesh_py_types_select.c @@ -246,7 +246,7 @@ static PyObject *bpy_bmeditselseq_subscript(BPy_BMEditSelSeq *self, PyObject *ke { /* don't need error check here */ if (PyIndex_Check(key)) { - Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); + const Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) { return NULL; } @@ -279,7 +279,7 @@ static PyObject *bpy_bmeditselseq_subscript(BPy_BMEditSelSeq *self, PyObject *ke if (start < 0 || stop < 0) { /* only get the length for negative values */ - Py_ssize_t len = bpy_bmeditselseq_length(self); + const Py_ssize_t len = bpy_bmeditselseq_length(self); if (start < 0) { start += len; } diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c index 405541554c9..89fe9f8c6aa 100644 --- a/source/blender/python/generic/bgl.c +++ b/source/blender/python/generic/bgl.c @@ -461,7 +461,7 @@ int BGL_typeSize(int type) static int gl_buffer_type_from_py_buffer(Py_buffer *pybuffer) { const char format = PyC_StructFmt_type_from_str(pybuffer->format); - Py_ssize_t itemsize = pybuffer->itemsize; + const Py_ssize_t itemsize = pybuffer->itemsize; if (PyC_StructFmt_type_is_float_any(format)) { if (itemsize == 4) { @@ -705,7 +705,7 @@ static int BGL_BufferOrOffsetConverter(PyObject *object, BufferOrOffset *buffer) return 1; } if (PyNumber_Check(object)) { - Py_ssize_t offset = PyNumber_AsSsize_t(object, PyExc_IndexError); + const Py_ssize_t offset = PyNumber_AsSsize_t(object, PyExc_IndexError); if (offset == -1 && PyErr_Occurred()) { return 0; } @@ -907,7 +907,7 @@ static int Buffer_ass_item(Buffer *self, int i, PyObject *v) Buffer *row = (Buffer *)Buffer_item(self, i); if (row) { - int ret = Buffer_ass_slice(row, 0, self->dimensions[1], v); + const int ret = Buffer_ass_slice(row, 0, self->dimensions[1], v); Py_DECREF(row); return ret; } diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index 615ce514a3e..314a34e3dec 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -435,7 +435,7 @@ static IDProperty *idp_from_PyBytes(const char *name, PyObject *ob) static int idp_array_type_from_formatstr_and_size(const char *typestr, Py_ssize_t itemsize) { - char format = PyC_StructFmt_type_from_str(typestr); + const char format = PyC_StructFmt_type_from_str(typestr); if (PyC_StructFmt_type_is_float_any(format)) { if (itemsize == 4) { @@ -473,7 +473,7 @@ static IDProperty *idp_from_PySequence_Buffer(const char *name, Py_buffer *buffe IDProperty *prop; IDPropertyTemplate val = {0}; - int id_type = idp_array_type_from_formatstr_and_size(buffer->format, buffer->itemsize); + const int id_type = idp_array_type_from_formatstr_and_size(buffer->format, buffer->itemsize); if (id_type == -1) { /* should never happen as the type has been checked before */ return NULL; @@ -560,7 +560,7 @@ static IDProperty *idp_from_PySequence(const char *name, PyObject *ob) if (PyObject_CheckBuffer(ob)) { PyObject_GetBuffer(ob, &buffer, PyBUF_SIMPLE | PyBUF_FORMAT); - char format = PyC_StructFmt_type_from_str(buffer.format); + const char format = PyC_StructFmt_type_from_str(buffer.format); if (PyC_StructFmt_type_is_float_any(format) || (PyC_StructFmt_type_is_int_any(format) && buffer.itemsize == 4)) { use_buffer = true; @@ -589,7 +589,7 @@ static IDProperty *idp_from_PySequence(const char *name, PyObject *ob) static IDProperty *idp_from_PyMapping(const char *name, PyObject *ob) { IDProperty *prop; - IDPropertyTemplate val = {0}; + const IDPropertyTemplate val = {0}; PyObject *keys, *vals, *key, *pval; int i, len; @@ -1559,8 +1559,8 @@ static int itemsize_by_idarray_type(int array_type) static int BPy_IDArray_getbuffer(BPy_IDArray *self, Py_buffer *view, int flags) { IDProperty *prop = self->prop; - int itemsize = itemsize_by_idarray_type(prop->subtype); - int length = itemsize * prop->len; + const int itemsize = itemsize_by_idarray_type(prop->subtype); + const int length = itemsize * prop->len; if (PyBuffer_FillInfo(view, (PyObject *)self, IDP_Array(prop), length, false, flags) == -1) { return -1; diff --git a/source/blender/python/generic/imbuf_py_api.c b/source/blender/python/generic/imbuf_py_api.c index 3536236754e..5dc4aa6ce7c 100644 --- a/source/blender/python/generic/imbuf_py_api.c +++ b/source/blender/python/generic/imbuf_py_api.c @@ -260,7 +260,7 @@ static int py_imbuf_filepath_set(Py_ImBuf *self, PyObject *value, void *UNUSED(c } ImBuf *ibuf = self->ibuf; - Py_ssize_t value_str_len_max = sizeof(ibuf->name); + const Py_ssize_t value_str_len_max = sizeof(ibuf->name); Py_ssize_t value_str_len; const char *value_str = _PyUnicode_AsStringAndSize(value, &value_str_len); if (value_str_len >= value_str_len_max) { @@ -425,8 +425,8 @@ static PyObject *M_imbuf_new(PyObject *UNUSED(self), PyObject *args, PyObject *k } /* TODO, make options */ - uchar planes = 4; - uint flags = IB_rect; + const uchar planes = 4; + const uint flags = IB_rect; ImBuf *ibuf = IMB_allocImBuf(UNPACK2(size), planes, flags); if (ibuf == NULL) { @@ -500,7 +500,7 @@ static PyObject *M_imbuf_write(PyObject *UNUSED(self), PyObject *args, PyObject filepath = py_imb->ibuf->name; } - bool ok = IMB_saveiff(py_imb->ibuf, filepath, IB_rect); + const bool ok = IMB_saveiff(py_imb->ibuf, filepath, IB_rect); if (ok == false) { PyErr_Format( PyExc_IOError, "write: Unable to write image file (%s) '%s'", strerror(errno), filepath); diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 838a1239210..195442d34f6 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -207,7 +207,7 @@ PyObject *PyC_Tuple_PackArray_Bool(const bool *array, uint len) */ void PyC_Tuple_Fill(PyObject *tuple, PyObject *value) { - uint tot = PyTuple_GET_SIZE(tuple); + const uint tot = PyTuple_GET_SIZE(tuple); uint i; for (i = 0; i < tot; i++) { @@ -218,7 +218,7 @@ void PyC_Tuple_Fill(PyObject *tuple, PyObject *value) void PyC_List_Fill(PyObject *list, PyObject *value) { - uint tot = PyList_GET_SIZE(list); + const uint tot = PyList_GET_SIZE(list); uint i; for (i = 0; i < tot; i++) { @@ -377,7 +377,7 @@ void PyC_StackSpit(void) } /* lame but handy */ - PyGILState_STATE gilstate = PyGILState_Ensure(); + const PyGILState_STATE gilstate = PyGILState_Ensure(); PyRun_SimpleString("__import__('traceback').print_stack()"); PyGILState_Release(gilstate); } @@ -948,7 +948,7 @@ void PyC_RunQuicky(const char *filepath, int n, ...) FILE *fp = fopen(filepath, "r"); if (fp) { - PyGILState_STATE gilstate = PyGILState_Ensure(); + const PyGILState_STATE gilstate = PyGILState_Ensure(); va_list vargs; @@ -1423,7 +1423,7 @@ bool PyC_RunString_AsString(const char *imports[], */ int PyC_Long_AsBool(PyObject *value) { - int test = _PyLong_AsInt(value); + const int test = _PyLong_AsInt(value); if (UNLIKELY((uint)test > 1)) { PyErr_SetString(PyExc_TypeError, "Python number not a bool (0/1)"); return -1; @@ -1433,7 +1433,7 @@ int PyC_Long_AsBool(PyObject *value) int8_t PyC_Long_AsI8(PyObject *value) { - int test = _PyLong_AsInt(value); + const int test = _PyLong_AsInt(value); if (UNLIKELY(test < INT8_MIN || test > INT8_MAX)) { PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C int8"); return -1; @@ -1443,7 +1443,7 @@ int8_t PyC_Long_AsI8(PyObject *value) int16_t PyC_Long_AsI16(PyObject *value) { - int test = _PyLong_AsInt(value); + const int test = _PyLong_AsInt(value); if (UNLIKELY(test < INT16_MIN || test > INT16_MAX)) { PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C int16"); return -1; @@ -1458,7 +1458,7 @@ int16_t PyC_Long_AsI16(PyObject *value) uint8_t PyC_Long_AsU8(PyObject *value) { - ulong test = PyLong_AsUnsignedLong(value); + const ulong test = PyLong_AsUnsignedLong(value); if (UNLIKELY(test > UINT8_MAX)) { PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C uint8"); return (uint8_t)-1; @@ -1468,7 +1468,7 @@ uint8_t PyC_Long_AsU8(PyObject *value) uint16_t PyC_Long_AsU16(PyObject *value) { - ulong test = PyLong_AsUnsignedLong(value); + const ulong test = PyLong_AsUnsignedLong(value); if (UNLIKELY(test > UINT16_MAX)) { PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C uint16"); return (uint16_t)-1; @@ -1478,7 +1478,7 @@ uint16_t PyC_Long_AsU16(PyObject *value) uint32_t PyC_Long_AsU32(PyObject *value) { - ulong test = PyLong_AsUnsignedLong(value); + const ulong test = PyLong_AsUnsignedLong(value); if (UNLIKELY(test > UINT32_MAX)) { PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C uint32"); return (uint32_t)-1; diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c index c1a6ce09d37..f9ff0558570 100644 --- a/source/blender/python/gpu/gpu_py_shader.c +++ b/source/blender/python/gpu/gpu_py_shader.c @@ -78,7 +78,7 @@ static int bpygpu_uniform_location_get(GPUShader *shader, const char *name, const char *error_prefix) { - int uniform = GPU_shader_get_uniform(shader, name); + const int uniform = GPU_shader_get_uniform(shader, name); if (uniform == -1) { PyErr_Format(PyExc_ValueError, "%s: uniform %.32s not found", error_prefix, name); @@ -158,7 +158,7 @@ static PyObject *bpygpu_shader_uniform_from_name(BPyGPUShader *self, PyObject *a return NULL; } - int uniform = bpygpu_uniform_location_get(self->shader, name, "GPUShader.get_uniform"); + const int uniform = bpygpu_uniform_location_get(self->shader, name, "GPUShader.get_uniform"); if (uniform == -1) { return NULL; @@ -184,7 +184,7 @@ static PyObject *bpygpu_shader_uniform_block_from_name(BPyGPUShader *self, PyObj return NULL; } - int uniform = GPU_shader_get_uniform_block(self->shader, name); + const int uniform = GPU_shader_get_uniform_block(self->shader, name); if (uniform == -1) { PyErr_Format(PyExc_ValueError, "GPUShader.get_uniform_block: uniform %.32s not found", name); @@ -504,7 +504,7 @@ static PyObject *bpygpu_shader_attr_from_name(BPyGPUShader *self, PyObject *arg) return NULL; } - int attr = GPU_shader_get_attribute(self->shader, name); + const int attr = GPU_shader_get_attribute(self->shader, name); if (attr == -1) { PyErr_Format(PyExc_ValueError, "GPUShader.attr_from_name: attribute %.32s not found", name); diff --git a/source/blender/python/gpu/gpu_py_vertex_buffer.c b/source/blender/python/gpu/gpu_py_vertex_buffer.c index 57290fdc3c4..9372770e45e 100644 --- a/source/blender/python/gpu/gpu_py_vertex_buffer.c +++ b/source/blender/python/gpu/gpu_py_vertex_buffer.c @@ -134,7 +134,7 @@ static bool bpygpu_vertbuf_fill_impl(GPUVertBuf *vbo, return false; } - uint comp_len = pybuffer.ndim == 1 ? 1 : (uint)pybuffer.shape[1]; + const uint comp_len = pybuffer.ndim == 1 ? 1 : (uint)pybuffer.shape[1]; if (pybuffer.shape[0] != vbo->vertex_len) { PyErr_Format( diff --git a/source/blender/python/gpu/gpu_py_vertex_format.c b/source/blender/python/gpu/gpu_py_vertex_format.c index d8266be7e2c..1cbcaba6bfb 100644 --- a/source/blender/python/gpu/gpu_py_vertex_format.c +++ b/source/blender/python/gpu/gpu_py_vertex_format.c @@ -112,7 +112,7 @@ static int bpygpu_ParseVertCompType(PyObject *o, void *p) return 0; } - int comp_type = bpygpu_parse_component_type(str, length); + const int comp_type = bpygpu_parse_component_type(str, length); if (comp_type == -1) { PyErr_Format(PyExc_ValueError, "unknown component type: '%s", str); return 0; @@ -132,7 +132,7 @@ static int bpygpu_ParseVertFetchMode(PyObject *o, void *p) return 0; } - int fetch_mode = bpygpu_parse_fetch_mode(str, length); + const int fetch_mode = bpygpu_parse_fetch_mode(str, length); if (fetch_mode == -1) { PyErr_Format(PyExc_ValueError, "unknown type literal: '%s'", str); return 0; diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index 4ee936aff91..f0de05f95b3 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -343,7 +343,7 @@ static PyObject *bpy_app_debug_value_get(PyObject *UNUSED(self), void *UNUSED(cl static int bpy_app_debug_value_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure)) { - short param = PyC_Long_AsI16(value); + const short param = PyC_Long_AsI16(value); if (param == -1 && PyErr_Occurred()) { PyC_Err_SetString_Prefix(PyExc_TypeError, diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index cdbd3bc0b9c..a874e23ff32 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -318,7 +318,7 @@ void bpy_app_generic_callback(struct Main *UNUSED(main), { PyObject *cb_list = py_cb_array[POINTER_AS_INT(arg)]; if (PyList_GET_SIZE(cb_list) > 0) { - PyGILState_STATE gilstate = PyGILState_Ensure(); + const PyGILState_STATE gilstate = PyGILState_Ensure(); const int num_arguments = 2; PyObject *args_all = PyTuple_New(num_arguments); /* save python creating each call */ diff --git a/source/blender/python/intern/bpy_app_icons.c b/source/blender/python/intern/bpy_app_icons.c index 2e688609961..7cca3ae4700 100644 --- a/source/blender/python/intern/bpy_app_icons.c +++ b/source/blender/python/intern/bpy_app_icons.c @@ -71,8 +71,8 @@ static PyObject *bpy_app_icons_new_triangles(PyObject *UNUSED(self), PyObject *a return NULL; } - int coords_size = sizeof(uchar[2]) * tris_len * 3; - int colors_size = sizeof(uchar[4]) * tris_len * 3; + const int coords_size = sizeof(uchar[2]) * tris_len * 3; + const int colors_size = sizeof(uchar[4]) * tris_len * 3; uchar(*coords)[2] = MEM_mallocN(coords_size, __func__); uchar(*colors)[4] = MEM_mallocN(colors_size, __func__); @@ -86,7 +86,7 @@ static PyObject *bpy_app_icons_new_triangles(PyObject *UNUSED(self), PyObject *a geom->coords = coords; geom->colors = colors; geom->icon_id = 0; - int icon_id = BKE_icon_geom_ensure(geom); + const int icon_id = BKE_icon_geom_ensure(geom); return PyLong_FromLong(icon_id); } @@ -117,7 +117,7 @@ static PyObject *bpy_app_icons_new_triangles_from_file(PyObject *UNUSED(self), PyErr_SetString(PyExc_ValueError, "Unable to load from file"); return NULL; } - int icon_id = BKE_icon_geom_ensure(geom); + const int icon_id = BKE_icon_geom_ensure(geom); return PyLong_FromLong(icon_id); } diff --git a/source/blender/python/intern/bpy_app_opensubdiv.c b/source/blender/python/intern/bpy_app_opensubdiv.c index 3f14c4dca57..09cd6201831 100644 --- a/source/blender/python/intern/bpy_app_opensubdiv.c +++ b/source/blender/python/intern/bpy_app_opensubdiv.c @@ -63,7 +63,7 @@ static PyObject *make_opensubdiv_info(void) #define SetObjItem(obj) PyStructSequence_SET_ITEM(opensubdiv_info, pos++, obj) #ifdef WITH_OPENSUBDIV - int curversion = openSubdiv_getVersionHex(); + const int curversion = openSubdiv_getVersionHex(); SetObjItem(PyBool_FromLong(1)); SetObjItem(PyC_Tuple_Pack_I32(curversion / 10000, (curversion / 100) % 100, curversion % 100)); SetObjItem(PyUnicode_FromFormat( diff --git a/source/blender/python/intern/bpy_app_timers.c b/source/blender/python/intern/bpy_app_timers.c index f1dd8b9e803..af299952b72 100644 --- a/source/blender/python/intern/bpy_app_timers.c +++ b/source/blender/python/intern/bpy_app_timers.c @@ -65,7 +65,7 @@ static double py_timer_execute(uintptr_t UNUSED(uuid), void *user_data) gilstate = PyGILState_Ensure(); PyObject *py_ret = PyObject_CallObject(function, NULL); - double ret = handle_returned_value(function, py_ret); + const double ret = handle_returned_value(function, py_ret); PyGILState_Release(gilstate); @@ -151,7 +151,7 @@ PyDoc_STRVAR(bpy_app_timers_is_registered_doc, " :rtype: bool\n"); static PyObject *bpy_app_timers_is_registered(PyObject *UNUSED(self), PyObject *function) { - bool ret = BLI_timer_is_registered((intptr_t)function); + const bool ret = BLI_timer_is_registered((intptr_t)function); return PyBool_FromLong(ret); } diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c index c152c920453..f95261df6b2 100644 --- a/source/blender/python/intern/bpy_app_translations.c +++ b/source/blender/python/intern/bpy_app_translations.c @@ -92,7 +92,7 @@ static GHashKey *_ghashutil_keyalloc(const void *msgctxt, const void *msgid) static uint _ghashutil_keyhash(const void *ptr) { const GHashKey *key = ptr; - uint hash = BLI_ghashutil_strhash(key->msgctxt); + const uint hash = BLI_ghashutil_strhash(key->msgctxt); return hash ^ BLI_ghashutil_strhash(key->msgid); } diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index 7fb4b0c469c..4ef685b7987 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -228,7 +228,7 @@ static void bpy_pydriver_namespace_clear_self(void) void BPY_driver_reset(void) { PyGILState_STATE gilstate; - bool use_gil = true; /* !PyC_IsInterpreterActive(); */ + const bool use_gil = true; /* !PyC_IsInterpreterActive(); */ if (use_gil) { gilstate = PyGILState_Ensure(); @@ -594,7 +594,7 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, #endif { /* try to get variable value */ - float tval = driver_get_variable_value(driver, dvar); + const float tval = driver_get_variable_value(driver, dvar); driver_arg = PyFloat_FromDouble((double)tval); } diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index b0b36baa839..bc7318e1a15 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -169,7 +169,7 @@ void BPY_text_free_code(Text *text) { if (text->compiled) { PyGILState_STATE gilstate; - bool use_gil = !PyC_IsInterpreterActive(); + const bool use_gil = !PyC_IsInterpreterActive(); if (use_gil) { gilstate = PyGILState_Ensure(); @@ -446,14 +446,14 @@ void BPY_python_backtrace(FILE *fp) void BPY_DECREF(void *pyob_ptr) { - PyGILState_STATE gilstate = PyGILState_Ensure(); + const PyGILState_STATE gilstate = PyGILState_Ensure(); Py_DECREF((PyObject *)pyob_ptr); PyGILState_Release(gilstate); } void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr) { - PyGILState_STATE gilstate = PyGILState_Ensure(); + const PyGILState_STATE gilstate = PyGILState_Ensure(); const int do_invalidate = (Py_REFCNT((PyObject *)pyob_ptr) > 1); Py_DECREF((PyObject *)pyob_ptr); if (do_invalidate) { @@ -509,7 +509,7 @@ void BPY_modules_load_user(bContext *C) int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *result) { PyGILState_STATE gilstate; - bool use_gil = !PyC_IsInterpreterActive(); + const bool use_gil = !PyC_IsInterpreterActive(); PyObject *pyctx; PyObject *item; @@ -544,7 +544,7 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult * PyErr_Clear(); } else { - int len = PySequence_Fast_GET_SIZE(seq_fast); + const int len = PySequence_Fast_GET_SIZE(seq_fast); PyObject **seq_fast_items = PySequence_Fast_ITEMS(seq_fast); int i; diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c index bcf13b1d88f..bdad4d03ae7 100644 --- a/source/blender/python/intern/bpy_library_load.c +++ b/source/blender/python/intern/bpy_library_load.c @@ -321,7 +321,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) { Main *bmain = CTX_data_main(BPy_GetContext()); Main *mainl = NULL; - int err = 0; + const int err = 0; const bool do_append = ((self->flag & FILE_LINK) == 0); BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true); @@ -338,7 +338,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) // printf("lib: %s\n", name_plural); if (ls && PyList_Check(ls)) { /* loop */ - Py_ssize_t size = PyList_GET_SIZE(ls); + const Py_ssize_t size = PyList_GET_SIZE(ls); Py_ssize_t i; for (i = 0; i < size; i++) { @@ -423,7 +423,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) const char *name_plural = BKE_idtype_idcode_to_name_plural(idcode); PyObject *ls = PyDict_GetItemString(self->dict, name_plural); if (ls && PyList_Check(ls)) { - Py_ssize_t size = PyList_GET_SIZE(ls); + const Py_ssize_t size = PyList_GET_SIZE(ls); Py_ssize_t i; PyObject *item; diff --git a/source/blender/python/intern/bpy_msgbus.c b/source/blender/python/intern/bpy_msgbus.c index 45c5aba1e3e..3739f56dc79 100644 --- a/source/blender/python/intern/bpy_msgbus.c +++ b/source/blender/python/intern/bpy_msgbus.c @@ -192,7 +192,7 @@ static void bpy_msgbus_notify(bContext *C, static void bpy_msgbus_subscribe_value_free_data(struct wmMsgSubscribeKey *UNUSED(msg_key), struct wmMsgSubscribeValue *msg_val) { - PyGILState_STATE gilstate = PyGILState_Ensure(); + const PyGILState_STATE gilstate = PyGILState_Ensure(); Py_DECREF(msg_val->owner); Py_DECREF(msg_val->user_data); PyGILState_Release(gilstate); diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 66c67ca061c..859f0027f14 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -351,7 +351,7 @@ static bool bpy_prop_boolean_get_cb(struct PointerRNA *ptr, struct PropertyRNA * value = false; } else { - int value_i = PyC_Long_AsBool(ret); + const int value_i = PyC_Long_AsBool(ret); if (value_i == -1 && PyErr_Occurred()) { PyC_Err_PrintWithFunc(py_func); @@ -443,7 +443,7 @@ static bool bpy_prop_poll_cb(struct PointerRNA *self, PyObject *ret; bool result; const int is_write_ok = pyrna_write_check(); - PyGILState_STATE gilstate = PyGILState_Ensure(); + const PyGILState_STATE gilstate = PyGILState_Ensure(); BLI_assert(self != NULL); @@ -560,7 +560,7 @@ static void bpy_prop_boolean_array_set_cb(struct PointerRNA *ptr, PyGILState_STATE gilstate; bool use_gil; const bool is_write_ok = pyrna_write_check(); - int len = RNA_property_array_length(ptr, prop); + const int len = RNA_property_array_length(ptr, prop); BLI_assert(py_data != NULL); @@ -804,7 +804,7 @@ static void bpy_prop_int_array_set_cb(struct PointerRNA *ptr, PyGILState_STATE gilstate; bool use_gil; const bool is_write_ok = pyrna_write_check(); - int len = RNA_property_array_length(ptr, prop); + const int len = RNA_property_array_length(ptr, prop); BLI_assert(py_data != NULL); @@ -1048,7 +1048,7 @@ static void bpy_prop_float_array_set_cb(struct PointerRNA *ptr, PyGILState_STATE gilstate; bool use_gil; const bool is_write_ok = pyrna_write_check(); - int len = RNA_property_array_length(ptr, prop); + const int len = RNA_property_array_length(ptr, prop); BLI_assert(py_data != NULL); diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 955a24bc880..a3ded8813ac 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -464,7 +464,7 @@ static int mathutils_rna_vector_set(BaseMathObject *bmo, int subtype) if (subtype == MATHUTILS_CB_SUBTYPE_EUL) { EulerObject *eul = (EulerObject *)bmo; PropertyRNA *prop_eul_order = NULL; - short order = pyrna_rotation_euler_order_get(&self->ptr, eul->order, &prop_eul_order); + const short order = pyrna_rotation_euler_order_get(&self->ptr, eul->order, &prop_eul_order); if (order != eul->order) { RNA_property_enum_set(&self->ptr, prop_eul_order, eul->order); if (RNA_property_update_check(prop_eul_order)) { @@ -599,7 +599,7 @@ static short pyrna_rotation_euler_order_get(PointerRNA *ptr, } if (*r_prop_eul_order) { - short order = RNA_property_enum_get(ptr, *r_prop_eul_order); + const short order = RNA_property_enum_get(ptr, *r_prop_eul_order); /* Could be quat or axisangle. */ if (order >= EULER_ORDER_XYZ && order <= EULER_ORDER_ZYX) { return order; @@ -714,7 +714,8 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) /* Attempt to get order, * only needed for thick types since wrapped with update via callbacks. */ PropertyRNA *prop_eul_order = NULL; - short order = pyrna_rotation_euler_order_get(ptr, EULER_ORDER_XYZ, &prop_eul_order); + const short order = pyrna_rotation_euler_order_get( + ptr, EULER_ORDER_XYZ, &prop_eul_order); ret = Euler_CreatePyObject(NULL, order, NULL); /* TODO, get order from RNA. */ RNA_property_float_get_array(ptr, prop, ((EulerObject *)ret)->eul); @@ -1725,7 +1726,7 @@ static int pyrna_py_to_prop( } case PROP_INT: { int overflow; - long param = PyLong_AsLongAndOverflow(value, &overflow); + const long param = PyLong_AsLongAndOverflow(value, &overflow); if (overflow || (param > INT_MAX) || (param < INT_MIN)) { PyErr_Format(PyExc_ValueError, "%.200s %.200s.%.200s value not in 'int' range " @@ -1757,7 +1758,7 @@ static int pyrna_py_to_prop( break; } case PROP_FLOAT: { - float param = PyFloat_AsDouble(value); + const float param = PyFloat_AsDouble(value); if (PyErr_Occurred()) { PyErr_Format(PyExc_TypeError, "%.200s %.200s.%.200s expected a float type, not %.200s", @@ -1935,8 +1936,8 @@ static int pyrna_py_to_prop( PyObject *value_new = NULL; StructRNA *ptr_type = RNA_property_pointer_type(ptr, prop); - int flag = RNA_property_flag(prop); - int flag_parameter = RNA_parameter_flag(prop); + const int flag = RNA_property_flag(prop); + const int flag_parameter = RNA_parameter_flag(prop); /* This is really nasty! Done so we can fake the operator having direct properties, eg: * layout.prop(self, "filepath") @@ -2075,7 +2076,7 @@ static int pyrna_py_to_prop( BKE_reports_init(&reports, RPT_STORE); RNA_property_pointer_set( ptr, prop, value == Py_None ? PointerRNA_NULL : param->ptr, &reports); - int err = (BPy_reports_to_error(&reports, PyExc_RuntimeError, true)); + const int err = (BPy_reports_to_error(&reports, PyExc_RuntimeError, true)); if (err == -1) { Py_XDECREF(value_new); return -1; @@ -2233,7 +2234,7 @@ static int pyrna_py_to_prop_array_index(BPy_PropertyArrayRNA *self, int index, P /* See if we can coerce into a Python type - 'PropertyType'. */ switch (RNA_property_type(prop)) { case PROP_BOOLEAN: { - int param = PyC_Long_AsBool(value); + const int param = PyC_Long_AsBool(value); if (param == -1) { /* Error is set. */ @@ -2698,7 +2699,7 @@ static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject return pyrna_prop_collection_subscript_str(self, _PyUnicode_AsString(key)); } if (PyIndex_Check(key)) { - Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); + const Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) { return NULL; } @@ -2732,7 +2733,7 @@ static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject if (start < 0 || stop < 0) { /* Only get the length for negative values. */ - Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop); + const Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop); if (start < 0) { start += len; } @@ -2827,7 +2828,7 @@ static int pyrna_prop_collection_ass_subscript(BPy_PropertyRNA *self, else #endif if (PyIndex_Check(key)) { - Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); + const Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) { return -1; } @@ -2899,7 +2900,7 @@ static PyObject *pyrna_prop_array_subscript(BPy_PropertyArrayRNA *self, PyObject else #endif if (PyIndex_Check(key)) { - Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); + const Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) { return NULL; } @@ -2919,11 +2920,11 @@ static PyObject *pyrna_prop_array_subscript(BPy_PropertyArrayRNA *self, PyObject if (key_slice->start == Py_None && key_slice->stop == Py_None) { /* Note: no significant advantage with optimizing [:] slice as with collections, * but include here for consistency with collection slice func */ - Py_ssize_t len = (Py_ssize_t)pyrna_prop_array_length(self); + const Py_ssize_t len = (Py_ssize_t)pyrna_prop_array_length(self); return pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, 0, len, len); } - int len = pyrna_prop_array_length(self); + const int len = pyrna_prop_array_length(self); Py_ssize_t start, stop, slicelength; if (PySlice_GetIndicesEx(key, len, &start, &stop, &step, &slicelength) < 0) { @@ -3055,7 +3056,7 @@ static int prop_subscript_ass_array_slice__bool_recursive(PyObject **value_items BLI_assert(totdim == 1); int i; for (i = 0; i != length; i++) { - int v = PyLong_AsLong(value_items[i]); + const int v = PyLong_AsLong(value_items[i]); value[i] = v; } return i; @@ -3097,7 +3098,7 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, } int dimsize[3]; - int totdim = RNA_property_array_dimension(ptr, prop, dimsize); + const int totdim = RNA_property_array_dimension(ptr, prop, dimsize); if (totdim > 1) { BLI_assert(dimsize[arraydim] == length); } @@ -3247,7 +3248,7 @@ static int pyrna_prop_array_ass_subscript(BPy_PropertyArrayRNA *self, } else if (PyIndex_Check(key)) { - Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); + const Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) { ret = -1; } @@ -3256,7 +3257,7 @@ static int pyrna_prop_array_ass_subscript(BPy_PropertyArrayRNA *self, } } else if (PySlice_Check(key)) { - Py_ssize_t len = pyrna_prop_array_length(self); + const Py_ssize_t len = pyrna_prop_array_length(self); Py_ssize_t start, stop, step, slicelength; if (PySlice_GetIndicesEx(key, len, &start, &stop, &step, &slicelength) < 0) { @@ -4249,7 +4250,7 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) ListBase newlb; short newtype; - int done = CTX_data_get(C, name, &newptr, &newlb, &newtype); + const int done = CTX_data_get(C, name, &newptr, &newlb, &newtype); if (done == 1) { /* Found. */ switch (newtype) { @@ -4401,7 +4402,7 @@ static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *attr, PyOb if (value) { /* Check if the value is a property. */ if (is_deferred_prop) { - int ret = deferred_register_prop(srna, attr, value); + const int ret = deferred_register_prop(srna, attr, value); if (ret == -1) { /* Error set. */ return ret; @@ -4471,7 +4472,7 @@ static int pyrna_struct_setattro(BPy_StructRNA *self, PyObject *pyname, PyObject ListBase newlb; short newtype; - int done = CTX_data_get(C, name, &newptr, &newlb, &newtype); + const int done = CTX_data_get(C, name, &newptr, &newlb, &newtype); if (done == 1) { PyErr_Format( @@ -4646,7 +4647,7 @@ static PyObject *pyrna_prop_collection_idprop_add(BPy_PropertyRNA *self) static PyObject *pyrna_prop_collection_idprop_remove(BPy_PropertyRNA *self, PyObject *value) { - int key = PyLong_AsLong(value); + const int key = PyLong_AsLong(value); #ifdef USE_PEDANTIC_WRITE if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { @@ -5172,7 +5173,7 @@ static int foreach_parse_args(BPy_PropertyRNA *self, static bool foreach_compat_buffer(RawPropertyType raw_type, int attr_signed, const char *format) { - char f = format ? *format : 'B'; /* B is assumed when not set */ + const char f = format ? *format : 'B'; /* B is assumed when not set */ switch (raw_type) { case PROP_RAW_CHAR: @@ -5400,7 +5401,7 @@ static PyObject *pyprop_array_foreach_getset(BPy_PropertyArrayRNA *self, PyObject *item = NULL; Py_ssize_t i, seq_size, size; void *array = NULL; - PropertyType prop_type = RNA_property_type(self->prop); + const PropertyType prop_type = RNA_property_type(self->prop); /* Get/set both take the same args currently. */ PyObject *seq; @@ -5498,7 +5499,7 @@ static PyObject *pyprop_array_foreach_getset(BPy_PropertyArrayRNA *self, } } else { - char f = buf.format ? buf.format[0] : 0; + const char f = buf.format ? buf.format[0] : 0; if ((prop_type == PROP_INT && (buf.itemsize != sizeof(int) || (f != 'l' && f != 'i'))) || (prop_type == PROP_FLOAT && (buf.itemsize != sizeof(float) || f != 'f'))) { PyBuffer_Release(&buf); @@ -8030,7 +8031,7 @@ static int rna_function_arg_count(FunctionRNA *func, int *min_count) const ListBase *lb = RNA_function_defined_parameters(func); PropertyRNA *parm; Link *link; - int flag = RNA_function_flag(func); + const int flag = RNA_function_flag(func); const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); int count = is_staticmethod ? 0 : 1; bool done_min_count = false; @@ -8273,7 +8274,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param ParameterIterator iter; PointerRNA funcptr; int err = 0, i, ret_len = 0, arg_count; - int flag = RNA_function_flag(func); + const int flag = RNA_function_flag(func); const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); const bool is_classmethod = (flag & FUNC_NO_SELF) && (flag & FUNC_USE_SELF_TYPE); @@ -9015,7 +9016,7 @@ void pyrna_struct_type_extend_capi(struct StructRNA *srna, py_method = PyCFunction_New(method, NULL); } - int err = PyDict_SetItemString(dict, method->ml_name, py_method); + const int err = PyDict_SetItemString(dict, method->ml_name, py_method); Py_DECREF(py_method); BLI_assert(!(err < 0)); UNUSED_VARS_NDEBUG(err); diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c index ae19f89c348..1d52706c5f9 100644 --- a/source/blender/python/intern/bpy_rna_anim.c +++ b/source/blender/python/intern/bpy_rna_anim.c @@ -131,7 +131,7 @@ static int pyrna_struct_anim_args_parse_ex(PointerRNA *ptr, } } else { - int array_len = RNA_property_array_length(&r_ptr, prop); + const int array_len = RNA_property_array_length(&r_ptr, prop); if ((*r_index) < -1 || (*r_index) >= array_len) { PyErr_Format(PyExc_TypeError, "%.200s index out of range \"%s\", given %d, array length is %d", @@ -316,7 +316,7 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb int index = -1; float cfra = FLT_MAX; const char *group_name = NULL; - char keytype = BEZT_KEYTYPE_KEYFRAME; /* XXX: Expose this as a one-off option... */ + const char keytype = BEZT_KEYTYPE_KEYFRAME; /* XXX: Expose this as a one-off option... */ int options = 0; PYRNA_STRUCT_CHECK_OBJ(self); diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c index 66e07d556a6..cb3fe9cb600 100644 --- a/source/blender/python/intern/bpy_rna_array.c +++ b/source/blender/python/intern/bpy_rna_array.c @@ -361,7 +361,7 @@ static int validate_array(PyObject *rvalue, const char *error_prefix) { int dimsize[MAX_ARRAY_DIMENSION]; - int totdim = RNA_property_array_dimension(ptr, prop, dimsize); + const int totdim = RNA_property_array_dimension(ptr, prop, dimsize); /* validate type first because length validation may modify property array length */ @@ -466,7 +466,7 @@ static char *copy_values(PyObject *seq, const ItemConvert_FuncArg *convert_item, RNA_SetIndexFunc rna_set_index) { - int totdim = RNA_property_array_dimension(ptr, prop, NULL); + const int totdim = RNA_property_array_dimension(ptr, prop, NULL); const Py_ssize_t seq_size = PySequence_Size(seq); Py_ssize_t i; @@ -487,7 +487,7 @@ static char *copy_values(PyObject *seq, if (dim == 0) { if (MatrixObject_Check(seq)) { MatrixObject *pymat = (MatrixObject *)seq; - size_t allocsize = pymat->num_col * pymat->num_row * sizeof(float); + const size_t allocsize = pymat->num_col * pymat->num_row * sizeof(float); /* read callback already done by validate */ /* since this is the first iteration we can assume data is allocated */ @@ -993,7 +993,7 @@ PyObject *pyrna_py_from_array(PointerRNA *ptr, PropertyRNA *prop) /* TODO, multi-dimensional arrays */ int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value) { - int len = RNA_property_array_length(ptr, prop); + const int len = RNA_property_array_length(ptr, prop); int type; int i; @@ -1011,7 +1011,7 @@ int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value) switch (type) { case PROP_FLOAT: { - float value_f = PyFloat_AsDouble(value); + const float value_f = PyFloat_AsDouble(value); if (value_f == -1 && PyErr_Occurred()) { PyErr_Clear(); return 0; @@ -1044,7 +1044,7 @@ int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value) break; } case PROP_INT: { - int value_i = PyC_Long_AsI32(value); + const int value_i = PyC_Long_AsI32(value); if (value_i == -1 && PyErr_Occurred()) { PyErr_Clear(); return 0; @@ -1077,7 +1077,7 @@ int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value) break; } case PROP_BOOLEAN: { - int value_i = PyC_Long_AsBool(value); + const int value_i = PyC_Long_AsBool(value); if (value_i == -1 && PyErr_Occurred()) { PyErr_Clear(); return 0; diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c index 976b8a65ac7..2f8be0c44e0 100644 --- a/source/blender/python/intern/bpy_rna_callback.c +++ b/source/blender/python/intern/bpy_rna_callback.c @@ -84,7 +84,7 @@ static void cb_region_draw(const bContext *C, ARegion *UNUSED(region), void *cus static PyObject *PyC_Tuple_CopySized(PyObject *src, int len_dst) { PyObject *dst = PyTuple_New(len_dst); - int len_src = PyTuple_GET_SIZE(src); + const int len_src = PyTuple_GET_SIZE(src); BLI_assert(len_src <= len_dst); for (int i = 0; i < len_src; i++) { PyObject *item = PyTuple_GET_ITEM(src, i); diff --git a/source/blender/python/intern/bpy_rna_driver.c b/source/blender/python/intern/bpy_rna_driver.c index 9240e34bbab..3bddd0ad8c0 100644 --- a/source/blender/python/intern/bpy_rna_driver.c +++ b/source/blender/python/intern/bpy_rna_driver.c @@ -57,7 +57,7 @@ PyObject *pyrna_driver_get_variable_value(struct ChannelDriver *driver, struct D } else { /* object & property */ - PropertyType type = RNA_property_type(prop); + const PropertyType type = RNA_property_type(prop); if (type == PROP_ENUM) { /* Note that enum's are converted to strings by default, * we want to avoid that, see: T52213 */ diff --git a/source/blender/python/intern/bpy_rna_gizmo.c b/source/blender/python/intern/bpy_rna_gizmo.c index 4ef718ef023..575824e8a86 100644 --- a/source/blender/python/intern/bpy_rna_gizmo.c +++ b/source/blender/python/intern/bpy_rna_gizmo.c @@ -63,7 +63,7 @@ static void py_rna_gizmo_handler_get_cb(const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop, void *value_p) { - PyGILState_STATE gilstate = PyGILState_Ensure(); + const PyGILState_STATE gilstate = PyGILState_Ensure(); struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data; PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_GIZMO_FN_SLOT_GET], NULL); @@ -110,7 +110,7 @@ static void py_rna_gizmo_handler_set_cb(const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop, const void *value_p) { - PyGILState_STATE gilstate = PyGILState_Ensure(); + const PyGILState_STATE gilstate = PyGILState_Ensure(); struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data; @@ -159,7 +159,7 @@ static void py_rna_gizmo_handler_range_get_cb(const wmGizmo *UNUSED(gz), { struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data; - PyGILState_STATE gilstate = PyGILState_Ensure(); + const PyGILState_STATE gilstate = PyGILState_Ensure(); PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_GIZMO_FN_SLOT_RANGE_GET], NULL); if (ret == NULL) { @@ -211,7 +211,7 @@ static void py_rna_gizmo_handler_free_cb(const wmGizmo *UNUSED(gz), wmGizmoPrope { struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data; - PyGILState_STATE gilstate = PyGILState_Ensure(); + const PyGILState_STATE gilstate = PyGILState_Ensure(); for (int i = 0; i < BPY_GIZMO_FN_SLOT_LEN; i++) { Py_XDECREF(data->fn_slots[i]); } @@ -234,7 +234,7 @@ PyDoc_STRVAR( " :type range: callable\n"); static PyObject *bpy_gizmo_target_set_handler(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - PyGILState_STATE gilstate = PyGILState_Ensure(); + const PyGILState_STATE gilstate = PyGILState_Ensure(); struct { PyObject *self; @@ -368,7 +368,7 @@ static PyObject *bpy_gizmo_target_get_value(PyObject *UNUSED(self), PyObject *ar return PyC_Tuple_PackArray_F32(value, array_len); } - float value = WM_gizmo_target_property_float_get(gz, gz_prop); + const float value = WM_gizmo_target_property_float_get(gz, gz_prop); return PyFloat_FromDouble(value); break; diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c index 308d2ef9618..ca38d7008f6 100644 --- a/source/blender/python/mathutils/mathutils.c +++ b/source/blender/python/mathutils/mathutils.c @@ -208,7 +208,7 @@ int mathutils_array_parse( if (size != -1) { if (flag & MU_ARRAY_ZERO) { - int size_left = array_max - size; + const int size_left = array_max - size; if (size_left) { memset(&array[size], 0, sizeof(float) * size_left); } @@ -541,9 +541,9 @@ int EXPP_FloatsAreEqual(float af, float bf, int maxDiff) { /* solid, fast routine across all platforms * with constant time behavior */ - int ai = *(int *)(&af); - int bi = *(int *)(&bf); - int test = SIGNMASK(ai ^ bi); + const int ai = *(int *)(&af); + const int bi = *(int *)(&bf); + const int test = SIGNMASK(ai ^ bi); int diff, v1, v2; assert((0 == test) || (0xFFFFFFFF == test)); diff --git a/source/blender/python/mathutils/mathutils_Color.c b/source/blender/python/mathutils/mathutils_Color.c index 6bffff467cd..8a7f782de3c 100644 --- a/source/blender/python/mathutils/mathutils_Color.c +++ b/source/blender/python/mathutils/mathutils_Color.c @@ -749,7 +749,7 @@ PyDoc_STRVAR(Color_channel_hsv_v_doc, "HSV Value component in [0, 1].\n\n:type: static PyObject *Color_channel_hsv_get(ColorObject *self, void *type) { float hsv[3]; - int i = POINTER_AS_INT(type); + const int i = POINTER_AS_INT(type); if (BaseMath_ReadCallback(self) == -1) { return NULL; @@ -763,7 +763,7 @@ static PyObject *Color_channel_hsv_get(ColorObject *self, void *type) static int Color_channel_hsv_set(ColorObject *self, PyObject *value, void *type) { float hsv[3]; - int i = POINTER_AS_INT(type); + const int i = POINTER_AS_INT(type); float f = PyFloat_AsDouble(value); if (f == -1 && PyErr_Occurred()) { diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index 236bb1de29d..0a524cbf24c 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -809,7 +809,7 @@ static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args) else { /* arbitrary plane */ - int vec_size = (matSize == 2 ? 2 : 3); + const int vec_size = (matSize == 2 ? 2 : 3); float tvec[4]; if (mathutils_array_parse(tvec, @@ -2156,7 +2156,8 @@ static PyObject *Matrix_str(MatrixObject *self) for (col = 0; col < self->num_col; col++) { maxsize[col] = 0; for (row = 0; row < self->num_row; row++) { - int size = BLI_snprintf(dummy_buf, sizeof(dummy_buf), "%.4f", MATRIX_ITEM(self, row, col)); + const int size = BLI_snprintf( + dummy_buf, sizeof(dummy_buf), "%.4f", MATRIX_ITEM(self, row, col)); maxsize[col] = max_ii(maxsize[col], size); } } diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index 3ee6e766413..9bc8c0dffed 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -356,7 +356,7 @@ PyDoc_STRVAR(Vector_normalize_doc, " however 4D Vectors w axis is left untouched.\n"); static PyObject *Vector_normalize(VectorObject *self) { - int size = (self->size == 4 ? 3 : self->size); + const int size = (self->size == 4 ? 3 : self->size); if (BaseMath_ReadCallback_ForWrite(self) == -1) { return NULL; } @@ -2027,7 +2027,7 @@ static PyObject *Vector_richcmpr(PyObject *objectA, PyObject *objectB, int compa { VectorObject *vecA = NULL, *vecB = NULL; int result = 0; - double epsilon = 0.000001f; + const double epsilon = 0.000001f; double lenA, lenB; if (!VectorObject_Check(objectA) || !VectorObject_Check(objectB)) { diff --git a/source/blender/python/mathutils/mathutils_bvhtree.c b/source/blender/python/mathutils/mathutils_bvhtree.c index 16ea05771d0..1d477421e30 100644 --- a/source/blender/python/mathutils/mathutils_bvhtree.c +++ b/source/blender/python/mathutils/mathutils_bvhtree.c @@ -589,7 +589,7 @@ static PyObject *py_bvhtree_overlap(PyBVHTree *self, PyBVHTree *other) /* pass */ } else { - bool use_unique = (self->orig_index || other->orig_index); + const bool use_unique = (self->orig_index || other->orig_index); GSet *pair_test = use_unique ? BLI_gset_new_ex(overlap_hash, overlap_cmp, __func__, overlap_len) : NULL; @@ -1037,7 +1037,7 @@ static Mesh *bvh_get_mesh(const char *funcname, { Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); /* we only need minimum mesh data for topology and vertex locations */ - CustomData_MeshMasks data_masks = CD_MASK_BAREMESH; + const CustomData_MeshMasks data_masks = CD_MASK_BAREMESH; const bool use_render = DEG_get_mode(depsgraph) == DAG_EVAL_RENDER; *r_free_mesh = false; diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c index f581b0bf471..1a161924f96 100644 --- a/source/blender/python/mathutils/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -315,7 +315,7 @@ static PyObject *M_Geometry_intersect_tri_tri_2d(PyObject *UNUSED(self), PyObjec } } - bool ret = isect_tri_tri_v2(UNPACK3(tri_pair[0]), UNPACK3(tri_pair[1])); + const bool ret = isect_tri_tri_v2(UNPACK3(tri_pair[0]), UNPACK3(tri_pair[1])); return PyBool_FromLong(ret); } @@ -492,7 +492,7 @@ static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObjec PyObject *py_line_a, *py_line_b, *py_plane_co, *py_plane_no; float line_a[3], line_b[3], plane_co[3], plane_no[3]; float isect[3]; - bool no_flip = false; + const bool no_flip = false; if (!PyArg_ParseTuple(args, "OOOO|O&:intersect_line_plane", diff --git a/source/blender/python/mathutils/mathutils_kdtree.c b/source/blender/python/mathutils/mathutils_kdtree.c index c3e66546dae..1de3c23838f 100644 --- a/source/blender/python/mathutils/mathutils_kdtree.c +++ b/source/blender/python/mathutils/mathutils_kdtree.c @@ -191,7 +191,7 @@ static int py_find_nearest_cb(void *user_data, int index, const float co[3], flo if (result) { bool use_node; - int ok = PyC_ParseBool(result, &use_node); + const int ok = PyC_ParseBool(result, &use_node); Py_DECREF(result); if (ok) { return (int)use_node; diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index efe600a846a..1dc45f58699 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -438,7 +438,10 @@ typedef struct wmNotifier { /* subtype 3d view editing */ #define NS_VIEW3D_GPU (16 << 8) -#define NS_VIEW3D_SHADING (16 << 9) +#define NS_VIEW3D_SHADING (17 << 8) + +/* subtype layer editing */ +#define NS_LAYER_COLLECTION (24 << 8) /* action classification */ #define NOTE_ACTION (0x000000FF) @@ -448,7 +451,8 @@ typedef struct wmNotifier { #define NA_REMOVED 4 #define NA_RENAME 5 #define NA_SELECTED 6 -#define NA_PAINTING 7 +#define NA_ACTIVATED 7 +#define NA_PAINTING 8 /* ************** Gesture Manager data ************** */ diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c index cecd324ff28..479768c3536 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c @@ -470,10 +470,10 @@ static void gizmos_draw_list(const wmGizmoMap *gzmap, const bContext *C, ListBas } else { if (is_depth) { - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } else { - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); } is_depth_prev = is_depth; } @@ -492,7 +492,7 @@ static void gizmos_draw_list(const wmGizmoMap *gzmap, const bContext *C, ListBas } if (is_depth_prev) { - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); } } @@ -534,10 +534,10 @@ static void gizmo_draw_select_3d_loop(const bContext *C, } else { if (is_depth) { - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } else { - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); } is_depth_prev = is_depth; } @@ -560,7 +560,7 @@ static void gizmo_draw_select_3d_loop(const bContext *C, } if (is_depth_prev) { - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); } if (is_depth_skip_prev) { GPU_depth_mask(true); diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index 67733ffc673..b245bbe054d 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -353,7 +353,7 @@ static void draw_filled_lasso(wmGesture *gt) draw_filled_lasso_px_cb, &lasso_fill_data); - GPU_blend(GPU_BLEND_ADDITIVE); + GPU_blend(GPU_BLEND_ADDITIVE_PREMULT); IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); GPU_shader_bind(state.shader); @@ -361,7 +361,7 @@ static void draw_filled_lasso(wmGesture *gt) state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red); immDrawPixelsTex( - &state, rect.xmin, rect.ymin, w, h, GL_R8, false, pixel_buf, 1.0f, 1.0f, NULL); + &state, rect.xmin, rect.ymin, w, h, GPU_R8, false, pixel_buf, 1.0f, 1.0f, NULL); GPU_shader_unbind(); |