diff --git a/source/blender/blenkernel/BKE_material.hh b/source/blender/blenkernel/BKE_material.hh index c8ee7d20b55..d455560507b 100644 --- a/source/blender/blenkernel/BKE_material.hh +++ b/source/blender/blenkernel/BKE_material.hh @@ -215,6 +215,11 @@ void ramp_blend(int type, float r_col[3], float fac, const float col[3]); /* -------------------------------------------------------------------- */ /** \name Default Materials + * + * TODO: Explain expected usages? Seems to be primarily defined for GPU/viewport code? + * + * \warning _NEVER_ use these materials as fallback data for regular ID data. They should only be + * used as template/copy source, or in some very specific, local and short-lived contexts. * \{ */ Material *BKE_material_default_empty(); diff --git a/source/blender/blenkernel/intern/grease_pencil.cc b/source/blender/blenkernel/intern/grease_pencil.cc index 81a0848c05c..dc3a65e8db0 100644 --- a/source/blender/blenkernel/intern/grease_pencil.cc +++ b/source/blender/blenkernel/intern/grease_pencil.cc @@ -2589,6 +2589,8 @@ Material *BKE_grease_pencil_object_material_ensure_from_brush(Main *bmain, } /* Fall back to default material. */ + /* XXX FIXME This is critical abuse of the 'default material' feature, these IDs should never be + * used/returned as 'regular' data. */ return BKE_material_default_gpencil(); } diff --git a/source/blender/blenkernel/intern/material.cc b/source/blender/blenkernel/intern/material.cc index 1325d92f6ca..1decbedc17e 100644 --- a/source/blender/blenkernel/intern/material.cc +++ b/source/blender/blenkernel/intern/material.cc @@ -88,8 +88,6 @@ static void material_init_data(ID *id) BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(material, id)); MEMCPY_STRUCT_AFTER(material, DNA_struct_default_get(Material), id); - - *((short *)id->name) = ID_MA; } static void material_copy_data(Main *bmain, @@ -937,6 +935,8 @@ Material *BKE_gpencil_material(Object *ob, short act) return ma; } + /* XXX FIXME This is critical abuse of the 'default material' feature, these IDs should never be + * used/returned as 'regular' data. */ return BKE_material_default_gpencil(); } @@ -2016,29 +2016,37 @@ void BKE_material_eval(Depsgraph *depsgraph, Material *material) * Used for rendering when objects have no materials assigned, and initializing * default shader nodes. */ -static Material default_material_empty; -static Material default_material_holdout; -static Material default_material_surface; -static Material default_material_volume; -static Material default_material_gpencil; +static Material *default_material_empty = nullptr; +static Material *default_material_holdout = nullptr; +static Material *default_material_surface = nullptr; +static Material *default_material_volume = nullptr; +static Material *default_material_gpencil = nullptr; -static Material *default_materials[] = {&default_material_empty, - &default_material_holdout, - &default_material_surface, - &default_material_volume, - &default_material_gpencil, - nullptr}; +static Material **default_materials[] = {&default_material_empty, + &default_material_holdout, + &default_material_surface, + &default_material_volume, + &default_material_gpencil, + nullptr}; -static void material_default_gpencil_init(Material *ma) +static Material *material_default_create(Material **ma_p, const char *name) { - BLI_strncpy(ma->id.name + 2, "Default GPencil", MAX_NAME); + *ma_p = static_cast( + BKE_libblock_alloc_in_lib(nullptr, std::nullopt, ID_MA, name, LIB_ID_CREATE_NO_MAIN)); + return *ma_p; +} + +static void material_default_gpencil_init(Material **ma_p) +{ + Material *ma = material_default_create(ma_p, "Default GPencil"); + BKE_gpencil_material_attr_init(ma); add_v3_fl(&ma->gp_style->stroke_rgba[0], 0.6f); } -static void material_default_surface_init(Material *ma) +static void material_default_surface_init(Material **ma_p) { - BLI_strncpy(ma->id.name + 2, "Default Surface", MAX_NAME); + Material *ma = material_default_create(ma_p, "Default Surface"); bNodeTree *ntree = blender::bke::node_tree_add_tree_embedded( nullptr, &ma->id, "Shader Nodetree", ntreeType_Shader->idname); @@ -2064,9 +2072,9 @@ static void material_default_surface_init(Material *ma) blender::bke::node_set_active(*ntree, *output); } -static void material_default_volume_init(Material *ma) +static void material_default_volume_init(Material **ma_p) { - BLI_strncpy(ma->id.name + 2, "Default Volume", MAX_NAME); + Material *ma = material_default_create(ma_p, "Default Volume"); bNodeTree *ntree = blender::bke::node_tree_add_tree_embedded( nullptr, &ma->id, "Shader Nodetree", ntreeType_Shader->idname); @@ -2090,9 +2098,9 @@ static void material_default_volume_init(Material *ma) blender::bke::node_set_active(*ntree, *output); } -static void material_default_holdout_init(Material *ma) +static void material_default_holdout_init(Material **ma_p) { - BLI_strncpy(ma->id.name + 2, "Default Holdout", MAX_NAME); + Material *ma = material_default_create(ma_p, "Default Holdout"); bNodeTree *ntree = blender::bke::node_tree_add_tree_embedded( nullptr, &ma->id, "Shader Nodetree", ntreeType_Shader->idname); @@ -2117,34 +2125,34 @@ static void material_default_holdout_init(Material *ma) Material *BKE_material_default_empty() { - return &default_material_empty; + return default_material_empty; } Material *BKE_material_default_holdout() { - return &default_material_holdout; + return default_material_holdout; } Material *BKE_material_default_surface() { - return &default_material_surface; + return default_material_surface; } Material *BKE_material_default_volume() { - return &default_material_volume; + return default_material_volume; } Material *BKE_material_default_gpencil() { - return &default_material_gpencil; + return default_material_gpencil; } void BKE_material_defaults_free_gpu() { for (int i = 0; default_materials[i]; i++) { - Material *ma = default_materials[i]; - if (ma->gpumaterial.first) { + Material *ma = *default_materials[i]; + if (ma && ma->gpumaterial.first) { GPU_material_free(&ma->gpumaterial); } } @@ -2155,13 +2163,12 @@ void BKE_material_defaults_free_gpu() void BKE_materials_init() { for (int i = 0; default_materials[i]; i++) { - /* Note: material_init_data() expects input struct to be initialized at zero. - * However, we are initializing global static materials in this function, which will only get - * properly defined in the respective material_default_*_init() functions. */ - memset(&default_materials[i]->id, 0, sizeof(Material)); - material_init_data(&default_materials[i]->id); + BLI_assert_msg(*default_materials[i] == nullptr, + "Default material pointers should always be null when initializing them, maybe " + "missing a call to `BKE_materials_exit` first?"); } + material_default_create(&default_material_empty, "Default Empty"); material_default_surface_init(&default_material_surface); material_default_volume_init(&default_material_volume); material_default_holdout_init(&default_material_holdout); @@ -2171,6 +2178,10 @@ void BKE_materials_init() void BKE_materials_exit() { for (int i = 0; default_materials[i]; i++) { - material_free_data(&default_materials[i]->id); + Material *ma = *default_materials[i]; + *default_materials[i] = nullptr; + if (ma) { + BKE_id_free(nullptr, &ma->id); + } } } diff --git a/source/blender/blenkernel/intern/pointcloud.cc b/source/blender/blenkernel/intern/pointcloud.cc index 4fcc0183b47..0cee2fa3517 100644 --- a/source/blender/blenkernel/intern/pointcloud.cc +++ b/source/blender/blenkernel/intern/pointcloud.cc @@ -284,9 +284,8 @@ PointCloud *BKE_pointcloud_add(Main *bmain, const char *name) PointCloud *BKE_pointcloud_add_default(Main *bmain, const char *name) { - PointCloud *pointcloud = static_cast(BKE_libblock_alloc(bmain, ID_PT, name, 0)); + PointCloud *pointcloud = static_cast(BKE_id_new(bmain, ID_PT, name)); - pointcloud_init_data(&pointcloud->id); pointcloud_random(pointcloud); return pointcloud; @@ -297,7 +296,7 @@ PointCloud *BKE_pointcloud_new_nomain(const int totpoint) PointCloud *pointcloud = static_cast(BKE_libblock_alloc( nullptr, ID_PT, BKE_idtype_idcode_to_name(ID_PT), LIB_ID_CREATE_LOCALIZE)); - pointcloud_init_data(&pointcloud->id); + BKE_libblock_init_empty(&pointcloud->id); CustomData_realloc(&pointcloud->pdata, 0, totpoint); pointcloud->totpoint = totpoint; diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.cc b/source/blender/draw/engines/eevee/eevee_lookdev.cc index 501c7d2a12b..ad2a64ca38c 100644 --- a/source/blender/draw/engines/eevee/eevee_lookdev.cc +++ b/source/blender/draw/engines/eevee/eevee_lookdev.cc @@ -31,8 +31,11 @@ namespace blender::eevee { LookdevWorld::LookdevWorld() { - bNodeTree *ntree = bke::node_tree_add_tree( - nullptr, "Lookdev World Nodetree", ntreeType_Shader->idname); + /* Create a dummy World data block to hold the nodetree generated for studio-lights. */ + world = static_cast<::World *>(BKE_id_new_nomain(ID_MA, "Lookdev")); + + bNodeTree *ntree = bke::node_tree_add_tree_embedded( + nullptr, &world->id, "Lookdev World Nodetree", ntreeType_Shader->idname); bNode *coordinate = bke::node_add_static_node(nullptr, *ntree, SH_NODE_TEX_COORD); bNodeSocket *coordinate_out = bke::node_find_socket(*coordinate, SOCK_OUT, "Generated"); @@ -65,12 +68,14 @@ LookdevWorld::LookdevWorld() bke::node_add_link(*ntree, *background, *background_out, *output, *output_in); bke::node_set_active(*ntree, *output); + world->use_nodes = true; + world->nodetree = ntree; + /* Create a dummy image data block to hold GPU textures generated by studio-lights. */ - STRNCPY(image.id.name, "IMLookdev"); - BKE_libblock_init_empty(&image.id); - image.type = IMA_TYPE_IMAGE; - image.source = IMA_SRC_GENERATED; - ImageTile *base_tile = BKE_image_get_tile(&image, 0); + image = static_cast<::Image *>(BKE_id_new_nomain(ID_IM, "Lookdev")); + image->type = IMA_TYPE_IMAGE; + image->source = IMA_SRC_GENERATED; + ImageTile *base_tile = BKE_image_get_tile(image, 0); base_tile->gen_x = 1; base_tile->gen_y = 1; base_tile->gen_type = IMA_GENTYPE_BLANK; @@ -78,19 +83,13 @@ LookdevWorld::LookdevWorld() /* TODO: This works around the issue that the first time the texture is accessed the image would * overwrite the set GPU texture. A better solution would be to use image data-blocks as part of * the studio-lights, but that requires a larger refactoring. */ - BKE_image_get_gpu_texture(&image, &environment_storage->iuser); - - /* Create a dummy image data block to hold GPU textures generated by studio-lights. */ - STRNCPY(world.id.name, "WOLookdev"); - BKE_libblock_init_empty(&world.id); - world.use_nodes = true; - world.nodetree = ntree; + BKE_image_get_gpu_texture(image, &environment_storage->iuser); } LookdevWorld::~LookdevWorld() { - BKE_libblock_free_datablock(&image.id, 0); - BKE_libblock_free_datablock(&world.id, 0); + BKE_id_free(nullptr, &image->id); + BKE_id_free(nullptr, &world->id); } bool LookdevWorld::sync(const LookdevParameters &new_parameters) @@ -101,7 +100,7 @@ bool LookdevWorld::sync(const LookdevParameters &new_parameters) intensity_socket_->value = parameters_.intensity; angle_socket_->value = parameters_.rot_z; - GPU_TEXTURE_FREE_SAFE(image.gputexture[TEXTARGET_2D][0]); + GPU_TEXTURE_FREE_SAFE(image->gputexture[TEXTARGET_2D][0]); environment_node_->id = nullptr; StudioLight *sl = BKE_studiolight_find(parameters_.hdri.c_str(), @@ -111,12 +110,12 @@ bool LookdevWorld::sync(const LookdevParameters &new_parameters) GPUTexture *texture = sl->equirect_radiance_gputexture; if (texture != nullptr) { GPU_texture_ref(texture); - image.gputexture[TEXTARGET_2D][0] = texture; - environment_node_->id = &image.id; + image->gputexture[TEXTARGET_2D][0] = texture; + environment_node_->id = &image->id; } } - GPU_material_free(&world.gpumaterial); + GPU_material_free(&world->gpumaterial); } return parameters_changed; } diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.hh b/source/blender/draw/engines/eevee/eevee_lookdev.hh index ce724732acd..f4a4fa726a9 100644 --- a/source/blender/draw/engines/eevee/eevee_lookdev.hh +++ b/source/blender/draw/engines/eevee/eevee_lookdev.hh @@ -72,8 +72,8 @@ class LookdevWorld { bNode *environment_node_ = nullptr; bNodeSocketValueFloat *intensity_socket_ = nullptr; bNodeSocketValueFloat *angle_socket_ = nullptr; - ::Image image = {}; - ::World world = {}; + ::Image *image = nullptr; + ::World *world = nullptr; LookdevParameters parameters_; @@ -86,7 +86,7 @@ class LookdevWorld { ::World *world_get() { - return &world; + return world; } float background_opacity_get() const