From 7a005e089daf068c6b400bfa96ac39d4240f3516 Mon Sep 17 00:00:00 2001 From: Joseph Eagar Date: Fri, 14 Oct 2022 14:34:46 -0700 Subject: Sculpt: fix crash when instancing sculpt objects --- source/blender/blenkernel/intern/pbvh.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index b23fe53e80c..b73f0746621 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -719,6 +719,11 @@ PBVH *BKE_pbvh_new(PBVHType type) pbvh->respect_hide = true; pbvh->draw_cache_invalid = true; pbvh->header.type = type; + + /* Initialize this to true, instead of waiting for a draw engine + * to set it. Prevents a crash in draw manager instancing code. + */ + pbvh->is_drawing = true; return pbvh; } -- cgit v1.2.3 From bc06fcca47caa182cad0818de6ccb8cde9ea215e Mon Sep 17 00:00:00 2001 From: Joseph Eagar Date: Fri, 14 Oct 2022 14:58:40 -0700 Subject: Sculpt: do not validate PBVH draw data in mesh_batch_cache_valid Turns out PBVH drawing and normal mesh batches are not mutually exclusive inside the draw cache; there are edge cases with modifiers and instancing where you need both, and forcing one or the other inside this function leads to memory corruption. --- source/blender/draw/intern/draw_cache_impl_mesh.cc | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.cc b/source/blender/draw/intern/draw_cache_impl_mesh.cc index d3e071c14e7..5ce658abfe4 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.cc +++ b/source/blender/draw/intern/draw_cache_impl_mesh.cc @@ -560,16 +560,7 @@ static bool mesh_batch_cache_valid(Object *object, Mesh *me) return false; } - if (object->sculpt && object->sculpt->pbvh) { - if (cache->pbvh_is_drawing != BKE_pbvh_is_drawing(object->sculpt->pbvh)) { - return false; - } - - if (BKE_pbvh_is_drawing(object->sculpt->pbvh) && - BKE_pbvh_draw_cache_invalid(object->sculpt->pbvh)) { - return false; - } - } + /* Note: PBVH draw data should not be checked here. */ if (cache->is_editmode != (me->edit_mesh != nullptr)) { return false; @@ -1443,7 +1434,6 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, } } - /* Verify that all surface batches have needed attribute layers. */ /* TODO(fclem): We could be a bit smarter here and only do it per @@ -1486,7 +1476,8 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, mesh_cd_layers_type_merge(&cache->cd_used_over_time, cache->cd_needed); mesh_cd_layers_type_clear(&cache->cd_needed); - drw_attributes_merge(&cache->attr_used_over_time, &cache->attr_needed, me->runtime->render_mutex); + drw_attributes_merge( + &cache->attr_used_over_time, &cache->attr_needed, me->runtime->render_mutex); drw_attributes_clear(&cache->attr_needed); } -- cgit v1.2.3 From 010c10febe46c1c24ca3e32ee8b03e2da2eea4fe Mon Sep 17 00:00:00 2001 From: Joseph Eagar Date: Fri, 14 Oct 2022 22:08:36 -0700 Subject: Sculpt: Ensure faces are uniquely assigned to PBVHNodes PBVH_FACES and PBVH_GRIDS do not store faces directly in nodes; instead they store 'primitives', which are tesselation triangles for PBVH_FACES and grids (which are per-loop) for PBVH_GRIDS. Primitives from the same face could sometimes end up in different PBVH nodes. This is now prevented in two ways: * All primitives of the same face are given the same boundary during PBVH build. This prevents them from being swapped away from each other during partitioning. * build_sub adjusts the final partition midpoint to fall between primitives of different faces. --- source/blender/blenkernel/BKE_pbvh.h | 3 +- source/blender/blenkernel/intern/paint.cc | 3 +- source/blender/blenkernel/intern/pbvh.c | 191 +++++++++++++++++++++++++++++- 3 files changed, 193 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 89743f1d2b4..42cd1536dcf 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -267,7 +267,8 @@ void BKE_pbvh_build_grids(PBVH *pbvh, void **gridfaces, struct DMFlagMat *flagmats, unsigned int **grid_hidden, - struct Mesh *me); + struct Mesh *me, + struct SubdivCCG *subdiv_ccg); /** * Build a PBVH from a BMesh. */ diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index d45ce776b64..934cfb3cc46 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -2237,7 +2237,8 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect (void **)subdiv_ccg->grid_faces, subdiv_ccg->grid_flag_mats, subdiv_ccg->grid_hidden, - base_mesh); + base_mesh, + subdiv_ccg); pbvh_show_mask_set(pbvh, ob->sculpt->show_mask); pbvh_show_face_sets_set(pbvh, ob->sculpt->show_face_sets); return pbvh; diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index b73f0746621..65a906e6580 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -39,8 +39,10 @@ #define LEAF_LIMIT 10000 -//#define PERFCNTRS +/* Uncomment to test that faces are only assigned to one PBVHNode */ +//#define VALIDATE_UNIQUE_NODE_FACES +//#define PERFCNTRS #define STACK_FIXED_DEPTH 100 typedef struct PBVHStack { @@ -422,6 +424,56 @@ static bool leaf_needs_material_split(PBVH *pbvh, int offset, int count) return false; } +static int adjust_partition_faces(PBVH *pbvh, int offset, int mid, int count) +{ + int poly = pbvh->looptri[pbvh->prim_indices[mid]].poly; + + /* Scan backwards. */ + while (mid > offset + 2) { /* First node should have at least 1 primitive */ + if (pbvh->looptri[pbvh->prim_indices[mid - 1]].poly != poly) { + return mid; + } + + mid--; + } + + /* If that didn't work try scanning forward. */ + while (mid < pbvh->totprim + count) { + if (pbvh->looptri[pbvh->prim_indices[mid]].poly != poly) { + break; + } + + mid++; + } + + return mid; +} + +static int adjust_partition_grids(PBVH *pbvh, int offset, int mid, int count) +{ + int poly = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, pbvh->prim_indices[mid]); + + /* Scan backwards. */ + while (mid > offset + 2) { /* First node should have at least 1 primitive */ + if (BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, pbvh->prim_indices[mid - 1]) != poly) { + return mid; + } + + mid--; + } + + /* If that didn't work try scanning forward. */ + while (mid < pbvh->totprim + count) { + if (BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, pbvh->prim_indices[mid]) != poly) { + break; + } + + mid++; + } + + return mid; +} + /* Recursively build a node in the tree * * vb is the voxel box around all of the primitives contained in @@ -478,6 +530,13 @@ static void build_sub(PBVH *pbvh, int node_index, BB *cb, BBC *prim_bbc, int off end = partition_indices_material(pbvh, offset, offset + count - 1); } + if (pbvh->header.type == PBVH_FACES) { + end = adjust_partition_faces(pbvh, offset, end, count); + } + else { + end = adjust_partition_grids(pbvh, offset, end, count); + } + /* Build children */ build_sub(pbvh, pbvh->nodes[node_index].children_offset, NULL, prim_bbc, offset, end - offset); build_sub(pbvh, @@ -587,6 +646,73 @@ static void pbvh_draw_args_init(PBVH *pbvh, PBVH_GPU_Args *args, PBVHNode *node) } } +#ifdef VALIDATE_UNIQUE_NODE_FACES +static void pbvh_validate_node_prims(PBVH *pbvh) +{ + int totface = 0; + + if (pbvh->header.type == PBVH_BMESH) { + return; + } + + for (int i = 0; i < pbvh->totnode; i++) { + PBVHNode *node = pbvh->nodes + i; + + if (!(node->flag & PBVH_Leaf)) { + continue; + } + + for (int j = 0; j < node->totprim; j++) { + int poly; + + if (pbvh->header.type == PBVH_FACES) { + poly = pbvh->looptri[node->prim_indices[j]].poly; + } + else { + poly = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, node->prim_indices[j]); + } + + totface = max_ii(totface, poly + 1); + } + } + + int *facemap = (int *)MEM_malloc_arrayN(totface, sizeof(*facemap), __func__); + + for (int i = 0; i < totface; i++) { + facemap[i] = -1; + } + + for (int i = 0; i < pbvh->totnode; i++) { + PBVHNode *node = pbvh->nodes + i; + + if (!(node->flag & PBVH_Leaf)) { + continue; + } + + for (int j = 0; j < node->totprim; j++) { + int poly; + + if (pbvh->header.type == PBVH_FACES) { + poly = pbvh->looptri[node->prim_indices[j]].poly; + } + else { + poly = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, node->prim_indices[j]); + } + + if (facemap[poly] != -1 && facemap[poly] != i) { + printf("%s: error: face spanned multiple nodes (old: %d new: %d)\n", + __func__, + facemap[poly], + i); + } + + facemap[poly] = i; + } + } + MEM_SAFE_FREE(facemap); +} +#endif + void BKE_pbvh_build_mesh(PBVH *pbvh, Mesh *mesh, const MPoly *mpoly, @@ -645,6 +771,32 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, BB_expand(&cb, bbc->bcentroid); } + /* Ensure all primitives belonging to the same base face + * have the same bounds. This is needed to prevent them + * from being swapped away from each other inside the partition + * array. + */ + for (int i = 0; i < looptri_num; i++) { + const MLoopTri *lt = &looptri[i]; + int poly = lt->poly; + BBC *bbc = prim_bbc + i; + int j = i + 1; + + while (j < looptri_num && looptri[j].poly == poly) { + BBC *bbc2 = prim_bbc + j; + + BB_expand((BB *)bbc, bbc2->bmin); + BB_expand((BB *)bbc, bbc2->bmax); + j++; + } + + j = i + 1; + while (j < looptri_num && looptri[j].poly == poly) { + prim_bbc[j] = prim_bbc[i]; + j++; + } + } + if (looptri_num) { pbvh_build(pbvh, &cb, prim_bbc, looptri_num); } @@ -655,6 +807,10 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, memset(pbvh->vert_bitmap, 0, sizeof(bool) * totvert); BKE_pbvh_update_active_vcol(pbvh, mesh); + +#ifdef VALIDATE_UNIQUE_NODE_FACES + pbvh_validate_node_prims(pbvh); +#endif } void BKE_pbvh_build_grids(PBVH *pbvh, @@ -664,7 +820,8 @@ void BKE_pbvh_build_grids(PBVH *pbvh, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap **grid_hidden, - Mesh *me) + Mesh *me, + SubdivCCG *subdiv_ccg) { const int gridsize = key->grid_size; @@ -675,6 +832,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh, pbvh->totgrid = totgrid; pbvh->gridkey = *key; pbvh->grid_hidden = grid_hidden; + pbvh->subdiv_ccg = subdiv_ccg; pbvh->leaf_limit = max_ii(LEAF_LIMIT / (gridsize * gridsize), 1); /* We need the base mesh attribute layout for PBVH draw. */ @@ -706,11 +864,40 @@ void BKE_pbvh_build_grids(PBVH *pbvh, BB_expand(&cb, bbc->bcentroid); } + /* Ensure all primitives belonging to the same base face + * have the same bounds. This is needed to prevent them + * from being swapped away from each other inside the partition + * array. + */ + for (int i = 0; i < totgrid; i++) { + int poly = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, i); + + BBC *bbc = prim_bbc + i; + int j = i + 1; + + while (j < totgrid && BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, j) == poly) { + BBC *bbc2 = prim_bbc + j; + + BB_expand((BB *)bbc, bbc2->bmin); + BB_expand((BB *)bbc, bbc2->bmax); + j++; + } + + j = i + 1; + while (j < totgrid && BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, j) == poly) { + prim_bbc[j] = prim_bbc[i]; + j++; + } + } + if (totgrid) { pbvh_build(pbvh, &cb, prim_bbc, totgrid); } MEM_freeN(prim_bbc); +#ifdef VALIDATE_UNIQUE_NODE_FACES + pbvh_validate_node_prims(pbvh); +#endif } PBVH *BKE_pbvh_new(PBVHType type) -- cgit v1.2.3 From c207571d44e6af7d52a3764f6a3794e9a884a56b Mon Sep 17 00:00:00 2001 From: Joseph Eagar Date: Fri, 14 Oct 2022 22:51:45 -0700 Subject: Sculpt: Fix draw artifacts when drawing multires mask --- source/blender/draw/intern/draw_pbvh.cc | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/source/blender/draw/intern/draw_pbvh.cc b/source/blender/draw/intern/draw_pbvh.cc index 880a5a445f4..381f8b55e9f 100644 --- a/source/blender/draw/intern/draw_pbvh.cc +++ b/source/blender/draw/intern/draw_pbvh.cc @@ -389,12 +389,18 @@ struct PBVHBatches { break; case CD_PBVH_MASK_TYPE: - foreach_grids([&](int /*x*/, int /*y*/, int /*grid_index*/, CCGElem *elems[4], int i) { - float *mask = CCG_elem_mask(&args->ccg_key, elems[i]); + if (args->ccg_key.has_mask) { + foreach_grids([&](int /*x*/, int /*y*/, int /*grid_index*/, CCGElem *elems[4], int i) { + float *mask = CCG_elem_mask(&args->ccg_key, elems[i]); - *static_cast(GPU_vertbuf_raw_step(&access)) = mask ? uchar(*mask * 255.0f) : - 255; - }); + *static_cast(GPU_vertbuf_raw_step(&access)) = uchar(*mask * 255.0f); + }); + } + else { + foreach_grids([&](int /*x*/, int /*y*/, int /*grid_index*/, CCGElem *elems[4], int i) { + *static_cast(GPU_vertbuf_raw_step(&access)) = 0; + }); + } break; case CD_PBVH_FSET_TYPE: { -- cgit v1.2.3 From b7ea79fde7b88eba37b57e897604574489aec43f Mon Sep 17 00:00:00 2001 From: Joseph Eagar Date: Fri, 14 Oct 2022 23:00:13 -0700 Subject: Sculpt: Fix face set relax being too strong --- source/blender/editors/sculpt_paint/sculpt_face_set.cc | 5 +++-- source/blender/editors/sculpt_paint/sculpt_intern.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.cc b/source/blender/editors/sculpt_paint/sculpt_face_set.cc index 5f5a555b428..ee1238e0f24 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.cc +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.cc @@ -198,8 +198,8 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata, const bool relax_face_sets = !(ss->cache->iteration_count % 3 == 0); /* This operations needs a strength tweak as the relax deformation is too weak by default. */ - if (relax_face_sets) { - bstrength *= 2.0f; + if (relax_face_sets && data->iteration < 2) { + bstrength *= 1.5f; } const int thread_id = BLI_task_parallel_thread_id(tls); @@ -261,6 +261,7 @@ void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in if (ss->cache->alt_smooth) { SCULPT_boundary_info_ensure(ob); for (int i = 0; i < 4; i++) { + data.iteration = i; BLI_task_parallel_range(0, totnode, &data, do_relax_face_sets_brush_task_cb_ex, &settings); } } diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index edb681466b5..bf47b64d176 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -332,7 +332,7 @@ typedef struct SculptThreadedTaskData { int mask_init_seed; ThreadMutex mutex; - + int iteration; } SculptThreadedTaskData; /*************** Brush testing declarations ****************/ -- cgit v1.2.3 From ebe9804cfa421b746148f3067797f16e7f460551 Mon Sep 17 00:00:00 2001 From: Joseph Eagar Date: Fri, 14 Oct 2022 23:03:10 -0700 Subject: Cleanup: comment out unused lambda parameter --- source/blender/draw/intern/draw_pbvh.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/blender/draw/intern/draw_pbvh.cc b/source/blender/draw/intern/draw_pbvh.cc index 381f8b55e9f..60a0d4e6bb2 100644 --- a/source/blender/draw/intern/draw_pbvh.cc +++ b/source/blender/draw/intern/draw_pbvh.cc @@ -397,9 +397,10 @@ struct PBVHBatches { }); } else { - foreach_grids([&](int /*x*/, int /*y*/, int /*grid_index*/, CCGElem *elems[4], int i) { - *static_cast(GPU_vertbuf_raw_step(&access)) = 0; - }); + foreach_grids( + [&](int /*x*/, int /*y*/, int /*grid_index*/, CCGElem * /*elems*/[4], int i) { + *static_cast(GPU_vertbuf_raw_step(&access)) = 0; + }); } break; -- cgit v1.2.3 From b898330c3744669a8c3805f1560130821422cca1 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sat, 15 Oct 2022 22:51:21 +0200 Subject: Fix T99450: Animated Holdout not updating on frame change Problem here was that layer_collection_objects_sync wasn't called when the holdout property is updated due to frame change, so the changed visibility flag was never applied to ob->base_flag. Turns out there's no real reason to handle the per-object holdout property through the layer system. So, instead of merging both the layer holdout and object holdout into base_flag and checking that from the render engines, only handle the layer holdout (which can't be animated, so no issue here) through base_flag and explicitly also check the object holdout in the render engines. --- source/blender/blenkernel/intern/layer.c | 2 +- source/blender/draw/engines/eevee/eevee_materials.c | 3 ++- .../blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp | 3 ++- source/blender/makesrna/intern/rna_object_api.c | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index fcb0adfde34..06d69b6ff61 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -1049,7 +1049,7 @@ static void layer_collection_objects_sync(ViewLayer *view_layer, } /* Holdout and indirect only */ - if ((layer->flag & LAYER_COLLECTION_HOLDOUT) || (base->object->visibility_flag & OB_HOLDOUT)) { + if ((layer->flag & LAYER_COLLECTION_HOLDOUT)) { base->flag_from_collection |= BASE_HOLDOUT; } if (layer->flag & LAYER_COLLECTION_INDIRECT_ONLY) { diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index f79e4e1d568..b5f81f3a307 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -759,7 +759,8 @@ BLI_INLINE Material *eevee_object_material_get(Object *ob, int slot, bool holdou BLI_INLINE EeveeMaterialCache eevee_material_cache_get( EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob, int slot, bool is_hair) { - const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0; + const bool holdout = ((ob->base_flag & BASE_HOLDOUT) != 0) || + ((ob->visibility_flag & OB_HOLDOUT) != 0); EeveeMaterialCache matcache; Material *ma = eevee_object_material_get(ob, slot, holdout); switch (ma->blend_method) { diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp index 19589491bc4..0d41b5a773d 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -73,7 +73,8 @@ NodeGroup *BlenderFileLoader::Load() break; } - if (ob->base_flag & (BASE_HOLDOUT | BASE_INDIRECT_ONLY)) { + if ((ob->base_flag & (BASE_HOLDOUT | BASE_INDIRECT_ONLY)) || + (ob->visibility_flag & OB_HOLDOUT)) { continue; } diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index c99c5fb723d..366a3597ce6 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -199,7 +199,7 @@ static bool rna_Object_holdout_get(Object *ob, bContext *C, PointerRNA *view_lay return false; } - return ((base->flag & BASE_HOLDOUT) != 0); + return ((base->flag & BASE_HOLDOUT) != 0) || ((ob->visibility_flag & OB_HOLDOUT) != 0); } static bool rna_Object_indirect_only_get(Object *ob, bContext *C, PointerRNA *view_layer_ptr) -- cgit v1.2.3 From 0c50f9c4aaf90eb26240c31fbeff12af519a8ab0 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sun, 16 Oct 2022 01:57:44 +0200 Subject: Fix T98672: Noise texture shows incorrect behaviour for large scales This was a floating point precision issue - or, to be more precise, an issue with how Cycles split floats into the integer and fractional parts for Perlin noise. For coordinates below -2^24, the integer could be wrong, leading to the fractional part being outside of 0-1 range, which breaks all sorts of other things. 2^24 sounds like a lot, but due to how the detail octaves work, it's not that hard to reach when combined with a large scale. Since this code is originally based on OSL, I checked if they changed it in the meantime, and sure enough, there's a fix for it: https://github.com/OpenImageIO/oiio/commit/5c9dc68391e9 So, this basically just ports over that change to Cycles. The original code mentions being faster, but as pointed out in the linked commit, the performance impact is actually irrelevant. I also checked in a simple scene with eight Noise textures at detail 15 (with >90% of render time being spent on the noise), and the render time went from 13.06sec to 13.05sec. So, yeah, no issue. --- intern/cycles/util/math.h | 10 +++------- intern/cycles/util/math_float3.h | 12 ------------ intern/cycles/util/ssef.h | 23 +++++++++++------------ 3 files changed, 14 insertions(+), 31 deletions(-) diff --git a/intern/cycles/util/math.h b/intern/cycles/util/math.h index 0905b3ec5c9..3a2e0e074a2 100644 --- a/intern/cycles/util/math.h +++ b/intern/cycles/util/math.h @@ -417,15 +417,11 @@ ccl_device_inline int floor_to_int(float f) return float_to_int(floorf(f)); } -ccl_device_inline int quick_floor_to_int(float x) -{ - return float_to_int(x) - ((x < 0) ? 1 : 0); -} - ccl_device_inline float floorfrac(float x, ccl_private int *i) { - *i = quick_floor_to_int(x); - return x - *i; + float f = floorf(x); + *i = float_to_int(f); + return x - f; } ccl_device_inline int ceil_to_int(float f) diff --git a/intern/cycles/util/math_float3.h b/intern/cycles/util/math_float3.h index c408eadf195..eec7122b9dc 100644 --- a/intern/cycles/util/math_float3.h +++ b/intern/cycles/util/math_float3.h @@ -535,18 +535,6 @@ ccl_device_inline float3 pow(float3 v, float e) return make_float3(powf(v.x, e), powf(v.y, e), powf(v.z, e)); } -ccl_device_inline int3 quick_floor_to_int3(const float3 a) -{ -#ifdef __KERNEL_SSE__ - int3 b = int3(_mm_cvttps_epi32(a.m128)); - int3 isneg = int3(_mm_castps_si128(_mm_cmplt_ps(a.m128, _mm_set_ps1(0.0f)))); - /* Unsaturated add 0xffffffff is the same as subtract -1. */ - return b + isneg; -#else - return make_int3(quick_floor_to_int(a.x), quick_floor_to_int(a.y), quick_floor_to_int(a.z)); -#endif -} - ccl_device_inline bool isfinite_safe(float3 v) { return isfinite_safe(v.x) && isfinite_safe(v.y) && isfinite_safe(v.z); diff --git a/intern/cycles/util/ssef.h b/intern/cycles/util/ssef.h index a2fff94303e..7f9e332a997 100644 --- a/intern/cycles/util/ssef.h +++ b/intern/cycles/util/ssef.h @@ -5,6 +5,8 @@ #ifndef __UTIL_SSEF_H__ #define __UTIL_SSEF_H__ +#include + #include "util/ssei.h" CCL_NAMESPACE_BEGIN @@ -534,6 +536,12 @@ __forceinline const ssef ceil(const ssef &a) return _mm_round_ps(a, _MM_FROUND_TO_POS_INF); # endif } +# else +/* Non-SSE4.1 fallback, needed for floorfrac. */ +__forceinline const ssef floor(const ssef &a) +{ + return _mm_set_ps(floorf(a.f[3]), floorf(a.f[2]), floorf(a.f[1]), floorf(a.f[0])); +} # endif __forceinline ssei truncatei(const ssef &a) @@ -541,20 +549,11 @@ __forceinline ssei truncatei(const ssef &a) return _mm_cvttps_epi32(a.m128); } -/* This is about 25% faster than straightforward floor to integer conversion - * due to better pipelining. - * - * Unsaturated add 0xffffffff (a < 0) is the same as subtract -1. - */ -__forceinline ssei floori(const ssef &a) -{ - return truncatei(a) + cast((a < 0.0f).m128); -} - __forceinline ssef floorfrac(const ssef &x, ssei *i) { - *i = floori(x); - return x - ssef(*i); + ssef f = floor(x); + *i = truncatei(f); + return x - f; } //////////////////////////////////////////////////////////////////////////////// -- cgit v1.2.3 From 4c320e2639ef41f093a71f6843b40ab64bdd021b Mon Sep 17 00:00:00 2001 From: Monique Dewanchand Date: Sun, 16 Oct 2022 11:16:07 +0200 Subject: Fix T101394: Ensure all viewlayers on scene copy. When a scene copy is called, all viewlayers are ensured before they are copied. In case of multiple viewlayers, a viewlayer can be out of sync. This triggers an assert in the BKE_view_layer_copy_data. Reviewed By: mont29 Maniphest Tasks: T101394 Differential Revision: https://developer.blender.org/D16214 --- source/blender/blenkernel/intern/scene.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/blenkernel/intern/scene.cc b/source/blender/blenkernel/intern/scene.cc index fc47fb71bf3..bd26075f81f 100644 --- a/source/blender/blenkernel/intern/scene.cc +++ b/source/blender/blenkernel/intern/scene.cc @@ -280,6 +280,9 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int } /* View Layers */ + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene_src->view_layers) { + BKE_view_layer_synced_ensure(scene_src, view_layer); + } BLI_duplicatelist(&scene_dst->view_layers, &scene_src->view_layers); for (ViewLayer *view_layer_src = static_cast(scene_src->view_layers.first), *view_layer_dst = static_cast(scene_dst->view_layers.first); -- cgit v1.2.3 From 25e84334f7d66b36ff962688c4c5b5818bd5db25 Mon Sep 17 00:00:00 2001 From: Joseph Eagar Date: Sun, 16 Oct 2022 13:24:26 -0700 Subject: Sculpt: Fix T101864: Mask initialization not updating multires data BKE_sculpt_mask_layers_ensure now takes a depsgraph argument and will evaluate the depsgraph if a multires mask layer is added. This is necassary to update the multires runtime data so that pbvh knows it has a grids mask layer. Also added code to update pbvh->gridkey. --- source/blender/blenkernel/BKE_paint.h | 13 ++++++++++++- source/blender/blenkernel/BKE_pbvh.h | 3 ++- source/blender/blenkernel/intern/paint.cc | 15 +++++++++++++-- source/blender/blenkernel/intern/pbvh.c | 9 +++++++-- source/blender/editors/mesh/editmesh_mask_extract.c | 4 ++-- source/blender/editors/object/object_modifier.cc | 5 +++-- source/blender/editors/sculpt_paint/paint_mask.c | 16 ++++++++++------ source/blender/editors/sculpt_paint/sculpt.c | 3 ++- source/blender/editors/sculpt_paint/sculpt_expand.c | 11 ++++++----- source/blender/editors/sculpt_paint/sculpt_filter_mask.c | 3 ++- source/blender/editors/sculpt_paint/sculpt_mask_expand.c | 8 ++++++-- source/blender/editors/sculpt_paint/sculpt_mask_init.c | 4 ++++ source/blender/editors/sculpt_paint/sculpt_ops.c | 7 ++++--- 13 files changed, 73 insertions(+), 28 deletions(-) diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 5312292d431..557edddac2a 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -860,7 +860,18 @@ int *BKE_sculpt_face_sets_ensure(struct Mesh *mesh); * (see #SCULPT_visibility_sync_all_from_faces). */ bool *BKE_sculpt_hide_poly_ensure(struct Mesh *mesh); -int BKE_sculpt_mask_layers_ensure(struct Object *ob, struct MultiresModifierData *mmd); + +/* Ensures a mask layer exists. If depsgraph and bmain are non-null, + * a mask doesn't exist and the object has a multiresolution modifier + * then the scene depsgraph will be evaluated to update the runtime + * subdivision data. + * + * Note: always call *before* BKE_sculpt_update_object_for_edit. + */ +int BKE_sculpt_mask_layers_ensure(struct Depsgraph *depsgraph, + struct Main *bmain, + struct Object *ob, + struct MultiresModifierData *mmd); void BKE_sculpt_toolsettings_data_ensure(struct Scene *scene); struct PBVH *BKE_sculpt_object_pbvh_ensure(struct Depsgraph *depsgraph, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 42cd1536dcf..b375d69b61c 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -505,7 +505,8 @@ void BKE_pbvh_grids_update(PBVH *pbvh, struct CCGElem **grids, void **gridfaces, struct DMFlagMat *flagmats, - unsigned int **grid_hidden); + unsigned int **grid_hidden, + struct CCGKey *key); void BKE_pbvh_subdiv_cgg_set(PBVH *pbvh, struct SubdivCCG *subdiv_ccg); void BKE_pbvh_face_sets_set(PBVH *pbvh, int *face_sets); diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index 934cfb3cc46..9248e4d520e 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -54,6 +54,7 @@ #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_pbvh.h" +#include "BKE_scene.h" #include "BKE_subdiv_ccg.h" #include "BKE_subsurf.h" @@ -1986,7 +1987,10 @@ bool *BKE_sculpt_hide_poly_ensure(Mesh *mesh) &mesh->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, mesh->totpoly, ".hide_poly")); } -int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd) +int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph, + Main *bmain, + Object *ob, + MultiresModifierData *mmd) { Mesh *me = static_cast(ob->data); const Span polys = me->polys(); @@ -2045,6 +2049,9 @@ int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd) } /* The evaluated multires CCG must be updated to contain the new data. */ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + if (depsgraph) { + BKE_scene_graph_evaluated_ensure(depsgraph, bmain); + } ret |= SCULPT_MASK_LAYER_CALC_LOOP; } @@ -2296,11 +2303,15 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob) void BKE_sculpt_bvh_update_from_ccg(PBVH *pbvh, SubdivCCG *subdiv_ccg) { + CCGKey key; + BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg); + BKE_pbvh_grids_update(pbvh, subdiv_ccg->grids, (void **)subdiv_ccg->grid_faces, subdiv_ccg->grid_flag_mats, - subdiv_ccg->grid_hidden); + subdiv_ccg->grid_hidden, + &key); } bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const View3D * /*v3d*/) diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 65a906e6580..98e89b09060 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -3064,9 +3064,14 @@ void BKE_pbvh_draw_debug_cb(PBVH *pbvh, } } -void BKE_pbvh_grids_update( - PBVH *pbvh, CCGElem **grids, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap **grid_hidden) +void BKE_pbvh_grids_update(PBVH *pbvh, + CCGElem **grids, + void **gridfaces, + DMFlagMat *flagmats, + BLI_bitmap **grid_hidden, + CCGKey *key) { + pbvh->gridkey = *key; pbvh->grids = grids; pbvh->gridfaces = gridfaces; diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c index fdf4746ab09..070f748c78e 100644 --- a/source/blender/editors/mesh/editmesh_mask_extract.c +++ b/source/blender/editors/mesh/editmesh_mask_extract.c @@ -88,7 +88,7 @@ static int geometry_extract_apply(bContext *C, ED_object_sculptmode_exit(C, depsgraph); - BKE_sculpt_mask_layers_ensure(ob, NULL); + BKE_sculpt_mask_layers_ensure(depsgraph, bmain, ob, NULL); /* Ensures that deformation from sculpt mode is taken into account before duplicating the mesh to * extract the geometry. */ @@ -481,7 +481,7 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op) Object *ob = CTX_data_active_object(C); View3D *v3d = CTX_wm_view3d(C); - BKE_sculpt_mask_layers_ensure(ob, NULL); + BKE_sculpt_mask_layers_ensure(NULL, NULL, ob, NULL); Mesh *mesh = ob->data; Mesh *new_mesh = (Mesh *)BKE_id_copy(bmain, &mesh->id); diff --git a/source/blender/editors/object/object_modifier.cc b/source/blender/editors/object/object_modifier.cc index c7995809438..85a35861329 100644 --- a/source/blender/editors/object/object_modifier.cc +++ b/source/blender/editors/object/object_modifier.cc @@ -218,7 +218,7 @@ ModifierData *ED_object_modifier_add( if (ob->mode & OB_MODE_SCULPT) { /* ensure that grid paint mask layer is created */ - BKE_sculpt_mask_layers_ensure(ob, (MultiresModifierData *)new_md); + BKE_sculpt_mask_layers_ensure(nullptr, nullptr, ob, (MultiresModifierData *)new_md); } } else if (type == eModifierType_Skin) { @@ -2041,7 +2041,8 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op) if (object->mode & OB_MODE_SCULPT) { /* ensure that grid paint mask layer is created */ - BKE_sculpt_mask_layers_ensure(object, mmd); + BKE_sculpt_mask_layers_ensure( + CTX_data_ensure_evaluated_depsgraph(C), CTX_data_main(C), object, mmd); } return OPERATOR_FINISHED; diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index e1fd731a4b7..571ebd79764 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -31,6 +31,7 @@ #include "BKE_multires.h" #include "BKE_paint.h" #include "BKE_pbvh.h" +#include "BKE_scene.h" #include "BKE_subsurf.h" #include "DEG_depsgraph.h" @@ -146,7 +147,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op) value = RNA_float_get(op->ptr, "value"); MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob); - BKE_sculpt_mask_layers_ensure(ob, mmd); + BKE_sculpt_mask_layers_ensure(depsgraph, CTX_data_main(C), ob, mmd); BKE_sculpt_update_object_for_edit(depsgraph, ob, false, true, false); pbvh = ob->sculpt->pbvh; @@ -861,7 +862,9 @@ static void sculpt_gesture_mask_end(bContext *C, SculptGestureContext *sgcontext BKE_pbvh_update_vertex_data(sgcontext->ss->pbvh, PBVH_UpdateMask); } -static void sculpt_gesture_init_mask_properties(SculptGestureContext *sgcontext, wmOperator *op) +static void sculpt_gesture_init_mask_properties(bContext *C, + SculptGestureContext *sgcontext, + wmOperator *op) { sgcontext->operation = MEM_callocN(sizeof(SculptGestureMaskOperation), "Mask Operation"); @@ -869,7 +872,8 @@ static void sculpt_gesture_init_mask_properties(SculptGestureContext *sgcontext, Object *object = sgcontext->vc.obact; MultiresModifierData *mmd = BKE_sculpt_multires_active(sgcontext->vc.scene, object); - BKE_sculpt_mask_layers_ensure(sgcontext->vc.obact, mmd); + BKE_sculpt_mask_layers_ensure( + CTX_data_depsgraph_pointer(C), CTX_data_main(C), sgcontext->vc.obact, mmd); mask_operation->op.sculpt_gesture_begin = sculpt_gesture_mask_begin; mask_operation->op.sculpt_gesture_apply_for_symmetry_pass = @@ -1514,7 +1518,7 @@ static int paint_mask_gesture_box_exec(bContext *C, wmOperator *op) if (!sgcontext) { return OPERATOR_CANCELLED; } - sculpt_gesture_init_mask_properties(sgcontext, op); + sculpt_gesture_init_mask_properties(C, sgcontext, op); sculpt_gesture_apply(C, sgcontext, op); sculpt_gesture_context_free(sgcontext); return OPERATOR_FINISHED; @@ -1526,7 +1530,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) if (!sgcontext) { return OPERATOR_CANCELLED; } - sculpt_gesture_init_mask_properties(sgcontext, op); + sculpt_gesture_init_mask_properties(C, sgcontext, op); sculpt_gesture_apply(C, sgcontext, op); sculpt_gesture_context_free(sgcontext); return OPERATOR_FINISHED; @@ -1538,7 +1542,7 @@ static int paint_mask_gesture_line_exec(bContext *C, wmOperator *op) if (!sgcontext) { return OPERATOR_CANCELLED; } - sculpt_gesture_init_mask_properties(sgcontext, op); + sculpt_gesture_init_mask_properties(C, sgcontext, op); sculpt_gesture_apply(C, sgcontext, op); sculpt_gesture_context_free(sgcontext); return OPERATOR_FINISHED; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index c46fd019725..0f71acd3698 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -41,6 +41,7 @@ #include "BKE_paint.h" #include "BKE_pbvh.h" #include "BKE_report.h" +#include "BKE_scene.h" #include "BKE_subdiv_ccg.h" #include "BKE_subsurf.h" @@ -5666,7 +5667,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent } if (SCULPT_tool_is_mask(brush->sculpt_tool)) { MultiresModifierData *mmd = BKE_sculpt_multires_active(ss->scene, ob); - BKE_sculpt_mask_layers_ensure(ob, mmd); + BKE_sculpt_mask_layers_ensure(CTX_data_depsgraph_pointer(C), CTX_data_main(C), ob, mmd); } if (SCULPT_tool_is_face_sets(brush->sculpt_tool)) { Mesh *mesh = BKE_object_get_original_mesh(ob); diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.c b/source/blender/editors/sculpt_paint/sculpt_expand.c index 90279cb339c..655b03bbb36 100644 --- a/source/blender/editors/sculpt_paint/sculpt_expand.c +++ b/source/blender/editors/sculpt_paint/sculpt_expand.c @@ -27,6 +27,7 @@ #include "BKE_paint.h" #include "BKE_pbvh.h" #include "BKE_report.h" +#include "BKE_scene.h" #include "BKE_subdiv_ccg.h" #include "DEG_depsgraph.h" @@ -2107,6 +2108,11 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even depsgraph = CTX_data_ensure_evaluated_depsgraph(C); } + if (ss->expand_cache->target == SCULPT_EXPAND_TARGET_MASK) { + MultiresModifierData *mmd = BKE_sculpt_multires_active(ss->scene, ob); + BKE_sculpt_mask_layers_ensure(depsgraph, CTX_data_main(C), ob, mmd); + } + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, needs_colors); /* Do nothing when the mesh has 0 vertices. */ @@ -2121,11 +2127,6 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even ss->face_sets = BKE_sculpt_face_sets_ensure(mesh); } - if (ss->expand_cache->target == SCULPT_EXPAND_TARGET_MASK) { - MultiresModifierData *mmd = BKE_sculpt_multires_active(ss->scene, ob); - BKE_sculpt_mask_layers_ensure(ob, mmd); - } - /* Face Set operations are not supported in dyntopo. */ if (ss->expand_cache->target == SCULPT_EXPAND_TARGET_FACE_SETS && BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c index 69eac9a6168..8e199a72858 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c @@ -16,6 +16,7 @@ #include "BKE_context.h" #include "BKE_paint.h" #include "BKE_pbvh.h" +#include "BKE_scene.h" #include "DEG_depsgraph.h" @@ -166,7 +167,7 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) int filter_type = RNA_enum_get(op->ptr, "filter_type"); MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob); - BKE_sculpt_mask_layers_ensure(ob, mmd); + BKE_sculpt_mask_layers_ensure(CTX_data_depsgraph_pointer(C), CTX_data_main(C), ob, mmd); BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c index 56ddb99fe28..1b8cc5347ac 100644 --- a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c +++ b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c @@ -14,6 +14,7 @@ #include "DNA_brush_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "BKE_ccg.h" @@ -331,6 +332,11 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent SculptCursorGeometryInfo sgi; const float mval_fl[2] = {UNPACK2(event->mval)}; + MultiresModifierData *mmd = BKE_sculpt_multires_active(CTX_data_scene(C), ob); + BKE_sculpt_mask_layers_ensure(depsgraph, CTX_data_main(C), ob, mmd); + + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); + SCULPT_vertex_random_access_ensure(ss); op->customdata = MEM_mallocN(sizeof(float[2]), "initial mouse position"); @@ -338,8 +344,6 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false); - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); - int vertex_count = SCULPT_vertex_count_get(ss); ss->filter_cache = MEM_callocN(sizeof(FilterCache), "filter cache"); diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_init.c b/source/blender/editors/sculpt_paint/sculpt_mask_init.c index 5d7ef9aab15..99a7bb8a926 100644 --- a/source/blender/editors/sculpt_paint/sculpt_mask_init.c +++ b/source/blender/editors/sculpt_paint/sculpt_mask_init.c @@ -15,6 +15,7 @@ #include "DNA_brush_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "BKE_ccg.h" @@ -110,6 +111,9 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op) const int mode = RNA_enum_get(op->ptr, "mode"); + MultiresModifierData *mmd = BKE_sculpt_multires_active(CTX_data_scene(C), ob); + BKE_sculpt_mask_layers_ensure(depsgraph, CTX_data_main(C), ob, mmd); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); PBVH *pbvh = ob->sculpt->pbvh; diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.c b/source/blender/editors/sculpt_paint/sculpt_ops.c index 56a35ee1774..a740ec2773b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_ops.c +++ b/source/blender/editors/sculpt_paint/sculpt_ops.c @@ -21,6 +21,7 @@ #include "DNA_listBase.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -1041,12 +1042,12 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op) Sculpt *sd = CTX_data_tool_settings(C)->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); + MultiresModifierData *mmd = BKE_sculpt_multires_active(CTX_data_scene(C), ob); + BKE_sculpt_mask_layers_ensure(depsgraph, CTX_data_main(C), ob, mmd); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); SCULPT_vertex_random_access_ensure(ss); - MultiresModifierData *mmd = BKE_sculpt_multires_active(CTX_data_scene(C), ob); - BKE_sculpt_mask_layers_ensure(ob, mmd); - SCULPT_undo_push_begin(ob, op); CavityBakeMixMode mode = RNA_enum_get(op->ptr, "mix_mode"); -- cgit v1.2.3 From 6ad04a031c0f4375769a9a6a47942905be544992 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Mon, 17 Oct 2022 00:56:19 +0200 Subject: Cycles: Fix floor intrinsic for ARM Neon --- intern/cycles/util/ssef.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/util/ssef.h b/intern/cycles/util/ssef.h index 7f9e332a997..1e2bfa90354 100644 --- a/intern/cycles/util/ssef.h +++ b/intern/cycles/util/ssef.h @@ -523,7 +523,7 @@ __forceinline const ssef round_zero(const ssef &a) __forceinline const ssef floor(const ssef &a) { # ifdef __KERNEL_NEON__ - return vrndnq_f32(a); + return vrndmq_f32(a); # else return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF); # endif -- cgit v1.2.3 From 2f3f208901b5bf0fde7fbc9c3f02b66f7591b169 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 17 Oct 2022 11:16:39 +1100 Subject: Cleanup: spelling in comments, unused arg warning --- source/blender/blenkernel/BKE_mesh_types.h | 6 +++--- source/blender/blenkernel/BKE_paint.h | 7 ++++--- source/blender/draw/intern/draw_pbvh.cc | 2 +- source/blender/editors/space_outliner/outliner_draw.cc | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh_types.h b/source/blender/blenkernel/BKE_mesh_types.h index dacc2188abb..80f61086052 100644 --- a/source/blender/blenkernel/BKE_mesh_types.h +++ b/source/blender/blenkernel/BKE_mesh_types.h @@ -99,7 +99,7 @@ struct MeshRuntime { /** Cache for BVH trees generated for the mesh. Defined in 'BKE_bvhutil.c' */ BVHCache *bvh_cache = nullptr; - /** Cache of non-manifold boundary data for Shrinkwrap Target Project. */ + /** Cache of non-manifold boundary data for Shrink-wrap Target Project. */ ShrinkwrapBoundaryData *shrinkwrap_data = nullptr; /** Needed in case we need to lazily initialize the mesh. */ @@ -136,8 +136,8 @@ struct MeshRuntime { /** * Caches for lazily computed vertex and polygon normals. These are stored here rather than in - * #CustomData because they can be calculated on a const mesh, and adding custom data layers on a - * const mesh is not thread-safe. + * #CustomData because they can be calculated on a `const` mesh, and adding custom data layers on + * a `const` mesh is not thread-safe. */ bool vert_normals_dirty = false; bool poly_normals_dirty = false; diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 557edddac2a..437a22e4782 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -861,12 +861,13 @@ int *BKE_sculpt_face_sets_ensure(struct Mesh *mesh); */ bool *BKE_sculpt_hide_poly_ensure(struct Mesh *mesh); -/* Ensures a mask layer exists. If depsgraph and bmain are non-null, - * a mask doesn't exist and the object has a multiresolution modifier +/** + * Ensures a mask layer exists. If depsgraph and bmain are non-null, + * a mask doesn't exist and the object has a multi-resolution modifier * then the scene depsgraph will be evaluated to update the runtime * subdivision data. * - * Note: always call *before* BKE_sculpt_update_object_for_edit. + * \note always call *before* #BKE_sculpt_update_object_for_edit. */ int BKE_sculpt_mask_layers_ensure(struct Depsgraph *depsgraph, struct Main *bmain, diff --git a/source/blender/draw/intern/draw_pbvh.cc b/source/blender/draw/intern/draw_pbvh.cc index 60a0d4e6bb2..38fb6d55245 100644 --- a/source/blender/draw/intern/draw_pbvh.cc +++ b/source/blender/draw/intern/draw_pbvh.cc @@ -398,7 +398,7 @@ struct PBVHBatches { } else { foreach_grids( - [&](int /*x*/, int /*y*/, int /*grid_index*/, CCGElem * /*elems*/[4], int i) { + [&](int /*x*/, int /*y*/, int /*grid_index*/, CCGElem * /*elems*/[4], int /*i*/) { *static_cast(GPU_vertbuf_raw_step(&access)) = 0; }); } diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc index 34d1e1bb546..e366c58349f 100644 --- a/source/blender/editors/space_outliner/outliner_draw.cc +++ b/source/blender/editors/space_outliner/outliner_draw.cc @@ -2954,7 +2954,7 @@ static bool outliner_is_main_row(const ARegion *region, const int ys) /** * Get the expected row background color to use for the data-block counter * - * This reproduces somes of the logic of outliner_draw_highlights. + * This reproduces some of the logic of outliner_draw_highlights. * At the moment it doesn't implement the search match color since * we don't draw the data-block counter in those cases. */ -- cgit v1.2.3 From 1d1cade9a9a7f75034669520e39c56959917803a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 17 Oct 2022 11:16:41 +1100 Subject: BLI_path: remove trailing NULL argument to BLI_path_join Using varargs had the disadvantages, replace with a macro which has some advantages. - Arguments are type checked. - Less verbose. - Unintended NULL arguments would silently terminate joining paths. - Passing in a NULL argument warns with GCC. --- intern/mantaflow/intern/MANTA_main.cpp | 38 +++----- source/blender/blenkernel/intern/appdir.c | 26 +++--- source/blender/blenkernel/intern/asset_catalog.cc | 3 +- source/blender/blenkernel/intern/blendfile.c | 4 +- source/blender/blenkernel/intern/fluid.c | 15 ++-- source/blender/blenkernel/intern/image_save.cc | 4 +- source/blender/blenkernel/intern/packedFile.c | 2 +- source/blender/blenkernel/intern/preferences.c | 3 +- source/blender/blenlib/BLI_path_util.h | 100 ++++++++++++++++++++- source/blender/blenlib/intern/path_util.c | 14 +-- source/blender/blenlib/tests/BLI_path_util_test.cc | 2 +- .../tests/blendfile_loading_base_test.cc | 2 +- source/blender/editors/physics/physics_fluid.c | 16 ++-- source/blender/editors/space_file/file_ops.c | 3 +- source/blender/editors/space_file/fsmenu.c | 8 +- source/blender/editors/util/ed_util.c | 2 +- source/blender/io/common/intern/path_util.cc | 3 +- .../blender/io/usd/intern/usd_writer_material.cc | 12 +-- source/blender/io/usd/intern/usd_writer_volume.cc | 2 +- source/blender/io/usd/tests/usd_tests_common.cc | 2 +- .../importer/obj_import_file_reader.cc | 2 +- source/blender/windowmanager/intern/wm_files.c | 30 +++---- .../windowmanager/intern/wm_splash_screen.c | 2 +- 23 files changed, 184 insertions(+), 111 deletions(-) diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp index f5f22dc700b..ae584e6e590 100644 --- a/intern/mantaflow/intern/MANTA_main.cpp +++ b/intern/mantaflow/intern/MANTA_main.cpp @@ -1507,13 +1507,9 @@ bool MANTA::bakeData(FluidModifierData *fmd, int framenr) string volume_format = getCacheFileEnding(fds->cache_data_format); + BLI_path_join(cacheDirData, sizeof(cacheDirData), fds->cache_directory, FLUID_DOMAIN_DIR_DATA); BLI_path_join( - cacheDirData, sizeof(cacheDirData), fds->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr); - BLI_path_join(cacheDirGuiding, - sizeof(cacheDirGuiding), - fds->cache_directory, - FLUID_DOMAIN_DIR_GUIDE, - nullptr); + cacheDirGuiding, sizeof(cacheDirGuiding), fds->cache_directory, FLUID_DOMAIN_DIR_GUIDE); BLI_path_make_safe(cacheDirData); BLI_path_make_safe(cacheDirGuiding); @@ -1540,7 +1536,7 @@ bool MANTA::bakeNoise(FluidModifierData *fmd, int framenr) string volume_format = getCacheFileEnding(fds->cache_data_format); BLI_path_join( - cacheDirNoise, sizeof(cacheDirNoise), fds->cache_directory, FLUID_DOMAIN_DIR_NOISE, nullptr); + cacheDirNoise, sizeof(cacheDirNoise), fds->cache_directory, FLUID_DOMAIN_DIR_NOISE); BLI_path_make_safe(cacheDirNoise); ss.str(""); @@ -1566,8 +1562,7 @@ bool MANTA::bakeMesh(FluidModifierData *fmd, int framenr) string volume_format = getCacheFileEnding(fds->cache_data_format); string mesh_format = getCacheFileEnding(fds->cache_mesh_format); - BLI_path_join( - cacheDirMesh, sizeof(cacheDirMesh), fds->cache_directory, FLUID_DOMAIN_DIR_MESH, nullptr); + BLI_path_join(cacheDirMesh, sizeof(cacheDirMesh), fds->cache_directory, FLUID_DOMAIN_DIR_MESH); BLI_path_make_safe(cacheDirMesh); ss.str(""); @@ -1596,8 +1591,7 @@ bool MANTA::bakeParticles(FluidModifierData *fmd, int framenr) BLI_path_join(cacheDirParticles, sizeof(cacheDirParticles), fds->cache_directory, - FLUID_DOMAIN_DIR_PARTICLES, - nullptr); + FLUID_DOMAIN_DIR_PARTICLES); BLI_path_make_safe(cacheDirParticles); ss.str(""); @@ -1623,11 +1617,8 @@ bool MANTA::bakeGuiding(FluidModifierData *fmd, int framenr) string volume_format = getCacheFileEnding(fds->cache_data_format); string resumable_cache = !(fds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE) ? "False" : "True"; - BLI_path_join(cacheDirGuiding, - sizeof(cacheDirGuiding), - fds->cache_directory, - FLUID_DOMAIN_DIR_GUIDE, - nullptr); + BLI_path_join( + cacheDirGuiding, sizeof(cacheDirGuiding), fds->cache_directory, FLUID_DOMAIN_DIR_GUIDE); BLI_path_make_safe(cacheDirGuiding); ss.str(""); @@ -1678,13 +1669,11 @@ bool MANTA::exportSmokeScript(FluidModifierData *fmd) FluidDomainSettings *fds = fmd->domain; - BLI_path_join( - cacheDir, sizeof(cacheDir), fds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, nullptr); + BLI_path_join(cacheDir, sizeof(cacheDir), fds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT); BLI_path_make_safe(cacheDir); /* Create 'script' subdir if it does not exist already */ BLI_dir_create_recursive(cacheDir); - BLI_path_join( - cacheDirScript, sizeof(cacheDirScript), cacheDir, FLUID_DOMAIN_SMOKE_SCRIPT, nullptr); + BLI_path_join(cacheDirScript, sizeof(cacheDirScript), cacheDir, FLUID_DOMAIN_SMOKE_SCRIPT); BLI_path_make_safe(cacheDir); bool noise = fds->flags & FLUID_DOMAIN_USE_NOISE; @@ -1791,13 +1780,11 @@ bool MANTA::exportLiquidScript(FluidModifierData *fmd) FluidDomainSettings *fds = fmd->domain; - BLI_path_join( - cacheDir, sizeof(cacheDir), fds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, nullptr); + BLI_path_join(cacheDir, sizeof(cacheDir), fds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT); BLI_path_make_safe(cacheDir); /* Create 'script' subdir if it does not exist already */ BLI_dir_create_recursive(cacheDir); - BLI_path_join( - cacheDirScript, sizeof(cacheDirScript), cacheDir, FLUID_DOMAIN_LIQUID_SCRIPT, nullptr); + BLI_path_join(cacheDirScript, sizeof(cacheDirScript), cacheDir, FLUID_DOMAIN_LIQUID_SCRIPT); BLI_path_make_safe(cacheDirScript); bool mesh = fds->flags & FLUID_DOMAIN_USE_MESH; @@ -2323,8 +2310,7 @@ bool MANTA::hasGuiding(FluidModifierData *fmd, int framenr, bool sourceDomain) string MANTA::getDirectory(FluidModifierData *fmd, string subdirectory) { char directory[FILE_MAX]; - BLI_path_join( - directory, sizeof(directory), fmd->domain->cache_directory, subdirectory.c_str(), nullptr); + BLI_path_join(directory, sizeof(directory), fmd->domain->cache_directory, subdirectory.c_str()); BLI_path_make_safe(directory); return directory; } diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index b2f1e75cd1d..21750980b53 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -191,7 +191,7 @@ bool BKE_appdir_folder_documents(char *dir) char try_documents_path[FILE_MAXDIR]; /* Own attempt at getting a valid Documents path. */ - BLI_path_join(try_documents_path, sizeof(try_documents_path), home_path, N_("Documents"), NULL); + BLI_path_join(try_documents_path, sizeof(try_documents_path), home_path, N_("Documents")); if (!BLI_is_dir(try_documents_path)) { return false; } @@ -214,11 +214,11 @@ bool BKE_appdir_folder_caches(char *r_path, const size_t path_len) #ifdef WIN32 BLI_path_join( - r_path, path_len, caches_root_path, "Blender Foundation", "Blender", "Cache", SEP_STR, NULL); + r_path, path_len, caches_root_path, "Blender Foundation", "Blender", "Cache", SEP_STR); #elif defined(__APPLE__) - BLI_path_join(r_path, path_len, caches_root_path, "Blender", SEP_STR, NULL); + BLI_path_join(r_path, path_len, caches_root_path, "Blender", SEP_STR); #else /* __linux__ */ - BLI_path_join(r_path, path_len, caches_root_path, "blender", SEP_STR, NULL); + BLI_path_join(r_path, path_len, caches_root_path, "blender", SEP_STR); #endif return true; @@ -281,7 +281,9 @@ static bool test_path(char *targetpath, /* Only the last argument should be NULL. */ BLI_assert(!(folder_name == NULL && (subfolder_name != NULL))); - BLI_path_join(targetpath, targetpath_len, path_base, folder_name, subfolder_name, NULL); + const char *path_array[] = {path_base, folder_name, subfolder_name}; + const int path_array_num = (folder_name ? (subfolder_name ? 3 : 2) : 1); + BLI_path_join_array(targetpath, targetpath_len, path_array, path_array_num); if (check_is_dir == false) { CLOG_INFO(&LOG, 3, "using without test: '%s'", targetpath); return true; @@ -365,7 +367,9 @@ static bool get_path_local_ex(char *targetpath, STR_OR_FALLBACK(subfolder_name)); if (folder_name) { /* `subfolder_name` may be NULL. */ - BLI_path_join(relfolder, sizeof(relfolder), folder_name, subfolder_name, NULL); + const char *path_array[] = {folder_name, subfolder_name}; + const int path_array_num = subfolder_name ? 2 : 1; + BLI_path_join_array(relfolder, sizeof(relfolder), path_array, path_array_num); } else { relfolder[0] = '\0'; @@ -379,8 +383,7 @@ static bool get_path_local_ex(char *targetpath, * we must move the blender_version dir with contents to Resources. * Add 4 + 9 for the temporary `/../` path & `Resources`. */ char osx_resourses[FILE_MAX + 4 + 9]; - BLI_path_join( - osx_resourses, sizeof(osx_resourses), g_app.program_dirname, "..", "Resources", NULL); + BLI_path_join(osx_resourses, sizeof(osx_resourses), g_app.program_dirname, "..", "Resources"); /* Remove the '/../' added above. */ BLI_path_normalize(NULL, osx_resourses); path_base = osx_resourses; @@ -525,7 +528,9 @@ static bool get_path_system_ex(char *targetpath, char relfolder[FILE_MAX]; if (folder_name) { /* `subfolder_name` may be NULL. */ - BLI_path_join(relfolder, sizeof(relfolder), folder_name, subfolder_name, NULL); + const char *path_array[] = {folder_name, subfolder_name}; + const int path_array_num = subfolder_name ? 2 : 1; + BLI_path_join_array(relfolder, sizeof(relfolder), path_array, path_array_num); } else { relfolder[0] = '\0'; @@ -1041,8 +1046,7 @@ bool BKE_appdir_app_template_has_userpref(const char *app_template) } char userpref_path[FILE_MAX]; - BLI_path_join( - userpref_path, sizeof(userpref_path), app_template_path, BLENDER_USERPREF_FILE, NULL); + BLI_path_join(userpref_path, sizeof(userpref_path), app_template_path, BLENDER_USERPREF_FILE); return BLI_exists(userpref_path); } diff --git a/source/blender/blenkernel/intern/asset_catalog.cc b/source/blender/blenkernel/intern/asset_catalog.cc index f7b14cc3479..cedb0d8b4bf 100644 --- a/source/blender/blenkernel/intern/asset_catalog.cc +++ b/source/blender/blenkernel/intern/asset_catalog.cc @@ -515,8 +515,7 @@ CatalogFilePath AssetCatalogService::find_suitable_cdf_path_for_writing( BLI_path_join(asset_lib_cdf_path, sizeof(asset_lib_cdf_path), suitable_root_path, - DEFAULT_CATALOG_FILENAME.c_str(), - nullptr); + DEFAULT_CATALOG_FILENAME.c_str()); return asset_lib_cdf_path; } diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index 6546659f6cd..85a43b7c479 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -737,7 +737,7 @@ bool BKE_blendfile_userdef_write_all(ReportList *reports) if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL))) { bool ok_write; - BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL); + BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE); printf("Writing userprefs: '%s' ", filepath); if (use_template_userpref) { @@ -764,7 +764,7 @@ bool BKE_blendfile_userdef_write_all(ReportList *reports) if (use_template_userpref) { if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, U.app_template))) { /* Also save app-template prefs */ - BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL); + BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE); printf("Writing userprefs app-template: '%s' ", filepath); if (BKE_blendfile_userdef_write(filepath, reports) != 0) { diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 0a39207184a..5470231cd07 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -327,17 +327,17 @@ void BKE_fluid_cache_free(FluidDomainSettings *fds, Object *ob, int cache_map) if (cache_map & FLUID_DOMAIN_OUTDATED_DATA) { flags &= ~(FLUID_DOMAIN_BAKING_DATA | FLUID_DOMAIN_BAKED_DATA | FLUID_DOMAIN_OUTDATED_DATA); - BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_CONFIG, NULL); + BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_CONFIG); BLI_path_abs(temp_dir, relbase); if (BLI_exists(temp_dir)) { BLI_delete(temp_dir, true, true); } - BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_DATA, NULL); + BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_DATA); BLI_path_abs(temp_dir, relbase); if (BLI_exists(temp_dir)) { BLI_delete(temp_dir, true, true); } - BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, NULL); + BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT); BLI_path_abs(temp_dir, relbase); if (BLI_exists(temp_dir)) { BLI_delete(temp_dir, true, true); @@ -346,7 +346,7 @@ void BKE_fluid_cache_free(FluidDomainSettings *fds, Object *ob, int cache_map) } if (cache_map & FLUID_DOMAIN_OUTDATED_NOISE) { flags &= ~(FLUID_DOMAIN_BAKING_NOISE | FLUID_DOMAIN_BAKED_NOISE | FLUID_DOMAIN_OUTDATED_NOISE); - BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_NOISE, NULL); + BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_NOISE); BLI_path_abs(temp_dir, relbase); if (BLI_exists(temp_dir)) { BLI_delete(temp_dir, true, true); @@ -355,7 +355,7 @@ void BKE_fluid_cache_free(FluidDomainSettings *fds, Object *ob, int cache_map) } if (cache_map & FLUID_DOMAIN_OUTDATED_MESH) { flags &= ~(FLUID_DOMAIN_BAKING_MESH | FLUID_DOMAIN_BAKED_MESH | FLUID_DOMAIN_OUTDATED_MESH); - BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_MESH, NULL); + BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_MESH); BLI_path_abs(temp_dir, relbase); if (BLI_exists(temp_dir)) { BLI_delete(temp_dir, true, true); @@ -365,8 +365,7 @@ void BKE_fluid_cache_free(FluidDomainSettings *fds, Object *ob, int cache_map) if (cache_map & FLUID_DOMAIN_OUTDATED_PARTICLES) { flags &= ~(FLUID_DOMAIN_BAKING_PARTICLES | FLUID_DOMAIN_BAKED_PARTICLES | FLUID_DOMAIN_OUTDATED_PARTICLES); - BLI_path_join( - temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_PARTICLES, NULL); + BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_PARTICLES); BLI_path_abs(temp_dir, relbase); if (BLI_exists(temp_dir)) { BLI_delete(temp_dir, true, true); @@ -375,7 +374,7 @@ void BKE_fluid_cache_free(FluidDomainSettings *fds, Object *ob, int cache_map) } if (cache_map & FLUID_DOMAIN_OUTDATED_GUIDE) { flags &= ~(FLUID_DOMAIN_BAKING_GUIDE | FLUID_DOMAIN_BAKED_GUIDE | FLUID_DOMAIN_OUTDATED_GUIDE); - BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_GUIDE, NULL); + BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_GUIDE); BLI_path_abs(temp_dir, relbase); if (BLI_exists(temp_dir)) { BLI_delete(temp_dir, true, true); diff --git a/source/blender/blenkernel/intern/image_save.cc b/source/blender/blenkernel/intern/image_save.cc index e227f9cba5e..4e47e71fb2b 100644 --- a/source/blender/blenkernel/intern/image_save.cc +++ b/source/blender/blenkernel/intern/image_save.cc @@ -175,12 +175,12 @@ bool BKE_image_save_options_init(ImageSaveOptions *opts, BLI_strncpy(opts->filepath, G.ima, sizeof(opts->filepath)); } else { - BLI_path_join(opts->filepath, sizeof(opts->filepath), "//", DATA_("untitled"), nullptr); + BLI_path_join(opts->filepath, sizeof(opts->filepath), "//", DATA_("untitled")); BLI_path_abs(opts->filepath, BKE_main_blendfile_path(bmain)); } } else { - BLI_path_join(opts->filepath, sizeof(opts->filepath), "//", ima->id.name + 2, nullptr); + BLI_path_join(opts->filepath, sizeof(opts->filepath), "//", ima->id.name + 2); BLI_path_make_safe(opts->filepath); BLI_path_abs(opts->filepath, is_prev_save ? G.ima : BKE_main_blendfile_path(bmain)); } diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 901b42ac0b2..0c9d9f5b048 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -545,7 +545,7 @@ static void unpack_generate_paths(const char *name, break; } if (dir_name) { - BLI_path_join(r_relpath, relpathlen, "//", dir_name, tempname, NULL); + BLI_path_join(r_relpath, relpathlen, "//", dir_name, tempname); } } diff --git a/source/blender/blenkernel/intern/preferences.c b/source/blender/blenkernel/intern/preferences.c index b2e795901fb..dd76f9eddc1 100644 --- a/source/blender/blenkernel/intern/preferences.c +++ b/source/blender/blenkernel/intern/preferences.c @@ -115,8 +115,7 @@ void BKE_preferences_asset_library_default_add(UserDef *userdef) userdef, DATA_(BKE_PREFS_ASSET_LIBRARY_DEFAULT_NAME), NULL); /* Add new "Default" library under '[doc_path]/Blender/Assets'. */ - BLI_path_join( - library->path, sizeof(library->path), documents_path, N_("Blender"), N_("Assets"), NULL); + BLI_path_join(library->path, sizeof(library->path), documents_path, N_("Blender"), N_("Assets")); } /** \} */ diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 1e45e76afe1..739b894eafe 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -7,7 +7,9 @@ */ #include "BLI_compiler_attrs.h" +#include "BLI_compiler_compat.h" #include "BLI_utildefines.h" +#include "BLI_utildefines_variadic.h" #ifdef __cplusplus extern "C" { @@ -80,6 +82,14 @@ void BLI_join_dirfile(char *__restrict dst, size_t maxlen, const char *__restrict dir, const char *__restrict file) ATTR_NONNULL(); +/** + * See #BLI_path_join doc-string. + */ +size_t BLI_path_join_array(char *__restrict dst, + const size_t dst_len, + const char *path_array[], + const int path_array_num); + /** * Join multiple strings into a path, ensuring only a single path separator between each, * and trailing slash is kept. @@ -95,8 +105,94 @@ void BLI_join_dirfile(char *__restrict dst, * \note If you want a trailing slash, add `SEP_STR` as the last path argument, * duplicate slashes will be cleaned up. */ -size_t BLI_path_join(char *__restrict dst, size_t dst_len, const char *path, ...) - ATTR_NONNULL(1, 3) ATTR_SENTINEL(0); +#define BLI_path_join(...) VA_NARGS_CALL_OVERLOAD(_BLI_path_join_, __VA_ARGS__) + +#define _BLI_PATH_JOIN_ARGS_1 char *__restrict dst, size_t dst_len, const char *a +#define _BLI_PATH_JOIN_ARGS_2 _BLI_PATH_JOIN_ARGS_1, const char *b +#define _BLI_PATH_JOIN_ARGS_3 _BLI_PATH_JOIN_ARGS_2, const char *c +#define _BLI_PATH_JOIN_ARGS_4 _BLI_PATH_JOIN_ARGS_3, const char *d +#define _BLI_PATH_JOIN_ARGS_5 _BLI_PATH_JOIN_ARGS_4, const char *e +#define _BLI_PATH_JOIN_ARGS_6 _BLI_PATH_JOIN_ARGS_5, const char *f +#define _BLI_PATH_JOIN_ARGS_7 _BLI_PATH_JOIN_ARGS_6, const char *g +#define _BLI_PATH_JOIN_ARGS_8 _BLI_PATH_JOIN_ARGS_7, const char *h +#define _BLI_PATH_JOIN_ARGS_9 _BLI_PATH_JOIN_ARGS_8, const char *i +#define _BLI_PATH_JOIN_ARGS_10 _BLI_PATH_JOIN_ARGS_9, const char *j +#define _BLI_PATH_JOIN_ARGS_11 _BLI_PATH_JOIN_ARGS_10, const char *k + +BLI_INLINE size_t _BLI_path_join_3(_BLI_PATH_JOIN_ARGS_1) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_path_join_4(_BLI_PATH_JOIN_ARGS_2) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_path_join_5(_BLI_PATH_JOIN_ARGS_3) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_path_join_6(_BLI_PATH_JOIN_ARGS_4) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_path_join_7(_BLI_PATH_JOIN_ARGS_5) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_path_join_8(_BLI_PATH_JOIN_ARGS_6) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_path_join_9(_BLI_PATH_JOIN_ARGS_7) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_path_join_10(_BLI_PATH_JOIN_ARGS_8) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_path_join_11(_BLI_PATH_JOIN_ARGS_9) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_path_join_12(_BLI_PATH_JOIN_ARGS_10) ATTR_NONNULL(); + +BLI_INLINE size_t _BLI_path_join_3(_BLI_PATH_JOIN_ARGS_1) +{ + const char *path_array[] = {a}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} +BLI_INLINE size_t _BLI_path_join_4(_BLI_PATH_JOIN_ARGS_2) +{ + const char *path_array[] = {a, b}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} +BLI_INLINE size_t _BLI_path_join_5(_BLI_PATH_JOIN_ARGS_3) +{ + const char *path_array[] = {a, b, c}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} +BLI_INLINE size_t _BLI_path_join_6(_BLI_PATH_JOIN_ARGS_4) +{ + const char *path_array[] = {a, b, c, d}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} +BLI_INLINE size_t _BLI_path_join_7(_BLI_PATH_JOIN_ARGS_5) +{ + const char *path_array[] = {a, b, c, d, e}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} +BLI_INLINE size_t _BLI_path_join_8(_BLI_PATH_JOIN_ARGS_6) +{ + const char *path_array[] = {a, b, c, d, e, f}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} +BLI_INLINE size_t _BLI_path_join_9(_BLI_PATH_JOIN_ARGS_7) +{ + const char *path_array[] = {a, b, c, d, e, f, g}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} +BLI_INLINE size_t _BLI_path_join_10(_BLI_PATH_JOIN_ARGS_8) +{ + const char *path_array[] = {a, b, c, d, e, f, g, h}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} +BLI_INLINE size_t _BLI_path_join_11(_BLI_PATH_JOIN_ARGS_9) +{ + const char *path_array[] = {a, b, c, d, e, f, g, h, i}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} +BLI_INLINE size_t _BLI_path_join_12(_BLI_PATH_JOIN_ARGS_10) +{ + const char *path_array[] = {a, b, c, d, e, f, g, h, i, j}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} + +#undef _BLI_PATH_JOIN_ARGS_1 +#undef _BLI_PATH_JOIN_ARGS_2 +#undef _BLI_PATH_JOIN_ARGS_3 +#undef _BLI_PATH_JOIN_ARGS_4 +#undef _BLI_PATH_JOIN_ARGS_5 +#undef _BLI_PATH_JOIN_ARGS_6 +#undef _BLI_PATH_JOIN_ARGS_7 +#undef _BLI_PATH_JOIN_ARGS_8 +#undef _BLI_PATH_JOIN_ARGS_9 +#undef _BLI_PATH_JOIN_ARGS_10 +#undef _BLI_PATH_JOIN_ARGS_11 + /** * Like Python's `os.path.basename()` * diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 6ff4d57aecb..0a6e39504df 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1490,14 +1490,20 @@ void BLI_join_dirfile(char *__restrict dst, BLI_strncpy(dst + dirlen, file, maxlen - dirlen); } -size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *path, ...) +size_t BLI_path_join_array(char *__restrict dst, + const size_t dst_len, + const char *path_array[], + const int path_array_num) { + BLI_assert(path_array_num > 0); #ifdef DEBUG_STRSIZE memset(dst, 0xff, sizeof(*dst) * dst_len); #endif if (UNLIKELY(dst_len == 0)) { return 0; } + const char *path = path_array[0]; + const size_t dst_last = dst_len - 1; size_t ofs = BLI_strncpy_rlen(dst, path, dst_len); @@ -1519,9 +1525,8 @@ size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *pat has_trailing_slash = (path[len] != '\0'); } - va_list args; - va_start(args, path); - while ((path = (const char *)va_arg(args, const char *))) { + for (int path_index = 1; path_index < path_array_num; path_index++) { + path = path_array[path_index]; has_trailing_slash = false; const char *path_init = path; while (ELEM(path[0], SEP, ALTSEP)) { @@ -1556,7 +1561,6 @@ size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *pat has_trailing_slash = (path_init != path); } } - va_end(args); if (has_trailing_slash) { if ((ofs != dst_last) && (ofs != 0) && (ELEM(dst[ofs - 1], SEP, ALTSEP) == 0)) { diff --git a/source/blender/blenlib/tests/BLI_path_util_test.cc b/source/blender/blenlib/tests/BLI_path_util_test.cc index 2d415534693..89e537235db 100644 --- a/source/blender/blenlib/tests/BLI_path_util_test.cc +++ b/source/blender/blenlib/tests/BLI_path_util_test.cc @@ -207,7 +207,7 @@ TEST(path_util, NameAtIndex_NoneComplexNeg) char result[(out_size) + 1024]; \ /* check we don't write past the last byte */ \ result[out_size] = '\0'; \ - BLI_path_join(result, out_size, __VA_ARGS__, NULL); \ + BLI_path_join(result, out_size, __VA_ARGS__); \ /* simplify expected string */ \ BLI_str_replace_char(result, '\\', '/'); \ EXPECT_STREQ(result, expect); \ diff --git a/source/blender/blenloader/tests/blendfile_loading_base_test.cc b/source/blender/blenloader/tests/blendfile_loading_base_test.cc index 615e30a728e..b657970d45f 100644 --- a/source/blender/blenloader/tests/blendfile_loading_base_test.cc +++ b/source/blender/blenloader/tests/blendfile_loading_base_test.cc @@ -117,7 +117,7 @@ bool BlendfileLoadingBaseTest::blendfile_load(const char *filepath) } char abspath[FILENAME_MAX]; - BLI_path_join(abspath, sizeof(abspath), test_assets_dir.c_str(), filepath, nullptr); + BLI_path_join(abspath, sizeof(abspath), test_assets_dir.c_str(), filepath); BlendFileReadReport bf_reports = {nullptr}; bfile = BLO_read_from_file(abspath, BLO_READ_SKIP_NONE, &bf_reports); diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index 07e8f5c5743..314796e96e4 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -368,7 +368,7 @@ static void fluid_bake_startjob(void *customdata, short *stop, short *do_update, BKE_spacedata_draw_locks(true); if (fluid_is_bake_noise(job) || fluid_is_bake_all(job)) { - BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_NOISE, NULL); + BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_NOISE); BLI_path_abs(temp_dir, relbase); BLI_dir_create_recursive(temp_dir); /* Create 'noise' subdir if it does not exist already */ fds->cache_flag &= ~(FLUID_DOMAIN_BAKED_NOISE | FLUID_DOMAIN_OUTDATED_NOISE); @@ -376,7 +376,7 @@ static void fluid_bake_startjob(void *customdata, short *stop, short *do_update, job->pause_frame = &fds->cache_frame_pause_noise; } if (fluid_is_bake_mesh(job) || fluid_is_bake_all(job)) { - BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_MESH, NULL); + BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_MESH); BLI_path_abs(temp_dir, relbase); BLI_dir_create_recursive(temp_dir); /* Create 'mesh' subdir if it does not exist already */ fds->cache_flag &= ~(FLUID_DOMAIN_BAKED_MESH | FLUID_DOMAIN_OUTDATED_MESH); @@ -384,8 +384,7 @@ static void fluid_bake_startjob(void *customdata, short *stop, short *do_update, job->pause_frame = &fds->cache_frame_pause_mesh; } if (fluid_is_bake_particle(job) || fluid_is_bake_all(job)) { - BLI_path_join( - temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_PARTICLES, NULL); + BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_PARTICLES); BLI_path_abs(temp_dir, relbase); /* Create 'particles' subdir if it does not exist already */ @@ -396,7 +395,7 @@ static void fluid_bake_startjob(void *customdata, short *stop, short *do_update, job->pause_frame = &fds->cache_frame_pause_particles; } if (fluid_is_bake_guiding(job) || fluid_is_bake_all(job)) { - BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_GUIDE, NULL); + BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_GUIDE); BLI_path_abs(temp_dir, relbase); BLI_dir_create_recursive(temp_dir); /* Create 'guiding' subdir if it does not exist already */ fds->cache_flag &= ~(FLUID_DOMAIN_BAKED_GUIDE | FLUID_DOMAIN_OUTDATED_GUIDE); @@ -404,11 +403,11 @@ static void fluid_bake_startjob(void *customdata, short *stop, short *do_update, job->pause_frame = &fds->cache_frame_pause_guide; } if (fluid_is_bake_data(job) || fluid_is_bake_all(job)) { - BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_CONFIG, NULL); + BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_CONFIG); BLI_path_abs(temp_dir, relbase); BLI_dir_create_recursive(temp_dir); /* Create 'config' subdir if it does not exist already */ - BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_DATA, NULL); + BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_DATA); BLI_path_abs(temp_dir, relbase); BLI_dir_create_recursive(temp_dir); /* Create 'data' subdir if it does not exist already */ fds->cache_flag &= ~(FLUID_DOMAIN_BAKED_DATA | FLUID_DOMAIN_OUTDATED_DATA); @@ -416,8 +415,7 @@ static void fluid_bake_startjob(void *customdata, short *stop, short *do_update, job->pause_frame = &fds->cache_frame_pause_data; if (fds->flags & FLUID_DOMAIN_EXPORT_MANTA_SCRIPT) { - BLI_path_join( - temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, NULL); + BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT); BLI_path_abs(temp_dir, relbase); BLI_dir_create_recursive(temp_dir); /* Create 'script' subdir if it does not exist already */ } diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index f7fd910d6e9..63aa71e9855 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -2457,8 +2457,7 @@ static void file_expand_directory(bContext *C) else if (params->dir[0] == '~') { char tmpstr[sizeof(params->dir) - 1]; BLI_strncpy(tmpstr, params->dir + 1, sizeof(tmpstr)); - BLI_path_join( - params->dir, sizeof(params->dir), BKE_appdir_folder_default_or_root(), tmpstr, NULL); + BLI_path_join(params->dir, sizeof(params->dir), BKE_appdir_folder_default_or_root(), tmpstr); } else if (params->dir[0] == '\0') diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index 35ce7ef364c..a6c5e0f1734 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -113,10 +113,10 @@ static GHash *fsmenu_xdg_user_dirs_parse(const char *home) char filepath[FILE_MAX]; const char *xdg_config_home = getenv("XDG_CONFIG_HOME"); if (xdg_config_home != NULL) { - BLI_path_join(filepath, sizeof(filepath), xdg_config_home, "user-dirs.dirs", NULL); + BLI_path_join(filepath, sizeof(filepath), xdg_config_home, "user-dirs.dirs"); } else { - BLI_path_join(filepath, sizeof(filepath), home, ".config", "user-dirs.dirs", NULL); + BLI_path_join(filepath, sizeof(filepath), home, ".config", "user-dirs.dirs"); } fp = BLI_fopen(filepath, "r"); if (!fp) { @@ -147,7 +147,7 @@ static GHash *fsmenu_xdg_user_dirs_parse(const char *home) * Based on the 'user-dirs.dirs' man page, * there is no need to resolve arbitrary environment variables. */ if (STRPREFIX(l_value, "$HOME" SEP_STR)) { - BLI_path_join(l_value_expanded, sizeof(l_value_expanded), home, l_value + 6, NULL); + BLI_path_join(l_value_expanded, sizeof(l_value_expanded), home, l_value + 6); l_value_final = l_value_expanded; } @@ -186,7 +186,7 @@ static void fsmenu_xdg_insert_entry(GHash *xdg_map, char xdg_path_buf[FILE_MAXDIR]; const char *xdg_path = xdg_map ? BLI_ghash_lookup(xdg_map, key) : NULL; if (xdg_path == NULL) { - BLI_path_join(xdg_path_buf, sizeof(xdg_path_buf), home, default_path, NULL); + BLI_path_join(xdg_path_buf, sizeof(xdg_path_buf), home, default_path); xdg_path = xdg_path_buf; } fsmenu_insert_entry( diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 12e77c6ef00..92d65688bf1 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -374,7 +374,7 @@ void unpack_menu(bContext *C, char local_name[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX]; BLI_split_file_part(abs_name, fi, sizeof(fi)); - BLI_path_join(local_name, sizeof(local_name), "//", folder, fi, NULL); + BLI_path_join(local_name, sizeof(local_name), "//", folder, fi); if (!STREQ(abs_name, local_name)) { switch (BKE_packedfile_compare_to_file(blendfile_path, local_name, pf)) { case PF_CMP_NOFILE: diff --git a/source/blender/io/common/intern/path_util.cc b/source/blender/io/common/intern/path_util.cc index 18632b410f8..63ff6cf29ee 100644 --- a/source/blender/io/common/intern/path_util.cc +++ b/source/blender/io/common/intern/path_util.cc @@ -28,8 +28,7 @@ std::string path_reference(StringRefNull filepath, } else if (mode == PATH_REFERENCE_COPY) { char filepath_cpy[PATH_MAX]; - BLI_path_join( - filepath_cpy, PATH_MAX, base_dst.c_str(), BLI_path_basename(filepath_abs), nullptr); + BLI_path_join(filepath_cpy, PATH_MAX, base_dst.c_str(), BLI_path_basename(filepath_abs)); copy_set->add(std::make_pair(filepath_abs, filepath_cpy)); BLI_strncpy(filepath_abs, filepath_cpy, PATH_MAX); mode = PATH_REFERENCE_RELATIVE; diff --git a/source/blender/io/usd/intern/usd_writer_material.cc b/source/blender/io/usd/intern/usd_writer_material.cc index c195bf0e0bd..75abae79519 100644 --- a/source/blender/io/usd/intern/usd_writer_material.cc +++ b/source/blender/io/usd/intern/usd_writer_material.cc @@ -380,7 +380,7 @@ static void export_in_memory_texture(Image *ima, BKE_image_path_ensure_ext_from_imformat(file_name, &imageFormat); char export_path[FILE_MAX]; - BLI_path_join(export_path, FILE_MAX, export_dir.c_str(), file_name, nullptr); + BLI_path_join(export_path, FILE_MAX, export_dir.c_str(), file_name); if (!allow_overwrite && BLI_exists(export_path)) { return; @@ -576,7 +576,7 @@ static std::string get_tex_image_asset_path(bNode *node, BLI_split_file_part(path.c_str(), file_path, FILE_MAX); if (export_params.relative_paths) { - BLI_path_join(exp_path, FILE_MAX, ".", "textures", file_path, nullptr); + BLI_path_join(exp_path, FILE_MAX, ".", "textures", file_path); } else { /* Create absolute path in the textures directory. */ @@ -588,7 +588,7 @@ static std::string get_tex_image_asset_path(bNode *node, char dir_path[FILE_MAX]; BLI_split_dir_part(stage_path.c_str(), dir_path, FILE_MAX); - BLI_path_join(exp_path, FILE_MAX, dir_path, "textures", file_path, nullptr); + BLI_path_join(exp_path, FILE_MAX, dir_path, "textures", file_path); } BLI_str_replace_char(exp_path, '\\', '/'); return exp_path; @@ -645,7 +645,7 @@ static void copy_tiled_textures(Image *ima, BLI_split_file_part(src_tile_path, dest_filename, sizeof(dest_filename)); char dest_tile_path[FILE_MAX]; - BLI_path_join(dest_tile_path, FILE_MAX, dest_dir.c_str(), dest_filename, nullptr); + BLI_path_join(dest_tile_path, FILE_MAX, dest_dir.c_str(), dest_filename); if (!allow_overwrite && BLI_exists(dest_tile_path)) { continue; @@ -680,7 +680,7 @@ static void copy_single_file(Image *ima, const std::string &dest_dir, const bool BLI_split_file_part(source_path, file_name, FILE_MAX); char dest_path[FILE_MAX]; - BLI_path_join(dest_path, FILE_MAX, dest_dir.c_str(), file_name, nullptr); + BLI_path_join(dest_path, FILE_MAX, dest_dir.c_str(), file_name); if (!allow_overwrite && BLI_exists(dest_path)) { return; @@ -726,7 +726,7 @@ static void export_texture(bNode *node, BLI_split_dir_part(stage_path.c_str(), usd_dir_path, FILE_MAX); char tex_dir_path[FILE_MAX]; - BLI_path_join(tex_dir_path, FILE_MAX, usd_dir_path, "textures", SEP_STR, nullptr); + BLI_path_join(tex_dir_path, FILE_MAX, usd_dir_path, "textures", SEP_STR); BLI_dir_create_recursive(tex_dir_path); diff --git a/source/blender/io/usd/intern/usd_writer_volume.cc b/source/blender/io/usd/intern/usd_writer_volume.cc index 8cc3c65ee70..c6a27c5f663 100644 --- a/source/blender/io/usd/intern/usd_writer_volume.cc +++ b/source/blender/io/usd/intern/usd_writer_volume.cc @@ -152,7 +152,7 @@ std::optional USDVolumeWriter::construct_vdb_file_path(const Volume strcat(vdb_file_name, ".vdb"); char vdb_file_path[FILE_MAX]; - BLI_path_join(vdb_file_path, sizeof(vdb_file_path), vdb_directory_path, vdb_file_name, nullptr); + BLI_path_join(vdb_file_path, sizeof(vdb_file_path), vdb_directory_path, vdb_file_name); return vdb_file_path; } diff --git a/source/blender/io/usd/tests/usd_tests_common.cc b/source/blender/io/usd/tests/usd_tests_common.cc index 9f18a289433..ea4e704006d 100644 --- a/source/blender/io/usd/tests/usd_tests_common.cc +++ b/source/blender/io/usd/tests/usd_tests_common.cc @@ -29,7 +29,7 @@ std::string register_usd_plugins_for_tests() } const size_t path_len = BLI_path_join( - usd_datafiles_dir, FILE_MAX, release_dir.c_str(), "datafiles", "usd", nullptr); + usd_datafiles_dir, FILE_MAX, release_dir.c_str(), "datafiles", "usd"); /* #BLI_path_join removes trailing slashes, but the USD library requires one in order to * recognize the path as directory. */ diff --git a/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc b/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc index 0781028c880..7d5f023af4b 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc @@ -765,7 +765,7 @@ MTLParser::MTLParser(StringRefNull mtl_library, StringRefNull obj_filepath) { char obj_file_dir[FILE_MAXDIR]; BLI_split_dir_part(obj_filepath.data(), obj_file_dir, FILE_MAXDIR); - BLI_path_join(mtl_file_path_, FILE_MAX, obj_file_dir, mtl_library.data(), nullptr); + BLI_path_join(mtl_file_path_, FILE_MAX, obj_file_dir, mtl_library.data()); BLI_split_dir_part(mtl_file_path_, mtl_dir_path_, FILE_MAXDIR); } diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 7ac55b2c27a..a3593a33bae 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -1166,12 +1166,10 @@ void wm_homefile_read_ex(bContext *C, const char *const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL); if (!use_factory_settings) { if (cfgdir) { - BLI_path_join( - filepath_startup, sizeof(filepath_startup), cfgdir, BLENDER_STARTUP_FILE, NULL); + BLI_path_join(filepath_startup, sizeof(filepath_startup), cfgdir, BLENDER_STARTUP_FILE); filepath_startup_is_factory = false; if (use_userdef) { - BLI_path_join( - filepath_userdef, sizeof(filepath_startup), cfgdir, BLENDER_USERPREF_FILE, NULL); + BLI_path_join(filepath_userdef, sizeof(filepath_startup), cfgdir, BLENDER_USERPREF_FILE); } } else { @@ -1214,12 +1212,9 @@ void wm_homefile_read_ex(bContext *C, /* note that the path is being set even when 'use_factory_settings == true' * this is done so we can load a templates factory-settings */ if (!use_factory_settings) { - BLI_path_join(app_template_config, sizeof(app_template_config), cfgdir, app_template, NULL); - BLI_path_join(filepath_startup, - sizeof(filepath_startup), - app_template_config, - BLENDER_STARTUP_FILE, - NULL); + BLI_path_join(app_template_config, sizeof(app_template_config), cfgdir, app_template); + BLI_path_join( + filepath_startup, sizeof(filepath_startup), app_template_config, BLENDER_STARTUP_FILE); filepath_startup_is_factory = false; if (BLI_access(filepath_startup, R_OK) != 0) { filepath_startup[0] = '\0'; @@ -1230,11 +1225,8 @@ void wm_homefile_read_ex(bContext *C, } if (filepath_startup[0] == '\0') { - BLI_path_join(filepath_startup, - sizeof(filepath_startup), - app_template_system, - BLENDER_STARTUP_FILE, - NULL); + BLI_path_join( + filepath_startup, sizeof(filepath_startup), app_template_system, BLENDER_STARTUP_FILE); filepath_startup_is_factory = true; /* Update defaults only for system templates. */ @@ -1303,16 +1295,14 @@ void wm_homefile_read_ex(bContext *C, char temp_path[FILE_MAX]; temp_path[0] = '\0'; if (!use_factory_settings) { - BLI_path_join( - temp_path, sizeof(temp_path), app_template_config, BLENDER_USERPREF_FILE, NULL); + BLI_path_join(temp_path, sizeof(temp_path), app_template_config, BLENDER_USERPREF_FILE); if (BLI_access(temp_path, R_OK) != 0) { temp_path[0] = '\0'; } } if (temp_path[0] == '\0') { - BLI_path_join( - temp_path, sizeof(temp_path), app_template_system, BLENDER_USERPREF_FILE, NULL); + BLI_path_join(temp_path, sizeof(temp_path), app_template_system, BLENDER_USERPREF_FILE); } if (use_userdef) { @@ -2132,7 +2122,7 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op) /* update keymaps in user preferences */ WM_keyconfig_update(wm); - BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_STARTUP_FILE, NULL); + BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_STARTUP_FILE); printf("Writing homefile: '%s' ", filepath); diff --git a/source/blender/windowmanager/intern/wm_splash_screen.c b/source/blender/windowmanager/intern/wm_splash_screen.c index 8fca3deef92..48325b28f5a 100644 --- a/source/blender/windowmanager/intern/wm_splash_screen.c +++ b/source/blender/windowmanager/intern/wm_splash_screen.c @@ -218,7 +218,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *region, void *UNUSE const char *const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL); if (cfgdir) { - BLI_path_join(userpref, sizeof(userpref), cfgdir, BLENDER_USERPREF_FILE, NULL); + BLI_path_join(userpref, sizeof(userpref), cfgdir, BLENDER_USERPREF_FILE); } /* Draw setup screen if no preferences have been saved yet. */ -- cgit v1.2.3 From 9f6a045e23cf4ab132ef78eeaf070bd53d0c509f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 17 Oct 2022 11:30:48 +1100 Subject: Cleanup: replace BLI_join_dirfile with BLI_path_join These functions are almost identical, the main difference being BLI_join_dirfile didn't trim existing slashes when joining paths however this isn't an important difference that warrants a separate function. --- intern/mantaflow/intern/MANTA_main.cpp | 2 +- source/blender/blenfont/intern/blf_dir.c | 2 +- source/blender/blenfont/intern/blf_font_default.c | 2 +- source/blender/blenkernel/intern/appdir.c | 4 +- source/blender/blenkernel/intern/asset_catalog.cc | 8 ++-- source/blender/blenkernel/intern/blender_undo.c | 2 +- source/blender/blenkernel/intern/bpath.c | 4 +- source/blender/blenkernel/intern/image.cc | 4 +- source/blender/blenkernel/intern/modifier.cc | 2 +- source/blender/blenkernel/intern/ocean.c | 2 +- source/blender/blenkernel/intern/pointcache.c | 6 +-- source/blender/blenlib/BLI_path_util.h | 12 +----- source/blender/blenlib/intern/BLI_filelist.c | 2 +- source/blender/blenlib/intern/fileops.c | 4 +- source/blender/blenlib/intern/path_util.c | 46 +--------------------- source/blender/blenloader/intern/versioning_250.c | 2 +- source/blender/blentranslation/intern/blt_lang.c | 2 +- source/blender/compositor/intern/COM_Debug.cc | 2 +- .../blender/compositor/nodes/COM_OutputFileNode.cc | 2 +- source/blender/editors/armature/pose_transform.c | 4 +- source/blender/editors/asset/intern/asset_list.cc | 2 +- source/blender/editors/asset/intern/asset_ops.cc | 2 +- source/blender/editors/interface/interface_icons.c | 4 +- source/blender/editors/interface/interface_ops.cc | 4 +- source/blender/editors/io/io_gpencil_import.c | 2 +- source/blender/editors/io/io_obj.c | 3 +- source/blender/editors/io/io_stl_ops.c | 2 +- source/blender/editors/physics/dynamicpaint_ops.c | 4 +- source/blender/editors/render/render_preview.cc | 2 +- source/blender/editors/screen/workspace_edit.c | 5 +-- source/blender/editors/space_clip/clip_ops.c | 2 +- source/blender/editors/space_file/file_draw.c | 6 +-- source/blender/editors/space_file/file_ops.c | 14 +++---- source/blender/editors/space_file/filelist.cc | 16 ++++---- source/blender/editors/space_file/filesel.c | 2 +- source/blender/editors/space_file/fsmenu.c | 18 ++++----- source/blender/editors/space_file/space_file.c | 2 +- .../blender/editors/space_image/image_sequence.c | 4 +- .../editors/space_outliner/outliner_edit.cc | 4 +- .../editors/space_sequencer/sequencer_add.c | 6 +-- .../editors/space_sequencer/sequencer_draw.c | 2 +- .../editors/space_sequencer/sequencer_edit.c | 2 +- source/blender/editors/space_view3d/view3d_ops.c | 4 +- .../freestyle/intern/python/BPy_Freestyle.cpp | 2 +- source/blender/imbuf/intern/colormanagement.c | 2 +- source/blender/imbuf/intern/indexer.c | 4 +- source/blender/io/collada/DocumentExporter.cpp | 2 +- source/blender/io/collada/DocumentImporter.cpp | 2 +- source/blender/io/collada/ImageExporter.cpp | 2 +- source/blender/makesrna/intern/rna_sequencer.c | 8 ++-- source/blender/render/intern/render_result.cc | 2 +- source/blender/sequencer/intern/proxy.c | 4 +- source/blender/sequencer/intern/render.c | 2 +- source/blender/sequencer/intern/strip_add.c | 4 +- source/blender/sequencer/intern/utils.c | 2 +- source/blender/windowmanager/intern/wm_files.c | 10 ++--- .../blender/windowmanager/intern/wm_files_link.c | 10 ++--- source/blender/windowmanager/intern/wm_init_exit.c | 2 +- .../windowmanager/intern/wm_platform_support.c | 2 +- .../windowmanager/intern/wm_splash_screen.c | 2 +- source/creator/creator_signals.c | 7 ++-- 61 files changed, 120 insertions(+), 175 deletions(-) diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp index ae584e6e590..5708cdc81aa 100644 --- a/intern/mantaflow/intern/MANTA_main.cpp +++ b/intern/mantaflow/intern/MANTA_main.cpp @@ -2321,7 +2321,7 @@ string MANTA::getFile( char targetFile[FILE_MAX]; string path = getDirectory(fmd, subdirectory); string filename = fname + "_####" + extension; - BLI_join_dirfile(targetFile, sizeof(targetFile), path.c_str(), filename.c_str()); + BLI_path_join(targetFile, sizeof(targetFile), path.c_str(), filename.c_str()); BLI_path_frame(targetFile, framenr, 0); return targetFile; } diff --git a/source/blender/blenfont/intern/blf_dir.c b/source/blender/blenfont/intern/blf_dir.c index 8534a8c583f..395d981cb0b 100644 --- a/source/blender/blenfont/intern/blf_dir.c +++ b/source/blender/blenfont/intern/blf_dir.c @@ -115,7 +115,7 @@ char *blf_dir_search(const char *file) char *s = NULL; for (dir = global_font_dir.first; dir; dir = dir->next) { - BLI_join_dirfile(full_path, sizeof(full_path), dir->path, file); + BLI_path_join(full_path, sizeof(full_path), dir->path, file); if (BLI_exists(full_path)) { s = BLI_strdup(full_path); break; diff --git a/source/blender/blenfont/intern/blf_font_default.c b/source/blender/blenfont/intern/blf_font_default.c index d35692f6eae..63b1cf34db5 100644 --- a/source/blender/blenfont/intern/blf_font_default.c +++ b/source/blender/blenfont/intern/blf_font_default.c @@ -32,7 +32,7 @@ static int blf_load_font_default(const char *filename, const bool unique) } char filepath[FILE_MAX]; - BLI_join_dirfile(filepath, sizeof(filepath), dir, filename); + BLI_path_join(filepath, sizeof(filepath), dir, filename); return (unique) ? BLF_load_unique(filepath) : BLF_load(filepath); } diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 21750980b53..965f48d1e51 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -954,7 +954,7 @@ bool BKE_appdir_program_python_search(char *fullpath, if (python_bin_dir) { for (int i = 0; i < ARRAY_SIZE(python_names); i++) { - BLI_join_dirfile(fullpath, fullpath_len, python_bin_dir, python_names[i]); + BLI_path_join(fullpath, fullpath_len, python_bin_dir, python_names[i]); if ( #ifdef _WIN32 @@ -1023,7 +1023,7 @@ bool BKE_appdir_app_template_id_search(const char *app_template, char *path, siz { for (int i = 0; i < ARRAY_SIZE(app_template_directory_id); i++) { char subdir[FILE_MAX]; - BLI_join_dirfile(subdir, sizeof(subdir), app_template_directory_search[i], app_template); + BLI_path_join(subdir, sizeof(subdir), app_template_directory_search[i], app_template); if (BKE_appdir_folder_id_ex(app_template_directory_id[i], subdir, path, path_len)) { return true; } diff --git a/source/blender/blenkernel/intern/asset_catalog.cc b/source/blender/blenkernel/intern/asset_catalog.cc index cedb0d8b4bf..38c712d7e75 100644 --- a/source/blender/blenkernel/intern/asset_catalog.cc +++ b/source/blender/blenkernel/intern/asset_catalog.cc @@ -284,10 +284,10 @@ AssetCatalog *AssetCatalogService::create_catalog(const AssetCatalogPath &catalo static std::string asset_definition_default_file_path_from_dir(StringRef asset_library_root) { char file_path[PATH_MAX]; - BLI_join_dirfile(file_path, - sizeof(file_path), - asset_library_root.data(), - AssetCatalogService::DEFAULT_CATALOG_FILENAME.data()); + BLI_path_join(file_path, + sizeof(file_path), + asset_library_root.data(), + AssetCatalogService::DEFAULT_CATALOG_FILENAME.data()); return file_path; } diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c index a5096b4f9eb..f22dfc6054a 100644 --- a/source/blender/blenkernel/intern/blender_undo.c +++ b/source/blender/blenkernel/intern/blender_undo.c @@ -116,7 +116,7 @@ MemFileUndoData *BKE_memfile_undo_encode(Main *bmain, MemFileUndoData *mfu_prev) counter = counter % U.undosteps; BLI_snprintf(numstr, sizeof(numstr), "%d.blend", counter); - BLI_join_dirfile(filepath, sizeof(filepath), BKE_tempdir_session(), numstr); + BLI_path_join(filepath, sizeof(filepath), BKE_tempdir_session(), numstr); /* success = */ /* UNUSED */ BLO_write_file( bmain, filepath, fileflags, &(const struct BlendFileWriteParams){0}, NULL); diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index f639d03ae0f..6bf121675bc 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -155,7 +155,7 @@ bool BKE_bpath_foreach_path_dirfile_fixed_process(BPathForeachPathData *bpath_da char path_src[FILE_MAX]; char path_dst[FILE_MAX]; - BLI_join_dirfile(path_src, sizeof(path_src), path_dir, path_file); + BLI_path_join(path_src, sizeof(path_src), path_dir, path_file); /* So that functions can access the old value. */ BLI_strncpy(path_dst, path_src, FILE_MAX); @@ -279,7 +279,7 @@ static bool missing_files_find__recursive(const char *search_directory, continue; } - BLI_join_dirfile(path, sizeof(path), search_directory, de->d_name); + BLI_path_join(path, sizeof(path), search_directory, de->d_name); if (BLI_stat(path, &status) == -1) { CLOG_WARN(&LOG, "Cannot get file status (`stat()`) of '%s'", path); diff --git a/source/blender/blenkernel/intern/image.cc b/source/blender/blenkernel/intern/image.cc index 409eb0067b5..51d8f02616f 100644 --- a/source/blender/blenkernel/intern/image.cc +++ b/source/blender/blenkernel/intern/image.cc @@ -297,7 +297,7 @@ static void image_foreach_path(ID *id, BPathForeachPathData *bpath_data) /* Put the filepath back together using the new directory and the original file name. */ char new_dir[FILE_MAXDIR]; BLI_split_dir_part(temp_path, new_dir, sizeof(new_dir)); - BLI_join_dirfile(ima->filepath, sizeof(ima->filepath), new_dir, orig_file); + BLI_path_join(ima->filepath, sizeof(ima->filepath), new_dir, orig_file); } } else { @@ -3331,7 +3331,7 @@ bool BKE_image_get_tile_info(char *filepath, ListBase *tiles, int *r_tile_start, MEM_SAFE_FREE(udim_pattern); if (all_valid_udim && min_udim <= IMA_UDIM_MAX) { - BLI_join_dirfile(filepath, FILE_MAX, dirname, filename); + BLI_path_join(filepath, FILE_MAX, dirname, filename); *r_tile_start = min_udim; *r_tile_range = max_udim - min_udim + 1; diff --git a/source/blender/blenkernel/intern/modifier.cc b/source/blender/blenkernel/intern/modifier.cc index fc1a0f47684..92a7c778b68 100644 --- a/source/blender/blenkernel/intern/modifier.cc +++ b/source/blender/blenkernel/intern/modifier.cc @@ -955,7 +955,7 @@ const char *BKE_modifier_path_relbase_from_global(Object *ob) void BKE_modifier_path_init(char *path, int path_maxlen, const char *name) { const char *blendfile_path = BKE_main_blendfile_path_from_global(); - BLI_join_dirfile(path, path_maxlen, blendfile_path[0] ? "//" : BKE_tempdir_session(), name); + BLI_path_join(path, path_maxlen, blendfile_path[0] ? "//" : BKE_tempdir_session(), name); } /** diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 396c3443a73..bcf382b6022 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -1144,7 +1144,7 @@ static void cache_filename( break; } - BLI_join_dirfile(cachepath, sizeof(cachepath), path, fname); + BLI_path_join(cachepath, sizeof(cachepath), path, fname); BKE_image_path_from_imtype( string, cachepath, relbase, frame, R_IMF_IMTYPE_OPENEXR, true, true, ""); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 5ec69f9bc45..ac98bed2cf0 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -2640,7 +2640,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, uint cfra) if (STREQLEN(filepath, de->d_name, len)) { /* Do we have the right prefix. */ if (mode == PTCACHE_CLEAR_ALL) { pid->cache->last_exact = MIN2(pid->cache->startframe, 0); - BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); + BLI_path_join(path_full, sizeof(path_full), path, de->d_name); BLI_delete(path_full, false, false); } else { @@ -2650,7 +2650,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, uint cfra) if (frame != -1) { if ((mode == PTCACHE_CLEAR_BEFORE && frame < cfra) || (mode == PTCACHE_CLEAR_AFTER && frame > cfra)) { - BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); + BLI_path_join(path_full, sizeof(path_full), path, de->d_name); BLI_delete(path_full, false, false); if (pid->cache->cached_frames && frame >= sta && frame <= end) { pid->cache->cached_frames[frame - sta] = 0; @@ -3524,7 +3524,7 @@ void BKE_ptcache_disk_cache_rename(PTCacheID *pid, const char *name_src, const c const int frame = ptcache_frame_from_filename(de->d_name, ext); if (frame != -1) { - BLI_join_dirfile(old_path_full, sizeof(old_path_full), path, de->d_name); + BLI_path_join(old_path_full, sizeof(old_path_full), path, de->d_name); ptcache_filepath(pid, new_path_full, frame, true, true); BLI_rename(old_path_full, new_path_full); } diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 739b894eafe..4610b71dcd5 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -71,17 +71,7 @@ const char *BLI_path_extension(const char *filepath) ATTR_NONNULL(); */ void BLI_path_append(char *__restrict dst, size_t maxlen, const char *__restrict file) ATTR_NONNULL(); -/** - * Simple appending of filename to dir, does not check for valid path! - * Puts result into `dst`, which may be same area as `dir`. - * - * \note Consider using #BLI_path_join for more general path joining - * that de-duplicates separators and can handle an arbitrary number of paths. - */ -void BLI_join_dirfile(char *__restrict dst, - size_t maxlen, - const char *__restrict dir, - const char *__restrict file) ATTR_NONNULL(); + /** * See #BLI_path_join doc-string. */ diff --git a/source/blender/blenlib/intern/BLI_filelist.c b/source/blender/blenlib/intern/BLI_filelist.c index 1ce6beab933..4bcb023691a 100644 --- a/source/blender/blenlib/intern/BLI_filelist.c +++ b/source/blender/blenlib/intern/BLI_filelist.c @@ -174,7 +174,7 @@ static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) struct direntry *file = &dir_ctx->files[dir_ctx->files_num]; while (dlink) { char fullname[PATH_MAX]; - BLI_join_dirfile(fullname, sizeof(fullname), dirname, dlink->name); + BLI_path_join(fullname, sizeof(fullname), dirname, dlink->name); memset(file, 0, sizeof(struct direntry)); file->relname = dlink->name; file->path = BLI_strdup(fullname); diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index 3abd482d6b3..a157302e51e 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -627,7 +627,7 @@ static void join_dirfile_alloc(char **dst, size_t *alloc_len, const char *dir, c *alloc_len = len; - BLI_join_dirfile(*dst, len + 1, dir, file); + BLI_path_join(*dst, len + 1, dir, file); } static char *strip_last_slash(const char *dir) @@ -1184,7 +1184,7 @@ static const char *check_destination(const char *file, const char *to) len = strlen(to) + strlen(filename) + 1; path = MEM_callocN(len + 1, "check_destination path"); - BLI_join_dirfile(path, len + 1, to, filename); + BLI_path_join(path, len + 1, to, filename); MEM_freeN(str); diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 0a6e39504df..afe8c3cc033 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -625,7 +625,7 @@ bool BLI_path_parent_dir(char *path) const char parent_dir[] = {'.', '.', SEP, '\0'}; /* "../" or "..\\" */ char tmp[FILE_MAX + 4]; - BLI_join_dirfile(tmp, sizeof(tmp), path, parent_dir); + BLI_path_join(tmp, sizeof(tmp), path, parent_dir); BLI_path_normalize(NULL, tmp); /* does all the work of normalizing the path for us */ if (!BLI_path_extension_check(tmp, parent_dir)) { @@ -1025,7 +1025,7 @@ bool BLI_path_abs_from_cwd(char *path, const size_t maxlen) if (BLI_current_working_dir(cwd, sizeof(cwd))) { char origpath[FILE_MAX]; BLI_strncpy(origpath, path, FILE_MAX); - BLI_join_dirfile(path, maxlen, cwd, origpath); + BLI_path_join(path, maxlen, cwd, origpath); } else { printf("Could not get the current working directory - $PWD for an unknown reason.\n"); @@ -1448,48 +1448,6 @@ void BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__re BLI_strncpy(dst + dirlen, file, maxlen - dirlen); } -void BLI_join_dirfile(char *__restrict dst, - const size_t maxlen, - const char *__restrict dir, - const char *__restrict file) -{ -#ifdef DEBUG_STRSIZE - memset(dst, 0xff, sizeof(*dst) * maxlen); -#endif - size_t dirlen = BLI_strnlen(dir, maxlen); - - /* Arguments can't match. */ - BLI_assert(!ELEM(dst, dir, file)); - - /* Files starting with a separator cause a double-slash which could later be interpreted - * as a relative path where: `dir == "/"` and `file == "/file"` would result in "//file". */ - BLI_assert(file[0] != SEP); - - if (dirlen == maxlen) { - memcpy(dst, dir, dirlen); - dst[dirlen - 1] = '\0'; - return; /* dir fills the path */ - } - - memcpy(dst, dir, dirlen + 1); - - if (dirlen + 1 >= maxlen) { - return; /* fills the path */ - } - - /* inline BLI_path_slash_ensure */ - if ((dirlen > 0) && !ELEM(dst[dirlen - 1], SEP, ALTSEP)) { - dst[dirlen++] = SEP; - dst[dirlen] = '\0'; - } - - if (dirlen >= maxlen) { - return; /* fills the path */ - } - - BLI_strncpy(dst + dirlen, file, maxlen - dirlen); -} - size_t BLI_path_join_array(char *__restrict dst, const size_t dst_len, const char *path_array[], diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index 3a39ed04d2a..0b543ad735b 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -630,7 +630,7 @@ static bool seq_sound_proxy_update_cb(Sequence *seq, void *user_data) Main *bmain = (Main *)user_data; if (seq->type == SEQ_TYPE_SOUND_HD) { char str[FILE_MAX]; - BLI_join_dirfile(str, sizeof(str), seq->strip->dir, seq->strip->stripdata->name); + BLI_path_join(str, sizeof(str), seq->strip->dir, seq->strip->stripdata->name); BLI_path_abs(str, BKE_main_blendfile_path(bmain)); seq->sound = BKE_sound_new_file(bmain, str); } diff --git a/source/blender/blentranslation/intern/blt_lang.c b/source/blender/blentranslation/intern/blt_lang.c index 0662adfb9ed..b8523f289c7 100644 --- a/source/blender/blentranslation/intern/blt_lang.c +++ b/source/blender/blentranslation/intern/blt_lang.c @@ -72,7 +72,7 @@ static void fill_locales(void) free_locales(); - BLI_join_dirfile(languages, FILE_MAX, languages_path, "languages"); + BLI_path_join(languages, FILE_MAX, languages_path, "languages"); line = lines = BLI_file_read_as_lines(languages); /* This whole "parsing" code is a bit weak, in that it expects strictly formatted input file... diff --git a/source/blender/compositor/intern/COM_Debug.cc b/source/blender/compositor/intern/COM_Debug.cc index d0f0be590f6..d184e5540ea 100644 --- a/source/blender/compositor/intern/COM_Debug.cc +++ b/source/blender/compositor/intern/COM_Debug.cc @@ -428,7 +428,7 @@ void DebugInfo::graphviz(const ExecutionSystem *system, StringRefNull name) else { BLI_strncpy(basename, (name + ".dot").c_str(), sizeof(basename)); } - BLI_join_dirfile(filepath, sizeof(filepath), BKE_tempdir_session(), basename); + BLI_path_join(filepath, sizeof(filepath), BKE_tempdir_session(), basename); file_index_++; std::cout << "Writing compositor debug to: " << filepath << "\n"; diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.cc b/source/blender/compositor/nodes/COM_OutputFileNode.cc index c83bcf42efd..fc4270cc222 100644 --- a/source/blender/compositor/nodes/COM_OutputFileNode.cc +++ b/source/blender/compositor/nodes/COM_OutputFileNode.cc @@ -104,7 +104,7 @@ void OutputFileNode::convert_to_operations(NodeConverter &converter, char path[FILE_MAX]; /* combine file path for the input */ - BLI_join_dirfile(path, FILE_MAX, storage->base_path, sockdata->path); + BLI_path_join(path, FILE_MAX, storage->base_path, sockdata->path); NodeOperation *output_operation = nullptr; diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index 2a23615caa3..9ed963f0c66 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -788,7 +788,7 @@ static int pose_copy_exec(bContext *C, wmOperator *op) * existing on its own. */ BKE_copybuffer_copy_tag_ID(&ob_copy.id); - BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer_pose.blend"); + BLI_path_join(str, sizeof(str), BKE_tempdir_base(), "copybuffer_pose.blend"); BKE_copybuffer_copy_end(temp_bmain, str, op->reports); /* We clear the lists so no datablocks gets freed, * This is required because objects in temp bmain shares same pointers @@ -844,7 +844,7 @@ static int pose_paste_exec(bContext *C, wmOperator *op) Main *tmp_bmain = BKE_main_new(); STRNCPY(tmp_bmain->filepath, BKE_main_blendfile_path_from_global()); - BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer_pose.blend"); + BLI_path_join(str, sizeof(str), BKE_tempdir_base(), "copybuffer_pose.blend"); if (!BKE_copybuffer_read(tmp_bmain, str, op->reports, FILTER_ID_OB)) { BKE_report(op->reports, RPT_ERROR, "Copy buffer is empty"); BKE_main_free(tmp_bmain); diff --git a/source/blender/editors/asset/intern/asset_list.cc b/source/blender/editors/asset/intern/asset_list.cc index b0ff5c86520..7fdb924d769 100644 --- a/source/blender/editors/asset/intern/asset_list.cc +++ b/source/blender/editors/asset/intern/asset_list.cc @@ -488,7 +488,7 @@ std::string ED_assetlist_asset_filepath_get(const bContext *C, const char *asset_relpath = asset_handle.file_data->relpath; char path[FILE_MAX_LIBEXTRA]; - BLI_join_dirfile(path, sizeof(path), library_path, asset_relpath); + BLI_path_join(path, sizeof(path), library_path, asset_relpath); return path; } diff --git a/source/blender/editors/asset/intern/asset_ops.cc b/source/blender/editors/asset/intern/asset_ops.cc index 08259090e0c..d1c46a8259f 100644 --- a/source/blender/editors/asset/intern/asset_ops.cc +++ b/source/blender/editors/asset/intern/asset_ops.cc @@ -860,7 +860,7 @@ static bool set_filepath_for_asset_lib(const Main *bmain, struct wmOperator *op) } char file_path[PATH_MAX]; - BLI_join_dirfile(file_path, sizeof(file_path), lib->path, blend_filename); + BLI_path_join(file_path, sizeof(file_path), lib->path, blend_filename); RNA_string_set(op->ptr, "filepath", file_path); return true; diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index c080dce0f08..deb3d84ae66 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -923,7 +923,7 @@ static void init_internal_icons(void) char iconfilestr[FILE_MAX]; if (icondir) { - BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile); + BLI_path_join(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile); /* if the image is missing bbuf will just be NULL */ bbuf = IMB_loadiffname(iconfilestr, IB_rect, NULL); @@ -1047,7 +1047,7 @@ static void init_iconfile_list(struct ListBase *list) /* check to see if the image is the right size, continue if not */ /* copying strings here should go ok, assuming that we never get back * a complete path to file longer than 256 chars */ - BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, filename); + BLI_path_join(iconfilestr, sizeof(iconfilestr), icondir, filename); bbuf = IMB_loadiffname(iconfilestr, IB_rect); if (bbuf) { diff --git a/source/blender/editors/interface/interface_ops.cc b/source/blender/editors/interface/interface_ops.cc index 8b29f1075b8..e089642963d 100644 --- a/source/blender/editors/interface/interface_ops.cc +++ b/source/blender/editors/interface/interface_ops.cc @@ -1859,7 +1859,7 @@ static void edittranslation_find_po_file(const char *root, /* First, full lang code. */ BLI_snprintf(tstr, sizeof(tstr), "%s.po", uilng); - BLI_join_dirfile(path, maxlen, root, uilng); + BLI_path_join(path, maxlen, root, uilng); BLI_path_append(path, maxlen, tstr); if (BLI_is_file(path)) { return; @@ -1885,7 +1885,7 @@ static void edittranslation_find_po_file(const char *root, BLI_strncpy(tstr + szt, tc, sizeof(tstr) - szt); } - BLI_join_dirfile(path, maxlen, root, tstr); + BLI_path_join(path, maxlen, root, tstr); strcat(tstr, ".po"); BLI_path_append(path, maxlen, tstr); if (BLI_is_file(path)) { diff --git a/source/blender/editors/io/io_gpencil_import.c b/source/blender/editors/io/io_gpencil_import.c index c7a6b20af7b..5325965e9a5 100644 --- a/source/blender/editors/io/io_gpencil_import.c +++ b/source/blender/editors/io/io_gpencil_import.c @@ -111,7 +111,7 @@ static int wm_gpencil_import_svg_exec(bContext *C, wmOperator *op) char file_path[FILE_MAX]; RNA_PROP_BEGIN (op->ptr, itemptr, prop) { char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0, NULL); - BLI_join_dirfile(file_path, sizeof(file_path), directory, filename); + BLI_path_join(file_path, sizeof(file_path), directory, filename); MEM_freeN(filename); /* Do Import. */ diff --git a/source/blender/editors/io/io_obj.c b/source/blender/editors/io/io_obj.c index 7559cd47b27..27994af8fe7 100644 --- a/source/blender/editors/io/io_obj.c +++ b/source/blender/editors/io/io_obj.c @@ -427,8 +427,7 @@ static int wm_obj_import_exec(bContext *C, wmOperator *op) for (int i = 0; i < files_len; i++) { RNA_property_collection_lookup_int(op->ptr, prop, i, &fileptr); RNA_string_get(&fileptr, "name", file_only); - BLI_join_dirfile( - import_params.filepath, sizeof(import_params.filepath), dir_only, file_only); + BLI_path_join(import_params.filepath, sizeof(import_params.filepath), dir_only, file_only); import_params.clear_selection = (i == 0); OBJ_import(C, &import_params); } diff --git a/source/blender/editors/io/io_stl_ops.c b/source/blender/editors/io/io_stl_ops.c index c27d42a07c0..bbdb494e48a 100644 --- a/source/blender/editors/io/io_stl_ops.c +++ b/source/blender/editors/io/io_stl_ops.c @@ -49,7 +49,7 @@ static int wm_stl_import_execute(bContext *C, wmOperator *op) for (int i = 0; i < files_len; i++) { RNA_property_collection_lookup_int(op->ptr, prop, i, &fileptr); RNA_string_get(&fileptr, "name", file_only); - BLI_join_dirfile(params.filepath, sizeof(params.filepath), dir_only, file_only); + BLI_path_join(params.filepath, sizeof(params.filepath), dir_only, file_only); STL_import(C, ¶ms); } } diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c index 1ce90849a88..41238eb171b 100644 --- a/source/blender/editors/physics/dynamicpaint_ops.c +++ b/source/blender/editors/physics/dynamicpaint_ops.c @@ -405,7 +405,7 @@ static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job) /* primary output layer */ if (surface->flags & MOD_DPAINT_OUT1) { /* set filepath */ - BLI_join_dirfile( + BLI_path_join( filepath, sizeof(filepath), surface->image_output_path, surface->output_name); BLI_path_frame(filepath, frame, 4); @@ -415,7 +415,7 @@ static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job) /* secondary output */ if (surface->flags & MOD_DPAINT_OUT2 && surface->type == MOD_DPAINT_SURFACE_T_PAINT) { /* set filepath */ - BLI_join_dirfile( + BLI_path_join( filepath, sizeof(filepath), surface->image_output_path, surface->output_name2); BLI_path_frame(filepath, frame, 4); diff --git a/source/blender/editors/render/render_preview.cc b/source/blender/editors/render/render_preview.cc index ad24f46f923..140199209da 100644 --- a/source/blender/editors/render/render_preview.cc +++ b/source/blender/editors/render/render_preview.cc @@ -1325,7 +1325,7 @@ static ImBuf *icon_preview_imbuf_from_brush(Brush *brush) const char *brushicons_dir = BKE_appdir_folder_id(BLENDER_DATAFILES, "brushicons"); /* Expected to be found, but don't crash if it's not. */ if (brushicons_dir) { - BLI_join_dirfile(filepath, sizeof(filepath), brushicons_dir, brush->icon_filepath); + BLI_path_join(filepath, sizeof(filepath), brushicons_dir, brush->icon_filepath); /* Use default color spaces. */ brush->icon_imbuf = IMB_loadiffname(filepath, flags, nullptr); diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c index 9a6bdc98d76..8cf11583b3a 100644 --- a/source/blender/editors/screen/workspace_edit.c +++ b/source/blender/editors/screen/workspace_edit.c @@ -405,7 +405,7 @@ static WorkspaceConfigFileData *workspace_config_file_read(const char *app_templ char startup_file_path[FILE_MAX] = {0}; if (cfgdir) { - BLI_join_dirfile(startup_file_path, sizeof(startup_file_path), cfgdir, BLENDER_STARTUP_FILE); + BLI_path_join(startup_file_path, sizeof(startup_file_path), cfgdir, BLENDER_STARTUP_FILE); } bool has_path = BLI_exists(startup_file_path); @@ -425,8 +425,7 @@ static WorkspaceConfigFileData *workspace_system_file_read(const char *app_templ } char startup_file_path[FILE_MAX]; - BLI_join_dirfile( - startup_file_path, sizeof(startup_file_path), template_dir, BLENDER_STARTUP_FILE); + BLI_path_join(startup_file_path, sizeof(startup_file_path), template_dir, BLENDER_STARTUP_FILE); bool has_path = BLI_exists(startup_file_path); return (has_path) ? BKE_blendfile_workspace_config_read(startup_file_path, NULL, 0, NULL) : NULL; diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index a625c124dd3..486f9f9ccb0 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -201,7 +201,7 @@ static int open_exec(bContext *C, wmOperator *op) RNA_property_collection_lookup_int(op->ptr, prop, 0, &fileptr); RNA_string_get(&fileptr, "name", file_only); - BLI_join_dirfile(str, sizeof(str), dir_only, file_only); + BLI_path_join(str, sizeof(str), dir_only, file_only); } else { BKE_report(op->reports, RPT_ERROR, "No files selected to be opened"); diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 554b628ba0f..e4085bbe9cc 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -544,10 +544,10 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname) ARegion *region = CTX_wm_region(C); FileSelectParams *params = ED_fileselect_get_active_params(sfile); - BLI_join_dirfile(orgname, sizeof(orgname), params->dir, oldname); + BLI_path_join(orgname, sizeof(orgname), params->dir, oldname); BLI_strncpy(filename, params->renamefile, sizeof(filename)); BLI_filename_make_safe(filename); - BLI_join_dirfile(newname, sizeof(newname), params->dir, filename); + BLI_path_join(newname, sizeof(newname), params->dir, filename); if (!STREQ(orgname, newname)) { if (!BLI_exists(newname)) { @@ -952,7 +952,7 @@ void file_draw_list(const bContext *C, ARegion *region) file = filelist_file(files, i); file_selflag = filelist_entry_select_get(sfile->files, file, CHECK_ALL); - BLI_join_dirfile(path, sizeof(path), root, file->relpath); + BLI_path_join(path, sizeof(path), root, file->relpath); if (!(file_selflag & FILE_SEL_EDITING)) { if ((params->highlight_file == i) || (file_selflag & FILE_SEL_HIGHLIGHTED) || diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 63aa71e9855..a4d4bf98474 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -386,7 +386,7 @@ static bool fsmenu_write_file_and_refresh_or_report_error(struct FSMenu *fsmenu, } char filepath[FILE_MAX]; - BLI_join_dirfile(filepath, sizeof(filepath), cfgdir, BLENDER_BOOKMARK_FILE); + BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_BOOKMARK_FILE); if (UNLIKELY(!fsmenu_write_file(fsmenu, filepath))) { BKE_reportf(reports, RPT_ERROR, "Unable to open or write bookmark file \"%s\"", filepath); return false; @@ -1564,7 +1564,7 @@ void file_sfile_to_operator_ex( PropertyRNA *prop; /* XXX, not real length */ - BLI_join_dirfile(filepath, FILE_MAX, params->dir, params->file); + BLI_path_join(filepath, FILE_MAX, params->dir, params->file); if ((prop = RNA_struct_find_property(op->ptr, "relative_path"))) { if (RNA_property_boolean_get(op->ptr, prop)) { @@ -1741,7 +1741,7 @@ bool file_draw_check_exists(SpaceFile *sfile) const FileSelectParams *params = ED_fileselect_get_active_params(sfile); if (params && (params->flag & FILE_CHECK_EXISTING)) { char filepath[FILE_MAX]; - BLI_join_dirfile(filepath, sizeof(filepath), params->dir, params->file); + BLI_path_join(filepath, sizeof(filepath), params->dir, params->file); if (BLI_is_file(filepath)) { return true; } @@ -2311,13 +2311,13 @@ static bool new_folder_path(const char *parent, char folder[FILE_MAX], char name int len = 0; BLI_strncpy(name, "New Folder", FILE_MAXFILE); - BLI_join_dirfile(folder, FILE_MAX, parent, name); + BLI_path_join(folder, FILE_MAX, parent, name); /* check whether folder with the name already exists, in this case * add number to the name. Check length of generated name to avoid * crazy case of huge number of folders each named 'New Folder (x)' */ while (BLI_exists(folder) && (len < FILE_MAXFILE)) { len = BLI_snprintf(name, FILE_MAXFILE, "New Folder(%d)", i); - BLI_join_dirfile(folder, FILE_MAX, parent, name); + BLI_path_join(folder, FILE_MAX, parent, name); i++; } @@ -2621,7 +2621,7 @@ void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg } if (matches == 1) { - BLI_join_dirfile(filepath, sizeof(params->dir), params->dir, params->file); + BLI_path_join(filepath, sizeof(params->dir), params->dir, params->file); /* if directory, open it and empty filename field */ if (filelist_is_dir(sfile->files, filepath)) { @@ -2849,7 +2849,7 @@ static bool file_delete_single(const FileSelectParams *params, const char **r_error_message) { char str[FILE_MAX]; - BLI_join_dirfile(str, sizeof(str), params->dir, file->relpath); + BLI_path_join(str, sizeof(str), params->dir, file->relpath); if (BLI_delete_soft(str, r_error_message) != 0 || BLI_exists(str)) { return false; } diff --git a/source/blender/editors/space_file/filelist.cc b/source/blender/editors/space_file/filelist.cc index c2dc8e9196d..b6f6ab39438 100644 --- a/source/blender/editors/space_file/filelist.cc +++ b/source/blender/editors/space_file/filelist.cc @@ -844,7 +844,7 @@ static bool is_filtered_lib_type(FileListInternEntry *file, { char path[FILE_MAX_LIBEXTRA], dir[FILE_MAX_LIBEXTRA], *group, *name; - BLI_join_dirfile(path, sizeof(path), root, file->relpath); + BLI_path_join(path, sizeof(path), root, file->relpath); if (BLO_library_path_explode(path, dir, &group, &name)) { return is_filtered_id_file_type(file, group, name, filter); @@ -1204,7 +1204,7 @@ static int filelist_geticon_ex(const FileDirEntry *file, target = file->redirection_path; } else if (root) { - BLI_join_dirfile(fullpath, sizeof(fullpath), root, file->relpath); + BLI_path_join(fullpath, sizeof(fullpath), root, file->relpath); BLI_path_slash_ensure(fullpath); } for (; tfsm; tfsm = tfsm->next) { @@ -1606,7 +1606,7 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry BLI_strncpy(preview->filepath, entry->redirection_path, FILE_MAXDIR); } else { - BLI_join_dirfile( + BLI_path_join( preview->filepath, sizeof(preview->filepath), filelist->filelist.root, entry->relpath); } // printf("%s: %d - %s\n", __func__, preview->index, preview->filepath); @@ -1894,7 +1894,7 @@ static char *fileentry_uiname(const char *root, if (typeflag & FILE_TYPE_FTFONT && !(typeflag & FILE_TYPE_BLENDERLIB)) { char abspath[FILE_MAX_LIBEXTRA]; - BLI_join_dirfile(abspath, sizeof(abspath), root, relpath); + BLI_path_join(abspath, sizeof(abspath), root, relpath); name = BLF_display_name_from_file(abspath); if (name) { /* Allocated string, so no need to #BLI_strdup. */ @@ -1906,7 +1906,7 @@ static char *fileentry_uiname(const char *root, char abspath[FILE_MAX_LIBEXTRA]; char *group; - BLI_join_dirfile(abspath, sizeof(abspath), root, relpath); + BLI_path_join(abspath, sizeof(abspath), root, relpath); BLO_library_path_explode(abspath, buff, &group, &name); if (!name) { name = group; @@ -2887,7 +2887,7 @@ static int filelist_readjob_list_dir(const char *root, entry->relpath = static_cast(MEM_dupallocN(files[i].relname)); entry->st = files[i].s; - BLI_join_dirfile(full_path, FILE_MAX, root, entry->relpath); + BLI_path_join(full_path, FILE_MAX, root, entry->relpath); char *target = full_path; /* Set initial file type and attributes. */ @@ -3525,7 +3525,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib, /* When loading entries recursive, the rel_path should be relative from the root dir. * we combine the relative path to the subdir with the relative path of the entry. */ - BLI_join_dirfile(dir, sizeof(dir), rel_subdir, entry->relpath); + BLI_path_join(dir, sizeof(dir), rel_subdir, entry->relpath); MEM_freeN(entry->relpath); entry->relpath = BLI_strdup(dir + 2); /* + 2 to remove '//' * added by BLI_path_rel to rel_subdir. */ @@ -3535,7 +3535,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib, if (filelist_readjob_should_recurse_into_entry( max_recursion, is_lib, recursion_level, entry)) { /* We have a directory we want to list, add it to todo list! */ - BLI_join_dirfile(dir, sizeof(dir), root, entry->relpath); + BLI_path_join(dir, sizeof(dir), root, entry->relpath); BLI_path_normalize_dir(job_params->main_name, dir); td_dir = static_cast(BLI_stack_push_r(todo_dirs)); td_dir->level = recursion_level + 1; diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 9ebc4872544..df7e9702e85 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -1174,7 +1174,7 @@ int autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v)) char path[FILE_MAX]; BLI_stat_t status; - BLI_join_dirfile(path, sizeof(path), dirname, de->d_name); + BLI_path_join(path, sizeof(path), dirname, de->d_name); if (BLI_stat(path, &status) == 0) { if (S_ISDIR(status.st_mode)) { /* is subdir */ diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index a6c5e0f1734..cea53908d4f 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -254,10 +254,10 @@ void ED_fsmenu_entry_set_path(struct FSMenuEntry *fsentry, const char *path) fsentry->path = (path && path[0]) ? BLI_strdup(path) : NULL; - BLI_join_dirfile(tmp_name, - sizeof(tmp_name), - BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), - BLENDER_BOOKMARK_FILE); + BLI_path_join(tmp_name, + sizeof(tmp_name), + BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), + BLENDER_BOOKMARK_FILE); fsmenu_write_file(ED_fsmenu_get(), tmp_name); } } @@ -318,10 +318,10 @@ void ED_fsmenu_entry_set_name(struct FSMenuEntry *fsentry, const char *name) BLI_strncpy(fsentry->name, name, sizeof(fsentry->name)); } - BLI_join_dirfile(tmp_name, - sizeof(tmp_name), - BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), - BLENDER_BOOKMARK_FILE); + BLI_path_join(tmp_name, + sizeof(tmp_name), + BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), + BLENDER_BOOKMARK_FILE); fsmenu_write_file(ED_fsmenu_get(), tmp_name); } } @@ -983,7 +983,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) if (xdg_runtime_dir != NULL) { struct direntry *dirs; char name[FILE_MAX]; - BLI_join_dirfile(name, sizeof(name), xdg_runtime_dir, "gvfs/"); + BLI_path_join(name, sizeof(name), xdg_runtime_dir, "gvfs/"); const uint dirs_num = BLI_filelist_dir_contents(name, &dirs); for (uint i = 0; i < dirs_num; i++) { if (dirs[i].type & S_IFDIR) { diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index a3182222263..74f1b8e838a 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -1157,7 +1157,7 @@ void ED_file_read_bookmarks(void) if (cfgdir) { char name[FILE_MAX]; - BLI_join_dirfile(name, sizeof(name), cfgdir, BLENDER_BOOKMARK_FILE); + BLI_path_join(name, sizeof(name), cfgdir, BLENDER_BOOKMARK_FILE); fsmenu_read_bookmarks(ED_fsmenu_get(), name); } } diff --git a/source/blender/editors/space_image/image_sequence.c b/source/blender/editors/space_image/image_sequence.c index 7108c258665..d2725652979 100644 --- a/source/blender/editors/space_image/image_sequence.c +++ b/source/blender/editors/space_image/image_sequence.c @@ -62,14 +62,14 @@ static void image_sequence_get_frame_ranges(wmOperator *op, ListBase *ranges) STREQLEN(base_tail, tail, FILE_MAX)) { /* Set filepath to first frame in the range. */ if (frame->framenr < range_first_frame) { - BLI_join_dirfile(range->filepath, sizeof(range->filepath), dir, filename); + BLI_path_join(range->filepath, sizeof(range->filepath), dir, filename); range_first_frame = frame->framenr; } } else { /* start a new frame range */ range = MEM_callocN(sizeof(*range), __func__); - BLI_join_dirfile(range->filepath, sizeof(range->filepath), dir, filename); + BLI_path_join(range->filepath, sizeof(range->filepath), dir, filename); BLI_addtail(ranges, range); BLI_strncpy(base_head, head, sizeof(base_head)); diff --git a/source/blender/editors/space_outliner/outliner_edit.cc b/source/blender/editors/space_outliner/outliner_edit.cc index 6eca6fffece..9a6a25fdbae 100644 --- a/source/blender/editors/space_outliner/outliner_edit.cc +++ b/source/blender/editors/space_outliner/outliner_edit.cc @@ -809,7 +809,7 @@ static int outliner_id_copy_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer.blend"); + BLI_path_join(str, sizeof(str), BKE_tempdir_base(), "copybuffer.blend"); BKE_copybuffer_copy_end(bmain, str, op->reports); BKE_reportf(op->reports, RPT_INFO, "Copied %d selected data-block(s)", num_ids); @@ -843,7 +843,7 @@ static int outliner_id_paste_exec(bContext *C, wmOperator *op) char str[FILE_MAX]; const short flag = FILE_AUTOSELECT | FILE_ACTIVE_COLLECTION; - BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer.blend"); + BLI_path_join(str, sizeof(str), BKE_tempdir_base(), "copybuffer.blend"); const int num_pasted = BKE_copybuffer_paste(C, str, flag, op->reports, 0); if (num_pasted == 0) { diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 6ef8d7fd108..b17d0bfac4e 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -274,7 +274,7 @@ static void load_data_init_from_operator(SeqLoadData *load_data, bContext *C, wm RNA_PROP_BEGIN (op->ptr, itemptr, prop) { char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0, NULL); BLI_strncpy(load_data->name, filename, sizeof(load_data->name)); - BLI_join_dirfile(load_data->path, sizeof(load_data->path), directory, filename); + BLI_path_join(load_data->path, sizeof(load_data->path), directory, filename); MEM_freeN(filename); break; } @@ -834,7 +834,7 @@ static void sequencer_add_movie_multiple_strips(bContext *C, char file_only[FILE_MAX]; RNA_string_get(op->ptr, "directory", dir_only); RNA_string_get(&itemptr, "name", file_only); - BLI_join_dirfile(load_data->path, sizeof(load_data->path), dir_only, file_only); + BLI_path_join(load_data->path, sizeof(load_data->path), dir_only, file_only); BLI_strncpy(load_data->name, file_only, sizeof(load_data->name)); Sequence *seq_movie = NULL; Sequence *seq_sound = NULL; @@ -1082,7 +1082,7 @@ static void sequencer_add_sound_multiple_strips(bContext *C, char file_only[FILE_MAX]; RNA_string_get(op->ptr, "directory", dir_only); RNA_string_get(&itemptr, "name", file_only); - BLI_join_dirfile(load_data->path, sizeof(load_data->path), dir_only, file_only); + BLI_path_join(load_data->path, sizeof(load_data->path), dir_only, file_only); BLI_strncpy(load_data->name, file_only, sizeof(load_data->name)); Sequence *seq = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data); if (seq == NULL) { diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 201425dafab..a6916f9d031 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -804,7 +804,7 @@ static void draw_seq_text_get_source(Sequence *seq, char *r_source, size_t sourc switch (seq->type) { case SEQ_TYPE_IMAGE: case SEQ_TYPE_MOVIE: { - BLI_join_dirfile(r_source, source_len, seq->strip->dir, seq->strip->stripdata->name); + BLI_path_join(r_source, source_len, seq->strip->dir, seq->strip->stripdata->name); break; } case SEQ_TYPE_SOUND_RAM: { diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 2938513f130..c0c7782c60c 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -2939,7 +2939,7 @@ static int sequencer_change_path_invoke(bContext *C, wmOperator *op, const wmEve Sequence *seq = SEQ_select_active_get(scene); char filepath[FILE_MAX]; - BLI_join_dirfile(filepath, sizeof(filepath), seq->strip->dir, seq->strip->stripdata->name); + BLI_path_join(filepath, sizeof(filepath), seq->strip->dir, seq->strip->stripdata->name); RNA_string_set(op->ptr, "directory", seq->strip->dir); RNA_string_set(op->ptr, "filepath", filepath); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 6fbd553e17b..ad12aef6d67 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -59,7 +59,7 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer.blend"); + BLI_path_join(str, sizeof(str), BKE_tempdir_base(), "copybuffer.blend"); BKE_copybuffer_copy_end(bmain, str, op->reports); BKE_reportf(op->reports, RPT_INFO, "Copied %d selected object(s)", num_copied); @@ -91,7 +91,7 @@ static int view3d_pastebuffer_exec(bContext *C, wmOperator *op) flag |= FILE_ACTIVE_COLLECTION; } - BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer.blend"); + BLI_path_join(str, sizeof(str), BKE_tempdir_base(), "copybuffer.blend"); const int num_pasted = BKE_copybuffer_paste(C, str, flag, op->reports, FILTER_ID_OB); if (num_pasted == 0) { diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp index 96887f7a83b..237f1802026 100644 --- a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp +++ b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp @@ -531,7 +531,7 @@ PyObject *Freestyle_Init(void) const char *const path = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, "freestyle"); if (path) { char modpath[FILE_MAX]; - BLI_join_dirfile(modpath, sizeof(modpath), path, "modules"); + BLI_path_join(modpath, sizeof(modpath), path, "modules"); PyObject *sys_path = PySys_GetObject("path"); /* borrow */ PyObject *py_modpath = PyUnicode_FromString(modpath); PyList_Append(sys_path, py_modpath); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index ea5f4ec275d..5e132826a4c 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -668,7 +668,7 @@ void colormanagement_init(void) configdir = BKE_appdir_folder_id(BLENDER_DATAFILES, "colormanagement"); if (configdir) { - BLI_join_dirfile(configfile, sizeof(configfile), configdir, BCM_CONFIG_FILE); + BLI_path_join(configfile, sizeof(configfile), configdir, BCM_CONFIG_FILE); #ifdef WIN32 { diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index 735472b6bdf..8965700c08a 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -426,7 +426,7 @@ static bool get_proxy_filepath(struct anim *anim, return false; } - BLI_join_dirfile(filepath, FILE_MAXFILE + FILE_MAXDIR, index_dir, proxy_name); + BLI_path_join(filepath, FILE_MAXFILE + FILE_MAXDIR, index_dir, proxy_name); return true; } @@ -457,7 +457,7 @@ static void get_tc_filename(struct anim *anim, IMB_Timecode_Type tc, char *filep get_index_dir(anim, index_dir, sizeof(index_dir)); - BLI_join_dirfile(filepath, FILE_MAXFILE + FILE_MAXDIR, index_dir, index_name); + BLI_path_join(filepath, FILE_MAXFILE + FILE_MAXDIR, index_dir, index_name); } /* ---------------------------------------------------------------------- diff --git a/source/blender/io/collada/DocumentExporter.cpp b/source/blender/io/collada/DocumentExporter.cpp index 56adbca13bd..07392e9c4ce 100644 --- a/source/blender/io/collada/DocumentExporter.cpp +++ b/source/blender/io/collada/DocumentExporter.cpp @@ -145,7 +145,7 @@ static COLLADABU::NativeString make_temp_filepath(const char *name, const char * name = "untitled"; } - BLI_join_dirfile(tempfile, sizeof(tempfile), BKE_tempdir_session(), name); + BLI_path_join(tempfile, sizeof(tempfile), BKE_tempdir_session(), name); if (extension) { BLI_path_extension_ensure(tempfile, FILE_MAX, extension); diff --git a/source/blender/io/collada/DocumentImporter.cpp b/source/blender/io/collada/DocumentImporter.cpp index 660bbd7edb2..5e432682564 100644 --- a/source/blender/io/collada/DocumentImporter.cpp +++ b/source/blender/io/collada/DocumentImporter.cpp @@ -937,7 +937,7 @@ bool DocumentImporter::writeImage(const COLLADAFW::Image *image) const char *workpath; BLI_split_dir_part(this->import_settings->filepath, dir, sizeof(dir)); - BLI_join_dirfile(absolute_path, sizeof(absolute_path), dir, imagepath.c_str()); + BLI_path_join(absolute_path, sizeof(absolute_path), dir, imagepath.c_str()); if (BLI_exists(absolute_path)) { workpath = absolute_path; } diff --git a/source/blender/io/collada/ImageExporter.cpp b/source/blender/io/collada/ImageExporter.cpp index 1223abbaf95..070eb36de31 100644 --- a/source/blender/io/collada/ImageExporter.cpp +++ b/source/blender/io/collada/ImageExporter.cpp @@ -70,7 +70,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) BLI_strncpy(export_file, name.c_str(), sizeof(export_file)); BKE_image_path_ensure_ext_from_imformat(export_file, &imageFormat); - BLI_join_dirfile(export_path, sizeof(export_path), export_dir, export_file); + BLI_path_join(export_path, sizeof(export_path), export_dir, export_file); /* make dest directory if it doesn't exist */ BLI_make_existing_file(export_path); diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 634754d54cc..c952210eecf 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -778,7 +778,7 @@ static void rna_Sequence_filepath_get(PointerRNA *ptr, char *value) { Sequence *seq = (Sequence *)(ptr->data); - BLI_join_dirfile(value, FILE_MAX, seq->strip->dir, seq->strip->stripdata->name); + BLI_path_join(value, FILE_MAX, seq->strip->dir, seq->strip->stripdata->name); } static int rna_Sequence_filepath_length(PointerRNA *ptr) @@ -786,7 +786,7 @@ static int rna_Sequence_filepath_length(PointerRNA *ptr) Sequence *seq = (Sequence *)(ptr->data); char path[FILE_MAX]; - BLI_join_dirfile(path, sizeof(path), seq->strip->dir, seq->strip->stripdata->name); + BLI_path_join(path, sizeof(path), seq->strip->dir, seq->strip->stripdata->name); return strlen(path); } @@ -804,7 +804,7 @@ static void rna_Sequence_proxy_filepath_get(PointerRNA *ptr, char *value) { StripProxy *proxy = (StripProxy *)(ptr->data); - BLI_join_dirfile(value, FILE_MAX, proxy->dir, proxy->file); + BLI_path_join(value, FILE_MAX, proxy->dir, proxy->file); } static int rna_Sequence_proxy_filepath_length(PointerRNA *ptr) @@ -812,7 +812,7 @@ static int rna_Sequence_proxy_filepath_length(PointerRNA *ptr) StripProxy *proxy = (StripProxy *)(ptr->data); char path[FILE_MAX]; - BLI_join_dirfile(path, sizeof(path), proxy->dir, proxy->file); + BLI_path_join(path, sizeof(path), proxy->dir, proxy->file); return strlen(path); } diff --git a/source/blender/render/intern/render_result.cc b/source/blender/render/intern/render_result.cc index e8603f5e1b3..bd5c6a0f5c4 100644 --- a/source/blender/render/intern/render_result.cc +++ b/source/blender/render/intern/render_result.cc @@ -962,7 +962,7 @@ static void render_result_exr_file_cache_path(Scene *sce, sce->id.name + 2, path_hexdigest); - BLI_join_dirfile(r_path, FILE_CACHE_MAX, root, filename_full); + BLI_path_join(r_path, FILE_CACHE_MAX, root, filename_full); if (BLI_path_is_rel(r_path)) { BLI_path_abs(r_path, dirname); } diff --git a/source/blender/sequencer/intern/proxy.c b/source/blender/sequencer/intern/proxy.c index 4220efab8bf..9f08db2aa45 100644 --- a/source/blender/sequencer/intern/proxy.c +++ b/source/blender/sequencer/intern/proxy.c @@ -106,7 +106,7 @@ bool seq_proxy_get_custom_file_fname(Sequence *seq, char *name, const int view_i return false; } - BLI_join_dirfile(fname, PROXY_MAXFILE, proxy->dir, proxy->file); + BLI_path_join(fname, PROXY_MAXFILE, proxy->dir, proxy->file); BLI_path_abs(fname, BKE_main_blendfile_path_from_global()); if (view_id > 0) { @@ -325,7 +325,7 @@ static bool seq_proxy_multiview_context_invalid(Sequence *seq, Scene *scene, con if (view_id == 0) { char path[FILE_MAX]; - BLI_join_dirfile(path, sizeof(path), seq->strip->dir, seq->strip->stripdata->name); + BLI_path_join(path, sizeof(path), seq->strip->dir, seq->strip->stripdata->name); BLI_path_abs(path, BKE_main_blendfile_path_from_global()); BKE_scene_multiview_view_prefix_get(scene, path, prefix, &ext); } diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c index 91ecccbe0f8..dbbece73695 100644 --- a/source/blender/sequencer/intern/render.c +++ b/source/blender/sequencer/intern/render.c @@ -938,7 +938,7 @@ static ImBuf *seq_render_image_strip(const SeqRenderData *context, return NULL; } - BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name); + BLI_path_join(name, sizeof(name), seq->strip->dir, s_elem->name); BLI_path_abs(name, BKE_main_blendfile_path_from_global()); /* Try to get a proxy image. */ diff --git a/source/blender/sequencer/intern/strip_add.c b/source/blender/sequencer/intern/strip_add.c index 753a6ee39e0..7f4c91724fc 100644 --- a/source/blender/sequencer/intern/strip_add.c +++ b/source/blender/sequencer/intern/strip_add.c @@ -204,7 +204,7 @@ void SEQ_add_image_init_alpha_mode(Sequence *seq) char name[FILE_MAX]; ImBuf *ibuf; - BLI_join_dirfile(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name); + BLI_path_join(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name); BLI_path_abs(name, BKE_main_blendfile_path_from_global()); /* Initialize input color space. */ @@ -545,7 +545,7 @@ void SEQ_add_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, const boo const bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 && (scene->r.scemode & R_MULTIVIEW) != 0; - BLI_join_dirfile(path, sizeof(path), seq->strip->dir, seq->strip->stripdata->name); + BLI_path_join(path, sizeof(path), seq->strip->dir, seq->strip->stripdata->name); BLI_path_abs(path, BKE_main_blendfile_path_from_global()); SEQ_relations_sequence_free_anim(seq); diff --git a/source/blender/sequencer/intern/utils.c b/source/blender/sequencer/intern/utils.c index 6d182b6bcca..5b70bc33e88 100644 --- a/source/blender/sequencer/intern/utils.c +++ b/source/blender/sequencer/intern/utils.c @@ -224,7 +224,7 @@ void seq_open_anim_file(Scene *scene, Sequence *seq, bool openfile) /* reset all the previously created anims */ SEQ_relations_sequence_free_anim(seq); - BLI_join_dirfile(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name); + BLI_path_join(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name); BLI_path_abs(name, BKE_main_blendfile_path_from_global()); proxy = seq->strip->proxy; diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index a3593a33bae..b009a67efba 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -1406,7 +1406,7 @@ void wm_history_file_read(void) LinkNode *l; int num; - BLI_join_dirfile(name, sizeof(name), cfgdir, BLENDER_HISTORY_FILE); + BLI_path_join(name, sizeof(name), cfgdir, BLENDER_HISTORY_FILE); LinkNode *lines = BLI_file_read_as_lines(name); @@ -1469,7 +1469,7 @@ static void wm_history_file_write(void) return; } - BLI_join_dirfile(name, sizeof(name), user_config_dir, BLENDER_HISTORY_FILE); + BLI_path_join(name, sizeof(name), user_config_dir, BLENDER_HISTORY_FILE); fp = BLI_fopen(name, "w"); if (fp) { @@ -1930,7 +1930,7 @@ static void wm_autosave_location(char filepath[FILE_MAX]) } #endif - BLI_join_dirfile(filepath, FILE_MAX, tempdir_base, path); + BLI_path_join(filepath, FILE_MAX, tempdir_base, path); } static void wm_autosave_write(Main *bmain, wmWindowManager *wm) @@ -2020,7 +2020,7 @@ void wm_autosave_delete(void) if (BLI_exists(filepath)) { char str[FILE_MAX]; - BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), BLENDER_QUIT_FILE); + BLI_path_join(str, sizeof(str), BKE_tempdir_base(), BLENDER_QUIT_FILE); /* if global undo; remove tempsave, otherwise rename */ if (U.uiflag & USER_GLOBALUNDO) { @@ -2915,7 +2915,7 @@ void WM_OT_revert_mainfile(wmOperatorType *ot) bool WM_file_recover_last_session(bContext *C, ReportList *reports) { char filepath[FILE_MAX]; - BLI_join_dirfile(filepath, sizeof(filepath), BKE_tempdir_base(), BLENDER_QUIT_FILE); + BLI_path_join(filepath, sizeof(filepath), BKE_tempdir_base(), BLENDER_QUIT_FILE); G.fileflags |= G_FILE_RECOVER_READ; const bool success = wm_file_read_opwrap(C, filepath, reports); G.fileflags &= ~G_FILE_RECOVER_READ; diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c index 0ea783af1af..bbe53bf7355 100644 --- a/source/blender/windowmanager/intern/wm_files_link.c +++ b/source/blender/windowmanager/intern/wm_files_link.c @@ -210,7 +210,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) RNA_string_get(op->ptr, "filename", relname); RNA_string_get(op->ptr, "directory", root); - BLI_join_dirfile(path, sizeof(path), root, relname); + BLI_path_join(path, sizeof(path), root, relname); /* test if we have a valid data */ if (!BLO_library_path_explode(path, libname, &group, &name)) { @@ -284,7 +284,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) RNA_BEGIN (op->ptr, itemptr, "files") { RNA_string_get(&itemptr, "name", relname); - BLI_join_dirfile(path, sizeof(path), root, relname); + BLI_path_join(path, sizeof(path), root, relname); if (BLO_library_path_explode(path, libname, &group, &name)) { if (!wm_link_append_item_poll(NULL, path, group, name, do_append)) { @@ -303,7 +303,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) RNA_BEGIN (op->ptr, itemptr, "files") { RNA_string_get(&itemptr, "name", relname); - BLI_join_dirfile(path, sizeof(path), root, relname); + BLI_path_join(path, sizeof(path), root, relname); if (BLO_library_path_explode(path, libname, &group, &name)) { BlendfileLinkAppendContextItem *item; @@ -683,7 +683,7 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload) return OPERATOR_CANCELLED; } - BLI_join_dirfile(path, sizeof(path), root, libname); + BLI_path_join(path, sizeof(path), root, libname); if (!BLI_exists(path)) { BKE_reportf(op->reports, @@ -739,7 +739,7 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload) RNA_BEGIN (op->ptr, itemptr, "files") { RNA_string_get(&itemptr, "name", relname); - BLI_join_dirfile(path, sizeof(path), root, relname); + BLI_path_join(path, sizeof(path), root, relname); if (BLI_path_cmp(path, lib->filepath_abs) == 0 || !BLO_has_bfile_extension(relname)) { continue; diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 32890b4014f..c5d7152246c 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -447,7 +447,7 @@ void WM_exit_ex(bContext *C, const bool do_python) bool has_edited; const int fileflags = G.fileflags & ~G_FILE_COMPRESS; - BLI_join_dirfile(filepath, sizeof(filepath), BKE_tempdir_base(), BLENDER_QUIT_FILE); + BLI_path_join(filepath, sizeof(filepath), BKE_tempdir_base(), BLENDER_QUIT_FILE); has_edited = ED_editors_flush_edits(bmain); diff --git a/source/blender/windowmanager/intern/wm_platform_support.c b/source/blender/windowmanager/intern/wm_platform_support.c index a0519506d29..ee93621545f 100644 --- a/source/blender/windowmanager/intern/wm_platform_support.c +++ b/source/blender/windowmanager/intern/wm_platform_support.c @@ -42,7 +42,7 @@ static bool wm_platform_support_check_approval(const char *platform_support_key, bool result = false; char filepath[FILE_MAX]; - BLI_join_dirfile(filepath, sizeof(filepath), cfgdir, BLENDER_PLATFORM_SUPPORT_FILE); + BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_PLATFORM_SUPPORT_FILE); LinkNode *lines = BLI_file_read_as_lines(filepath); for (LinkNode *line_node = lines; line_node; line_node = line_node->next) { char *line = line_node->link; diff --git a/source/blender/windowmanager/intern/wm_splash_screen.c b/source/blender/windowmanager/intern/wm_splash_screen.c index 48325b28f5a..16e5f983bea 100644 --- a/source/blender/windowmanager/intern/wm_splash_screen.c +++ b/source/blender/windowmanager/intern/wm_splash_screen.c @@ -140,7 +140,7 @@ static ImBuf *wm_block_splash_image(int width, int *r_height) char template_directory[FILE_MAX]; if (BKE_appdir_app_template_id_search( U.app_template, template_directory, sizeof(template_directory))) { - BLI_join_dirfile(splash_filepath, sizeof(splash_filepath), template_directory, "splash.png"); + BLI_path_join(splash_filepath, sizeof(splash_filepath), template_directory, "splash.png"); ibuf = IMB_loadiffname(splash_filepath, IB_rect, NULL); } } diff --git a/source/creator/creator_signals.c b/source/creator/creator_signals.c index f67c4dde41d..c733ee617cb 100644 --- a/source/creator/creator_signals.c +++ b/source/creator/creator_signals.c @@ -101,7 +101,7 @@ static void sig_handle_crash(int signum) char fname[FILE_MAX]; if (!(G_MAIN && G_MAIN->filepath[0])) { - BLI_join_dirfile(fname, sizeof(fname), BKE_tempdir_base(), "crash.blend"); + BLI_path_join(fname, sizeof(fname), BKE_tempdir_base(), "crash.blend"); } else { STRNCPY(fname, G_MAIN->filepath); @@ -122,11 +122,10 @@ static void sig_handle_crash(int signum) char fname[FILE_MAX]; if (!(G_MAIN && G_MAIN->filepath[0])) { - BLI_join_dirfile(fname, sizeof(fname), BKE_tempdir_base(), "blender.crash.txt"); + BLI_path_join(fname, sizeof(fname), BKE_tempdir_base(), "blender.crash.txt"); } else { - BLI_join_dirfile( - fname, sizeof(fname), BKE_tempdir_base(), BLI_path_basename(G_MAIN->filepath)); + BLI_path_join(fname, sizeof(fname), BKE_tempdir_base(), BLI_path_basename(G_MAIN->filepath)); BLI_path_extension_replace(fname, sizeof(fname), ".crash.txt"); } -- cgit v1.2.3 From 94ce176e754d47831638c50dfd54f5068048e950 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 17 Oct 2022 12:18:16 +1100 Subject: Cleanup: renaming GHOST/Wayland functions & private members - Use `_` suffix for private members. - Use `wl_` prefix for Wayland native types to help distinguish them from local types. - Replace single character names `d` & `w` with `display` `window`. - Rename `selection` to `clipboard`. Using the primary selection as a clipboard is a separate and as yet unsupported feature. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 247 ++++++++++++++------------- intern/ghost/intern/GHOST_SystemWayland.h | 13 +- intern/ghost/intern/GHOST_WindowWayland.cpp | 254 ++++++++++++++-------------- intern/ghost/intern/GHOST_WindowWayland.h | 6 +- 4 files changed, 262 insertions(+), 258 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 250c7a48899..0778938a8e4 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -504,8 +504,8 @@ struct GWL_Seat { struct GWL_Display { GHOST_SystemWayland *system = nullptr; - struct wl_display *display = nullptr; - struct wl_compositor *compositor = nullptr; + struct wl_display *wl_display = nullptr; + struct wl_compositor *wl_compositor = nullptr; #ifdef WITH_GHOST_WAYLAND_LIBDECOR WGL_LibDecor_System *libdecor = nullptr; @@ -514,7 +514,7 @@ struct GWL_Display { WGL_XDG_Decor_System *xdg_decor = nullptr; struct zxdg_output_manager_v1 *xdg_output_manager = nullptr; - struct wl_shm *shm = nullptr; + struct wl_shm *wl_shm = nullptr; std::vector outputs; std::vector seats; @@ -535,7 +535,7 @@ struct GWL_Display { static GHOST_WindowManager *window_manager = nullptr; /** Check this lock before accessing `GHOST_SystemWayland::selection` from a thread. */ -static std::mutex system_selection_mutex; +static std::mutex system_clipboard_mutex; /** * Callback for WAYLAND to run when there is an error. @@ -578,22 +578,22 @@ static GWL_SeatStatePointer *seat_state_pointer_from_cursor_surface(GWL_Seat *se return nullptr; } -static void display_destroy(GWL_Display *d) +static void display_destroy(GWL_Display *display) { - if (d->data_device_manager) { - wl_data_device_manager_destroy(d->data_device_manager); + if (display->data_device_manager) { + wl_data_device_manager_destroy(display->data_device_manager); } - if (d->tablet_manager) { - zwp_tablet_manager_v2_destroy(d->tablet_manager); + if (display->tablet_manager) { + zwp_tablet_manager_v2_destroy(display->tablet_manager); } - for (GWL_Output *output : d->outputs) { + for (GWL_Output *output : display->outputs) { wl_output_destroy(output->wl_output); delete output; } - for (GWL_Seat *seat : d->seats) { + for (GWL_Seat *seat : display->seats) { /* First handle members that require locking. * While highly unlikely, it's possible they are being used while this function runs. */ @@ -661,45 +661,45 @@ static void display_destroy(GWL_Display *d) delete seat; } - if (d->shm) { - wl_shm_destroy(d->shm); + if (display->wl_shm) { + wl_shm_destroy(display->wl_shm); } - if (d->relative_pointer_manager) { - zwp_relative_pointer_manager_v1_destroy(d->relative_pointer_manager); + if (display->relative_pointer_manager) { + zwp_relative_pointer_manager_v1_destroy(display->relative_pointer_manager); } - if (d->pointer_constraints) { - zwp_pointer_constraints_v1_destroy(d->pointer_constraints); + if (display->pointer_constraints) { + zwp_pointer_constraints_v1_destroy(display->pointer_constraints); } - if (d->compositor) { - wl_compositor_destroy(d->compositor); + if (display->wl_compositor) { + wl_compositor_destroy(display->wl_compositor); } #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { - if (d->libdecor) { - wgl_libdecor_system_destroy(d->libdecor); + if (display->libdecor) { + wgl_libdecor_system_destroy(display->libdecor); } } else #endif { - if (d->xdg_decor) { - wgl_xdg_decor_system_destroy(d->xdg_decor); + if (display->xdg_decor) { + wgl_xdg_decor_system_destroy(display->xdg_decor); } } if (eglGetDisplay) { - ::eglTerminate(eglGetDisplay(EGLNativeDisplayType(d->display))); + ::eglTerminate(eglGetDisplay(EGLNativeDisplayType(display->wl_display))); } - if (d->display) { - wl_display_disconnect(d->display); + if (display->wl_display) { + wl_display_disconnect(display->wl_display); } - delete d; + delete display; } static GHOST_TKey xkb_map_gkey(const xkb_keysym_t sym) @@ -1518,7 +1518,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat * 'text_update_edited' to behave like dropped text was pasted. */ CLOG_INFO(LOG, 2, "drop_read_uris_fn (text_plain, text_utf8), unhandled!"); } - wl_display_roundtrip(system->display()); + wl_display_roundtrip(system->wl_display()); }; /* Pass in `seat->wl_surface_focus_dnd` instead of accessing it from `seat` since the leave @@ -1551,7 +1551,6 @@ static void data_device_handle_selection(void *data, return; } CLOG_INFO(LOG, 2, "selection"); - /* Get new data offer. */ data_offer = static_cast(wl_data_offer_get_user_data(id)); seat->data_offer_copy_paste = data_offer; @@ -1572,8 +1571,8 @@ static void data_device_handle_selection(void *data, data_offer, mime_receive, &seat->data_offer_copy_paste_mutex); { - std::lock_guard lock{system_selection_mutex}; - system->selection_set(data); + std::lock_guard lock{system_clipboard_mutex}; + system->clipboard_set(data); } }; @@ -1668,7 +1667,7 @@ static void cursor_surface_handle_enter(void *data, wl_surface); const GWL_Output *reg_output = ghost_wl_output_user_data(wl_output); seat_state_pointer->outputs.insert(reg_output); - update_cursor_scale(seat->cursor, seat->system->shm(), seat_state_pointer, wl_surface); + update_cursor_scale(seat->cursor, seat->system->wl_shm(), seat_state_pointer, wl_surface); } static void cursor_surface_handle_leave(void *data, @@ -1686,7 +1685,7 @@ static void cursor_surface_handle_leave(void *data, wl_surface); const GWL_Output *reg_output = ghost_wl_output_user_data(wl_output); seat_state_pointer->outputs.erase(reg_output); - update_cursor_scale(seat->cursor, seat->system->shm(), seat_state_pointer, wl_surface); + update_cursor_scale(seat->cursor, seat->system->wl_shm(), seat_state_pointer, wl_surface); } static const struct wl_surface_listener cursor_surface_listener = { @@ -2258,7 +2257,7 @@ static void tablet_seat_handle_tool_added(void *data, tablet_tool->seat = seat; /* Every tool has it's own cursor wl_surface. */ - tablet_tool->wl_surface_cursor = wl_compositor_create_surface(seat->system->compositor()); + tablet_tool->wl_surface_cursor = wl_compositor_create_surface(seat->system->wl_compositor()); ghost_wl_surface_tag_cursor_tablet(tablet_tool->wl_surface_cursor); wl_surface_add_listener(tablet_tool->wl_surface_cursor, &cursor_surface_listener, (void *)seat); @@ -2705,7 +2704,7 @@ static void seat_handle_capabilities(void *data, if (capabilities & WL_SEAT_CAPABILITY_POINTER) { seat->wl_pointer = wl_seat_get_pointer(wl_seat); - seat->cursor.wl_surface = wl_compositor_create_surface(seat->system->compositor()); + seat->cursor.wl_surface = wl_compositor_create_surface(seat->system->wl_compositor()); seat->cursor.visible = true; seat->cursor.wl_buffer = nullptr; if (!get_cursor_settings(seat->cursor.theme_name, seat->cursor.size)) { @@ -3023,7 +3022,7 @@ static void global_handle_add(void *data, struct GWL_Display *display = static_cast(data); if (STREQ(interface, wl_compositor_interface.name)) { - display->compositor = static_cast( + display->wl_compositor = static_cast( wl_registry_bind(wl_registry, name, &wl_compositor_interface, 3)); } else if (STREQ(interface, xdg_wm_base_interface.name)) { @@ -3073,7 +3072,7 @@ static void global_handle_add(void *data, wl_seat_add_listener(seat->wl_seat, &seat_listener, seat); } else if (STREQ(interface, wl_shm_interface.name)) { - display->shm = static_cast( + display->wl_shm = static_cast( wl_registry_bind(wl_registry, name, &wl_shm_interface, 1)); } else if (STREQ(interface, wl_data_device_manager_interface.name)) { @@ -3144,34 +3143,34 @@ static const struct wl_registry_listener registry_listener = { * WAYLAND specific implementation of the #GHOST_System interface. * \{ */ -GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new GWL_Display) +GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Display) { wl_log_set_handler_client(ghost_wayland_log_handler); - d->system = this; + display_->system = this; /* Connect to the Wayland server. */ - d->display = wl_display_connect(nullptr); - if (!d->display) { - display_destroy(d); + display_->wl_display = wl_display_connect(nullptr); + if (!display_->wl_display) { + display_destroy(display_); throw std::runtime_error("Wayland: unable to connect to display!"); } /* This may be removed later if decorations are required, needed as part of registration. */ - d->xdg_decor = new WGL_XDG_Decor_System; + display_->xdg_decor = new WGL_XDG_Decor_System; /* Register interfaces. */ - struct wl_registry *registry = wl_display_get_registry(d->display); - wl_registry_add_listener(registry, ®istry_listener, d); + struct wl_registry *registry = wl_display_get_registry(display_->wl_display); + wl_registry_add_listener(registry, ®istry_listener, display_); /* Call callback for registry listener. */ - wl_display_roundtrip(d->display); + wl_display_roundtrip(display_->wl_display); /* Call callbacks for registered listeners. */ - wl_display_roundtrip(d->display); + wl_display_roundtrip(display_->wl_display); wl_registry_destroy(registry); #ifdef WITH_GHOST_WAYLAND_LIBDECOR - if (d->libdecor_required) { - wgl_xdg_decor_system_destroy(d->xdg_decor); - d->xdg_decor = nullptr; + if (display_->libdecor_required) { + wgl_xdg_decor_system_destroy(display_->xdg_decor); + display_->xdg_decor = nullptr; if (!has_libdecor) { # ifdef WITH_GHOST_X11 @@ -3180,7 +3179,7 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new GWL_Display) "WAYLAND found but libdecor was not, install libdecor for Wayland support, " "falling back to X11\n"); # endif - display_destroy(d); + display_destroy(display_); throw std::runtime_error("Wayland: unable to find libdecor!"); } } @@ -3191,36 +3190,37 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new GWL_Display) #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { - d->libdecor = new WGL_LibDecor_System; - WGL_LibDecor_System &decor = *d->libdecor; - decor.context = libdecor_new(d->display, &libdecor_interface); + display_->libdecor = new WGL_LibDecor_System; + WGL_LibDecor_System &decor = *display_->libdecor; + decor.context = libdecor_new(display_->wl_display, &libdecor_interface); if (!decor.context) { - display_destroy(d); + display_destroy(display_); throw std::runtime_error("Wayland: unable to create window decorations!"); } } else #endif { - WGL_XDG_Decor_System &decor = *d->xdg_decor; + WGL_XDG_Decor_System &decor = *display_->xdg_decor; if (!decor.shell) { - display_destroy(d); + display_destroy(display_); throw std::runtime_error("Wayland: unable to access xdg_shell!"); } } /* Register data device per seat for IPC between Wayland clients. */ - if (d->data_device_manager) { - for (GWL_Seat *seat : d->seats) { - seat->data_device = wl_data_device_manager_get_data_device(d->data_device_manager, + if (display_->data_device_manager) { + for (GWL_Seat *seat : display_->seats) { + seat->data_device = wl_data_device_manager_get_data_device(display_->data_device_manager, seat->wl_seat); wl_data_device_add_listener(seat->data_device, &data_device_listener, seat); } } - if (d->tablet_manager) { - for (GWL_Seat *seat : d->seats) { - seat->tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(d->tablet_manager, seat->wl_seat); + if (display_->tablet_manager) { + for (GWL_Seat *seat : display_->seats) { + seat->tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(display_->tablet_manager, + seat->wl_seat); zwp_tablet_seat_v2_add_listener(seat->tablet_seat, &tablet_seat_listener, seat); } } @@ -3228,7 +3228,7 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new GWL_Display) GHOST_SystemWayland::~GHOST_SystemWayland() { - display_destroy(d); + display_destroy(display_); } GHOST_TSuccess GHOST_SystemWayland::init() @@ -3263,10 +3263,10 @@ bool GHOST_SystemWayland::processEvents(bool waitForEvent) #endif /* WITH_INPUT_NDOF */ if (waitForEvent) { - wl_display_dispatch(d->display); + wl_display_dispatch(display_->wl_display); } else { - wl_display_roundtrip(d->display); + wl_display_roundtrip(display_->wl_display); } if (getEventManager()->getNumEvents() > 0) { @@ -3283,11 +3283,11 @@ bool GHOST_SystemWayland::setConsoleWindowState(GHOST_TConsoleWindowState /*acti GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) const { - if (UNLIKELY(d->seats.empty())) { + if (UNLIKELY(display_->seats.empty())) { return GHOST_kFailure; } - GWL_Seat *seat = d->seats[0]; + GWL_Seat *seat = display_->seats[0]; const xkb_mod_mask_t state = xkb_state_serialize_mods(seat->xkb_state, XKB_STATE_MODS_DEPRESSED); @@ -3345,10 +3345,10 @@ GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) co GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const { - if (UNLIKELY(d->seats.empty())) { + if (UNLIKELY(display_->seats.empty())) { return GHOST_kFailure; } - GWL_Seat *seat = d->seats[0]; + GWL_Seat *seat = display_->seats[0]; GWL_SeatStatePointer *seat_state_pointer = seat_state_pointer_active(seat); if (!seat_state_pointer) { return GHOST_kFailure; @@ -3360,18 +3360,18 @@ GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const char *GHOST_SystemWayland::getClipboard(bool /*selection*/) const { - char *clipboard = static_cast(malloc(selection.size() + 1)); - memcpy(clipboard, selection.data(), selection.size() + 1); + char *clipboard = static_cast(malloc(clipboard_.size() + 1)); + memcpy(clipboard, clipboard_.data(), clipboard_.size() + 1); return clipboard; } void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) const { - if (UNLIKELY(!d->data_device_manager || d->seats.empty())) { + if (UNLIKELY(!display_->data_device_manager || display_->seats.empty())) { return; } - GWL_Seat *seat = d->seats[0]; + GWL_Seat *seat = display_->seats[0]; std::lock_guard lock{seat->data_source_mutex}; @@ -3383,7 +3383,8 @@ void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) c data_source->buffer_out = static_cast(malloc(buffer_size)); std::memcpy(data_source->buffer_out, buffer, buffer_size); - data_source->data_source = wl_data_device_manager_create_data_source(d->data_device_manager); + data_source->data_source = wl_data_device_manager_create_data_source( + display_->data_device_manager); wl_data_source_add_listener(data_source->data_source, &data_source_listener, seat); @@ -3399,7 +3400,7 @@ void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) c uint8_t GHOST_SystemWayland::getNumDisplays() const { - return d ? uint8_t(d->outputs.size()) : 0; + return display_ ? uint8_t(display_->outputs.size()) : 0; } static GHOST_TSuccess getCursorPositionClientRelative_impl( @@ -3441,10 +3442,10 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorPositionClientRelative(const GHOST_ int32_t &x, int32_t &y) const { - if (UNLIKELY(d->seats.empty())) { + if (UNLIKELY(display_->seats.empty())) { return GHOST_kFailure; } - GWL_Seat *seat = d->seats[0]; + GWL_Seat *seat = display_->seats[0]; GWL_SeatStatePointer *seat_state_pointer = seat_state_pointer_active(seat); if (!seat_state_pointer || !seat_state_pointer->wl_surface) { return GHOST_kFailure; @@ -3457,20 +3458,20 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorPositionClientRelative(GHOST_IWindo const int32_t x, const int32_t y) { - if (UNLIKELY(d->seats.empty())) { + if (UNLIKELY(display_->seats.empty())) { return GHOST_kFailure; } - GWL_Seat *seat = d->seats[0]; + GWL_Seat *seat = display_->seats[0]; GHOST_WindowWayland *win = static_cast(window); return setCursorPositionClientRelative_impl(seat, win, x, y); } GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(int32_t &x, int32_t &y) const { - if (UNLIKELY(d->seats.empty())) { + if (UNLIKELY(display_->seats.empty())) { return GHOST_kFailure; } - GWL_Seat *seat = d->seats[0]; + GWL_Seat *seat = display_->seats[0]; GWL_SeatStatePointer *seat_state_pointer = seat_state_pointer_active(seat); if (!seat_state_pointer) { return GHOST_kFailure; @@ -3485,10 +3486,10 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(int32_t &x, int32_t &y) co GHOST_TSuccess GHOST_SystemWayland::setCursorPosition(const int32_t x, const int32_t y) { - if (UNLIKELY(d->seats.empty())) { + if (UNLIKELY(display_->seats.empty())) { return GHOST_kFailure; } - GWL_Seat *seat = d->seats[0]; + GWL_Seat *seat = display_->seats[0]; /* Intentionally different from `getCursorPosition` which supports both tablet & pointer. * In the case of setting the cursor location, tablets don't support this. */ @@ -3505,8 +3506,8 @@ void GHOST_SystemWayland::getMainDisplayDimensions(uint32_t &width, uint32_t &he return; } /* We assume first output as main. */ - width = uint32_t(d->outputs[0]->size_native[0]); - height = uint32_t(d->outputs[0]->size_native[1]); + width = uint32_t(display_->outputs[0]->size_native[0]); + height = uint32_t(display_->outputs[0]->size_native[1]); } void GHOST_SystemWayland::getAllDisplayDimensions(uint32_t &width, uint32_t &height) const @@ -3514,7 +3515,7 @@ void GHOST_SystemWayland::getAllDisplayDimensions(uint32_t &width, uint32_t &hei int32_t xy_min[2] = {INT32_MAX, INT32_MAX}; int32_t xy_max[2] = {INT32_MIN, INT32_MIN}; - for (const GWL_Output *output : d->outputs) { + for (const GWL_Output *output : display_->outputs) { int32_t xy[2] = {0, 0}; if (output->has_position_logical) { xy[0] = output->position_logical[0]; @@ -3575,10 +3576,10 @@ static GHOST_Context *createOffscreenContext_impl(GHOST_SystemWayland *system, GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings /*glSettings*/) { /* Create new off-screen window. */ - wl_surface *wl_surface = wl_compositor_create_surface(compositor()); + wl_surface *wl_surface = wl_compositor_create_surface(wl_compositor()); wl_egl_window *egl_window = wl_surface ? wl_egl_window_create(wl_surface, 1, 1) : nullptr; - GHOST_Context *context = createOffscreenContext_impl(this, d->display, egl_window); + GHOST_Context *context = createOffscreenContext_impl(this, display_->wl_display, egl_window); if (!context) { GHOST_PRINT("Cannot create off-screen EGL context" << std::endl); @@ -3841,7 +3842,7 @@ static bool cursor_is_software(const GHOST_TGrabCursorMode mode, const bool use_ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor shape) { - if (UNLIKELY(d->seats.empty())) { + if (UNLIKELY(display_->seats.empty())) { return GHOST_kFailure; } auto cursor_find = cursors.find(shape); @@ -3849,12 +3850,13 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor s cursors.at(GHOST_kStandardCursorDefault) : (*cursor_find).second; - GWL_Seat *seat = d->seats[0]; + GWL_Seat *seat = display_->seats[0]; GWL_Cursor *c = &seat->cursor; if (!c->wl_theme) { /* The cursor wl_surface hasn't entered an output yet. Initialize theme with scale 1. */ - c->wl_theme = wl_cursor_theme_load(c->theme_name.c_str(), c->size, d->seats[0]->system->shm()); + c->wl_theme = wl_cursor_theme_load( + c->theme_name.c_str(), c->size, display_->seats[0]->system->wl_shm()); } wl_cursor *cursor = wl_cursor_theme_get_cursor(c->wl_theme, cursor_name); @@ -3901,11 +3903,11 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap, const int hotY, const bool /*canInvertColor*/) { - if (UNLIKELY(d->seats.empty())) { + if (UNLIKELY(display_->seats.empty())) { return GHOST_kFailure; } - GWL_Cursor *cursor = &d->seats[0]->cursor; + GWL_Cursor *cursor = &display_->seats[0]->cursor; if (cursor->custom_data) { munmap(cursor->custom_data, cursor->custom_data_size); @@ -3914,8 +3916,11 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap, } const int32_t size_xy[2] = {sizex, sizey}; - wl_buffer *buffer = ghost_wl_buffer_create_for_image( - d->shm, size_xy, WL_SHM_FORMAT_ARGB8888, &cursor->custom_data, &cursor->custom_data_size); + wl_buffer *buffer = ghost_wl_buffer_create_for_image(display_->wl_shm, + size_xy, + WL_SHM_FORMAT_ARGB8888, + &cursor->custom_data, + &cursor->custom_data_size); if (buffer == nullptr) { return GHOST_kFailure; } @@ -3961,14 +3966,14 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap, cursor->wl_image.hotspot_x = uint32_t(hotX); cursor->wl_image.hotspot_y = uint32_t(hotY); - cursor_buffer_set(d->seats[0], buffer); + cursor_buffer_set(display_->seats[0], buffer); return GHOST_kSuccess; } GHOST_TSuccess GHOST_SystemWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitmap) { - GWL_Cursor *cursor = &d->seats[0]->cursor; + GWL_Cursor *cursor = &display_->seats[0]->cursor; if (cursor->custom_data == nullptr) { return GHOST_kFailure; } @@ -3989,11 +3994,11 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitma GHOST_TSuccess GHOST_SystemWayland::setCursorVisibility(const bool visible) { - if (UNLIKELY(d->seats.empty())) { + if (UNLIKELY(display_->seats.empty())) { return GHOST_kFailure; } - GWL_Seat *seat = d->seats[0]; + GWL_Seat *seat = display_->seats[0]; cursor_visible_set(seat, visible, seat->cursor.is_hardware, CURSOR_VISIBLE_ALWAYS_SET); return GHOST_kSuccess; } @@ -4013,12 +4018,12 @@ bool GHOST_SystemWayland::supportsWindowPosition() bool GHOST_SystemWayland::getCursorGrabUseSoftwareDisplay(const GHOST_TGrabCursorMode mode) { - if (UNLIKELY(d->seats.empty())) { + if (UNLIKELY(display_->seats.empty())) { return false; } #ifdef USE_GNOME_CONFINE_HACK - GWL_Seat *seat = d->seats[0]; + GWL_Seat *seat = display_->seats[0]; const bool use_software_confine = seat->use_pointer_software_confine; #else const bool use_software_confine = false; @@ -4125,45 +4130,45 @@ void ghost_wl_surface_tag_cursor_tablet(struct wl_surface *wl_surface) * Expose some members via methods. * \{ */ -wl_display *GHOST_SystemWayland::display() +wl_display *GHOST_SystemWayland::wl_display() { - return d->display; + return display_->wl_display; } -wl_compositor *GHOST_SystemWayland::compositor() +wl_compositor *GHOST_SystemWayland::wl_compositor() { - return d->compositor; + return display_->wl_compositor; } #ifdef WITH_GHOST_WAYLAND_LIBDECOR libdecor *GHOST_SystemWayland::libdecor_context() { - return d->libdecor->context; + return display_->libdecor->context; } #endif /* !WITH_GHOST_WAYLAND_LIBDECOR */ xdg_wm_base *GHOST_SystemWayland::xdg_decor_shell() { - return d->xdg_decor->shell; + return display_->xdg_decor->shell; } zxdg_decoration_manager_v1 *GHOST_SystemWayland::xdg_decor_manager() { - return d->xdg_decor->manager; + return display_->xdg_decor->manager; } /* End `xdg_decor`. */ const std::vector &GHOST_SystemWayland::outputs() const { - return d->outputs; + return display_->outputs; } -wl_shm *GHOST_SystemWayland::shm() const +struct wl_shm *GHOST_SystemWayland::wl_shm() const { - return d->shm; + return display_->wl_shm; } /** \} */ @@ -4197,9 +4202,9 @@ GHOST_WindowWayland *ghost_wl_surface_user_data(struct wl_surface *wl_surface) * Functionality only used for the WAYLAND implementation. * \{ */ -void GHOST_SystemWayland::selection_set(const std::string &selection) +void GHOST_SystemWayland::clipboard_set(const std::string &clipboard) { - this->selection = selection; + clipboard_ = clipboard; } void GHOST_SystemWayland::window_surface_unref(const wl_surface *wl_surface) @@ -4211,7 +4216,7 @@ void GHOST_SystemWayland::window_surface_unref(const wl_surface *wl_surface) ((void)0); /* Only clear window surfaces (not cursors, off-screen surfaces etc). */ - for (GWL_Seat *seat : d->seats) { + for (GWL_Seat *seat : display_->seats) { SURFACE_CLEAR_PTR(seat->pointer.wl_surface); SURFACE_CLEAR_PTR(seat->tablet.wl_surface); SURFACE_CLEAR_PTR(seat->keyboard.wl_surface); @@ -4229,11 +4234,11 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod const int scale) { /* Ignore, if the required protocols are not supported. */ - if (UNLIKELY(!d->relative_pointer_manager || !d->pointer_constraints)) { + if (UNLIKELY(!display_->relative_pointer_manager || !display_->pointer_constraints)) { return GHOST_kFailure; } - if (UNLIKELY(d->seats.empty())) { + if (UNLIKELY(display_->seats.empty())) { return GHOST_kFailure; } /* No change, success. */ @@ -4241,7 +4246,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod return GHOST_kSuccess; } - GWL_Seat *seat = d->seats[0]; + GWL_Seat *seat = display_->seats[0]; #ifdef USE_GNOME_CONFINE_HACK const bool was_software_confine = seat->use_pointer_software_confine; @@ -4361,11 +4366,11 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod * An alternative could be to draw the cursor in software (and hide the real cursor), * or just accept a locked cursor on WAYLAND. */ seat->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer( - d->relative_pointer_manager, seat->wl_pointer); + display_->relative_pointer_manager, seat->wl_pointer); zwp_relative_pointer_v1_add_listener( seat->relative_pointer, &relative_pointer_listener, seat); seat->locked_pointer = zwp_pointer_constraints_v1_lock_pointer( - d->pointer_constraints, + display_->pointer_constraints, wl_surface, seat->wl_pointer, nullptr, @@ -4383,7 +4388,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod else if (grab_state_next.use_confine) { if (!grab_state_prev.use_confine) { seat->confined_pointer = zwp_pointer_constraints_v1_confine_pointer( - d->pointer_constraints, + display_->pointer_constraints, wl_surface, seat->wl_pointer, nullptr, diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index 7d19a5cf8b9..5d2cfe45582 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -157,9 +157,8 @@ class GHOST_SystemWayland : public GHOST_System { /* WAYLAND direct-data access. */ - wl_display *display(); - - wl_compositor *compositor(); + struct wl_display *wl_display(); + struct wl_compositor *wl_compositor(); #ifdef WITH_GHOST_WAYLAND_LIBDECOR libdecor *libdecor_context(); @@ -170,11 +169,11 @@ class GHOST_SystemWayland : public GHOST_System { const std::vector &outputs() const; - wl_shm *shm() const; + struct wl_shm *wl_shm() const; /* WAYLAND utility functions. */ - void selection_set(const std::string &selection); + void clipboard_set(const std::string &clipboard); /** Clear all references to this surface to prevent accessing NULL pointers. */ void window_surface_unref(const wl_surface *wl_surface); @@ -192,6 +191,6 @@ class GHOST_SystemWayland : public GHOST_System { #endif private: - struct GWL_Display *d; - std::string selection; + struct GWL_Display *display_; + std::string clipboard_; }; diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp index 5f9202f1227..b29c5efd8d4 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.cpp +++ b/intern/ghost/intern/GHOST_WindowWayland.cpp @@ -78,7 +78,7 @@ static void wgl_xdg_decor_window_destroy(WGL_XDG_Decor_Window *decor) } struct GWL_Window { - GHOST_WindowWayland *w = nullptr; + GHOST_WindowWayland *ghost_window = nullptr; struct wl_surface *wl_surface = nullptr; /** * Outputs on which the window is currently shown on. @@ -220,7 +220,7 @@ static void xdg_toplevel_handle_configure(void *data, static void xdg_toplevel_handle_close(void *data, xdg_toplevel * /*xdg_toplevel*/) { CLOG_INFO(LOG, 2, "close"); - static_cast(data)->w->close(); + static_cast(data)->ghost_window->close(); } static const xdg_toplevel_listener toplevel_listener = { @@ -263,7 +263,7 @@ static void frame_handle_configure(struct libdecor_frame *frame, win->size[1] = win->scale * size_next[1]; wl_egl_window_resize(win->egl_window, UNPACK2(win->size), 0, 0); - win->w->notify_size(); + win->ghost_window->notify_size(); if (!libdecor_configuration_get_window_state(configuration, &window_state)) { window_state = LIBDECOR_WINDOW_STATE_NONE; @@ -273,7 +273,7 @@ static void frame_handle_configure(struct libdecor_frame *frame, win->is_fullscreen = window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN; win->is_active = window_state & LIBDECOR_WINDOW_STATE_ACTIVE; - win->is_active ? win->w->activate() : win->w->deactivate(); + win->is_active ? win->ghost_window->activate() : win->ghost_window->deactivate(); state = libdecor_state_new(UNPACK2(size_next)); libdecor_frame_commit(frame, state, configuration); @@ -286,7 +286,7 @@ static void frame_handle_close(struct libdecor_frame * /*frame*/, void *data) { CLOG_INFO(LOG, 2, "close"); - static_cast(data)->w->close(); + static_cast(data)->ghost_window->close(); } static void frame_handle_commit(struct libdecor_frame * /*frame*/, void *data) @@ -294,8 +294,8 @@ static void frame_handle_commit(struct libdecor_frame * /*frame*/, void *data) CLOG_INFO(LOG, 2, "commit"); /* We have to swap twice to keep any pop-up menus alive. */ - static_cast(data)->w->swapBuffers(); - static_cast(data)->w->swapBuffers(); + static_cast(data)->ghost_window->swapBuffers(); + static_cast(data)->ghost_window->swapBuffers(); } static struct libdecor_frame_interface libdecor_frame_iface = { @@ -360,14 +360,14 @@ static void xdg_surface_handle_configure(void *data, wl_egl_window_resize(win->egl_window, UNPACK2(win->size), 0, 0); win->size_pending[0] = 0; win->size_pending[1] = 0; - win->w->notify_size(); + win->ghost_window->notify_size(); } if (win->is_active) { - win->w->activate(); + win->ghost_window->activate(); } else { - win->w->deactivate(); + win->ghost_window->deactivate(); } xdg_surface_ack_configure(xdg_surface, serial); @@ -439,7 +439,7 @@ static struct wl_surface_listener wl_surface_listener = { GHOST_TSuccess GHOST_WindowWayland::hasCursorShape(GHOST_TStandardCursor cursorShape) { - return m_system->hasCursorShape(cursorShape); + return system_->hasCursorShape(cursorShape); } GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system, @@ -455,20 +455,20 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system, const bool stereoVisual, const bool exclusive) : GHOST_Window(width, height, state, stereoVisual, exclusive), - m_system(system), - w(new GWL_Window) + system_(system), + window_(new GWL_Window) { /* Globally store pointer to window manager. */ if (!window_manager) { - window_manager = m_system->getWindowManager(); + window_manager = system_->getWindowManager(); } - w->w = this; + window_->ghost_window = this; - w->size[0] = int32_t(width); - w->size[1] = int32_t(height); + window_->size[0] = int32_t(width); + window_->size[1] = int32_t(height); - w->is_dialog = is_dialog; + window_->is_dialog = is_dialog; /* NOTE(@campbellbarton): The scale set here to avoid flickering on startup. * When all monitors use the same scale (which is quite common) there aren't any problems. @@ -479,22 +479,23 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system, * * Using the maximum scale is best as it results in the window first being smaller, * avoiding a large window flashing before it's made smaller. */ - w->scale = outputs_max_scale_or_default(this->m_system->outputs(), 1, &w->dpi); + window_->scale = outputs_max_scale_or_default(system_->outputs(), 1, &window_->dpi); /* Window surfaces. */ - w->wl_surface = wl_compositor_create_surface(m_system->compositor()); - ghost_wl_surface_tag(w->wl_surface); + window_->wl_surface = wl_compositor_create_surface(system_->wl_compositor()); + ghost_wl_surface_tag(window_->wl_surface); - wl_surface_set_buffer_scale(w->wl_surface, w->scale); + wl_surface_set_buffer_scale(window_->wl_surface, window_->scale); - wl_surface_add_listener(w->wl_surface, &wl_surface_listener, this); + wl_surface_add_listener(window_->wl_surface, &wl_surface_listener, this); - w->egl_window = wl_egl_window_create(w->wl_surface, int(w->size[0]), int(w->size[1])); + window_->egl_window = wl_egl_window_create( + window_->wl_surface, int(window_->size[0]), int(window_->size[1])); /* NOTE: The limit is in points (not pixels) so Hi-DPI will limit to larger number of pixels. * This has the advantage that the size limit is the same when moving the window between monitors * with different scales set. If it was important to limit in pixels it could be re-calculated - * when the `w->scale` changed. */ + * when the `window_->scale` changed. */ const int32_t size_min[2] = {320, 240}; /* This value is expected to match the base name of the `.desktop` file. see T101805. @@ -508,68 +509,68 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system, #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { - w->libdecor = new WGL_LibDecor_Window; - WGL_LibDecor_Window &decor = *w->libdecor; + window_->libdecor = new WGL_LibDecor_Window; + WGL_LibDecor_Window &decor = *window_->libdecor; /* create window decorations */ decor.frame = libdecor_decorate( - m_system->libdecor_context(), w->wl_surface, &libdecor_frame_iface, w); - libdecor_frame_map(w->libdecor->frame); + system_->libdecor_context(), window_->wl_surface, &libdecor_frame_iface, window_); + libdecor_frame_map(window_->libdecor->frame); libdecor_frame_set_min_content_size(decor.frame, UNPACK2(size_min)); libdecor_frame_set_app_id(decor.frame, xdg_app_id); if (parentWindow) { WGL_LibDecor_Window &decor_parent = - *dynamic_cast(parentWindow)->w->libdecor; + *dynamic_cast(parentWindow)->window_->libdecor; libdecor_frame_set_parent(decor.frame, decor_parent.frame); } } else #endif { - w->xdg_decor = new WGL_XDG_Decor_Window; - WGL_XDG_Decor_Window &decor = *w->xdg_decor; - decor.surface = xdg_wm_base_get_xdg_surface(m_system->xdg_decor_shell(), w->wl_surface); + window_->xdg_decor = new WGL_XDG_Decor_Window; + WGL_XDG_Decor_Window &decor = *window_->xdg_decor; + decor.surface = xdg_wm_base_get_xdg_surface(system_->xdg_decor_shell(), window_->wl_surface); decor.toplevel = xdg_surface_get_toplevel(decor.surface); xdg_toplevel_set_min_size(decor.toplevel, UNPACK2(size_min)); xdg_toplevel_set_app_id(decor.toplevel, xdg_app_id); - if (m_system->xdg_decor_manager()) { + if (system_->xdg_decor_manager()) { decor.toplevel_decor = zxdg_decoration_manager_v1_get_toplevel_decoration( - m_system->xdg_decor_manager(), decor.toplevel); + system_->xdg_decor_manager(), decor.toplevel); zxdg_toplevel_decoration_v1_add_listener( - decor.toplevel_decor, &toplevel_decoration_v1_listener, w); + decor.toplevel_decor, &toplevel_decoration_v1_listener, window_); zxdg_toplevel_decoration_v1_set_mode(decor.toplevel_decor, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); } - xdg_surface_add_listener(decor.surface, &xdg_surface_listener, w); - xdg_toplevel_add_listener(decor.toplevel, &toplevel_listener, w); + xdg_surface_add_listener(decor.surface, &xdg_surface_listener, window_); + xdg_toplevel_add_listener(decor.toplevel, &toplevel_listener, window_); if (parentWindow && is_dialog) { WGL_XDG_Decor_Window &decor_parent = - *dynamic_cast(parentWindow)->w->xdg_decor; + *dynamic_cast(parentWindow)->window_->xdg_decor; xdg_toplevel_set_parent(decor.toplevel, decor_parent.toplevel); } } setTitle(title); - wl_surface_set_user_data(w->wl_surface, this); + wl_surface_set_user_data(window_->wl_surface, this); /* Call top-level callbacks. */ - wl_surface_commit(w->wl_surface); - wl_display_roundtrip(m_system->display()); + wl_surface_commit(window_->wl_surface); + wl_display_roundtrip(system_->wl_display()); #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { - WGL_LibDecor_Window &decor = *w->libdecor; + WGL_LibDecor_Window &decor = *window_->libdecor; /* It's important not to return until the window is configured or * calls to `setState` from Blender will crash `libdecor`. */ while (!decor.configured) { - if (libdecor_dispatch(m_system->libdecor_context(), 0) < 0) { + if (libdecor_dispatch(system_->libdecor_context(), 0) < 0) { break; } } @@ -607,13 +608,13 @@ GHOST_TSuccess GHOST_WindowWayland::setWindowCursorGrab(GHOST_TGrabCursorMode mo } bounds = &bounds_buf; } - if (m_system->window_cursor_grab_set(mode, - m_cursorGrab, - m_cursorGrabInitPos, - bounds, - m_cursorGrabAxis, - w->wl_surface, - w->scale)) { + if (system_->window_cursor_grab_set(mode, + m_cursorGrab, + m_cursorGrabInitPos, + bounds, + m_cursorGrabAxis, + window_->wl_surface, + window_->scale)) { return GHOST_kSuccess; } return GHOST_kFailure; @@ -621,47 +622,47 @@ GHOST_TSuccess GHOST_WindowWayland::setWindowCursorGrab(GHOST_TGrabCursorMode mo GHOST_TSuccess GHOST_WindowWayland::setWindowCursorShape(GHOST_TStandardCursor shape) { - const GHOST_TSuccess ok = m_system->setCursorShape(shape); + const GHOST_TSuccess ok = system_->setCursorShape(shape); m_cursorShape = (ok == GHOST_kSuccess) ? shape : GHOST_kStandardCursorDefault; return ok; } bool GHOST_WindowWayland::getCursorGrabUseSoftwareDisplay() { - return m_system->getCursorGrabUseSoftwareDisplay(m_cursorGrab); + return system_->getCursorGrabUseSoftwareDisplay(m_cursorGrab); } GHOST_TSuccess GHOST_WindowWayland::setWindowCustomCursorShape( uint8_t *bitmap, uint8_t *mask, int sizex, int sizey, int hotX, int hotY, bool canInvertColor) { - return m_system->setCustomCursorShape(bitmap, mask, sizex, sizey, hotX, hotY, canInvertColor); + return system_->setCustomCursorShape(bitmap, mask, sizex, sizey, hotX, hotY, canInvertColor); } GHOST_TSuccess GHOST_WindowWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitmap) { - return m_system->getCursorBitmap(bitmap); + return system_->getCursorBitmap(bitmap); } void GHOST_WindowWayland::setTitle(const char *title) { #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { - WGL_LibDecor_Window &decor = *w->libdecor; + WGL_LibDecor_Window &decor = *window_->libdecor; libdecor_frame_set_title(decor.frame, title); } else #endif { - WGL_XDG_Decor_Window &decor = *w->xdg_decor; + WGL_XDG_Decor_Window &decor = *window_->xdg_decor; xdg_toplevel_set_title(decor.toplevel, title); } - this->title = title; + title_ = title; } std::string GHOST_WindowWayland::getTitle() const { - return this->title.empty() ? "untitled" : this->title; + return title_.empty() ? "untitled" : title_; } void GHOST_WindowWayland::getWindowBounds(GHOST_Rect &bounds) const @@ -671,29 +672,29 @@ void GHOST_WindowWayland::getWindowBounds(GHOST_Rect &bounds) const void GHOST_WindowWayland::getClientBounds(GHOST_Rect &bounds) const { - bounds.set(0, 0, UNPACK2(w->size)); + bounds.set(0, 0, UNPACK2(window_->size)); } GHOST_TSuccess GHOST_WindowWayland::setClientWidth(const uint32_t width) { - return setClientSize(width, uint32_t(w->size[1])); + return setClientSize(width, uint32_t(window_->size[1])); } GHOST_TSuccess GHOST_WindowWayland::setClientHeight(const uint32_t height) { - return setClientSize(uint32_t(w->size[0]), height); + return setClientSize(uint32_t(window_->size[0]), height); } GHOST_TSuccess GHOST_WindowWayland::setClientSize(const uint32_t width, const uint32_t height) { - wl_egl_window_resize(w->egl_window, int(width), int(height), 0, 0); + wl_egl_window_resize(window_->egl_window, int(width), int(height), 0, 0); /* Override any pending size that may be set. */ - w->size_pending[0] = 0; - w->size_pending[1] = 0; + window_->size_pending[0] = 0; + window_->size_pending[1] = 0; - w->size[0] = width; - w->size[1] = height; + window_->size[0] = width; + window_->size[1] = height; notify_size(); @@ -722,40 +723,40 @@ GHOST_WindowWayland::~GHOST_WindowWayland() { releaseNativeHandles(); - wl_egl_window_destroy(w->egl_window); + wl_egl_window_destroy(window_->egl_window); #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { - wgl_libdecor_window_destroy(w->libdecor); + wgl_libdecor_window_destroy(window_->libdecor); } else #endif { - wgl_xdg_decor_window_destroy(w->xdg_decor); + wgl_xdg_decor_window_destroy(window_->xdg_decor); } /* Clear any pointers to this window. This is needed because there are no guarantees * that flushing the display will the "leave" handlers before handling events. */ - m_system->window_surface_unref(w->wl_surface); + system_->window_surface_unref(window_->wl_surface); - wl_surface_destroy(w->wl_surface); + wl_surface_destroy(window_->wl_surface); /* NOTE(@campbellbarton): Flushing will often run the appropriate handlers event * (#wl_surface_listener.leave in particular) to avoid attempted access to the freed surfaces. * This is not fool-proof though, hence the call to #window_surface_unref, see: T99078. */ - wl_display_flush(m_system->display()); + wl_display_flush(system_->wl_display()); - delete w; + delete window_; } uint16_t GHOST_WindowWayland::getDPIHint() { - return w->dpi; + return window_->dpi; } GHOST_TSuccess GHOST_WindowWayland::setWindowCursorVisibility(bool visible) { - return m_system->setCursorVisibility(visible); + return system_->setCursorVisibility(visible); } GHOST_TSuccess GHOST_WindowWayland::setState(GHOST_TWindowState state) @@ -767,24 +768,24 @@ GHOST_TSuccess GHOST_WindowWayland::setState(GHOST_TWindowState state) case GHOST_kWindowStateMaximized: { #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { - libdecor_frame_unset_maximized(w->libdecor->frame); + libdecor_frame_unset_maximized(window_->libdecor->frame); } else #endif { - xdg_toplevel_unset_maximized(w->xdg_decor->toplevel); + xdg_toplevel_unset_maximized(window_->xdg_decor->toplevel); } break; } case GHOST_kWindowStateFullScreen: { #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { - libdecor_frame_unset_fullscreen(w->libdecor->frame); + libdecor_frame_unset_fullscreen(window_->libdecor->frame); } else #endif { - xdg_toplevel_unset_fullscreen(w->xdg_decor->toplevel); + xdg_toplevel_unset_fullscreen(window_->xdg_decor->toplevel); } break; } @@ -796,36 +797,36 @@ GHOST_TSuccess GHOST_WindowWayland::setState(GHOST_TWindowState state) case GHOST_kWindowStateMaximized: { #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { - libdecor_frame_set_maximized(w->libdecor->frame); + libdecor_frame_set_maximized(window_->libdecor->frame); } else #endif { - xdg_toplevel_set_maximized(w->xdg_decor->toplevel); + xdg_toplevel_set_maximized(window_->xdg_decor->toplevel); } break; } case GHOST_kWindowStateMinimized: { #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { - libdecor_frame_set_minimized(w->libdecor->frame); + libdecor_frame_set_minimized(window_->libdecor->frame); } else #endif { - xdg_toplevel_set_minimized(w->xdg_decor->toplevel); + xdg_toplevel_set_minimized(window_->xdg_decor->toplevel); } break; } case GHOST_kWindowStateFullScreen: { #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { - libdecor_frame_set_fullscreen(w->libdecor->frame, nullptr); + libdecor_frame_set_fullscreen(window_->libdecor->frame, nullptr); } else #endif { - xdg_toplevel_set_fullscreen(w->xdg_decor->toplevel, nullptr); + xdg_toplevel_set_fullscreen(window_->xdg_decor->toplevel, nullptr); } break; } @@ -838,10 +839,10 @@ GHOST_TSuccess GHOST_WindowWayland::setState(GHOST_TWindowState state) GHOST_TWindowState GHOST_WindowWayland::getState() const { - if (w->is_fullscreen) { + if (window_->is_fullscreen) { return GHOST_kWindowStateFullScreen; } - if (w->is_maximised) { + if (window_->is_maximised) { return GHOST_kWindowStateMaximized; } return GHOST_kWindowStateNormal; @@ -861,12 +862,12 @@ GHOST_TSuccess GHOST_WindowWayland::beginFullScreen() const { #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { - libdecor_frame_set_fullscreen(w->libdecor->frame, nullptr); + libdecor_frame_set_fullscreen(window_->libdecor->frame, nullptr); } else #endif { - xdg_toplevel_set_fullscreen(w->xdg_decor->toplevel, nullptr); + xdg_toplevel_set_fullscreen(window_->xdg_decor->toplevel, nullptr); } return GHOST_kSuccess; @@ -876,19 +877,19 @@ GHOST_TSuccess GHOST_WindowWayland::endFullScreen() const { #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { - libdecor_frame_unset_fullscreen(w->libdecor->frame); + libdecor_frame_unset_fullscreen(window_->libdecor->frame); } else #endif { - xdg_toplevel_unset_fullscreen(w->xdg_decor->toplevel); + xdg_toplevel_unset_fullscreen(window_->xdg_decor->toplevel); } return GHOST_kSuccess; } bool GHOST_WindowWayland::isDialog() const { - return w->is_dialog; + return window_->is_dialog; } #ifdef GHOST_OPENGL_ALPHA @@ -897,9 +898,9 @@ void GHOST_WindowWayland::setOpaque() const struct wl_region *region; /* Make the window opaque. */ - region = wl_compositor_create_region(m_system->compositor()); - wl_region_add(region, 0, 0, UNPACK2(w->size)); - wl_surface_set_opaque_region(w->surface, region); + region = wl_compositor_create_region(system_->compositor()); + wl_region_add(region, 0, 0, UNPACK2(window_->size)); + wl_surface_set_opaque_region(window_->surface, region); wl_region_destroy(region); } #endif @@ -917,10 +918,10 @@ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType break; case GHOST_kDrawingContextTypeOpenGL: for (int minor = 6; minor >= 0; --minor) { - context = new GHOST_ContextEGL(this->m_system, + context = new GHOST_ContextEGL(system_, m_wantStereoVisual, - EGLNativeWindowType(w->egl_window), - EGLNativeDisplayType(m_system->display()), + EGLNativeWindowType(window_->egl_window), + EGLNativeDisplayType(system_->wl_display()), EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, 4, minor, @@ -933,10 +934,10 @@ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType } delete context; } - context = new GHOST_ContextEGL(this->m_system, + context = new GHOST_ContextEGL(system_, m_wantStereoVisual, - EGLNativeWindowType(w->egl_window), - EGLNativeDisplayType(m_system->display()), + EGLNativeWindowType(window_->egl_window), + EGLNativeDisplayType(system_->wl_display()), EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, 3, 3, @@ -958,22 +959,22 @@ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType uint16_t GHOST_WindowWayland::dpi() const { - return w->dpi; + return window_->dpi; } int GHOST_WindowWayland::scale() const { - return w->scale; + return window_->scale; } wl_surface *GHOST_WindowWayland::wl_surface() const { - return w->wl_surface; + return window_->wl_surface; } const std::vector &GHOST_WindowWayland::outputs() { - return w->outputs; + return window_->outputs; } /** \} */ @@ -986,24 +987,24 @@ const std::vector &GHOST_WindowWayland::outputs() GHOST_TSuccess GHOST_WindowWayland::close() { - return m_system->pushEvent( - new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowClose, this)); + return system_->pushEvent( + new GHOST_Event(system_->getMilliSeconds(), GHOST_kEventWindowClose, this)); } GHOST_TSuccess GHOST_WindowWayland::activate() { - if (m_system->getWindowManager()->setActiveWindow(this) == GHOST_kFailure) { + if (system_->getWindowManager()->setActiveWindow(this) == GHOST_kFailure) { return GHOST_kFailure; } - return m_system->pushEvent( - new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowActivate, this)); + return system_->pushEvent( + new GHOST_Event(system_->getMilliSeconds(), GHOST_kEventWindowActivate, this)); } GHOST_TSuccess GHOST_WindowWayland::deactivate() { - m_system->getWindowManager()->setWindowInactive(this); - return m_system->pushEvent( - new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowDeactivate, this)); + system_->getWindowManager()->setWindowInactive(this); + return system_->pushEvent( + new GHOST_Event(system_->getMilliSeconds(), GHOST_kEventWindowDeactivate, this)); } GHOST_TSuccess GHOST_WindowWayland::notify_size() @@ -1012,8 +1013,8 @@ GHOST_TSuccess GHOST_WindowWayland::notify_size() setOpaque(); #endif - return m_system->pushEvent( - new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowSize, this)); + return system_->pushEvent( + new GHOST_Event(system_->getMilliSeconds(), GHOST_kEventWindowSize, this)); } /** \} */ @@ -1030,30 +1031,29 @@ GHOST_TSuccess GHOST_WindowWayland::notify_size() bool GHOST_WindowWayland::outputs_changed_update_scale() { uint32_t dpi_next; - const int scale_next = outputs_max_scale_or_default(this->outputs(), 0, &dpi_next); + const int scale_next = outputs_max_scale_or_default(outputs(), 0, &dpi_next); if (UNLIKELY(scale_next == 0)) { return false; } - GWL_Window *win = this->w; - const uint32_t dpi_curr = win->dpi; - const int scale_curr = win->scale; + const uint32_t dpi_curr = window_->dpi; + const int scale_curr = window_->scale; bool changed = false; if (scale_next != scale_curr) { /* Unlikely but possible there is a pending size change is set. */ - win->size_pending[0] = (win->size_pending[0] / scale_curr) * scale_next; - win->size_pending[1] = (win->size_pending[1] / scale_curr) * scale_next; + window_->size_pending[0] = (window_->size_pending[0] / scale_curr) * scale_next; + window_->size_pending[1] = (window_->size_pending[1] / scale_curr) * scale_next; - win->scale = scale_next; - wl_surface_set_buffer_scale(w->wl_surface, scale_next); + window_->scale = scale_next; + wl_surface_set_buffer_scale(window_->wl_surface, scale_next); changed = true; } if (dpi_next != dpi_curr) { /* Using the real DPI will cause wrong scaling of the UI * use a multiplier for the default DPI as workaround. */ - win->dpi = dpi_next; + window_->dpi = dpi_next; changed = true; /* As this is a low-level function, we might want adding this event to be optional, @@ -1068,7 +1068,7 @@ bool GHOST_WindowWayland::outputs_changed_update_scale() bool GHOST_WindowWayland::outputs_enter(GWL_Output *output) { - std::vector &outputs = w->outputs; + std::vector &outputs = window_->outputs; auto it = std::find(outputs.begin(), outputs.end(), output); if (it != outputs.end()) { return false; @@ -1079,7 +1079,7 @@ bool GHOST_WindowWayland::outputs_enter(GWL_Output *output) bool GHOST_WindowWayland::outputs_leave(GWL_Output *output) { - std::vector &outputs = w->outputs; + std::vector &outputs = window_->outputs; auto it = std::find(outputs.begin(), outputs.end(), output); if (it == outputs.end()) { return false; diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h index 9b4c17ecd95..e95f5386310 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.h +++ b/intern/ghost/intern/GHOST_WindowWayland.h @@ -115,9 +115,9 @@ class GHOST_WindowWayland : public GHOST_Window { bool outputs_changed_update_scale(); private: - GHOST_SystemWayland *m_system; - struct GWL_Window *w; - std::string title; + GHOST_SystemWayland *system_; + struct GWL_Window *window_; + std::string title_; /** * \param type: The type of rendering context create. -- cgit v1.2.3 From 3e35beae6143d865636edb7c66a8f86873618f19 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 17 Oct 2022 12:41:56 +1100 Subject: Cleanup: correct doc-string & remove unused define Minor edits to recent commits. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 2 +- source/blender/blenlib/BLI_path_util.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 0778938a8e4..04c7e103bde 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -534,7 +534,7 @@ struct GWL_Display { static GHOST_WindowManager *window_manager = nullptr; -/** Check this lock before accessing `GHOST_SystemWayland::selection` from a thread. */ +/** Check this lock before accessing #GHOST_SystemWayland::clipboard_ from a thread. */ static std::mutex system_clipboard_mutex; /** diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 4610b71dcd5..d4d2ddead71 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -107,7 +107,6 @@ size_t BLI_path_join_array(char *__restrict dst, #define _BLI_PATH_JOIN_ARGS_8 _BLI_PATH_JOIN_ARGS_7, const char *h #define _BLI_PATH_JOIN_ARGS_9 _BLI_PATH_JOIN_ARGS_8, const char *i #define _BLI_PATH_JOIN_ARGS_10 _BLI_PATH_JOIN_ARGS_9, const char *j -#define _BLI_PATH_JOIN_ARGS_11 _BLI_PATH_JOIN_ARGS_10, const char *k BLI_INLINE size_t _BLI_path_join_3(_BLI_PATH_JOIN_ARGS_1) ATTR_NONNULL(); BLI_INLINE size_t _BLI_path_join_4(_BLI_PATH_JOIN_ARGS_2) ATTR_NONNULL(); @@ -181,7 +180,6 @@ BLI_INLINE size_t _BLI_path_join_12(_BLI_PATH_JOIN_ARGS_10) #undef _BLI_PATH_JOIN_ARGS_8 #undef _BLI_PATH_JOIN_ARGS_9 #undef _BLI_PATH_JOIN_ARGS_10 -#undef _BLI_PATH_JOIN_ARGS_11 /** * Like Python's `os.path.basename()` -- cgit v1.2.3 From 89effac57e057249b787454191b95be392633ecf Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 17 Oct 2022 11:02:13 +0200 Subject: Fix T101851: Duplicating a particle system crashes --- source/blender/editors/physics/particle_object.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index 71ed32caede..4986ed8f343 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -1204,9 +1204,7 @@ static bool copy_particle_systems_to_object(const bContext *C, #undef PSYS_FROM_FIRST #undef PSYS_FROM_NEXT - if (duplicate_settings) { - DEG_relations_tag_update(bmain); - } + DEG_relations_tag_update(bmain); DEG_id_tag_update(&ob_to->id, ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, ob_to); return true; -- cgit v1.2.3 From 11bb38e887d29635498fb184f6434144546e9fb4 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 17 Oct 2022 11:03:21 +0200 Subject: Make sure all dependency graphs are updated on particles system copy --- source/blender/editors/physics/particle_object.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index 4986ed8f343..210757173eb 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -1267,8 +1267,7 @@ static int copy_particle_systems_exec(bContext *C, wmOperator *op) CTX_DATA_END; if (changed_tot > 0) { - Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); - DEG_graph_tag_relations_update(depsgraph); + DEG_relations_tag_update(CTX_data_main(C)); } if ((changed_tot == 0 && fail == 0) || fail) { -- cgit v1.2.3 From db40b62252e5a7716cd403a0574cc164163b2ce9 Mon Sep 17 00:00:00 2001 From: Pablo Vazquez Date: Mon, 17 Oct 2022 11:17:42 +0200 Subject: Sculpt: Auto-masking UI improvements Add auto-masking as a popover in the header while in Sculpt mode, following the design in T101593. These properties were present in the Options panel (and popover), they have been removed from there. Moreover, this commit makes the auto-masking section in Brush settings match the new popover. In the future this popover can be used for other modes that support auto-masking such as Grease Pencil. See D16145 for details and screenshots. Reviewed By: JulienKaspar Differential Revision: https://developer.blender.org/D16145 --- .../startup/bl_ui/properties_paint_common.py | 72 ++++++++++++------- release/scripts/startup/bl_ui/space_view3d.py | 82 +++++++++++++++++++++- .../scripts/startup/bl_ui/space_view3d_toolbar.py | 46 ------------ source/blender/makesrna/intern/rna_brush.c | 9 ++- source/blender/makesrna/intern/rna_sculpt_paint.c | 9 ++- 5 files changed, 138 insertions(+), 80 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index 72a87703bd5..0e49a506e73 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -928,60 +928,80 @@ def brush_settings_advanced(layout, context, brush, popover=False): use_frontface = False if mode == 'SCULPT': + sculpt = context.tool_settings.sculpt capabilities = brush.sculpt_capabilities use_accumulate = capabilities.has_accumulate use_frontface = True col = layout.column(heading="Auto-Masking", align=True) - # topology automasking + col = layout.column(align=True) col.prop(brush, "use_automasking_topology", text="Topology") - - # face masks automasking col.prop(brush, "use_automasking_face_sets", text="Face Sets") - # boundary edges/face sets automasking + layout.separator() + + col = layout.column(align=True) col.prop(brush, "use_automasking_boundary_edges", text="Mesh Boundary") col.prop(brush, "use_automasking_boundary_face_sets", text="Face Sets Boundary") - col.prop(brush, "use_automasking_cavity", text="Cavity") - col.prop(brush, "use_automasking_cavity_inverted", text="Cavity (Inverted)") - col.prop(brush, "use_automasking_start_normal", text="Area Normal") - col.prop(brush, "use_automasking_view_normal", text="View Normal") - col.separator() - col.prop(brush, "automasking_boundary_edges_propagation_steps") + if brush.use_automasking_boundary_edges or brush.use_automasking_boundary_face_sets: + col = layout.column() + col.use_property_split = False + split = col.split(factor=0.4) + col = split.column() + split.prop(brush, "automasking_boundary_edges_propagation_steps") - sculpt = context.tool_settings.sculpt + layout.separator() - if brush.use_automasking_start_normal: - col.separator() + col = layout.column(align=True) + row = col.row() + row.prop(brush, "use_automasking_cavity", text="Cavity") - col.prop(sculpt, "automasking_start_normal_limit") - col.prop(sculpt, "automasking_start_normal_falloff") + is_cavity_active = brush.use_automasking_cavity or brush.use_automasking_cavity_inverted - if brush.use_automasking_view_normal: - col.separator() + if is_cavity_active: + row.operator("sculpt.mask_from_cavity", text="Create Mask") - col.prop(brush, "use_automasking_view_occlusion", text="Occlusion") - col.prop(sculpt, "automasking_view_normal_limit") - col.prop(sculpt, "automasking_view_normal_falloff") + col.prop(brush, "use_automasking_cavity_inverted", text="Cavity (inverted)") - if brush.use_automasking_cavity or brush.use_automasking_cavity_inverted: - col.separator() + if is_cavity_active: + col = layout.column(align=True) + col.prop(brush, "automasking_cavity_factor", text="Factor") + col.prop(brush, "automasking_cavity_blur_steps", text="Blur") - col.prop(brush, "automasking_cavity_factor", text="Cavity Factor") - col.prop(brush, "automasking_cavity_blur_steps", text="Cavity Blur") - col.prop(brush, "use_automasking_custom_cavity_curve", text="Use Curve") + col = layout.column() + col.prop(brush, "use_automasking_custom_cavity_curve", text="Custom Curve") if brush.use_automasking_custom_cavity_curve: col.template_curve_mapping(brush, "automasking_cavity_curve") layout.separator() + col = layout.column(align=True) + col.prop(brush, "use_automasking_view_normal", text="View Normal") + + if brush.use_automasking_view_normal: + col.prop(brush, "use_automasking_view_occlusion", text="Occlusion") + subcol = col.column(align=True) + subcol.active = not brush.use_automasking_view_occlusion + subcol.prop(sculpt, "automasking_view_normal_limit", text="Limit") + subcol.prop(sculpt, "automasking_view_normal_falloff", text="Falloff") + + col = layout.column() + col.prop(brush, "use_automasking_start_normal", text="Area Normal") + + if brush.use_automasking_start_normal: + col = layout.column(align=True) + col.prop(sculpt, "automasking_start_normal_limit", text="Limit") + col.prop(sculpt, "automasking_start_normal_falloff", text="Falloff") + + layout.separator() + # sculpt plane settings if capabilities.has_sculpt_plane: layout.prop(brush, "sculpt_plane") - col = layout.column(heading="Use Original", align=True) + col = layout.column(heading="Original", align=True) col.prop(brush, "use_original_normal", text="Normal") col.prop(brush, "use_original_plane", text="Plane") layout.separator() diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 3a02492635a..ea257498e11 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -838,12 +838,18 @@ class VIEW3D_HT_header(Header): text="Guides", ) - layout.separator_spacer() + elif object_mode == 'SCULPT': + layout.popover( + panel="VIEW3D_PT_sculpt_automasking", + text="", + icon="MOD_MASK" + ) + else: # Transform settings depending on tool header visibility VIEW3D_HT_header.draw_xform_template(layout, context) - layout.separator_spacer() + layout.separator_spacer() # Viewport Settings layout.popover( @@ -7680,6 +7686,77 @@ class VIEW3D_PT_paint_weight_context_menu(Panel): ) +class VIEW3D_PT_sculpt_automasking(Panel): + bl_space_type = 'VIEW_3D' + bl_region_type = 'HEADER' + bl_label = "Auto-Masking" + bl_ui_units_x = 10 + + def draw(self, context): + layout = self.layout + + tool_settings = context.tool_settings + sculpt = tool_settings.sculpt + layout.label(text="Auto-Masking") + + col = layout.column(align=True) + col.prop(sculpt, "use_automasking_topology", text="Topology") + col.prop(sculpt, "use_automasking_face_sets", text="Face Sets") + + col.separator() + + col = layout.column(align=True) + col.prop(sculpt, "use_automasking_boundary_edges", text="Mesh Boundary") + col.prop(sculpt, "use_automasking_boundary_face_sets", text="Face Sets Boundary") + + if sculpt.use_automasking_boundary_edges or sculpt.use_automasking_boundary_face_sets: + col.prop(sculpt.brush, "automasking_boundary_edges_propagation_steps") + + col.separator() + + col = layout.column(align=True) + row = col.row() + row.prop(sculpt, "use_automasking_cavity", text="Cavity") + + is_cavity_active = sculpt.use_automasking_cavity or sculpt.use_automasking_cavity_inverted + + if is_cavity_active: + row.operator("sculpt.mask_from_cavity", text="Create Mask") + + col.prop(sculpt, "use_automasking_cavity_inverted", text="Cavity (inverted)") + + if is_cavity_active: + col = layout.column(align=True) + col.prop(sculpt, "automasking_cavity_factor", text="Factor") + col.prop(sculpt, "automasking_cavity_blur_steps", text="Blur") + + col = layout.column() + col.prop(sculpt, "use_automasking_custom_cavity_curve", text="Custom Curve") + + if sculpt.use_automasking_custom_cavity_curve: + col.template_curve_mapping(sculpt, "automasking_cavity_curve") + + col.separator() + + col = layout.column(align=True) + col.prop(sculpt, "use_automasking_view_normal", text="View Normal") + + if sculpt.use_automasking_view_normal: + col.prop(sculpt, "use_automasking_view_occlusion", text="Occlusion") + subcol = col.column(align=True) + subcol.active = not sculpt.use_automasking_view_occlusion + subcol.prop(sculpt, "automasking_view_normal_limit", text="Limit") + subcol.prop(sculpt, "automasking_view_normal_falloff", text="Falloff") + + col = layout.column() + col.prop(sculpt, "use_automasking_start_normal", text="Area Normal") + + if sculpt.use_automasking_start_normal: + col = layout.column(align=True) + col.prop(sculpt, "automasking_start_normal_limit", text="Limit") + col.prop(sculpt, "automasking_start_normal_falloff", text="Falloff") + + class VIEW3D_PT_sculpt_context_menu(Panel): # Only for popover, these are dummy values. bl_space_type = 'VIEW_3D' @@ -8070,6 +8147,7 @@ classes = ( VIEW3D_PT_gpencil_sculpt_context_menu, VIEW3D_PT_gpencil_weight_context_menu, VIEW3D_PT_gpencil_draw_context_menu, + VIEW3D_PT_sculpt_automasking, VIEW3D_PT_sculpt_context_menu, TOPBAR_PT_gpencil_materials, TOPBAR_PT_gpencil_vertexcolor, diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 3357676bf2f..328e45f79b9 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -964,52 +964,6 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel): col.prop(sculpt, "use_sculpt_delay_updates") col.prop(sculpt, "use_deform_only") - col.separator() - - col = layout.column(heading="Auto-Masking", align=True) - - col.prop(sculpt, "use_automasking_topology", text="Topology") - col.prop(sculpt, "use_automasking_face_sets", text="Face Sets") - col.prop(sculpt, "use_automasking_boundary_edges", text="Mesh Boundary") - col.prop(sculpt, "use_automasking_boundary_face_sets", text="Face Sets Boundary") - col.prop(sculpt, "use_automasking_cavity", text="Cavity") - col.prop(sculpt, "use_automasking_cavity_inverted", text="Cavity (Inverted)") - col.prop(sculpt, "use_automasking_start_normal", text="Area Normal") - col.prop(sculpt, "use_automasking_view_normal", text="View Normal") - - if sculpt.use_automasking_start_normal: - col.separator() - - col.prop(sculpt, "automasking_start_normal_limit") - col.prop(sculpt, "automasking_start_normal_falloff") - - if sculpt.use_automasking_view_normal: - col.separator() - - col.prop(sculpt, "use_automasking_view_occlusion", text="Occlusion") - col.prop(sculpt, "automasking_view_normal_limit") - col.prop(sculpt, "automasking_view_normal_falloff") - - col.separator() - col.prop(sculpt.brush, "automasking_boundary_edges_propagation_steps") - - if sculpt.use_automasking_cavity or sculpt.use_automasking_cavity_inverted: - col.separator() - - col2 = col.column() - props = col2.operator("sculpt.mask_from_cavity", text="Mask From Cavity") - props.use_automask_settings = True - - col2 = col.column() - - col2.prop(sculpt, "automasking_cavity_factor", text="Cavity Factor") - col2.prop(sculpt, "automasking_cavity_blur_steps", text="Cavity Blur") - - col2.prop(sculpt, "use_automasking_custom_cavity_curve", text="Use Curve") - - if sculpt.use_automasking_custom_cavity_curve: - col2.template_curve_mapping(sculpt, "automasking_cavity_curve") - class VIEW3D_PT_sculpt_options_gravity(Panel, View3DPaintPanel): bl_context = ".sculpt_mode" # dot on purpose (access from topbar) diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 5e4b08d8a41..b44b0620329 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -3240,18 +3240,21 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Brush_update"); } while ((++entry)->identifier); - prop = RNA_def_property(srna, "automasking_cavity_factor", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "automasking_cavity_factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "automasking_cavity_factor"); + RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Cavity Factor", "The contrast of the cavity mask"); - RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); RNA_def_property_range(prop, 0.0f, 5.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Brush_update"); prop = RNA_def_property(srna, "automasking_cavity_blur_steps", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "automasking_cavity_blur_steps"); + RNA_def_property_int_default(prop, 0); RNA_def_property_ui_text(prop, "Blur Steps", "The number of times the cavity mask is blurred"); - RNA_def_property_range(prop, 0.0f, 25.0f); + RNA_def_property_range(prop, 0, 25); + RNA_def_property_ui_range(prop, 0, 10, 1, 1); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Brush_update"); diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index d8ad3d1f41e..440309849ab 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -927,17 +927,20 @@ static void rna_def_sculpt(BlenderRNA *brna) RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); } while ((++entry)->identifier); - prop = RNA_def_property(srna, "automasking_cavity_factor", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "automasking_cavity_factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "automasking_cavity_factor"); RNA_def_property_ui_text(prop, "Cavity Factor", "The contrast of the cavity mask"); - RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); + RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0.0f, 5.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); prop = RNA_def_property(srna, "automasking_cavity_blur_steps", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "automasking_cavity_blur_steps"); RNA_def_property_ui_text(prop, "Blur Steps", "The number of times the cavity mask is blurred"); - RNA_def_property_range(prop, 0.0f, 25.0f); + RNA_def_property_int_default(prop, 0); + RNA_def_property_range(prop, 0, 25); + RNA_def_property_ui_range(prop, 0, 10, 1, 1); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); prop = RNA_def_property(srna, "automasking_cavity_curve", PROP_POINTER, PROP_NONE); -- cgit v1.2.3 From e5425b566d0f25f60b5895c4025c183fd67c7d9c Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 17 Oct 2022 11:39:40 +0200 Subject: Geometry Nodes: separate Instances from InstancesComponent This makes instance handling more consistent with all the other geometry component types. For example, `MeshComponent` contains a `Mesh *` and now `InstancesComponent` has a `Instances *`. Differential Revision: https://developer.blender.org/D16137 --- source/blender/blenkernel/BKE_geometry_fields.hh | 13 +- source/blender/blenkernel/BKE_geometry_set.hh | 251 ++------------ source/blender/blenkernel/BKE_instances.hh | 270 +++++++++++++++ source/blender/blenkernel/CMakeLists.txt | 2 + .../intern/geometry_component_instances.cc | 385 ++++----------------- .../blender/blenkernel/intern/geometry_fields.cc | 16 +- source/blender/blenkernel/intern/geometry_set.cc | 58 +++- .../blenkernel/intern/geometry_set_instances.cc | 45 ++- source/blender/blenkernel/intern/instances.cc | 348 +++++++++++++++++++ source/blender/blenkernel/intern/object_dupli.cc | 17 +- .../space_spreadsheet/spreadsheet_column.cc | 3 +- .../spreadsheet_data_source_geometry.cc | 49 +-- .../space_spreadsheet/spreadsheet_layout.cc | 13 +- .../space_spreadsheet/spreadsheet_row_filter.cc | 16 +- .../blender/geometry/intern/realize_instances.cc | 46 +-- .../geometry/nodes/node_geo_collection_info.cc | 18 +- .../geometry/nodes/node_geo_delete_geometry.cc | 7 +- .../geometry/nodes/node_geo_duplicate_elements.cc | 32 +- .../nodes/node_geo_geometry_to_instance.cc | 12 +- .../nodes/node_geo_input_instance_rotation.cc | 9 +- .../nodes/node_geo_input_instance_scale.cc | 9 +- .../geometry/nodes/node_geo_instance_on_points.cc | 42 ++- .../geometry/nodes/node_geo_instances_to_points.cc | 5 +- .../nodes/geometry/nodes/node_geo_join_geometry.cc | 35 +- .../nodes/geometry/nodes/node_geo_object_info.cc | 10 +- .../geometry/nodes/node_geo_rotate_instances.cc | 17 +- .../geometry/nodes/node_geo_scale_instances.cc | 17 +- .../geometry/nodes/node_geo_string_to_curves.cc | 24 +- .../nodes/geometry/nodes/node_geo_transform.cc | 19 +- .../geometry/nodes/node_geo_translate_instances.cc | 19 +- source/blender/nodes/intern/geometry_nodes_log.cc | 2 +- 31 files changed, 1027 insertions(+), 782 deletions(-) create mode 100644 source/blender/blenkernel/BKE_instances.hh create mode 100644 source/blender/blenkernel/intern/instances.cc diff --git a/source/blender/blenkernel/BKE_geometry_fields.hh b/source/blender/blenkernel/BKE_geometry_fields.hh index 988e0017f04..2eef67dba98 100644 --- a/source/blender/blenkernel/BKE_geometry_fields.hh +++ b/source/blender/blenkernel/BKE_geometry_fields.hh @@ -75,14 +75,14 @@ class PointCloudFieldContext : public fn::FieldContext { class InstancesFieldContext : public fn::FieldContext { private: - const InstancesComponent &instances_; + const Instances &instances_; public: - InstancesFieldContext(const InstancesComponent &instances) : instances_(instances) + InstancesFieldContext(const Instances &instances) : instances_(instances) { } - const InstancesComponent &instances() const + const Instances &instances() const { return instances_; } @@ -128,13 +128,13 @@ class GeometryFieldContext : public fn::FieldContext { const Mesh *mesh() const; const CurvesGeometry *curves() const; const PointCloud *pointcloud() const; - const InstancesComponent *instances() const; + const Instances *instances() const; private: GeometryFieldContext(const Mesh &mesh, eAttrDomain domain); GeometryFieldContext(const CurvesGeometry &curves, eAttrDomain domain); GeometryFieldContext(const PointCloud &points); - GeometryFieldContext(const InstancesComponent &instances); + GeometryFieldContext(const Instances &instances); }; class GeometryFieldInput : public fn::FieldInput { @@ -187,8 +187,7 @@ class InstancesFieldInput : public fn::FieldInput { GVArray get_varray_for_context(const fn::FieldContext &context, IndexMask mask, ResourceScope &scope) const override; - virtual GVArray get_varray_for_context(const InstancesComponent &instances, - IndexMask mask) const = 0; + virtual GVArray get_varray_for_context(const Instances &instances, IndexMask mask) const = 0; }; class AttributeFieldInput : public GeometryFieldInput { diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index 2ef9556afc7..b488806c8e7 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -43,6 +43,7 @@ enum class GeometryOwnershipType { namespace blender::bke { class ComponentAttributeProviders; class CurvesEditHints; +class Instances; } // namespace blender::bke class GeometryComponent; @@ -246,6 +247,12 @@ struct GeometrySet { */ static GeometrySet create_with_curves( Curves *curves, GeometryOwnershipType ownership = GeometryOwnershipType::Owned); + /** + * Create a new geometry set that only contains the given instances. + */ + static GeometrySet create_with_instances( + blender::bke::Instances *instances, + GeometryOwnershipType ownership = GeometryOwnershipType::Owned); /* Utility methods for access. */ /** @@ -293,6 +300,10 @@ struct GeometrySet { * Returns a read-only curves data-block or null. */ const Curves *get_curves_for_read() const; + /** + * Returns read-only instances or null. + */ + const blender::bke::Instances *get_instances_for_read() const; /** * Returns read-only curve edit hints or null. */ @@ -314,6 +325,10 @@ struct GeometrySet { * Returns a mutable curves data-block or null. No ownership is transferred. */ Curves *get_curves_for_write(); + /** + * Returns mutable instances or null. No ownership is transferred. + */ + blender::bke::Instances *get_instances_for_write(); /** * Returns mutable curve edit hints or null. */ @@ -339,6 +354,11 @@ struct GeometrySet { */ void replace_curves(Curves *curves, GeometryOwnershipType ownership = GeometryOwnershipType::Owned); + /** + * Clear the existing instances and replace them with the given one. + */ + void replace_instances(blender::bke::Instances *instances, + GeometryOwnershipType ownership = GeometryOwnershipType::Owned); private: /** @@ -515,244 +535,35 @@ class CurveComponent : public GeometryComponent { }; /** - * Holds a reference to conceptually unique geometry or a pointer to object/collection data - * that is instanced with a transform in #InstancesComponent. - */ -class InstanceReference { - public: - enum class Type { - /** - * An empty instance. This allows an `InstanceReference` to be default constructed without - * being in an invalid state. There might also be other use cases that we haven't explored much - * yet (such as changing the instance later on, and "disabling" some instances). - */ - None, - Object, - Collection, - GeometrySet, - }; - - private: - Type type_ = Type::None; - /** Depending on the type this is either null, an Object or Collection pointer. */ - void *data_ = nullptr; - std::unique_ptr geometry_set_; - - public: - InstanceReference() = default; - - InstanceReference(Object &object) : type_(Type::Object), data_(&object) - { - } - - InstanceReference(Collection &collection) : type_(Type::Collection), data_(&collection) - { - } - - InstanceReference(GeometrySet geometry_set) - : type_(Type::GeometrySet), - geometry_set_(std::make_unique(std::move(geometry_set))) - { - } - - InstanceReference(const InstanceReference &other) : type_(other.type_), data_(other.data_) - { - if (other.geometry_set_) { - geometry_set_ = std::make_unique(*other.geometry_set_); - } - } - - InstanceReference(InstanceReference &&other) - : type_(other.type_), data_(other.data_), geometry_set_(std::move(other.geometry_set_)) - { - other.type_ = Type::None; - other.data_ = nullptr; - } - - InstanceReference &operator=(const InstanceReference &other) - { - if (this == &other) { - return *this; - } - this->~InstanceReference(); - new (this) InstanceReference(other); - return *this; - } - - InstanceReference &operator=(InstanceReference &&other) - { - if (this == &other) { - return *this; - } - this->~InstanceReference(); - new (this) InstanceReference(std::move(other)); - return *this; - } - - Type type() const - { - return type_; - } - - Object &object() const - { - BLI_assert(type_ == Type::Object); - return *(Object *)data_; - } - - Collection &collection() const - { - BLI_assert(type_ == Type::Collection); - return *(Collection *)data_; - } - - const GeometrySet &geometry_set() const - { - BLI_assert(type_ == Type::GeometrySet); - return *geometry_set_; - } - - bool owns_direct_data() const - { - if (type_ != Type::GeometrySet) { - /* The object and collection instances are not direct data. */ - return true; - } - return geometry_set_->owns_direct_data(); - } - - void ensure_owns_direct_data() - { - if (type_ != Type::GeometrySet) { - return; - } - geometry_set_->ensure_owns_direct_data(); - } - - uint64_t hash() const - { - return blender::get_default_hash_2(data_, geometry_set_.get()); - } - - friend bool operator==(const InstanceReference &a, const InstanceReference &b) - { - return a.data_ == b.data_ && a.geometry_set_.get() == b.geometry_set_.get(); - } -}; - -/** - * A geometry component that stores instances. The instance data can be any type described by - * #InstanceReference. Geometry instances can even contain instances themselves, for nested - * instancing. Each instance has an index into an array of unique instance data, and a transform. - * The component can also store generic attributes for each instance. - * - * The component works differently from other geometry components in that it stores - * data about instancing directly, rather than owning a pointer to a separate data structure. - * - * This component is not responsible for handling the interface to a render engine, or other - * areas that work with all visible geometry, that is handled by the dependency graph iterator - * (see `DEG_depsgraph_query.h`). + * A geometry component that stores #Instances. */ class InstancesComponent : public GeometryComponent { private: - /** - * Indexed set containing information about the data that is instanced. - * Actual instances store an index ("handle") into this set. - */ - blender::VectorSet references_; - - /** Index into `references_`. Determines what data is instanced. */ - blender::Vector instance_reference_handles_; - /** Transformation of the instances. */ - blender::Vector instance_transforms_; - - /* These almost unique ids are generated based on the `id` attribute, which might not contain - * unique ids at all. They are *almost* unique, because under certain very unlikely - * circumstances, they are not unique. Code using these ids should not crash when they are not - * unique but can generally expect them to be unique. */ - mutable std::mutex almost_unique_ids_mutex_; - mutable blender::Array almost_unique_ids_; - - blender::bke::CustomDataAttributes attributes_; + blender::bke::Instances *instances_ = nullptr; + GeometryOwnershipType ownership_ = GeometryOwnershipType::Owned; public: InstancesComponent(); - ~InstancesComponent() = default; + ~InstancesComponent(); GeometryComponent *copy() const override; void clear(); - void reserve(int min_capacity); - /** - * Resize the transform, handles, and attributes to the specified capacity. - * - * \note This function should be used carefully, only when it's guaranteed - * that the data will be filled. - */ - void resize(int capacity); + const blender::bke::Instances *get_for_read() const; + blender::bke::Instances *get_for_write(); - /** - * Returns a handle for the given reference. - * If the reference exists already, the handle of the existing reference is returned. - * Otherwise a new handle is added. - */ - int add_reference(const InstanceReference &reference); - /** - * Add a reference to the instance reference with an index specified by the #instance_handle - * argument. For adding many instances, using #resize and accessing the transform array directly - * is preferred. - */ - void add_instance(int instance_handle, const blender::float4x4 &transform); - - blender::Span references() const; - void remove_unused_references(); - - /** - * If references have a collection or object type, convert them into geometry instances - * recursively. After that, the geometry sets can be edited. There may still be instances of - * other types of they can't be converted to geometry sets. - */ - void ensure_geometry_instances(); - /** - * With write access to the instances component, the data in the instanced geometry sets can be - * changed. This is a function on the component rather than each reference to ensure `const` - * correctness for that reason. - */ - GeometrySet &geometry_set_from_reference(int reference_index); - - blender::Span instance_reference_handles() const; - blender::MutableSpan instance_reference_handles(); - blender::MutableSpan instance_transforms(); - blender::Span instance_transforms() const; - - int instances_num() const; - int references_num() const; - - /** - * Remove the indices that are not contained in the mask input, and remove unused instance - * references afterwards. - */ - void remove_instances(const blender::IndexMask mask); - - blender::Span almost_unique_ids() const; - - blender::bke::CustomDataAttributes &instance_attributes(); - const blender::bke::CustomDataAttributes &instance_attributes() const; - - std::optional attributes() const final; - std::optional attributes_for_write() final; - - void foreach_referenced_geometry( - blender::FunctionRef callback) const; + void replace(blender::bke::Instances *instances, + GeometryOwnershipType ownership = GeometryOwnershipType::Owned); bool is_empty() const final; bool owns_direct_data() const override; void ensure_owns_direct_data() override; - static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_INSTANCES; + std::optional attributes() const final; + std::optional attributes_for_write() final; - private: + static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_INSTANCES; }; /** diff --git a/source/blender/blenkernel/BKE_instances.hh b/source/blender/blenkernel/BKE_instances.hh new file mode 100644 index 00000000000..69b6f944838 --- /dev/null +++ b/source/blender/blenkernel/BKE_instances.hh @@ -0,0 +1,270 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +/** \file + * \ingroup bke + * + * #Instances is a container for geometry instances. It fullfills some key requirements: + * - Support nested instances. + * - Support instance attributes. + * - Support referencing different kinds of instances (objects, collections, geometry sets). + * - Support efficiently iterating over the instanced geometries, i.e. without have to iterate over + * all instances. + * + * #Instances has an ordered set of #InstanceReference. An #InstanceReference contains information + * about a particular instanced geometry. Each #InstanceReference has a handle (integer index) + * which is then stored per instance. Many instances can use the same #InstanceReference. + */ + +#include + +#include "BLI_float4x4.hh" +#include "BLI_vector.hh" +#include "BLI_vector_set.hh" + +#include "BKE_attribute.hh" + +class GeometrySet; +struct Object; +struct Collection; + +namespace blender::bke { + +/** + * Holds a reference to conceptually unique geometry or a pointer to object/collection data + * that is instanced with a transform in #Instances. + */ +class InstanceReference { + public: + enum class Type { + /** + * An empty instance. This allows an `InstanceReference` to be default constructed without + * being in an invalid state. There might also be other use cases that we haven't explored + * much yet (such as changing the instance later on, and "disabling" some instances). + */ + None, + Object, + Collection, + GeometrySet, + }; + + private: + Type type_ = Type::None; + /** Depending on the type this is either null, an Object or Collection pointer. */ + void *data_ = nullptr; + std::unique_ptr geometry_set_; + + public: + InstanceReference() = default; + InstanceReference(Object &object); + InstanceReference(Collection &collection); + InstanceReference(GeometrySet geometry_set); + + InstanceReference(const InstanceReference &other); + InstanceReference(InstanceReference &&other); + + InstanceReference &operator=(const InstanceReference &other); + InstanceReference &operator=(InstanceReference &&other); + + Type type() const; + Object &object() const; + Collection &collection() const; + const GeometrySet &geometry_set() const; + + bool owns_direct_data() const; + void ensure_owns_direct_data(); + + uint64_t hash() const; + friend bool operator==(const InstanceReference &a, const InstanceReference &b); +}; + +class Instances { + private: + /** + * Indexed set containing information about the data that is instanced. + * Actual instances store an index ("handle") into this set. + */ + blender::VectorSet references_; + + /** Indices into `references_`. Determines what data is instanced. */ + blender::Vector reference_handles_; + /** Transformation of the instances. */ + blender::Vector transforms_; + + /* These almost unique ids are generated based on the `id` attribute, which might not contain + * unique ids at all. They are *almost* unique, because under certain very unlikely + * circumstances, they are not unique. Code using these ids should not crash when they are not + * unique but can generally expect them to be unique. */ + mutable std::mutex almost_unique_ids_mutex_; + mutable blender::Array almost_unique_ids_; + + CustomDataAttributes attributes_; + + public: + Instances() = default; + Instances(const Instances &other); + + void reserve(int min_capacity); + /** + * Resize the transform, handles, and attributes to the specified capacity. + * + * \note This function should be used carefully, only when it's guaranteed + * that the data will be filled. + */ + void resize(int capacity); + + /** + * Returns a handle for the given reference. + * If the reference exists already, the handle of the existing reference is returned. + * Otherwise a new handle is added. + */ + int add_reference(const InstanceReference &reference); + /** + * Add a reference to the instance reference with an index specified by the #instance_handle + * argument. For adding many instances, using #resize and accessing the transform array + * directly is preferred. + */ + void add_instance(int instance_handle, const blender::float4x4 &transform); + + blender::Span references() const; + void remove_unused_references(); + + /** + * If references have a collection or object type, convert them into geometry instances + * recursively. After that, the geometry sets can be edited. There may still be instances of + * other types of they can't be converted to geometry sets. + */ + void ensure_geometry_instances(); + /** + * With write access to the instances component, the data in the instanced geometry sets can be + * changed. This is a function on the component rather than each reference to ensure `const` + * correctness for that reason. + */ + GeometrySet &geometry_set_from_reference(int reference_index); + + blender::Span reference_handles() const; + blender::MutableSpan reference_handles(); + blender::MutableSpan transforms(); + blender::Span transforms() const; + + int instances_num() const; + int references_num() const; + + /** + * Remove the indices that are not contained in the mask input, and remove unused instance + * references afterwards. + */ + void remove(const blender::IndexMask mask); + /** + * Get an id for every instance. These can be used for e.g. motion blur. + */ + blender::Span almost_unique_ids() const; + + blender::bke::AttributeAccessor attributes() const; + blender::bke::MutableAttributeAccessor attributes_for_write(); + + CustomDataAttributes &custom_data_attributes(); + const CustomDataAttributes &custom_data_attributes() const; + + void foreach_referenced_geometry( + blender::FunctionRef callback) const; + + bool owns_direct_data() const; + void ensure_owns_direct_data(); +}; + +/* -------------------------------------------------------------------- */ +/** \name #InstanceReference Inline Methods + * \{ */ + +inline InstanceReference::InstanceReference(Object &object) : type_(Type::Object), data_(&object) +{ +} + +inline InstanceReference::InstanceReference(Collection &collection) + : type_(Type::Collection), data_(&collection) +{ +} + +inline InstanceReference::InstanceReference(const InstanceReference &other) + : type_(other.type_), data_(other.data_) +{ + if (other.geometry_set_) { + geometry_set_ = std::make_unique(*other.geometry_set_); + } +} + +inline InstanceReference::InstanceReference(InstanceReference &&other) + : type_(other.type_), data_(other.data_), geometry_set_(std::move(other.geometry_set_)) +{ + other.type_ = Type::None; + other.data_ = nullptr; +} + +inline InstanceReference &InstanceReference::operator=(const InstanceReference &other) +{ + if (this == &other) { + return *this; + } + this->~InstanceReference(); + new (this) InstanceReference(other); + return *this; +} + +inline InstanceReference &InstanceReference::operator=(InstanceReference &&other) +{ + if (this == &other) { + return *this; + } + this->~InstanceReference(); + new (this) InstanceReference(std::move(other)); + return *this; +} + +inline InstanceReference::Type InstanceReference::type() const +{ + return type_; +} + +inline Object &InstanceReference::object() const +{ + BLI_assert(type_ == Type::Object); + return *(Object *)data_; +} + +inline Collection &InstanceReference::collection() const +{ + BLI_assert(type_ == Type::Collection); + return *(Collection *)data_; +} + +inline const GeometrySet &InstanceReference::geometry_set() const +{ + BLI_assert(type_ == Type::GeometrySet); + return *geometry_set_; +} + +inline CustomDataAttributes &Instances::custom_data_attributes() +{ + return attributes_; +} + +inline const CustomDataAttributes &Instances::custom_data_attributes() const +{ + return attributes_; +} + +inline uint64_t InstanceReference::hash() const +{ + return blender::get_default_hash_2(data_, geometry_set_.get()); +} + +inline bool operator==(const InstanceReference &a, const InstanceReference &b) +{ + return a.data_ == b.data_ && a.geometry_set_.get() == b.geometry_set_.get(); +} + +/** \} */ + +} // namespace blender::bke diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 97bdff217d0..7d43fa7e6af 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -163,6 +163,7 @@ set(SRC intern/image_gpu.cc intern/image_partial_update.cc intern/image_save.cc + intern/instances.cc intern/ipo.c intern/kelvinlet.c intern/key.c @@ -398,6 +399,7 @@ set(SRC BKE_image_partial_update.hh BKE_image_save.h BKE_image_wrappers.hh + BKE_instances.hh BKE_ipo.h BKE_kelvinlet.h BKE_key.h diff --git a/source/blender/blenkernel/intern/geometry_component_instances.cc b/source/blender/blenkernel/intern/geometry_component_instances.cc index 0b5f7cbf902..be1d9524509 100644 --- a/source/blender/blenkernel/intern/geometry_component_instances.cc +++ b/source/blender/blenkernel/intern/geometry_component_instances.cc @@ -16,6 +16,7 @@ #include "BKE_attribute_math.hh" #include "BKE_geometry_set.hh" #include "BKE_geometry_set_instances.hh" +#include "BKE_instances.hh" #include "attribute_access_intern.hh" @@ -29,8 +30,8 @@ using blender::MutableSpan; using blender::Set; using blender::Span; using blender::VectorSet; - -BLI_CPP_TYPE_MAKE(InstanceReference, InstanceReference, CPPTypeFlags::None) +using blender::bke::InstanceReference; +using blender::bke::Instances; /* -------------------------------------------------------------------- */ /** \name Geometry Component Implementation @@ -40,339 +41,76 @@ InstancesComponent::InstancesComponent() : GeometryComponent(GEO_COMPONENT_TYPE_ { } -GeometryComponent *InstancesComponent::copy() const -{ - InstancesComponent *new_component = new InstancesComponent(); - new_component->instance_reference_handles_ = instance_reference_handles_; - new_component->instance_transforms_ = instance_transforms_; - new_component->references_ = references_; - new_component->attributes_ = attributes_; - return new_component; -} - -void InstancesComponent::reserve(int min_capacity) +InstancesComponent::~InstancesComponent() { - instance_reference_handles_.reserve(min_capacity); - instance_transforms_.reserve(min_capacity); - attributes_.reallocate(min_capacity); + this->clear(); } -void InstancesComponent::resize(int capacity) +GeometryComponent *InstancesComponent::copy() const { - instance_reference_handles_.resize(capacity); - instance_transforms_.resize(capacity); - attributes_.reallocate(capacity); + InstancesComponent *new_component = new InstancesComponent(); + if (instances_ != nullptr) { + new_component->instances_ = new Instances(*instances_); + new_component->ownership_ = GeometryOwnershipType::Owned; + } + return new_component; } void InstancesComponent::clear() { - instance_reference_handles_.clear(); - instance_transforms_.clear(); - attributes_.clear(); - references_.clear(); -} - -void InstancesComponent::add_instance(const int instance_handle, const float4x4 &transform) -{ - BLI_assert(instance_handle >= 0); - BLI_assert(instance_handle < references_.size()); - instance_reference_handles_.append(instance_handle); - instance_transforms_.append(transform); - attributes_.reallocate(this->instances_num()); -} - -blender::Span InstancesComponent::instance_reference_handles() const -{ - return instance_reference_handles_; -} - -blender::MutableSpan InstancesComponent::instance_reference_handles() -{ - return instance_reference_handles_; -} - -blender::MutableSpan InstancesComponent::instance_transforms() -{ - return instance_transforms_; -} -blender::Span InstancesComponent::instance_transforms() const -{ - return instance_transforms_; -} - -GeometrySet &InstancesComponent::geometry_set_from_reference(const int reference_index) -{ - /* If this assert fails, it means #ensure_geometry_instances must be called first or that the - * reference can't be converted to a geometry set. */ - BLI_assert(references_[reference_index].type() == InstanceReference::Type::GeometrySet); - - /* The const cast is okay because the instance's hash in the set - * is not changed by adjusting the data inside the geometry set. */ - return const_cast(references_[reference_index].geometry_set()); -} - -int InstancesComponent::add_reference(const InstanceReference &reference) -{ - return references_.index_of_or_add_as(reference); -} - -blender::Span InstancesComponent::references() const -{ - return references_; -} - -template -static void copy_data_based_on_mask(Span src, MutableSpan dst, IndexMask mask) -{ - BLI_assert(src.data() != dst.data()); - using namespace blender; - threading::parallel_for(mask.index_range(), 1024, [&](IndexRange range) { - for (const int i : range) { - dst[i] = src[mask[i]]; - } - }); -} - -void InstancesComponent::remove_instances(const IndexMask mask) -{ - using namespace blender; - if (mask.is_range() && mask.as_range().start() == 0) { - /* Deleting from the end of the array can be much faster since no data has to be shifted. */ - this->resize(mask.size()); - this->remove_unused_references(); - return; + BLI_assert(this->is_mutable()); + if (ownership_ == GeometryOwnershipType::Owned) { + delete instances_; } - - Vector new_handles(mask.size()); - copy_data_based_on_mask(this->instance_reference_handles(), new_handles, mask); - instance_reference_handles_ = std::move(new_handles); - Vector new_transforms(mask.size()); - copy_data_based_on_mask(this->instance_transforms(), new_transforms, mask); - instance_transforms_ = std::move(new_transforms); - - const bke::CustomDataAttributes &src_attributes = attributes_; - - bke::CustomDataAttributes dst_attributes; - dst_attributes.reallocate(mask.size()); - - src_attributes.foreach_attribute( - [&](const bke::AttributeIDRef &id, const bke::AttributeMetaData &meta_data) { - if (!id.should_be_kept()) { - return true; - } - - GSpan src = *src_attributes.get_for_read(id); - dst_attributes.create(id, meta_data.data_type); - GMutableSpan dst = *dst_attributes.get_for_write(id); - - attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { - using T = decltype(dummy); - copy_data_based_on_mask(src.typed(), dst.typed(), mask); - }); - return true; - }, - ATTR_DOMAIN_INSTANCE); - - attributes_ = std::move(dst_attributes); - this->remove_unused_references(); + instances_ = nullptr; } -void InstancesComponent::remove_unused_references() +bool InstancesComponent::is_empty() const { - using namespace blender; - using namespace blender::bke; - - const int tot_instances = this->instances_num(); - const int tot_references_before = references_.size(); - - if (tot_instances == 0) { - /* If there are no instances, no reference is needed. */ - references_.clear(); - return; - } - if (tot_references_before == 1) { - /* There is only one reference and at least one instance. So the only existing reference is - * used. Nothing to do here. */ - return; - } - - Array usage_by_handle(tot_references_before, false); - std::mutex mutex; - - /* Loop over all instances to see which references are used. */ - threading::parallel_for(IndexRange(tot_instances), 1000, [&](IndexRange range) { - /* Use local counter to avoid lock contention. */ - Array local_usage_by_handle(tot_references_before, false); - - for (const int i : range) { - const int handle = instance_reference_handles_[i]; - BLI_assert(handle >= 0 && handle < tot_references_before); - local_usage_by_handle[handle] = true; - } - - std::lock_guard lock{mutex}; - for (const int i : IndexRange(tot_references_before)) { - usage_by_handle[i] |= local_usage_by_handle[i]; - } - }); - - if (!usage_by_handle.as_span().contains(false)) { - /* All references are used. */ - return; - } - - /* Create new references and a mapping for the handles. */ - Vector handle_mapping; - VectorSet new_references; - int next_new_handle = 0; - bool handles_have_to_be_updated = false; - for (const int old_handle : IndexRange(tot_references_before)) { - if (!usage_by_handle[old_handle]) { - /* Add some dummy value. It won't be read again. */ - handle_mapping.append(-1); - } - else { - const InstanceReference &reference = references_[old_handle]; - handle_mapping.append(next_new_handle); - new_references.add_new(reference); - if (old_handle != next_new_handle) { - handles_have_to_be_updated = true; - } - next_new_handle++; + if (instances_ != nullptr) { + if (instances_->instances_num() > 0) { + return false; } } - references_ = new_references; - - if (!handles_have_to_be_updated) { - /* All remaining handles are the same as before, so they don't have to be updated. This happens - * when unused handles are only at the end. */ - return; - } - - /* Update handles of instances. */ - threading::parallel_for(IndexRange(tot_instances), 1000, [&](IndexRange range) { - for (const int i : range) { - instance_reference_handles_[i] = handle_mapping[instance_reference_handles_[i]]; - } - }); -} - -int InstancesComponent::instances_num() const -{ - return instance_transforms_.size(); -} - -int InstancesComponent::references_num() const -{ - return references_.size(); -} - -bool InstancesComponent::is_empty() const -{ - return this->instance_reference_handles_.size() == 0; + return true; } bool InstancesComponent::owns_direct_data() const { - for (const InstanceReference &reference : references_) { - if (!reference.owns_direct_data()) { - return false; - } + if (instances_ != nullptr) { + return instances_->owns_direct_data(); } return true; } void InstancesComponent::ensure_owns_direct_data() { - BLI_assert(this->is_mutable()); - for (const InstanceReference &const_reference : references_) { - /* Const cast is fine because we are not changing anything that would change the hash of the - * reference. */ - InstanceReference &reference = const_cast(const_reference); - reference.ensure_owns_direct_data(); + if (instances_ != nullptr) { + instances_->ensure_owns_direct_data(); } } -static blender::Array generate_unique_instance_ids(Span original_ids) +const blender::bke::Instances *InstancesComponent::get_for_read() const { - using namespace blender; - Array unique_ids(original_ids.size()); - - Set used_unique_ids; - used_unique_ids.reserve(original_ids.size()); - Vector instances_with_id_collision; - for (const int instance_index : original_ids.index_range()) { - const int original_id = original_ids[instance_index]; - if (used_unique_ids.add(original_id)) { - /* The original id has not been used by another instance yet. */ - unique_ids[instance_index] = original_id; - } - else { - /* The original id of this instance collided with a previous instance, it needs to be looked - * at again in a second pass. Don't generate a new random id here, because this might collide - * with other existing ids. */ - instances_with_id_collision.append(instance_index); - } - } - - Map generator_by_original_id; - for (const int instance_index : instances_with_id_collision) { - const int original_id = original_ids[instance_index]; - RandomNumberGenerator &rng = generator_by_original_id.lookup_or_add_cb(original_id, [&]() { - RandomNumberGenerator rng; - rng.seed_random(original_id); - return rng; - }); - - const int max_iteration = 100; - for (int iteration = 0;; iteration++) { - /* Try generating random numbers until an unused one has been found. */ - const int random_id = rng.get_int32(); - if (used_unique_ids.add(random_id)) { - /* This random id is not used by another instance. */ - unique_ids[instance_index] = random_id; - break; - } - if (iteration == max_iteration) { - /* It seems to be very unlikely that we ever run into this case (assuming there are less - * than 2^30 instances). However, if that happens, it's better to use an id that is not - * unique than to be stuck in an infinite loop. */ - unique_ids[instance_index] = original_id; - break; - } - } - } - - return unique_ids; + return instances_; } -blender::Span InstancesComponent::almost_unique_ids() const +blender::bke::Instances *InstancesComponent::get_for_write() { - std::lock_guard lock(almost_unique_ids_mutex_); - std::optional instance_ids_gspan = attributes_.get_for_read("id"); - if (instance_ids_gspan) { - Span instance_ids = instance_ids_gspan->typed(); - if (almost_unique_ids_.size() != instance_ids.size()) { - almost_unique_ids_ = generate_unique_instance_ids(instance_ids); - } - } - else { - almost_unique_ids_.reinitialize(this->instances_num()); - for (const int i : almost_unique_ids_.index_range()) { - almost_unique_ids_[i] = i; - } + BLI_assert(this->is_mutable()); + if (ownership_ == GeometryOwnershipType::ReadOnly) { + instances_ = new Instances(*instances_); + ownership_ = GeometryOwnershipType::Owned; } - return almost_unique_ids_; + return instances_; } -blender::bke::CustomDataAttributes &InstancesComponent::instance_attributes() +void InstancesComponent::replace(Instances *instances, GeometryOwnershipType ownership) { - return this->attributes_; -} - -const blender::bke::CustomDataAttributes &InstancesComponent::instance_attributes() const -{ - return this->attributes_; + BLI_assert(this->is_mutable()); + this->clear(); + instances_ = instances; + ownership_ = ownership; } namespace blender::bke { @@ -397,16 +135,21 @@ class InstancePositionAttributeProvider final : public BuiltinAttributeProvider GVArray try_get_for_read(const void *owner) const final { - const InstancesComponent &instances_component = *static_cast( - owner); - Span transforms = instances_component.instance_transforms(); + const Instances *instances = static_cast(owner); + if (instances == nullptr) { + return {}; + } + Span transforms = instances->transforms(); return VArray::ForDerivedSpan(transforms); } GAttributeWriter try_get_for_write(void *owner) const final { - InstancesComponent &instances_component = *static_cast(owner); - MutableSpan transforms = instances_component.instance_transforms(); + Instances *instances = static_cast(owner); + if (instances == nullptr) { + return {}; + } + MutableSpan transforms = instances->transforms(); return {VMutableArray::ForDerivedSpan(transforms), @@ -434,16 +177,16 @@ static ComponentAttributeProviders create_attribute_providers_for_instances() static InstancePositionAttributeProvider position; static CustomDataAccessInfo instance_custom_data_access = { [](void *owner) -> CustomData * { - InstancesComponent &inst = *static_cast(owner); - return &inst.instance_attributes().data; + Instances *instances = static_cast(owner); + return &instances->custom_data_attributes().data; }, [](const void *owner) -> const CustomData * { - const InstancesComponent &inst = *static_cast(owner); - return &inst.instance_attributes().data; + const Instances *instances = static_cast(owner); + return &instances->custom_data_attributes().data; }, [](const void *owner) -> int { - const InstancesComponent &inst = *static_cast(owner); - return inst.instances_num(); + const Instances *instances = static_cast(owner); + return instances->instances_num(); }}; /** @@ -479,10 +222,10 @@ static AttributeAccessorFunctions get_instances_accessor_functions() if (owner == nullptr) { return 0; } - const InstancesComponent &instances = *static_cast(owner); + const Instances *instances = static_cast(owner); switch (domain) { case ATTR_DOMAIN_INSTANCE: - return instances.instances_num(); + return instances->instances_num(); default: return 0; } @@ -508,18 +251,30 @@ static const AttributeAccessorFunctions &get_instances_accessor_functions_ref() return fn; } +blender::bke::AttributeAccessor Instances::attributes() const +{ + return blender::bke::AttributeAccessor(this, + blender::bke::get_instances_accessor_functions_ref()); +} + +blender::bke::MutableAttributeAccessor Instances::attributes_for_write() +{ + return blender::bke::MutableAttributeAccessor( + this, blender::bke::get_instances_accessor_functions_ref()); +} + } // namespace blender::bke std::optional InstancesComponent::attributes() const { - return blender::bke::AttributeAccessor(this, + return blender::bke::AttributeAccessor(instances_, blender::bke::get_instances_accessor_functions_ref()); } std::optional InstancesComponent::attributes_for_write() { return blender::bke::MutableAttributeAccessor( - this, blender::bke::get_instances_accessor_functions_ref()); + instances_, blender::bke::get_instances_accessor_functions_ref()); } /** \} */ diff --git a/source/blender/blenkernel/intern/geometry_fields.cc b/source/blender/blenkernel/intern/geometry_fields.cc index b492af4af77..82ffda57398 100644 --- a/source/blender/blenkernel/intern/geometry_fields.cc +++ b/source/blender/blenkernel/intern/geometry_fields.cc @@ -4,6 +4,7 @@ #include "BKE_curves.hh" #include "BKE_geometry_fields.hh" #include "BKE_geometry_set.hh" +#include "BKE_instances.hh" #include "BKE_mesh.h" #include "BKE_pointcloud.h" #include "BKE_type_conversions.hh" @@ -64,7 +65,7 @@ GeometryFieldContext::GeometryFieldContext(const GeometryComponent &component, case GEO_COMPONENT_TYPE_INSTANCES: { const InstancesComponent &instances_component = static_cast( component); - geometry_ = &instances_component; + geometry_ = instances_component.get_for_read(); break; } case GEO_COMPONENT_TYPE_VOLUME: @@ -86,7 +87,7 @@ GeometryFieldContext::GeometryFieldContext(const PointCloud &points) : geometry_(&points), type_(GEO_COMPONENT_TYPE_POINT_CLOUD), domain_(ATTR_DOMAIN_POINT) { } -GeometryFieldContext::GeometryFieldContext(const InstancesComponent &instances) +GeometryFieldContext::GeometryFieldContext(const Instances &instances) : geometry_(&instances), type_(GEO_COMPONENT_TYPE_INSTANCES), domain_(ATTR_DOMAIN_INSTANCE) { } @@ -102,7 +103,7 @@ std::optional GeometryFieldContext::attributes() const if (const PointCloud *pointcloud = this->pointcloud()) { return pointcloud->attributes(); } - if (const InstancesComponent *instances = this->instances()) { + if (const Instances *instances = this->instances()) { return instances->attributes(); } return {}; @@ -124,11 +125,10 @@ const PointCloud *GeometryFieldContext::pointcloud() const static_cast(geometry_) : nullptr; } -const InstancesComponent *GeometryFieldContext::instances() const +const Instances *GeometryFieldContext::instances() const { - return this->type() == GEO_COMPONENT_TYPE_INSTANCES ? - static_cast(geometry_) : - nullptr; + return this->type() == GEO_COMPONENT_TYPE_INSTANCES ? static_cast(geometry_) : + nullptr; } GVArray GeometryFieldInput::get_varray_for_context(const fn::FieldContext &context, @@ -230,7 +230,7 @@ GVArray InstancesFieldInput::get_varray_for_context(const fn::FieldContext &cont { if (const GeometryFieldContext *geometry_context = dynamic_cast( &context)) { - if (const InstancesComponent *instances = geometry_context->instances()) { + if (const Instances *instances = geometry_context->instances()) { return this->get_varray_for_context(*instances, mask); } } diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc index 46ff8141504..90568a8a080 100644 --- a/source/blender/blenkernel/intern/geometry_set.cc +++ b/source/blender/blenkernel/intern/geometry_set.cc @@ -9,6 +9,7 @@ #include "BKE_attribute.h" #include "BKE_curves.hh" #include "BKE_geometry_set.hh" +#include "BKE_instances.hh" #include "BKE_lib_id.h" #include "BKE_mesh.h" #include "BKE_mesh_wrapper.h" @@ -31,6 +32,8 @@ using blender::MutableSpan; using blender::Span; using blender::StringRef; using blender::Vector; +using blender::bke::InstanceReference; +using blender::bke::Instances; /* -------------------------------------------------------------------- */ /** \name Geometry Component @@ -256,8 +259,7 @@ std::ostream &operator<<(std::ostream &stream, const GeometrySet &geometry_set) parts.append(std::to_string(BKE_volume_num_grids(volume)) + " volume grids"); } if (geometry_set.has_instances()) { - parts.append(std::to_string( - geometry_set.get_component_for_read()->instances_num()) + + parts.append(std::to_string(geometry_set.get_instances_for_read()->instances_num()) + " instances"); } if (geometry_set.get_curve_edit_hints_for_read()) { @@ -338,6 +340,12 @@ const Curves *GeometrySet::get_curves_for_read() const return (component == nullptr) ? nullptr : component->get_for_read(); } +const Instances *GeometrySet::get_instances_for_read() const +{ + const InstancesComponent *component = this->get_component_for_read(); + return (component == nullptr) ? nullptr : component->get_for_read(); +} + const blender::bke::CurvesEditHints *GeometrySet::get_curve_edit_hints_for_read() const { const GeometryComponentEditData *component = @@ -354,7 +362,8 @@ bool GeometrySet::has_pointcloud() const bool GeometrySet::has_instances() const { const InstancesComponent *component = this->get_component_for_read(); - return component != nullptr && component->instances_num() >= 1; + return component != nullptr && component->get_for_read() != nullptr && + component->get_for_read()->instances_num() >= 1; } bool GeometrySet::has_volume() const @@ -428,6 +437,14 @@ GeometrySet GeometrySet::create_with_curves(Curves *curves, GeometryOwnershipTyp return geometry_set; } +GeometrySet GeometrySet::create_with_instances(Instances *instances, + GeometryOwnershipType ownership) +{ + GeometrySet geometry_set; + geometry_set.replace_instances(instances, ownership); + return geometry_set; +} + void GeometrySet::replace_mesh(Mesh *mesh, GeometryOwnershipType ownership) { if (mesh == nullptr) { @@ -456,6 +473,20 @@ void GeometrySet::replace_curves(Curves *curves, GeometryOwnershipType ownership component.replace(curves, ownership); } +void GeometrySet::replace_instances(Instances *instances, GeometryOwnershipType ownership) +{ + if (instances == nullptr) { + this->remove(); + return; + } + if (instances == this->get_instances_for_read()) { + return; + } + this->remove(); + InstancesComponent &component = this->get_component_for_write(); + component.replace(instances, ownership); +} + void GeometrySet::replace_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership) { if (pointcloud == nullptr) { @@ -508,6 +539,12 @@ Curves *GeometrySet::get_curves_for_write() return component == nullptr ? nullptr : component->get_for_write(); } +Instances *GeometrySet::get_instances_for_write() +{ + InstancesComponent *component = this->get_component_ptr(); + return component == nullptr ? nullptr : component->get_for_write(); +} + blender::bke::CurvesEditHints *GeometrySet::get_curve_edit_hints_for_write() { if (!this->has()) { @@ -539,7 +576,7 @@ void GeometrySet::attribute_foreach(const Span component_ } } if (include_instances && this->has_instances()) { - const InstancesComponent &instances = *this->get_component_for_read(); + const Instances &instances = *this->get_instances_for_read(); instances.foreach_referenced_geometry([&](const GeometrySet &instance_geometry_set) { instance_geometry_set.attribute_foreach(component_types, include_instances, callback); }); @@ -611,7 +648,7 @@ static void gather_component_types_recursive(const GeometrySet &geometry_set, if (!include_instances) { return; } - const InstancesComponent *instances = geometry_set.get_component_for_read(); + const blender::bke::Instances *instances = geometry_set.get_instances_for_read(); if (instances == nullptr) { return; } @@ -638,12 +675,11 @@ static void gather_mutable_geometry_sets(GeometrySet &geometry_set, } /* In the future this can be improved by deduplicating instance references across different * instances. */ - InstancesComponent &instances_component = - geometry_set.get_component_for_write(); - instances_component.ensure_geometry_instances(); - for (const int handle : instances_component.references().index_range()) { - if (instances_component.references()[handle].type() == InstanceReference::Type::GeometrySet) { - GeometrySet &instance_geometry = instances_component.geometry_set_from_reference(handle); + Instances &instances = *geometry_set.get_instances_for_write(); + instances.ensure_geometry_instances(); + for (const int handle : instances.references().index_range()) { + if (instances.references()[handle].type() == InstanceReference::Type::GeometrySet) { + GeometrySet &instance_geometry = instances.geometry_set_from_reference(handle); gather_mutable_geometry_sets(instance_geometry, r_geometry_sets); } } diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc index 0ae49a586f1..e078991187d 100644 --- a/source/blender/blenkernel/intern/geometry_set_instances.cc +++ b/source/blender/blenkernel/intern/geometry_set_instances.cc @@ -2,6 +2,7 @@ #include "BKE_collection.h" #include "BKE_geometry_set_instances.hh" +#include "BKE_instances.hh" #include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_mesh_wrapper.h" @@ -62,12 +63,11 @@ GeometrySet object_get_evaluated_geometry_set(const Object &object) return geometry_set; } if (object.type == OB_EMPTY && object.instance_collection != nullptr) { - GeometrySet geometry_set; Collection &collection = *object.instance_collection; - InstancesComponent &instances = geometry_set.get_component_for_write(); - const int handle = instances.add_reference(collection); - instances.add_instance(handle, float4x4::identity()); - return geometry_set; + std::unique_ptr instances = std::make_unique(); + const int handle = instances->add_reference(collection); + instances->add_instance(handle, float4x4::identity()); + return GeometrySet::create_with_instances(instances.release()); } /* Return by value since there is not always an existing geometry set owned elsewhere to use. */ @@ -115,12 +115,11 @@ static void geometry_set_collect_recursive(const GeometrySet &geometry_set, r_sets.append({geometry_set, {transform}}); if (geometry_set.has_instances()) { - const InstancesComponent &instances_component = - *geometry_set.get_component_for_read(); + const Instances &instances = *geometry_set.get_instances_for_read(); - Span transforms = instances_component.instance_transforms(); - Span handles = instances_component.instance_reference_handles(); - Span references = instances_component.references(); + Span transforms = instances.transforms(); + Span handles = instances.reference_handles(); + Span references = instances.references(); for (const int i : transforms.index_range()) { const InstanceReference &reference = references[handles[i]]; const float4x4 instance_transform = transform * transforms[i]; @@ -156,9 +155,7 @@ void geometry_set_gather_instances(const GeometrySet &geometry_set, geometry_set_collect_recursive(geometry_set, float4x4::identity(), r_instance_groups); } -} // namespace blender::bke - -void InstancesComponent::foreach_referenced_geometry( +void Instances::foreach_referenced_geometry( blender::FunctionRef callback) const { using namespace blender::bke; @@ -191,7 +188,7 @@ void InstancesComponent::foreach_referenced_geometry( } } -void InstancesComponent::ensure_geometry_instances() +void Instances::ensure_geometry_instances() { using namespace blender; using namespace blender::bke; @@ -211,9 +208,7 @@ void InstancesComponent::ensure_geometry_instances() const Object &object = reference.object(); GeometrySet object_geometry_set = object_get_evaluated_geometry_set(object); if (object_geometry_set.has_instances()) { - InstancesComponent &component = - object_geometry_set.get_component_for_write(); - component.ensure_geometry_instances(); + object_geometry_set.get_instances_for_write()->ensure_geometry_instances(); } new_references.add_new(std::move(object_geometry_set)); break; @@ -221,22 +216,22 @@ void InstancesComponent::ensure_geometry_instances() case InstanceReference::Type::Collection: { /* Create a new reference that contains a geometry set that contains all objects from the * collection as instances. */ - GeometrySet collection_geometry_set; - InstancesComponent &component = - collection_geometry_set.get_component_for_write(); + std::unique_ptr instances = std::make_unique(); Collection &collection = reference.collection(); FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (&collection, object) { - const int handle = component.add_reference(*object); - component.add_instance(handle, object->obmat); - float4x4 &transform = component.instance_transforms().last(); + const int handle = instances->add_reference(*object); + instances->add_instance(handle, object->obmat); + float4x4 &transform = instances->transforms().last(); sub_v3_v3(transform.values[3], collection.instance_offset); } FOREACH_COLLECTION_OBJECT_RECURSIVE_END; - component.ensure_geometry_instances(); - new_references.add_new(std::move(collection_geometry_set)); + instances->ensure_geometry_instances(); + new_references.add_new(GeometrySet::create_with_instances(instances.release())); break; } } } references_ = std::move(new_references); } + +} // namespace blender::bke diff --git a/source/blender/blenkernel/intern/instances.cc b/source/blender/blenkernel/intern/instances.cc new file mode 100644 index 00000000000..dd759453630 --- /dev/null +++ b/source/blender/blenkernel/intern/instances.cc @@ -0,0 +1,348 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_cpp_type_make.hh" +#include "BLI_rand.hh" +#include "BLI_task.hh" + +#include "BKE_attribute_math.hh" +#include "BKE_geometry_set.hh" +#include "BKE_instances.hh" + +BLI_CPP_TYPE_MAKE(InstanceReference, blender::bke::InstanceReference, CPPTypeFlags::None) + +namespace blender::bke { + +InstanceReference::InstanceReference(GeometrySet geometry_set) + : type_(Type::GeometrySet), + geometry_set_(std::make_unique(std::move(geometry_set))) +{ +} + +void InstanceReference::ensure_owns_direct_data() +{ + if (type_ != Type::GeometrySet) { + return; + } + geometry_set_->ensure_owns_direct_data(); +} + +bool InstanceReference::owns_direct_data() const +{ + if (type_ != Type::GeometrySet) { + /* The object and collection instances are not direct data. */ + return true; + } + return geometry_set_->owns_direct_data(); +} + +Instances::Instances(const Instances &other) + : references_(other.references_), + reference_handles_(other.reference_handles_), + transforms_(other.transforms_), + almost_unique_ids_(other.almost_unique_ids_), + attributes_(other.attributes_) +{ +} + +void Instances::reserve(int min_capacity) +{ + reference_handles_.reserve(min_capacity); + transforms_.reserve(min_capacity); + attributes_.reallocate(min_capacity); +} + +void Instances::resize(int capacity) +{ + reference_handles_.resize(capacity); + transforms_.resize(capacity); + attributes_.reallocate(capacity); +} + +void Instances::add_instance(const int instance_handle, const float4x4 &transform) +{ + BLI_assert(instance_handle >= 0); + BLI_assert(instance_handle < references_.size()); + reference_handles_.append(instance_handle); + transforms_.append(transform); + attributes_.reallocate(this->instances_num()); +} + +blender::Span Instances::reference_handles() const +{ + return reference_handles_; +} + +blender::MutableSpan Instances::reference_handles() +{ + return reference_handles_; +} + +blender::MutableSpan Instances::transforms() +{ + return transforms_; +} +blender::Span Instances::transforms() const +{ + return transforms_; +} + +GeometrySet &Instances::geometry_set_from_reference(const int reference_index) +{ + /* If this assert fails, it means #ensure_geometry_instances must be called first or that the + * reference can't be converted to a geometry set. */ + BLI_assert(references_[reference_index].type() == InstanceReference::Type::GeometrySet); + + /* The const cast is okay because the instance's hash in the set + * is not changed by adjusting the data inside the geometry set. */ + return const_cast(references_[reference_index].geometry_set()); +} + +int Instances::add_reference(const InstanceReference &reference) +{ + return references_.index_of_or_add_as(reference); +} + +blender::Span Instances::references() const +{ + return references_; +} + +template +static void copy_data_based_on_mask(Span src, MutableSpan dst, IndexMask mask) +{ + BLI_assert(src.data() != dst.data()); + using namespace blender; + threading::parallel_for(mask.index_range(), 1024, [&](IndexRange range) { + for (const int i : range) { + dst[i] = src[mask[i]]; + } + }); +} + +void Instances::remove(const IndexMask mask) +{ + using namespace blender; + if (mask.is_range() && mask.as_range().start() == 0) { + /* Deleting from the end of the array can be much faster since no data has to be shifted. */ + this->resize(mask.size()); + this->remove_unused_references(); + return; + } + + Vector new_handles(mask.size()); + copy_data_based_on_mask(this->reference_handles(), new_handles, mask); + reference_handles_ = std::move(new_handles); + Vector new_transforms(mask.size()); + copy_data_based_on_mask(this->transforms(), new_transforms, mask); + transforms_ = std::move(new_transforms); + + const bke::CustomDataAttributes &src_attributes = attributes_; + + bke::CustomDataAttributes dst_attributes; + dst_attributes.reallocate(mask.size()); + + src_attributes.foreach_attribute( + [&](const bke::AttributeIDRef &id, const bke::AttributeMetaData &meta_data) { + if (!id.should_be_kept()) { + return true; + } + + GSpan src = *src_attributes.get_for_read(id); + dst_attributes.create(id, meta_data.data_type); + GMutableSpan dst = *dst_attributes.get_for_write(id); + + attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { + using T = decltype(dummy); + copy_data_based_on_mask(src.typed(), dst.typed(), mask); + }); + return true; + }, + ATTR_DOMAIN_INSTANCE); + + attributes_ = std::move(dst_attributes); + this->remove_unused_references(); +} + +void Instances::remove_unused_references() +{ + using namespace blender; + using namespace blender::bke; + + const int tot_instances = this->instances_num(); + const int tot_references_before = references_.size(); + + if (tot_instances == 0) { + /* If there are no instances, no reference is needed. */ + references_.clear(); + return; + } + if (tot_references_before == 1) { + /* There is only one reference and at least one instance. So the only existing reference is + * used. Nothing to do here. */ + return; + } + + Array usage_by_handle(tot_references_before, false); + std::mutex mutex; + + /* Loop over all instances to see which references are used. */ + threading::parallel_for(IndexRange(tot_instances), 1000, [&](IndexRange range) { + /* Use local counter to avoid lock contention. */ + Array local_usage_by_handle(tot_references_before, false); + + for (const int i : range) { + const int handle = reference_handles_[i]; + BLI_assert(handle >= 0 && handle < tot_references_before); + local_usage_by_handle[handle] = true; + } + + std::lock_guard lock{mutex}; + for (const int i : IndexRange(tot_references_before)) { + usage_by_handle[i] |= local_usage_by_handle[i]; + } + }); + + if (!usage_by_handle.as_span().contains(false)) { + /* All references are used. */ + return; + } + + /* Create new references and a mapping for the handles. */ + Vector handle_mapping; + VectorSet new_references; + int next_new_handle = 0; + bool handles_have_to_be_updated = false; + for (const int old_handle : IndexRange(tot_references_before)) { + if (!usage_by_handle[old_handle]) { + /* Add some dummy value. It won't be read again. */ + handle_mapping.append(-1); + } + else { + const InstanceReference &reference = references_[old_handle]; + handle_mapping.append(next_new_handle); + new_references.add_new(reference); + if (old_handle != next_new_handle) { + handles_have_to_be_updated = true; + } + next_new_handle++; + } + } + references_ = new_references; + + if (!handles_have_to_be_updated) { + /* All remaining handles are the same as before, so they don't have to be updated. This happens + * when unused handles are only at the end. */ + return; + } + + /* Update handles of instances. */ + threading::parallel_for(IndexRange(tot_instances), 1000, [&](IndexRange range) { + for (const int i : range) { + reference_handles_[i] = handle_mapping[reference_handles_[i]]; + } + }); +} + +int Instances::instances_num() const +{ + return transforms_.size(); +} + +int Instances::references_num() const +{ + return references_.size(); +} + +bool Instances::owns_direct_data() const +{ + for (const InstanceReference &reference : references_) { + if (!reference.owns_direct_data()) { + return false; + } + } + return true; +} + +void Instances::ensure_owns_direct_data() +{ + for (const InstanceReference &const_reference : references_) { + /* Const cast is fine because we are not changing anything that would change the hash of the + * reference. */ + InstanceReference &reference = const_cast(const_reference); + reference.ensure_owns_direct_data(); + } +} + +static blender::Array generate_unique_instance_ids(Span original_ids) +{ + using namespace blender; + Array unique_ids(original_ids.size()); + + Set used_unique_ids; + used_unique_ids.reserve(original_ids.size()); + Vector instances_with_id_collision; + for (const int instance_index : original_ids.index_range()) { + const int original_id = original_ids[instance_index]; + if (used_unique_ids.add(original_id)) { + /* The original id has not been used by another instance yet. */ + unique_ids[instance_index] = original_id; + } + else { + /* The original id of this instance collided with a previous instance, it needs to be looked + * at again in a second pass. Don't generate a new random id here, because this might collide + * with other existing ids. */ + instances_with_id_collision.append(instance_index); + } + } + + Map generator_by_original_id; + for (const int instance_index : instances_with_id_collision) { + const int original_id = original_ids[instance_index]; + RandomNumberGenerator &rng = generator_by_original_id.lookup_or_add_cb(original_id, [&]() { + RandomNumberGenerator rng; + rng.seed_random(original_id); + return rng; + }); + + const int max_iteration = 100; + for (int iteration = 0;; iteration++) { + /* Try generating random numbers until an unused one has been found. */ + const int random_id = rng.get_int32(); + if (used_unique_ids.add(random_id)) { + /* This random id is not used by another instance. */ + unique_ids[instance_index] = random_id; + break; + } + if (iteration == max_iteration) { + /* It seems to be very unlikely that we ever run into this case (assuming there are less + * than 2^30 instances). However, if that happens, it's better to use an id that is not + * unique than to be stuck in an infinite loop. */ + unique_ids[instance_index] = original_id; + break; + } + } + } + + return unique_ids; +} + +blender::Span Instances::almost_unique_ids() const +{ + std::lock_guard lock(almost_unique_ids_mutex_); + std::optional instance_ids_gspan = attributes_.get_for_read("id"); + if (instance_ids_gspan) { + Span instance_ids = instance_ids_gspan->typed(); + if (almost_unique_ids_.size() != instance_ids.size()) { + almost_unique_ids_ = generate_unique_instance_ids(instance_ids); + } + } + else { + almost_unique_ids_.reinitialize(this->instances_num()); + for (const int i : almost_unique_ids_.index_range()) { + almost_unique_ids_[i] = i; + } + } + return almost_unique_ids_; +} + +} // namespace blender::bke diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index 96da99af97e..d43eff6f9b4 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -41,6 +41,7 @@ #include "BKE_geometry_set.hh" #include "BKE_global.h" #include "BKE_idprop.h" +#include "BKE_instances.hh" #include "BKE_lattice.h" #include "BKE_main.h" #include "BKE_mesh.h" @@ -70,6 +71,8 @@ using blender::float3; using blender::float4x4; using blender::Span; using blender::Vector; +using blender::bke::InstanceReference; +using blender::bke::Instances; namespace geo_log = blender::nodes::geo_eval_log; /* -------------------------------------------------------------------- */ @@ -874,8 +877,8 @@ static void make_duplis_geometry_set_impl(const DupliContext *ctx, } const bool creates_duplis_for_components = component_index >= 1; - const InstancesComponent *component = geometry_set.get_component_for_read(); - if (component == nullptr) { + const Instances *instances = geometry_set.get_instances_for_read(); + if (instances == nullptr) { return; } @@ -890,13 +893,13 @@ static void make_duplis_geometry_set_impl(const DupliContext *ctx, instances_ctx = &new_instances_ctx; } - Span instance_offset_matrices = component->instance_transforms(); - Span instance_reference_handles = component->instance_reference_handles(); - Span almost_unique_ids = component->almost_unique_ids(); - Span references = component->references(); + Span instance_offset_matrices = instances->transforms(); + Span reference_handles = instances->reference_handles(); + Span almost_unique_ids = instances->almost_unique_ids(); + Span references = instances->references(); for (int64_t i : instance_offset_matrices.index_range()) { - const InstanceReference &reference = references[instance_reference_handles[i]]; + const InstanceReference &reference = references[reference_handles[i]]; const int id = almost_unique_ids[i]; const DupliContext *ctx_for_instance = instances_ctx; diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_column.cc b/source/blender/editors/space_spreadsheet/spreadsheet_column.cc index 46e98acb8e8..af41225f42a 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_column.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_column.cc @@ -12,6 +12,7 @@ #include "BLI_string_ref.hh" #include "BKE_geometry_set.hh" +#include "BKE_instances.hh" #include "spreadsheet_column.hh" #include "spreadsheet_column_values.hh" @@ -44,7 +45,7 @@ eSpreadsheetColumnValueType cpp_type_to_column_type(const CPPType &type) if (type.is()) { return SPREADSHEET_VALUE_TYPE_STRING; } - if (type.is()) { + if (type.is()) { return SPREADSHEET_VALUE_TYPE_INSTANCES; } if (type.is()) { diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc index b2f9cfc6395..59a8daf4f4a 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc @@ -10,6 +10,7 @@ #include "BKE_editmesh.h" #include "BKE_geometry_fields.hh" #include "BKE_global.h" +#include "BKE_instances.hh" #include "BKE_lib_id.h" #include "BKE_mesh.h" #include "BKE_mesh_wrapper.h" @@ -143,29 +144,31 @@ std::unique_ptr GeometryDataSource::get_column_values( } if (component_->type() == GEO_COMPONENT_TYPE_INSTANCES) { - const InstancesComponent &instances = static_cast(*component_); - if (STREQ(column_id.name, "Name")) { - Span reference_handles = instances.instance_reference_handles(); - Span references = instances.references(); - return std::make_unique( - column_id.name, - VArray::ForFunc(domain_num, - [reference_handles, references](int64_t index) { - return references[reference_handles[index]]; - })); - } - Span transforms = instances.instance_transforms(); - if (STREQ(column_id.name, "Rotation")) { - return std::make_unique( - column_id.name, VArray::ForFunc(domain_num, [transforms](int64_t index) { - return transforms[index].to_euler(); - })); - } - if (STREQ(column_id.name, "Scale")) { - return std::make_unique( - column_id.name, VArray::ForFunc(domain_num, [transforms](int64_t index) { - return transforms[index].scale(); - })); + if (const bke::Instances *instances = + static_cast(*component_).get_for_read()) { + if (STREQ(column_id.name, "Name")) { + Span reference_handles = instances->reference_handles(); + Span references = instances->references(); + return std::make_unique( + column_id.name, + VArray::ForFunc( + domain_num, [reference_handles, references](int64_t index) { + return references[reference_handles[index]]; + })); + } + Span transforms = instances->transforms(); + if (STREQ(column_id.name, "Rotation")) { + return std::make_unique( + column_id.name, VArray::ForFunc(domain_num, [transforms](int64_t index) { + return transforms[index].to_euler(); + })); + } + if (STREQ(column_id.name, "Scale")) { + return std::make_unique( + column_id.name, VArray::ForFunc(domain_num, [transforms](int64_t index) { + return transforms[index].scale(); + })); + } } } else if (G.debug_value == 4001 && component_->type() == GEO_COMPONENT_TYPE_MESH) { diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc b/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc index b4b8417c172..06eb338bd00 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc @@ -6,6 +6,7 @@ #include "BLI_math_vec_types.hh" #include "BKE_geometry_set.hh" +#include "BKE_instances.hh" #include "spreadsheet_column_values.hh" #include "spreadsheet_layout.hh" @@ -197,10 +198,10 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer { const ColorGeometry4b value = data.get(real_index); this->draw_byte_color(params, value); } - else if (data.type().is()) { - const InstanceReference value = data.get(real_index); + else if (data.type().is()) { + const bke::InstanceReference value = data.get(real_index); switch (value.type()) { - case InstanceReference::Type::Object: { + case bke::InstanceReference::Type::Object: { const Object &object = value.object(); uiDefIconTextBut(params.block, UI_BTYPE_LABEL, @@ -219,7 +220,7 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer { nullptr); break; } - case InstanceReference::Type::Collection: { + case bke::InstanceReference::Type::Collection: { Collection &collection = value.collection(); uiDefIconTextBut(params.block, UI_BTYPE_LABEL, @@ -238,7 +239,7 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer { nullptr); break; } - case InstanceReference::Type::GeometrySet: { + case bke::InstanceReference::Type::GeometrySet: { uiDefIconTextBut(params.block, UI_BTYPE_LABEL, 0, @@ -256,7 +257,7 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer { nullptr); break; } - case InstanceReference::Type::None: { + case bke::InstanceReference::Type::None: { break; } } diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc index 96827692a25..3586389b00b 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc @@ -14,6 +14,8 @@ #include "RNA_access.h" +#include "BKE_instances.hh" + #include "spreadsheet_data_source_geometry.hh" #include "spreadsheet_intern.hh" #include "spreadsheet_layout.hh" @@ -280,22 +282,22 @@ static void apply_row_filter(const SpreadsheetRowFilter &row_filter, } } } - else if (column_data.type().is()) { + else if (column_data.type().is()) { const StringRef value = row_filter.value_string; apply_filter_operation( - column_data.typed(), - [&](const InstanceReference cell) { + column_data.typed(), + [&](const bke::InstanceReference cell) { switch (cell.type()) { - case InstanceReference::Type::Object: { + case bke::InstanceReference::Type::Object: { return value == (reinterpret_cast(cell.object()).name + 2); } - case InstanceReference::Type::Collection: { + case bke::InstanceReference::Type::Collection: { return value == (reinterpret_cast(cell.collection()).name + 2); } - case InstanceReference::Type::GeometrySet: { + case bke::InstanceReference::Type::GeometrySet: { return false; } - case InstanceReference::Type::None: { + case bke::InstanceReference::Type::None: { return false; } } diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index 7b3c307cf37..daafe0e4aa7 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -17,6 +17,7 @@ #include "BKE_curves.hh" #include "BKE_deform.h" #include "BKE_geometry_set_instances.hh" +#include "BKE_instances.hh" #include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_pointcloud.h" @@ -30,6 +31,8 @@ using blender::bke::AttributeMetaData; using blender::bke::custom_data_type_to_cpp_type; using blender::bke::CustomDataAttributes; using blender::bke::GSpanAttributeWriter; +using blender::bke::InstanceReference; +using blender::bke::Instances; using blender::bke::object_get_evaluated_geometry_set; using blender::bke::SpanAttributeWriter; @@ -370,11 +373,11 @@ static void gather_realize_tasks_recursive(GatherTasksInfo &gather_info, */ static Vector> prepare_attribute_fallbacks( GatherTasksInfo &gather_info, - const InstancesComponent &instances_component, + const Instances &instances, const OrderedAttributes &ordered_attributes) { Vector> attributes_to_override; - const CustomDataAttributes &attributes = instances_component.instance_attributes(); + const CustomDataAttributes &attributes = instances.custom_data_attributes(); attributes.foreach_attribute( [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { const int attribute_index = ordered_attributes.ids.index_of_try(attribute_id); @@ -394,7 +397,7 @@ static Vector> prepare_attribute_fallbacks( } /* Convert the attribute on the instances component to the expected attribute type. */ std::unique_ptr> temporary_array = std::make_unique>( - to_type, instances_component.instances_num()); + to_type, instances.instances_num()); conversions.convert_to_initialized_n(span, temporary_array->as_mutable_span()); span = temporary_array->as_span(); gather_info.r_temporary_arrays.append(std::move(temporary_array)); @@ -450,17 +453,17 @@ static void foreach_geometry_in_reference( } static void gather_realize_tasks_for_instances(GatherTasksInfo &gather_info, - const InstancesComponent &instances_component, + const Instances &instances, const float4x4 &base_transform, const InstanceContext &base_instance_context) { - const Span references = instances_component.references(); - const Span handles = instances_component.instance_reference_handles(); - const Span transforms = instances_component.instance_transforms(); + const Span references = instances.references(); + const Span handles = instances.reference_handles(); + const Span transforms = instances.transforms(); Span stored_instance_ids; if (gather_info.create_id_attribute_on_any_component) { - std::optional ids = instances_component.instance_attributes().get_for_read("id"); + std::optional ids = instances.custom_data_attributes().get_for_read("id"); if (ids.has_value()) { stored_instance_ids = ids->typed(); } @@ -469,11 +472,11 @@ static void gather_realize_tasks_for_instances(GatherTasksInfo &gather_info, /* Prepare attribute fallbacks. */ InstanceContext instance_context = base_instance_context; Vector> pointcloud_attributes_to_override = prepare_attribute_fallbacks( - gather_info, instances_component, gather_info.pointclouds.attributes); + gather_info, instances, gather_info.pointclouds.attributes); Vector> mesh_attributes_to_override = prepare_attribute_fallbacks( - gather_info, instances_component, gather_info.meshes.attributes); + gather_info, instances, gather_info.meshes.attributes); Vector> curve_attributes_to_override = prepare_attribute_fallbacks( - gather_info, instances_component, gather_info.curves.attributes); + gather_info, instances, gather_info.curves.attributes); for (const int i : transforms.index_range()) { const int handle = handles[i]; @@ -584,8 +587,11 @@ static void gather_realize_tasks_recursive(GatherTasksInfo &gather_info, case GEO_COMPONENT_TYPE_INSTANCES: { const InstancesComponent &instances_component = *static_cast( component); - gather_realize_tasks_for_instances( - gather_info, instances_component, base_transform, base_instance_context); + const Instances *instances = instances_component.get_for_read(); + if (instances != nullptr && instances->instances_num() > 0) { + gather_realize_tasks_for_instances( + gather_info, *instances, base_transform, base_instance_context); + } break; } case GEO_COMPONENT_TYPE_VOLUME: { @@ -645,8 +651,7 @@ static void gather_pointclouds_to_realize(const GeometrySet &geometry_set, r_pointclouds.add(pointcloud); } } - if (const InstancesComponent *instances = - geometry_set.get_component_for_read()) { + if (const Instances *instances = geometry_set.get_instances_for_read()) { instances->foreach_referenced_geometry([&](const GeometrySet &instance_geometry_set) { gather_pointclouds_to_realize(instance_geometry_set, r_pointclouds); }); @@ -827,8 +832,7 @@ static void gather_meshes_to_realize(const GeometrySet &geometry_set, r_meshes.add(mesh); } } - if (const InstancesComponent *instances = - geometry_set.get_component_for_read()) { + if (const Instances *instances = geometry_set.get_instances_for_read()) { instances->foreach_referenced_geometry([&](const GeometrySet &instance_geometry_set) { gather_meshes_to_realize(instance_geometry_set, r_meshes); }); @@ -1148,8 +1152,7 @@ static void gather_curves_to_realize(const GeometrySet &geometry_set, r_curves.add(curves); } } - if (const InstancesComponent *instances = - geometry_set.get_component_for_read()) { + if (const Instances *instances = geometry_set.get_instances_for_read()) { instances->foreach_referenced_geometry([&](const GeometrySet &instance_geometry_set) { gather_curves_to_realize(instance_geometry_set, r_curves); }); @@ -1415,9 +1418,8 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options, static void remove_id_attribute_from_instances(GeometrySet &geometry_set) { geometry_set.modify_geometry_sets([&](GeometrySet &sub_geometry) { - if (sub_geometry.has()) { - InstancesComponent &component = sub_geometry.get_component_for_write(); - component.instance_attributes().remove("id"); + if (Instances *instances = sub_geometry.get_instances_for_write()) { + instances->custom_data_attributes().remove("id"); } }); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc b/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc index c4bee09e07b..df677e1c399 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc @@ -8,6 +8,7 @@ #include "UI_resources.h" #include "BKE_collection.h" +#include "BKE_instances.hh" #include "node_geometry_util.hh" @@ -69,8 +70,7 @@ static void node_geo_exec(GeoNodeExecParams params) const bool use_relative_transform = (storage.transform_space == GEO_NODE_TRANSFORM_SPACE_RELATIVE); - GeometrySet geometry_set_out; - InstancesComponent &instances = geometry_set_out.get_component_for_write(); + std::unique_ptr instances = std::make_unique(); const bool separate_children = params.get_input("Separate Children"); if (separate_children) { @@ -84,7 +84,7 @@ static void node_geo_exec(GeoNodeExecParams params) children_objects.append(collection_object->ob); } - instances.reserve(children_collections.size() + children_objects.size()); + instances->reserve(children_collections.size() + children_objects.size()); Vector entries; entries.reserve(children_collections.size() + children_objects.size()); @@ -99,11 +99,11 @@ static void node_geo_exec(GeoNodeExecParams params) sub_v3_v3(transform.values[3], collection->instance_offset); } } - const int handle = instances.add_reference(*child_collection); + const int handle = instances->add_reference(*child_collection); entries.append({handle, &(child_collection->id.name[2]), transform}); } for (Object *child_object : children_objects) { - const int handle = instances.add_reference(*child_object); + const int handle = instances->add_reference(*child_object); float4x4 transform = float4x4::identity(); if (!reset_children) { if (use_relative_transform) { @@ -123,7 +123,7 @@ static void node_geo_exec(GeoNodeExecParams params) return BLI_strcasecmp_natural(a.name, b.name) < 0; }); for (const InstanceListEntry &entry : entries) { - instances.add_instance(entry.handle, entry.transform); + instances->add_instance(entry.handle, entry.transform); } } else { @@ -133,11 +133,11 @@ static void node_geo_exec(GeoNodeExecParams params) mul_m4_m4_pre(transform.values, self_object->imat); } - const int handle = instances.add_reference(*collection); - instances.add_instance(handle, transform); + const int handle = instances->add_reference(*collection); + instances->add_instance(handle, transform); } - params.set_output("Geometry", geometry_set_out); + params.set_output("Geometry", GeometrySet::create_with_instances(instances.release())); } } // namespace blender::nodes::node_geo_collection_info_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc index 86c8cd64489..a433a0df9b0 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -12,6 +12,7 @@ #include "BKE_attribute_math.hh" #include "BKE_curves.hh" #include "BKE_customdata.h" +#include "BKE_instances.hh" #include "BKE_mesh.h" #include "BKE_pointcloud.h" @@ -392,8 +393,8 @@ static void separate_point_cloud_selection(GeometrySet &geometry_set, static void delete_selected_instances(GeometrySet &geometry_set, const Field &selection_field) { - InstancesComponent &instances = geometry_set.get_component_for_write(); - bke::GeometryFieldContext field_context{instances, ATTR_DOMAIN_INSTANCE}; + bke::Instances &instances = *geometry_set.get_instances_for_write(); + bke::InstancesFieldContext field_context{instances}; fn::FieldEvaluator evaluator{field_context, instances.instances_num()}; evaluator.set_selection(selection_field); @@ -404,7 +405,7 @@ static void delete_selected_instances(GeometrySet &geometry_set, return; } - instances.remove_instances(selection); + instances.remove(selection); } static void compute_selected_verts_from_vertex_selection(const Span vertex_selection, diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc index 82d7e1d3652..70583625a7a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc @@ -11,6 +11,7 @@ #include "BKE_attribute_math.hh" #include "BKE_curves.hh" +#include "BKE_instances.hh" #include "BKE_mesh.h" #include "BKE_pointcloud.h" @@ -1031,10 +1032,9 @@ static void duplicate_instances(GeometrySet &geometry_set, return; } - const InstancesComponent &src_instances = - *geometry_set.get_component_for_read(); + const bke::Instances &src_instances = *geometry_set.get_instances_for_read(); - bke::GeometryFieldContext field_context{src_instances, ATTR_DOMAIN_INSTANCE}; + bke::InstancesFieldContext field_context{src_instances}; FieldEvaluator evaluator{field_context, src_instances.instances_num()}; evaluator.add(count_field); evaluator.set_selection(selection_field); @@ -1048,20 +1048,20 @@ static void duplicate_instances(GeometrySet &geometry_set, return; } - GeometrySet dst_geometry; - InstancesComponent &dst_instances = dst_geometry.get_component_for_write(); - dst_instances.resize(offsets.last()); + std::unique_ptr dst_instances = std::make_unique(); + + dst_instances->resize(offsets.last()); for (const int i_selection : selection.index_range()) { const IndexRange range = range_for_offsets_index(offsets, i_selection); if (range.size() == 0) { continue; } - const int old_handle = src_instances.instance_reference_handles()[i_selection]; - const InstanceReference reference = src_instances.references()[old_handle]; - const int new_handle = dst_instances.add_reference(reference); - const float4x4 transform = src_instances.instance_transforms()[i_selection]; - dst_instances.instance_transforms().slice(range).fill(transform); - dst_instances.instance_reference_handles().slice(range).fill(new_handle); + const int old_handle = src_instances.reference_handles()[i_selection]; + const bke::InstanceReference reference = src_instances.references()[old_handle]; + const int new_handle = dst_instances->add_reference(reference); + const float4x4 transform = src_instances.transforms()[i_selection]; + dst_instances->transforms().slice(range).fill(transform); + dst_instances->reference_handles().slice(range).fill(new_handle); } copy_attributes_without_id(geometry_set, @@ -1069,18 +1069,18 @@ static void duplicate_instances(GeometrySet &geometry_set, ATTR_DOMAIN_INSTANCE, offsets, selection, - *src_instances.attributes(), - *dst_instances.attributes_for_write()); + src_instances.attributes(), + dst_instances->attributes_for_write()); if (attribute_outputs.duplicate_index) { - create_duplicate_index_attribute(*dst_instances.attributes_for_write(), + create_duplicate_index_attribute(dst_instances->attributes_for_write(), ATTR_DOMAIN_INSTANCE, selection, attribute_outputs, offsets); } - geometry_set = std::move(dst_geometry); + geometry_set = GeometrySet::create_with_instances(dst_instances.release()); } /** \} */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_geometry_to_instance.cc b/source/blender/nodes/geometry/nodes/node_geo_geometry_to_instance.cc index 8e64209a418..45808ff9996 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_geometry_to_instance.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_geometry_to_instance.cc @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BKE_instances.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_geometry_to_instance_cc { @@ -13,15 +15,13 @@ static void node_declare(NodeDeclarationBuilder &b) static void node_geo_exec(GeoNodeExecParams params) { Vector geometries = params.extract_input>("Geometry"); - GeometrySet instances_geometry; - InstancesComponent &instances_component = - instances_geometry.get_component_for_write(); + std::unique_ptr instances = std::make_unique(); for (GeometrySet &geometry : geometries) { geometry.ensure_owns_direct_data(); - const int handle = instances_component.add_reference(std::move(geometry)); - instances_component.add_instance(handle, float4x4::identity()); + const int handle = instances->add_reference(std::move(geometry)); + instances->add_instance(handle, float4x4::identity()); } - params.set_output("Instances", std::move(instances_geometry)); + params.set_output("Instances", GeometrySet::create_with_instances(instances.release())); } } // namespace blender::nodes::node_geo_geometry_to_instance_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_instance_rotation.cc b/source/blender/nodes/geometry/nodes/node_geo_input_instance_rotation.cc index 75d43d2f771..f78815ebe74 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_instance_rotation.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_instance_rotation.cc @@ -2,6 +2,8 @@ #include "node_geometry_util.hh" +#include "BKE_instances.hh" + namespace blender::nodes::node_geo_input_instance_rotation_cc { static void node_declare(NodeDeclarationBuilder &b) @@ -15,12 +17,9 @@ class InstanceRotationFieldInput final : public bke::InstancesFieldInput { { } - GVArray get_varray_for_context(const InstancesComponent &instances, - const IndexMask /*mask*/) const final + GVArray get_varray_for_context(const bke::Instances &instances, IndexMask /*mask*/) const final { - auto rotation_fn = [&](const int i) -> float3 { - return instances.instance_transforms()[i].to_euler(); - }; + auto rotation_fn = [&](const int i) -> float3 { return instances.transforms()[i].to_euler(); }; return VArray::ForFunc(instances.instances_num(), rotation_fn); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_instance_scale.cc b/source/blender/nodes/geometry/nodes/node_geo_input_instance_scale.cc index dbb98d7e393..12ac48f8f11 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_instance_scale.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_instance_scale.cc @@ -2,6 +2,8 @@ #include "node_geometry_util.hh" +#include "BKE_instances.hh" + namespace blender::nodes::node_geo_input_instance_scale_cc { static void node_declare(NodeDeclarationBuilder &b) @@ -15,12 +17,9 @@ class InstanceScaleFieldInput final : public bke::InstancesFieldInput { { } - GVArray get_varray_for_context(const InstancesComponent &instances, - const IndexMask /*mask*/) const final + GVArray get_varray_for_context(const bke::Instances &instances, IndexMask /*mask*/) const final { - auto scale_fn = [&](const int i) -> float3 { - return instances.instance_transforms()[i].scale(); - }; + auto scale_fn = [&](const int i) -> float3 { return instances.transforms()[i].scale(); }; return VArray::ForFunc(instances.instances_num(), scale_fn); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc index c6f214e72ac..affeb43e33b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc @@ -9,6 +9,7 @@ #include "UI_resources.h" #include "BKE_attribute_math.hh" +#include "BKE_instances.hh" #include "node_geometry_util.hh" @@ -43,7 +44,7 @@ static void node_declare(NodeDeclarationBuilder &b) } static void add_instances_from_component( - InstancesComponent &dst_component, + bke::Instances &dst_component, const GeometryComponent &src_component, const GeometrySet &instance, const GeoNodeExecParams ¶ms, @@ -80,25 +81,23 @@ static void add_instances_from_component( const int select_len = selection.index_range().size(); dst_component.resize(start_len + select_len); - MutableSpan dst_handles = dst_component.instance_reference_handles().slice(start_len, - select_len); - MutableSpan dst_transforms = dst_component.instance_transforms().slice(start_len, - select_len); + MutableSpan dst_handles = dst_component.reference_handles().slice(start_len, select_len); + MutableSpan dst_transforms = dst_component.transforms().slice(start_len, select_len); VArray positions = src_component.attributes()->lookup_or_default( "position", domain, {0, 0, 0}); - const InstancesComponent *src_instances = instance.get_component_for_read(); + const bke::Instances *src_instances = instance.get_instances_for_read(); /* Maps handles from the source instances to handles on the new instance. */ Array handle_mapping; /* Only fill #handle_mapping when it may be used below. */ if (src_instances != nullptr && (!pick_instance.is_single() || pick_instance.get_internal_single())) { - Span src_references = src_instances->references(); + Span src_references = src_instances->references(); handle_mapping.reinitialize(src_references.size()); for (const int src_instance_handle : src_references.index_range()) { - const InstanceReference &reference = src_references[src_instance_handle]; + const bke::InstanceReference &reference = src_references[src_instance_handle]; const int dst_instance_handle = dst_component.add_reference(reference); handle_mapping[src_instance_handle] = dst_instance_handle; } @@ -106,7 +105,7 @@ static void add_instances_from_component( const int full_instance_handle = dst_component.add_reference(instance); /* Add this reference last, because it is the most likely one to be removed later on. */ - const int empty_reference_handle = dst_component.add_reference(InstanceReference()); + const int empty_reference_handle = dst_component.add_reference(bke::InstanceReference()); threading::parallel_for(selection.index_range(), 1024, [&](IndexRange selection_range) { for (const int range_i : selection_range) { @@ -129,12 +128,11 @@ static void add_instances_from_component( const int index = mod_i(original_index, std::max(src_instances_num, 1)); if (index < src_instances_num) { /* Get the reference to the source instance. */ - const int src_handle = src_instances->instance_reference_handles()[index]; + const int src_handle = src_instances->reference_handles()[index]; dst_handle = handle_mapping[src_handle]; /* Take transforms of the source instance into account. */ - mul_m4_m4_post(dst_transform.values, - src_instances->instance_transforms()[index].values); + mul_m4_m4_post(dst_transform.values, src_instances->transforms()[index].values); } } } @@ -157,7 +155,7 @@ static void add_instances_from_component( } } - bke::CustomDataAttributes &instance_attributes = dst_component.instance_attributes(); + bke::CustomDataAttributes &instance_attributes = dst_component.custom_data_attributes(); for (const auto item : attributes_to_propagate.items()) { const AttributeIDRef &attribute_id = item.key; const AttributeKind attribute_kind = item.value; @@ -196,7 +194,15 @@ static void node_geo_exec(GeoNodeExecParams params) instance.ensure_owns_direct_data(); geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { - InstancesComponent &instances = geometry_set.get_component_for_write(); + /* It's important not to invalidate the existing #InstancesComponent because it owns references + * to other geometry sets that are processed by this node. */ + InstancesComponent &instances_component = + geometry_set.get_component_for_write(); + bke::Instances *dst_instances = instances_component.get_for_write(); + if (dst_instances == nullptr) { + dst_instances = new bke::Instances(); + instances_component.replace(dst_instances); + } const Array types{ GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_POINT_CLOUD, GEO_COMPONENT_TYPE_CURVE}; @@ -208,14 +214,13 @@ static void node_geo_exec(GeoNodeExecParams params) for (const GeometryComponentType type : types) { if (geometry_set.has(type)) { - add_instances_from_component(instances, + add_instances_from_component(*dst_instances, *geometry_set.get_component_for_read(type), instance, params, attributes_to_propagate); } } - geometry_set.remove_geometry_during_modify(); }); @@ -223,8 +228,9 @@ static void node_geo_exec(GeoNodeExecParams params) * process them needlessly. * This should eventually be moved into the loop above, but currently this is quite tricky * because it might remove references that the loop still wants to iterate over. */ - InstancesComponent &instances = geometry_set.get_component_for_write(); - instances.remove_unused_references(); + if (bke::Instances *instances = geometry_set.get_instances_for_write()) { + instances->remove_unused_references(); + } params.set_output("Instances", std::move(geometry_set)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc index d4072a05e5f..acd00d119ab 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc @@ -3,6 +3,7 @@ #include "DNA_pointcloud_types.h" #include "BKE_attribute_math.hh" +#include "BKE_instances.hh" #include "BKE_pointcloud.h" #include "node_geometry_util.hh" @@ -27,7 +28,7 @@ static void convert_instances_to_points(GeometrySet &geometry_set, Field radius_field, const Field selection_field) { - const InstancesComponent &instances = *geometry_set.get_component_for_read(); + const bke::Instances &instances = *geometry_set.get_instances_for_read(); const bke::InstancesFieldContext context{instances}; fn::FieldEvaluator evaluator{context, instances.instances_num()}; @@ -70,7 +71,7 @@ static void convert_instances_to_points(GeometrySet &geometry_set, const AttributeIDRef &attribute_id = item.key; const AttributeKind attribute_kind = item.value; - const GVArray src = instances.attributes()->lookup_or_default( + const GVArray src = instances.attributes().lookup_or_default( attribute_id, ATTR_DOMAIN_INSTANCE, attribute_kind.data_type); BLI_assert(src); GSpanAttributeWriter dst = point_attributes.lookup_or_add_for_write_only_span( diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc index 74d1b5561bb..ec9b9faf4ec 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc @@ -2,6 +2,8 @@ #include "GEO_realize_instances.hh" +#include "BKE_instances.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_join_geometry_cc { @@ -97,31 +99,36 @@ static void join_attributes(Span src_components, static void join_components(Span src_components, GeometrySet &result) { - InstancesComponent &dst_component = result.get_component_for_write(); + std::unique_ptr dst_instances = std::make_unique(); int tot_instances = 0; for (const InstancesComponent *src_component : src_components) { - tot_instances += src_component->instances_num(); + tot_instances += src_component->get_for_read()->instances_num(); } - dst_component.reserve(tot_instances); + dst_instances->reserve(tot_instances); for (const InstancesComponent *src_component : src_components) { - Span src_references = src_component->references(); + const bke::Instances &src_instances = *src_component->get_for_read(); + + Span src_references = src_instances.references(); Array handle_map(src_references.size()); for (const int src_handle : src_references.index_range()) { - handle_map[src_handle] = dst_component.add_reference(src_references[src_handle]); + handle_map[src_handle] = dst_instances->add_reference(src_references[src_handle]); } - Span src_transforms = src_component->instance_transforms(); - Span src_reference_handles = src_component->instance_reference_handles(); + Span src_transforms = src_instances.transforms(); + Span src_reference_handles = src_instances.reference_handles(); for (const int i : src_transforms.index_range()) { const int src_handle = src_reference_handles[i]; const int dst_handle = handle_map[src_handle]; const float4x4 &transform = src_transforms[i]; - dst_component.add_instance(dst_handle, transform); + dst_instances->add_instance(dst_handle, transform); } } + + result.replace_instances(dst_instances.release()); + InstancesComponent &dst_component = result.get_component_for_write(); join_attributes(to_base_components(src_components), dst_component, {"position"}); } @@ -151,25 +158,23 @@ static void join_component_type(Span src_geometry_sets, GeometrySet return; } - GeometrySet instances_geometry_set; - InstancesComponent &instances = - instances_geometry_set.get_component_for_write(); - if constexpr (is_same_any_v) { join_components(components, result); } else { + std::unique_ptr instances = std::make_unique(); for (const Component *component : components) { GeometrySet tmp_geo; tmp_geo.add(*component); - const int handle = instances.add_reference(InstanceReference{tmp_geo}); - instances.add_instance(handle, float4x4::identity()); + const int handle = instances->add_reference(bke::InstanceReference{tmp_geo}); + instances->add_instance(handle, float4x4::identity()); } geometry::RealizeInstancesOptions options; options.keep_original_ids = true; options.realize_instance_attributes = false; - GeometrySet joined_components = geometry::realize_instances(instances_geometry_set, options); + GeometrySet joined_components = geometry::realize_instances( + GeometrySet::create_with_instances(instances.release()), options); result.add(joined_components.get_component_for_write()); } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc index 3ce16fac464..bf064c6fcbe 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc @@ -3,6 +3,7 @@ #include "BLI_math_matrix.h" #include "BKE_geometry_set_instances.hh" +#include "BKE_instances.hh" #include "UI_interface.h" #include "UI_resources.h" @@ -68,14 +69,15 @@ static void node_geo_exec(GeoNodeExecParams params) GeometrySet geometry_set; if (params.get_input("As Instance")) { - InstancesComponent &instances = geometry_set.get_component_for_write(); - const int handle = instances.add_reference(*object); + std::unique_ptr instances = std::make_unique(); + const int handle = instances->add_reference(*object); if (transform_space_relative) { - instances.add_instance(handle, transform); + instances->add_instance(handle, transform); } else { - instances.add_instance(handle, float4x4::identity()); + instances->add_instance(handle, float4x4::identity()); } + geometry_set = GeometrySet::create_with_instances(instances.release()); } else { geometry_set = bke::object_get_evaluated_geometry_set(*object); diff --git a/source/blender/nodes/geometry/nodes/node_geo_rotate_instances.cc b/source/blender/nodes/geometry/nodes/node_geo_rotate_instances.cc index 4ed94e67e74..fac92a7500c 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_rotate_instances.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_rotate_instances.cc @@ -2,6 +2,8 @@ #include "BLI_task.hh" +#include "BKE_instances.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_rotate_instances_cc { @@ -16,10 +18,10 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_output(N_("Instances")); } -static void rotate_instances(GeoNodeExecParams ¶ms, InstancesComponent &instances_component) +static void rotate_instances(GeoNodeExecParams ¶ms, bke::Instances &instances) { - const bke::InstancesFieldContext context{instances_component}; - fn::FieldEvaluator evaluator{context, instances_component.instances_num()}; + const bke::InstancesFieldContext context{instances}; + fn::FieldEvaluator evaluator{context, instances.instances_num()}; evaluator.set_selection(params.extract_input>("Selection")); evaluator.add(params.extract_input>("Rotation")); evaluator.add(params.extract_input>("Pivot Point")); @@ -31,14 +33,14 @@ static void rotate_instances(GeoNodeExecParams ¶ms, InstancesComponent &inst const VArray pivots = evaluator.get_evaluated(1); const VArray local_spaces = evaluator.get_evaluated(2); - MutableSpan instance_transforms = instances_component.instance_transforms(); + MutableSpan transforms = instances.transforms(); threading::parallel_for(selection.index_range(), 512, [&](IndexRange range) { for (const int i_selection : range) { const int i = selection[i_selection]; const float3 pivot = pivots[i]; const float3 euler = rotations[i]; - float4x4 &instance_transform = instance_transforms[i]; + float4x4 &instance_transform = transforms[i]; float4x4 rotation_matrix; float3 used_pivot; @@ -81,9 +83,8 @@ static void rotate_instances(GeoNodeExecParams ¶ms, InstancesComponent &inst static void node_geo_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input("Instances"); - if (geometry_set.has_instances()) { - InstancesComponent &instances = geometry_set.get_component_for_write(); - rotate_instances(params, instances); + if (bke::Instances *instances = geometry_set.get_instances_for_write()) { + rotate_instances(params, *instances); } params.set_output("Instances", std::move(geometry_set)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_scale_instances.cc b/source/blender/nodes/geometry/nodes/node_geo_scale_instances.cc index 21fe724e194..dacb130337f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_scale_instances.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_scale_instances.cc @@ -2,6 +2,8 @@ #include "BLI_task.hh" +#include "BKE_instances.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_scale_instances_cc { @@ -19,10 +21,10 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_output(N_("Instances")); } -static void scale_instances(GeoNodeExecParams ¶ms, InstancesComponent &instances_component) +static void scale_instances(GeoNodeExecParams ¶ms, bke::Instances &instances) { - const bke::InstancesFieldContext context{instances_component}; - fn::FieldEvaluator evaluator{context, instances_component.instances_num()}; + const bke::InstancesFieldContext context{instances}; + fn::FieldEvaluator evaluator{context, instances.instances_num()}; evaluator.set_selection(params.extract_input>("Selection")); evaluator.add(params.extract_input>("Scale")); evaluator.add(params.extract_input>("Center")); @@ -34,13 +36,13 @@ static void scale_instances(GeoNodeExecParams ¶ms, InstancesComponent &insta const VArray pivots = evaluator.get_evaluated(1); const VArray local_spaces = evaluator.get_evaluated(2); - MutableSpan instance_transforms = instances_component.instance_transforms(); + MutableSpan transforms = instances.transforms(); threading::parallel_for(selection.index_range(), 512, [&](IndexRange range) { for (const int i_selection : range) { const int i = selection[i_selection]; const float3 pivot = pivots[i]; - float4x4 &instance_transform = instance_transforms[i]; + float4x4 &instance_transform = transforms[i]; if (local_spaces[i]) { instance_transform *= float4x4::from_location(pivot); @@ -61,9 +63,8 @@ static void scale_instances(GeoNodeExecParams ¶ms, InstancesComponent &insta static void node_geo_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input("Instances"); - if (geometry_set.has_instances()) { - InstancesComponent &instances = geometry_set.get_component_for_write(); - scale_instances(params, instances); + if (bke::Instances *instances = geometry_set.get_instances_for_write()) { + scale_instances(params, *instances); } params.set_output("Instances", std::move(geometry_set)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc b/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc index bbdabc09099..769a63f58cf 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc @@ -6,6 +6,7 @@ #include "BKE_curve.h" #include "BKE_curve_legacy_convert.hh" #include "BKE_curves.hh" +#include "BKE_instances.hh" #include "BKE_vfont.h" #include "BLI_hash.h" @@ -270,7 +271,7 @@ static std::optional get_text_layout(GeoNodeExecParams ¶ms) /* Returns a mapping of UTF-32 character code to instance handle. */ static Map create_curve_instances(GeoNodeExecParams ¶ms, TextLayout &layout, - InstancesComponent &instances) + bke::Instances &instances) { VFont *vfont = reinterpret_cast(params.node().id); Map handles; @@ -315,13 +316,13 @@ static Map create_curve_instances(GeoNodeExecParams ¶ms, return handles; } -static void add_instances_from_handles(InstancesComponent &instances, +static void add_instances_from_handles(bke::Instances &instances, const Map &char_handles, const TextLayout &layout) { instances.resize(layout.positions.size()); - MutableSpan handles = instances.instance_reference_handles(); - MutableSpan transforms = instances.instance_transforms(); + MutableSpan handles = instances.reference_handles(); + MutableSpan transforms = instances.transforms(); threading::parallel_for(IndexRange(layout.positions.size()), 256, [&](IndexRange range) { for (const int i : range) { @@ -333,9 +334,9 @@ static void add_instances_from_handles(InstancesComponent &instances, static void create_attributes(GeoNodeExecParams ¶ms, const TextLayout &layout, - InstancesComponent &instances) + bke::Instances &instances) { - MutableAttributeAccessor attributes = *instances.attributes_for_write(); + MutableAttributeAccessor attributes = instances.attributes_for_write(); if (params.output_is_required("Line")) { StrongAnonymousAttributeID line_id = StrongAnonymousAttributeID("Line"); @@ -385,13 +386,12 @@ static void node_geo_exec(GeoNodeExecParams params) } /* Create and add instances. */ - GeometrySet geometry_set_out; - InstancesComponent &instances = geometry_set_out.get_component_for_write(); - Map char_handles = create_curve_instances(params, *layout, instances); - add_instances_from_handles(instances, char_handles, *layout); - create_attributes(params, *layout, instances); + std::unique_ptr instances = std::make_unique(); + Map char_handles = create_curve_instances(params, *layout, *instances); + add_instances_from_handles(*instances, char_handles, *layout); + create_attributes(params, *layout, *instances); - params.set_output("Curve Instances", std::move(geometry_set_out)); + params.set_output("Curve Instances", GeometrySet::create_with_instances(instances.release())); } } // namespace blender::nodes::node_geo_string_to_curves_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_transform.cc b/source/blender/nodes/geometry/nodes/node_geo_transform.cc index 4130cad3bda..3c8a3f3ca76 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_transform.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_transform.cc @@ -11,6 +11,7 @@ #include "DNA_volume_types.h" #include "BKE_curves.hh" +#include "BKE_instances.hh" #include "BKE_mesh.h" #include "BKE_pointcloud.h" #include "BKE_volume.h" @@ -67,18 +68,18 @@ static void transform_pointcloud(PointCloud &pointcloud, const float4x4 &transfo position.finish(); } -static void translate_instances(InstancesComponent &instances, const float3 translation) +static void translate_instances(bke::Instances &instances, const float3 translation) { - MutableSpan transforms = instances.instance_transforms(); + MutableSpan transforms = instances.transforms(); for (float4x4 &transform : transforms) { add_v3_v3(transform.ptr()[3], translation); } } -static void transform_instances(InstancesComponent &instances, const float4x4 &transform) +static void transform_instances(bke::Instances &instances, const float4x4 &transform) { - MutableSpan instance_transforms = instances.instance_transforms(); - for (float4x4 &instance_transform : instance_transforms) { + MutableSpan transforms = instances.transforms(); + for (float4x4 &instance_transform : transforms) { instance_transform = transform * instance_transform; } } @@ -185,8 +186,8 @@ static void translate_geometry_set(GeoNodeExecParams ¶ms, if (Volume *volume = geometry.get_volume_for_write()) { translate_volume(params, *volume, translation, depsgraph); } - if (geometry.has_instances()) { - translate_instances(geometry.get_component_for_write(), translation); + if (bke::Instances *instances = geometry.get_instances_for_write()) { + translate_instances(*instances, translation); } if (bke::CurvesEditHints *curve_edit_hints = geometry.get_curve_edit_hints_for_write()) { translate_curve_edit_hints(*curve_edit_hints, translation); @@ -210,8 +211,8 @@ void transform_geometry_set(GeoNodeExecParams ¶ms, if (Volume *volume = geometry.get_volume_for_write()) { transform_volume(params, *volume, transform, depsgraph); } - if (geometry.has_instances()) { - transform_instances(geometry.get_component_for_write(), transform); + if (bke::Instances *instances = geometry.get_instances_for_write()) { + transform_instances(*instances, transform); } if (bke::CurvesEditHints *curve_edit_hints = geometry.get_curve_edit_hints_for_write()) { transform_curve_edit_hints(*curve_edit_hints, transform); diff --git a/source/blender/nodes/geometry/nodes/node_geo_translate_instances.cc b/source/blender/nodes/geometry/nodes/node_geo_translate_instances.cc index 3e9fe99adb0..23052abddc4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_translate_instances.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_translate_instances.cc @@ -2,6 +2,8 @@ #include "BLI_task.hh" +#include "BKE_instances.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_translate_instances_cc { @@ -15,10 +17,10 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_output(N_("Instances")); } -static void translate_instances(GeoNodeExecParams ¶ms, InstancesComponent &instances_component) +static void translate_instances(GeoNodeExecParams ¶ms, bke::Instances &instances) { - const bke::InstancesFieldContext context{instances_component}; - fn::FieldEvaluator evaluator{context, instances_component.instances_num()}; + const bke::InstancesFieldContext context{instances}; + fn::FieldEvaluator evaluator{context, instances.instances_num()}; evaluator.set_selection(params.extract_input>("Selection")); evaluator.add(params.extract_input>("Translation")); evaluator.add(params.extract_input>("Local Space")); @@ -28,16 +30,16 @@ static void translate_instances(GeoNodeExecParams ¶ms, InstancesComponent &i const VArray translations = evaluator.get_evaluated(0); const VArray local_spaces = evaluator.get_evaluated(1); - MutableSpan instance_transforms = instances_component.instance_transforms(); + MutableSpan transforms = instances.transforms(); threading::parallel_for(selection.index_range(), 1024, [&](IndexRange range) { for (const int i_selection : range) { const int i = selection[i_selection]; if (local_spaces[i]) { - instance_transforms[i] *= float4x4::from_location(translations[i]); + transforms[i] *= float4x4::from_location(translations[i]); } else { - add_v3_v3(instance_transforms[i].values[3], translations[i]); + add_v3_v3(transforms[i].values[3], translations[i]); } } }); @@ -46,9 +48,8 @@ static void translate_instances(GeoNodeExecParams ¶ms, InstancesComponent &i static void node_geo_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input("Instances"); - if (geometry_set.has_instances()) { - InstancesComponent &instances = geometry_set.get_component_for_write(); - translate_instances(params, instances); + if (bke::Instances *instances = geometry_set.get_instances_for_write()) { + translate_instances(params, *instances); } params.set_output("Instances", std::move(geometry_set)); } diff --git a/source/blender/nodes/intern/geometry_nodes_log.cc b/source/blender/nodes/intern/geometry_nodes_log.cc index 167bfef0f83..0f122307328 100644 --- a/source/blender/nodes/intern/geometry_nodes_log.cc +++ b/source/blender/nodes/intern/geometry_nodes_log.cc @@ -101,7 +101,7 @@ GeometryInfoLog::GeometryInfoLog(const GeometrySet &geometry_set) case GEO_COMPONENT_TYPE_INSTANCES: { const InstancesComponent &instances_component = *(const InstancesComponent *)component; InstancesInfo &info = this->instances_info.emplace(); - info.instances_num = instances_component.instances_num(); + info.instances_num = instances_component.attribute_domain_size(ATTR_DOMAIN_INSTANCE); break; } case GEO_COMPONENT_TYPE_EDIT: { -- cgit v1.2.3 From a6b83617e9de01c3a4719770f88fc0ad2933e55a Mon Sep 17 00:00:00 2001 From: Iliya Katueshenock Date: Mon, 17 Oct 2022 12:00:09 +0200 Subject: Fix T101705: crash when connecting reroute to multi-input socket Differential Revision: https://developer.blender.org/D16203 --- source/blender/blenkernel/BKE_node.h | 6 ++++ source/blender/blenkernel/intern/node.cc | 32 +++++++++++++++++++ .../nodes/intern/geometry_nodes_lazy_function.cc | 37 +++------------------- 3 files changed, 43 insertions(+), 32 deletions(-) diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index b1b4045370c..ecf7a556459 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -792,6 +792,12 @@ void nodeChainIterBackwards(const bNodeTree *ntree, */ void nodeParentsIter(bNode *node, bool (*callback)(bNode *, void *), void *userdata); +/** + * A dangling reroute node is a reroute node that does *not* have a "data source", i.e. no + * non-reroute node is connected to its input. + */ +bool nodeIsDanglingReroute(const struct bNodeTree *ntree, const struct bNode *node); + struct bNodeLink *nodeFindLink(struct bNodeTree *ntree, const struct bNodeSocket *from, const struct bNodeSocket *to); diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 654eb06a781..8028f990c42 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -2157,6 +2157,38 @@ void nodeParentsIter(bNode *node, bool (*callback)(bNode *, void *), void *userd } } +bool nodeIsDanglingReroute(const bNodeTree *ntree, const bNode *node) +{ + ntree->ensure_topology_cache(); + BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*ntree)); + BLI_assert(!ntree->has_available_link_cycle()); + + const bNode *iter_node = node; + if (!iter_node->is_reroute()) { + return false; + } + + while (true) { + const blender::Span links = + iter_node->input_socket(0).directly_linked_links(); + BLI_assert(links.size() <= 1); + if (links.is_empty()) { + return true; + } + const bNodeLink &link = *links[0]; + if (!link.is_available()) { + return false; + } + if (link.is_muted()) { + return false; + } + iter_node = link.fromnode; + if (!iter_node->is_reroute()) { + return false; + } + } +} + /* ************** Add stuff ********** */ void nodeUniqueName(bNodeTree *ntree, bNode *node) diff --git a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc index 6475a16477a..5bf245f1832 100644 --- a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc +++ b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc @@ -158,8 +158,9 @@ class LazyFunctionForMultiInput : public LazyFunction { base_type_ = get_socket_cpp_type(socket); BLI_assert(base_type_ != nullptr); BLI_assert(socket.is_multi_input()); + const bNodeTree &btree = socket.owner_tree(); for (const bNodeLink *link : socket.directly_linked_links()) { - if (!link->is_muted()) { + if (!(link->is_muted() || nodeIsDanglingReroute(&btree, link->fromnode))) { inputs_.append({"Input", *base_type_}); } } @@ -1073,9 +1074,7 @@ struct GeometryNodesLazyFunctionGraphBuilder { void insert_links_from_socket(const bNodeSocket &from_bsocket, lf::OutputSocket &from_lf_socket) { - const bNode &from_bnode = from_bsocket.owner_node(); - if (this->is_dangling_reroute_input(from_bnode)) { - /* Dangling reroutes should not be used as source of values. */ + if (nodeIsDanglingReroute(&btree_, &from_bsocket.owner_node())) { return; } @@ -1145,7 +1144,8 @@ struct GeometryNodesLazyFunctionGraphBuilder { if (multi_input_link == link) { break; } - if (!multi_input_link->is_muted()) { + if (!(multi_input_link->is_muted() || + nodeIsDanglingReroute(&btree_, multi_input_link->fromnode))) { link_index++; } } @@ -1174,33 +1174,6 @@ struct GeometryNodesLazyFunctionGraphBuilder { } } - bool is_dangling_reroute_input(const bNode &node) - { - if (!node.is_reroute()) { - return false; - } - const bNode *iter_node = &node; - /* It is guaranteed at a higher level that there are no link cycles. */ - while (true) { - const Span links = iter_node->input_socket(0).directly_linked_links(); - BLI_assert(links.size() <= 1); - if (links.is_empty()) { - return true; - } - const bNodeLink &link = *links[0]; - if (!link.is_available()) { - return false; - } - if (link.is_muted()) { - return false; - } - iter_node = link.fromnode; - if (!iter_node->is_reroute()) { - return false; - } - } - } - lf::OutputSocket *insert_type_conversion_if_necessary( lf::OutputSocket &from_socket, const CPPType &to_type, -- cgit v1.2.3 From e96ad822b382c131f9f55857364b330f6fff1521 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 17 Oct 2022 20:50:02 +1100 Subject: Fix AssetCatalogTest failure on WIN32 Recent changes to path handling (most likely [0]) caused AssetCatalogTest.create_catalog_after_loading_file to fail on WIN32. The test relied on the resulting path to be joined with "/" as a path separator. The resulting path used both forward and back-slashes. While these do work for some API's on WIN32, mixing both in a file path isn't expected behavior in most cases, so update the tests to use native slash direction for file-paths. [0]: 9f6a045e23cf4ab132ef78eeaf070bd53d0c509f --- .../blenkernel/intern/asset_catalog_test.cc | 76 ++++++++++++---------- .../intern/asset_library_service_test.cc | 7 +- 2 files changed, 46 insertions(+), 37 deletions(-) diff --git a/source/blender/blenkernel/intern/asset_catalog_test.cc b/source/blender/blenkernel/intern/asset_catalog_test.cc index 81eb1786322..ee2dd652b61 100644 --- a/source/blender/blenkernel/intern/asset_catalog_test.cc +++ b/source/blender/blenkernel/intern/asset_catalog_test.cc @@ -98,7 +98,7 @@ class AssetCatalogTest : public testing::Test { FAIL(); } - asset_library_root_ = test_files_dir + "/" + "asset_library"; + asset_library_root_ = test_files_dir + SEP_STR + "asset_library"; temp_library_path_ = ""; } @@ -116,7 +116,7 @@ class AssetCatalogTest : public testing::Test { { BKE_tempdir_init(""); const CatalogFilePath tempdir = BKE_tempdir_session(); - temp_library_path_ = tempdir + "test-temporary-path/"; + temp_library_path_ = tempdir + "test-temporary-path" + SEP_STR; return temp_library_path_; } @@ -202,9 +202,10 @@ class AssetCatalogTest : public testing::Test { void save_from_memory_into_existing_asset_lib(const bool should_top_level_cdf_exist) { const CatalogFilePath target_dir = create_temp_path(); /* Has trailing slash. */ - const CatalogFilePath original_cdf_file = asset_library_root_ + "/blender_assets.cats.txt"; - const CatalogFilePath registered_asset_lib = target_dir + "my_asset_library/"; - const CatalogFilePath asset_lib_subdir = registered_asset_lib + "subdir/"; + const CatalogFilePath original_cdf_file = asset_library_root_ + SEP_STR + + "blender_assets.cats.txt"; + const CatalogFilePath registered_asset_lib = target_dir + "my_asset_library" + SEP_STR; + const CatalogFilePath asset_lib_subdir = registered_asset_lib + "subdir" + SEP_STR; CatalogFilePath cdf_toplevel = registered_asset_lib + AssetCatalogService::DEFAULT_CATALOG_FILENAME; CatalogFilePath cdf_in_subdir = asset_lib_subdir + @@ -272,7 +273,7 @@ class AssetCatalogTest : public testing::Test { TEST_F(AssetCatalogTest, load_single_file) { AssetCatalogService service(asset_library_root_); - service.load_from_disk(asset_library_root_ + "/" + "blender_assets.cats.txt"); + service.load_from_disk(asset_library_root_ + SEP_STR + "blender_assets.cats.txt"); /* Test getting a non-existent catalog ID. */ EXPECT_EQ(nullptr, service.find_catalog(BLI_uuid_generate_random())); @@ -313,7 +314,7 @@ TEST_F(AssetCatalogTest, load_single_file) TEST_F(AssetCatalogTest, load_catalog_path_backslashes) { AssetCatalogService service(asset_library_root_); - service.load_from_disk(asset_library_root_ + "/" + "blender_assets.cats.txt"); + service.load_from_disk(asset_library_root_ + SEP_STR + "blender_assets.cats.txt"); const AssetCatalog *found_by_id = service.find_catalog(UUID_POSES_ELLIE_BACKSLASHES); ASSERT_NE(nullptr, found_by_id); @@ -332,7 +333,7 @@ TEST_F(AssetCatalogTest, load_catalog_path_backslashes) TEST_F(AssetCatalogTest, is_first_loaded_flag) { AssetCatalogService service(asset_library_root_); - service.load_from_disk(asset_library_root_ + "/" + "blender_assets.cats.txt"); + service.load_from_disk(asset_library_root_ + SEP_STR + "blender_assets.cats.txt"); AssetCatalog *new_cat = service.create_catalog("never/before/seen/path"); EXPECT_FALSE(new_cat->flags.is_first_loaded) @@ -435,7 +436,7 @@ TEST_F(AssetCatalogTest, insert_item_into_tree) TEST_F(AssetCatalogTest, load_single_file_into_tree) { AssetCatalogService service(asset_library_root_); - service.load_from_disk(asset_library_root_ + "/" + "blender_assets.cats.txt"); + service.load_from_disk(asset_library_root_ + SEP_STR + "blender_assets.cats.txt"); /* Contains not only paths from the CDF but also the missing parents (implicitly defined * catalogs). */ @@ -476,7 +477,7 @@ TEST_F(AssetCatalogTest, foreach_in_tree) } AssetCatalogService service(asset_library_root_); - service.load_from_disk(asset_library_root_ + "/" + "blender_assets.cats.txt"); + service.load_from_disk(asset_library_root_ + SEP_STR + "blender_assets.cats.txt"); std::vector expected_root_items{{"character", "path"}}; AssetCatalogTree *tree = service.get_catalog_tree(); @@ -499,7 +500,7 @@ TEST_F(AssetCatalogTest, foreach_in_tree) TEST_F(AssetCatalogTest, find_catalog_by_path) { TestableAssetCatalogService service(asset_library_root_); - service.load_from_disk(asset_library_root_ + "/" + + service.load_from_disk(asset_library_root_ + SEP_STR + AssetCatalogService::DEFAULT_CATALOG_FILENAME); AssetCatalog *catalog; @@ -522,7 +523,7 @@ TEST_F(AssetCatalogTest, find_catalog_by_path) TEST_F(AssetCatalogTest, write_single_file) { TestableAssetCatalogService service(asset_library_root_); - service.load_from_disk(asset_library_root_ + "/" + + service.load_from_disk(asset_library_root_ + SEP_STR + AssetCatalogService::DEFAULT_CATALOG_FILENAME); const CatalogFilePath save_to_path = use_temp_path() + @@ -550,7 +551,7 @@ TEST_F(AssetCatalogTest, write_single_file) TEST_F(AssetCatalogTest, read_write_unicode_filepath) { TestableAssetCatalogService service(asset_library_root_); - const CatalogFilePath load_from_path = asset_library_root_ + "/новый/" + + const CatalogFilePath load_from_path = asset_library_root_ + SEP_STR + "новый" + SEP_STR + AssetCatalogService::DEFAULT_CATALOG_FILENAME; service.load_from_disk(load_from_path); @@ -588,8 +589,9 @@ TEST_F(AssetCatalogTest, on_blendfile_save__with_existing_cdf) const CatalogFilePath top_level_dir = create_temp_path(); /* Has trailing slash. */ /* Create a copy of the CDF in SVN, so we can safely write to it. */ - const CatalogFilePath original_cdf_file = asset_library_root_ + "/blender_assets.cats.txt"; - const CatalogFilePath cdf_dirname = top_level_dir + "other_dir/"; + const CatalogFilePath original_cdf_file = asset_library_root_ + SEP_STR + + "blender_assets.cats.txt"; + const CatalogFilePath cdf_dirname = top_level_dir + "other_dir" + SEP_STR; const CatalogFilePath cdf_filename = cdf_dirname + AssetCatalogService::DEFAULT_CATALOG_FILENAME; ASSERT_TRUE(BLI_dir_create_recursive(cdf_dirname.c_str())); ASSERT_EQ(0, BLI_copy(original_cdf_file.c_str(), cdf_filename.c_str())) @@ -600,7 +602,7 @@ TEST_F(AssetCatalogTest, on_blendfile_save__with_existing_cdf) service.load_from_disk(); const AssetCatalog *cat = service.create_catalog("some/catalog/path"); - const CatalogFilePath blendfilename = top_level_dir + "subdir/some_file.blend"; + const CatalogFilePath blendfilename = top_level_dir + "subdir" + SEP_STR + "some_file.blend"; ASSERT_TRUE(service.write_to_disk(blendfilename)); EXPECT_EQ(cdf_filename, service.get_catalog_definition_file()->file_path); @@ -650,7 +652,8 @@ TEST_F(AssetCatalogTest, on_blendfile_save__from_memory_into_empty_directory) TEST_F(AssetCatalogTest, on_blendfile_save__from_memory_into_existing_cdf_and_merge) { const CatalogFilePath target_dir = create_temp_path(); /* Has trailing slash. */ - const CatalogFilePath original_cdf_file = asset_library_root_ + "/blender_assets.cats.txt"; + const CatalogFilePath original_cdf_file = asset_library_root_ + SEP_STR + + "blender_assets.cats.txt"; CatalogFilePath writable_cdf_file = target_dir + AssetCatalogService::DEFAULT_CATALOG_FILENAME; BLI_path_slash_native(writable_cdf_file.data()); ASSERT_EQ(0, BLI_copy(original_cdf_file.c_str(), writable_cdf_file.c_str())); @@ -719,7 +722,7 @@ TEST_F(AssetCatalogTest, create_first_catalog_from_scratch) service.write_to_disk(temp_lib_root + "phony.blend"); EXPECT_TRUE(BLI_is_dir(temp_lib_root.c_str())); - const CatalogFilePath definition_file_path = temp_lib_root + "/" + + const CatalogFilePath definition_file_path = temp_lib_root + SEP_STR + AssetCatalogService::DEFAULT_CATALOG_FILENAME; EXPECT_TRUE(BLI_is_file(definition_file_path.c_str())); @@ -739,7 +742,7 @@ TEST_F(AssetCatalogTest, create_catalog_after_loading_file) /* Copy the asset catalog definition files to a separate location, so that we can test without * overwriting the test file in SVN. */ - const CatalogFilePath default_catalog_path = asset_library_root_ + "/" + + const CatalogFilePath default_catalog_path = asset_library_root_ + SEP_STR + AssetCatalogService::DEFAULT_CATALOG_FILENAME; const CatalogFilePath writable_catalog_path = temp_lib_root + AssetCatalogService::DEFAULT_CATALOG_FILENAME; @@ -801,7 +804,7 @@ TEST_F(AssetCatalogTest, create_catalog_simple_name) TEST_F(AssetCatalogTest, delete_catalog_leaf) { AssetCatalogService service(asset_library_root_); - service.load_from_disk(asset_library_root_ + "/" + "blender_assets.cats.txt"); + service.load_from_disk(asset_library_root_ + SEP_STR + "blender_assets.cats.txt"); /* Delete a leaf catalog, i.e. one that is not a parent of another catalog. * This keeps this particular test easy. */ @@ -833,7 +836,7 @@ TEST_F(AssetCatalogTest, delete_catalog_leaf) TEST_F(AssetCatalogTest, delete_catalog_parent_by_id) { TestableAssetCatalogService service(asset_library_root_); - service.load_from_disk(asset_library_root_ + "/" + "blender_assets.cats.txt"); + service.load_from_disk(asset_library_root_ + SEP_STR + "blender_assets.cats.txt"); /* Delete a parent catalog. */ service.delete_catalog_by_id_soft(UUID_POSES_RUZENA); @@ -847,7 +850,7 @@ TEST_F(AssetCatalogTest, delete_catalog_parent_by_id) TEST_F(AssetCatalogTest, delete_catalog_parent_by_path) { AssetCatalogService service(asset_library_root_); - service.load_from_disk(asset_library_root_ + "/" + "blender_assets.cats.txt"); + service.load_from_disk(asset_library_root_ + SEP_STR + "blender_assets.cats.txt"); /* Create an extra catalog with the to-be-deleted path, and one with a child of that. * This creates some duplicates that are bound to occur in production asset libraries as well. @@ -887,14 +890,14 @@ TEST_F(AssetCatalogTest, delete_catalog_parent_by_path) TEST_F(AssetCatalogTest, delete_catalog_write_to_disk) { TestableAssetCatalogService service(asset_library_root_); - service.load_from_disk(asset_library_root_ + "/" + + service.load_from_disk(asset_library_root_ + SEP_STR + AssetCatalogService::DEFAULT_CATALOG_FILENAME); service.delete_catalog_by_id_soft(UUID_POSES_ELLIE); const CatalogFilePath save_to_path = use_temp_path(); AssetCatalogDefinitionFile *cdf = service.get_catalog_definition_file(); - cdf->write_to_disk(save_to_path + "/" + AssetCatalogService::DEFAULT_CATALOG_FILENAME); + cdf->write_to_disk(save_to_path + SEP_STR + AssetCatalogService::DEFAULT_CATALOG_FILENAME); AssetCatalogService loaded_service(save_to_path); loaded_service.load_from_disk(); @@ -911,7 +914,7 @@ TEST_F(AssetCatalogTest, delete_catalog_write_to_disk) TEST_F(AssetCatalogTest, update_catalog_path) { AssetCatalogService service(asset_library_root_); - service.load_from_disk(asset_library_root_ + "/" + + service.load_from_disk(asset_library_root_ + SEP_STR + AssetCatalogService::DEFAULT_CATALOG_FILENAME); const AssetCatalog *orig_cat = service.find_catalog(UUID_POSES_RUZENA); @@ -940,7 +943,7 @@ TEST_F(AssetCatalogTest, update_catalog_path) TEST_F(AssetCatalogTest, update_catalog_path_simple_name) { AssetCatalogService service(asset_library_root_); - service.load_from_disk(asset_library_root_ + "/" + + service.load_from_disk(asset_library_root_ + SEP_STR + AssetCatalogService::DEFAULT_CATALOG_FILENAME); service.update_catalog_path(UUID_POSES_RUZENA, "charlib/Ružena"); @@ -956,7 +959,7 @@ TEST_F(AssetCatalogTest, update_catalog_path_simple_name) TEST_F(AssetCatalogTest, update_catalog_path_longer_than_simplename) { AssetCatalogService service(asset_library_root_); - service.load_from_disk(asset_library_root_ + "/" + + service.load_from_disk(asset_library_root_ + SEP_STR + AssetCatalogService::DEFAULT_CATALOG_FILENAME); const std::string new_path = "this/is/a/very/long/path/that/exceeds/the/simple-name/length/of/assets"; @@ -978,7 +981,7 @@ TEST_F(AssetCatalogTest, update_catalog_path_longer_than_simplename) TEST_F(AssetCatalogTest, update_catalog_path_add_slashes) { AssetCatalogService service(asset_library_root_); - service.load_from_disk(asset_library_root_ + "/" + + service.load_from_disk(asset_library_root_ + SEP_STR + AssetCatalogService::DEFAULT_CATALOG_FILENAME); const AssetCatalog *orig_cat = service.find_catalog(UUID_POSES_RUZENA); @@ -1019,8 +1022,10 @@ TEST_F(AssetCatalogTest, update_catalog_path_add_slashes) TEST_F(AssetCatalogTest, merge_catalog_files) { const CatalogFilePath cdf_dir = create_temp_path(); - const CatalogFilePath original_cdf_file = asset_library_root_ + "/blender_assets.cats.txt"; - const CatalogFilePath modified_cdf_file = asset_library_root_ + "/modified_assets.cats.txt"; + const CatalogFilePath original_cdf_file = asset_library_root_ + SEP_STR + + "blender_assets.cats.txt"; + const CatalogFilePath modified_cdf_file = asset_library_root_ + SEP_STR + + "modified_assets.cats.txt"; const CatalogFilePath temp_cdf_file = cdf_dir + "blender_assets.cats.txt"; ASSERT_EQ(0, BLI_copy(original_cdf_file.c_str(), temp_cdf_file.c_str())); @@ -1059,8 +1064,10 @@ TEST_F(AssetCatalogTest, merge_catalog_files) TEST_F(AssetCatalogTest, refresh_catalogs_with_modification) { const CatalogFilePath cdf_dir = create_temp_path(); - const CatalogFilePath original_cdf_file = asset_library_root_ + "/blender_assets.cats.txt"; - const CatalogFilePath modified_cdf_file = asset_library_root_ + "/catalog_reload_test.cats.txt"; + const CatalogFilePath original_cdf_file = asset_library_root_ + SEP_STR + + "blender_assets.cats.txt"; + const CatalogFilePath modified_cdf_file = asset_library_root_ + SEP_STR + + "catalog_reload_test.cats.txt"; const CatalogFilePath temp_cdf_file = cdf_dir + "blender_assets.cats.txt"; ASSERT_EQ(0, BLI_copy(original_cdf_file.c_str(), temp_cdf_file.c_str())); @@ -1131,8 +1138,9 @@ TEST_F(AssetCatalogTest, refresh_catalogs_with_modification) TEST_F(AssetCatalogTest, backups) { const CatalogFilePath cdf_dir = create_temp_path(); - const CatalogFilePath original_cdf_file = asset_library_root_ + "/blender_assets.cats.txt"; - const CatalogFilePath writable_cdf_file = cdf_dir + "/blender_assets.cats.txt"; + const CatalogFilePath original_cdf_file = asset_library_root_ + SEP_STR + + "blender_assets.cats.txt"; + const CatalogFilePath writable_cdf_file = cdf_dir + SEP_STR + "blender_assets.cats.txt"; ASSERT_EQ(0, BLI_copy(original_cdf_file.c_str(), writable_cdf_file.c_str())); /* Read a CDF, modify, and write it. */ diff --git a/source/blender/blenkernel/intern/asset_library_service_test.cc b/source/blender/blenkernel/intern/asset_library_service_test.cc index de6180cb684..d105c5644de 100644 --- a/source/blender/blenkernel/intern/asset_library_service_test.cc +++ b/source/blender/blenkernel/intern/asset_library_service_test.cc @@ -39,7 +39,7 @@ class AssetLibraryServiceTest : public testing::Test { if (test_files_dir.empty()) { FAIL(); } - asset_library_root_ = test_files_dir + "/" + "asset_library"; + asset_library_root_ = test_files_dir + SEP_STR + "asset_library"; temp_library_path_ = ""; } @@ -59,7 +59,7 @@ class AssetLibraryServiceTest : public testing::Test { { BKE_tempdir_init(""); const CatalogFilePath tempdir = BKE_tempdir_session(); - temp_library_path_ = tempdir + "test-temporary-path/"; + temp_library_path_ = tempdir + "test-temporary-path" + SEP_STR; return temp_library_path_; } @@ -168,7 +168,8 @@ TEST_F(AssetLibraryServiceTest, has_any_unsaved_catalogs) TEST_F(AssetLibraryServiceTest, has_any_unsaved_catalogs_after_write) { const CatalogFilePath writable_dir = create_temp_path(); /* Has trailing slash. */ - const CatalogFilePath original_cdf_file = asset_library_root_ + "/blender_assets.cats.txt"; + const CatalogFilePath original_cdf_file = asset_library_root_ + SEP_STR + + "blender_assets.cats.txt"; CatalogFilePath writable_cdf_file = writable_dir + AssetCatalogService::DEFAULT_CATALOG_FILENAME; BLI_path_slash_native(writable_cdf_file.data()); ASSERT_EQ(0, BLI_copy(original_cdf_file.c_str(), writable_cdf_file.c_str())); -- cgit v1.2.3 From 69e7274d4f58f76e750b7104c1bc0334243a9b91 Mon Sep 17 00:00:00 2001 From: Pablo Vazquez Date: Mon, 17 Oct 2022 14:11:11 +0200 Subject: Brush: Fix mismatch in DNA Brush defaults Missed changing the DNA brush default in rBdb40b6 Thanks to SteffenD for reporting in blender.chat! --- source/blender/makesdna/DNA_brush_defaults.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesdna/DNA_brush_defaults.h b/source/blender/makesdna/DNA_brush_defaults.h index 348e8f4e098..6e88275672a 100644 --- a/source/blender/makesdna/DNA_brush_defaults.h +++ b/source/blender/makesdna/DNA_brush_defaults.h @@ -92,7 +92,7 @@ .hardness = 0.0f, \ .automasking_boundary_edges_propagation_steps = 1, \ .automasking_cavity_blur_steps = 0,\ - .automasking_cavity_factor = 0.5f,\ + .automasking_cavity_factor = 1.0f,\ \ /* A kernel radius of 1 has almost no effect (T63233). */ \ .blur_kernel_radius = 2, \ -- cgit v1.2.3 From 390cf2fe756e2759ec2f0dcc0ef4b1f84142f1d6 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 17 Oct 2022 14:34:13 +0200 Subject: Cleanup: compiler warnings --- source/blender/blenkernel/BKE_instances.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/BKE_instances.hh b/source/blender/blenkernel/BKE_instances.hh index 69b6f944838..6502fefec88 100644 --- a/source/blender/blenkernel/BKE_instances.hh +++ b/source/blender/blenkernel/BKE_instances.hh @@ -25,7 +25,7 @@ #include "BKE_attribute.hh" -class GeometrySet; +struct GeometrySet; struct Object; struct Collection; -- cgit v1.2.3 From baa9a00f5f97c04330f0247f36af34bb335e2dcb Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 17 Oct 2022 13:24:00 +0200 Subject: Fix Wayland not being disabled when dependencies are not found --- build_files/cmake/platform/platform_unix.cmake | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake index 7b7937959bf..85a6080cc3f 100644 --- a/build_files/cmake/platform/platform_unix.cmake +++ b/build_files/cmake/platform/platform_unix.cmake @@ -740,27 +740,27 @@ if(WITH_GHOST_WAYLAND) set(wayland-cursor_FOUND ON) endif() - if (NOT ${wayland-client_FOUND}) + if (NOT wayland-client_FOUND) message(STATUS "wayland-client not found, disabling WITH_GHOST_WAYLAND") set(WITH_GHOST_WAYLAND OFF) endif() - if (NOT ${wayland-egl_FOUND}) + if (NOT wayland-egl_FOUND) message(STATUS "wayland-egl not found, disabling WITH_GHOST_WAYLAND") set(WITH_GHOST_WAYLAND OFF) endif() - if (NOT ${wayland-scanner_FOUND}) + if (NOT wayland-scanner_FOUND) message(STATUS "wayland-scanner not found, disabling WITH_GHOST_WAYLAND") set(WITH_GHOST_WAYLAND OFF) endif() - if (NOT ${wayland-cursor_FOUND}) + if (NOT wayland-cursor_FOUND) message(STATUS "wayland-cursor not found, disabling WITH_GHOST_WAYLAND") set(WITH_GHOST_WAYLAND OFF) endif() - if (NOT ${wayland-protocols_FOUND}) + if (NOT wayland-protocols_FOUND) message(STATUS "wayland-protocols not found, disabling WITH_GHOST_WAYLAND") set(WITH_GHOST_WAYLAND OFF) endif() - if (NOT ${xkbcommon_FOUND}) + if (NOT xkbcommon_FOUND) message(STATUS "xkbcommon not found, disabling WITH_GHOST_WAYLAND") set(WITH_GHOST_WAYLAND OFF) endif() -- cgit v1.2.3 From 3eaf2b7fc69668cacd4ddb221faf90e60736015e Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 17 Oct 2022 13:24:24 +0200 Subject: Fix OpenPGL and OneAPI being detected by CMake when Cycles is disabled --- build_files/cmake/platform/platform_apple.cmake | 2 +- build_files/cmake/platform/platform_unix.cmake | 4 ++-- build_files/cmake/platform/platform_win32.cmake | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake index 9f1824ec827..04f5a312030 100644 --- a/build_files/cmake/platform/platform_apple.cmake +++ b/build_files/cmake/platform/platform_apple.cmake @@ -429,7 +429,7 @@ if(WITH_HARU) endif() endif() -if(WITH_CYCLES_PATH_GUIDING) +if(WITH_CYCLES AND WITH_CYCLES_PATH_GUIDING) find_package(openpgl QUIET) if(openpgl_FOUND) get_target_property(OPENPGL_LIBRARIES openpgl::openpgl LOCATION) diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake index 85a6080cc3f..695ea3d773e 100644 --- a/build_files/cmake/platform/platform_unix.cmake +++ b/build_files/cmake/platform/platform_unix.cmake @@ -329,7 +329,7 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL) endif() endif() -if(WITH_CYCLES_DEVICE_ONEAPI) +if(WITH_CYCLES AND WITH_CYCLES_DEVICE_ONEAPI) set(CYCLES_LEVEL_ZERO ${LIBDIR}/level-zero CACHE PATH "Path to Level Zero installation") if(EXISTS ${CYCLES_LEVEL_ZERO} AND NOT LEVEL_ZERO_ROOT_DIR) set(LEVEL_ZERO_ROOT_DIR ${CYCLES_LEVEL_ZERO}) @@ -592,7 +592,7 @@ if(WITH_HARU) endif() endif() -if(WITH_CYCLES_PATH_GUIDING) +if(WITH_CYCLES AND WITH_CYCLES_PATH_GUIDING) find_package_wrapper(openpgl) if(openpgl_FOUND) get_target_property(OPENPGL_LIBRARIES openpgl::openpgl LOCATION) diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index 7031b1faac4..cfb8bf34b81 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -936,7 +936,7 @@ if(WITH_HARU) endif() endif() -if(WITH_CYCLES_PATH_GUIDING) +if(WITH_CYCLES AND WITH_CYCLES_PATH_GUIDING) find_package(openpgl QUIET) if(openpgl_FOUND) get_target_property(OPENPGL_LIBRARIES_RELEASE openpgl::openpgl LOCATION_RELEASE) @@ -952,7 +952,7 @@ endif() set(ZSTD_INCLUDE_DIRS ${LIBDIR}/zstd/include) set(ZSTD_LIBRARIES ${LIBDIR}/zstd/lib/zstd_static.lib) -if(WITH_CYCLES_DEVICE_ONEAPI) +if(WITH_CYCLES AND WITH_CYCLES_DEVICE_ONEAPI) set(LEVEL_ZERO_ROOT_DIR ${LIBDIR}/level_zero) set(CYCLES_SYCL ${LIBDIR}/dpcpp CACHE PATH "Path to oneAPI DPC++ compiler") if(EXISTS ${CYCLES_SYCL} AND NOT SYCL_ROOT_DIR) -- cgit v1.2.3 From 0a35afbf86c86963ebb638f0804a706d17df5b50 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 17 Oct 2022 14:20:42 +0200 Subject: Fix T99565: Cycles reading TGA files with alpha different than Blender Thanks to Lukas for tracking down the cause in OIIO. --- intern/cycles/scene/image_oiio.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/intern/cycles/scene/image_oiio.cpp b/intern/cycles/scene/image_oiio.cpp index 8792393e5a1..d59359970c6 100644 --- a/intern/cycles/scene/image_oiio.cpp +++ b/intern/cycles/scene/image_oiio.cpp @@ -192,8 +192,17 @@ bool OIIOImageLoader::load_pixels(const ImageMetaData &metadata, return false; } - const bool do_associate_alpha = associate_alpha && - spec.get_int_attribute("oiio:UnassociatedAlpha", 0); + bool do_associate_alpha = false; + if (associate_alpha) { + do_associate_alpha = spec.get_int_attribute("oiio:UnassociatedAlpha", 0); + + /* Workaround OIIO not detecting TGA file alpha the same as Blender (since #3019). + * We want anything not marked as premultiplied alpha to get associated. */ + if (!do_associate_alpha && spec.alpha_channel != -1 && + strcmp(in->format_name(), "targa") == 0) { + do_associate_alpha = spec.get_int_attribute("targa:alpha_type", -1) != 4; + } + } switch (metadata.type) { case IMAGE_DATA_TYPE_BYTE: -- cgit v1.2.3 From 1111af5cb4964369963c587b5400ab784a4397c6 Mon Sep 17 00:00:00 2001 From: Pablo Vazquez Date: Mon, 17 Oct 2022 14:47:49 +0200 Subject: Sculpt: add versioning for Auto-masking cavity factor default Also remove automasking_cavity_factor default from RNA for brushes. Data-blocks set their defaults via `DNA_brush_defaults.h` Continuation from previous commit and rBdb40b6 Thanks to Dalai for the help! --- source/blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenloader/intern/versioning_300.cc | 7 +++++++ source/blender/makesrna/intern/rna_brush.c | 1 - 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 3c8f7d758b6..96df8f7a443 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -25,7 +25,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 3 +#define BLENDER_FILE_SUBVERSION 4 /* 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/blenloader/intern/versioning_300.cc b/source/blender/blenloader/intern/versioning_300.cc index 5328107e1f2..e2b98b2283f 100644 --- a/source/blender/blenloader/intern/versioning_300.cc +++ b/source/blender/blenloader/intern/versioning_300.cc @@ -3623,6 +3623,13 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) } } + if (!MAIN_VERSION_ATLEAST(bmain, 304, 4)) { + /* Update brush sculpt settings. */ + LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) { + brush->automasking_cavity_factor = 1.0f; + } + } + /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index b44b0620329..35e01be366b 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -3242,7 +3242,6 @@ static void rna_def_brush(BlenderRNA *brna) prop = RNA_def_property(srna, "automasking_cavity_factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "automasking_cavity_factor"); - RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Cavity Factor", "The contrast of the cavity mask"); RNA_def_property_range(prop, 0.0f, 5.0f); RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); -- cgit v1.2.3 From 660c47596e17229dbadca2b129767ec9a17338e9 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sat, 15 Oct 2022 22:07:03 +0300 Subject: Weight Paint: relax heuristic to determine when final mesh can be used. Checking for polygon and loop data to be referenced is too fragile re changes in geometry node implementations. Instead, compare counts of polygons, face corners and vertices: topology changes are unlikely to keep all three unchanged. Ref D15501 --- source/blender/blenkernel/intern/paint.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index 9248e4d520e..13243925b28 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -1786,8 +1786,8 @@ static void sculpt_update_object( /* If the fully evaluated mesh has the same topology as the deform-only version, use it. * This matters because crazyspace evaluation is very restrictive and excludes even modifiers * that simply recompute vertex weights (which can even include Geometry Nodes). */ - if (me_eval_deform->polys().data() == me_eval->polys().data() && - me_eval_deform->loops().data() == me_eval->loops().data() && + if (me_eval_deform->totpoly == me_eval->totpoly && + me_eval_deform->totloop == me_eval->totloop && me_eval_deform->totvert == me_eval->totvert) { BKE_sculptsession_free_deformMats(ss); -- cgit v1.2.3 From 694481095baca58d13474aed26ee7619615399b2 Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Mon, 17 Oct 2022 08:35:11 -0700 Subject: Fix for T101506: BLF Disable Kerning in Main Font Disable kerning in our main font to exactly restore the spacing of text as seen in Blender 3.1 - 3.3 See D16186 for more details. Differential Revision: https://developer.blender.org/D16186 Reviewed by Brecht Van Lommel --- source/blender/blenfont/intern/blf.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index a673f4a1bc7..d4f5be617fd 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -162,6 +162,14 @@ int BLF_load_unique(const char *name) } FontBLF *font = blf_font_new(name, filepath); + + /* XXX: Temporarily disable kerning in our main font. Kerning had been accidentally removed from + * our font in 3.1. In 3.4 we disable kerning here in the new version to keep spacing the same + * (T101506). Enable again later with change of font, placement, or rendering - Harley. */ + if (font && BLI_str_endswith(filepath, BLF_DEFAULT_PROPORTIONAL_FONT)) { + font->face_flags &= ~FT_FACE_FLAG_KERNING; + } + MEM_freeN(filepath); if (!font) { -- cgit v1.2.3 From d3b47fa84297dbbf5d5f91d0d68473468c363bd4 Mon Sep 17 00:00:00 2001 From: Jason Fielder Date: Mon, 17 Oct 2022 17:39:59 +0200 Subject: FIX T101445: halo Particles are not working. color uniform assignment needing to be changed to ucolor was missed. Ref T101445 Reviewed By: fclem Maniphest Tasks: T101445 Differential Revision: https://developer.blender.org/D16236 --- source/blender/draw/engines/overlay/overlay_particle.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/draw/engines/overlay/overlay_particle.cc b/source/blender/draw/engines/overlay/overlay_particle.cc index 6f77a777ba0..c9e3ccba008 100644 --- a/source/blender/draw/engines/overlay/overlay_particle.cc +++ b/source/blender/draw/engines/overlay/overlay_particle.cc @@ -181,14 +181,14 @@ void OVERLAY_particle_cache_populate(OVERLAY_Data *vedata, Object *ob) default: case PART_DRAW_DOT: grp = DRW_shgroup_create_sub(pd->particle_dots_grp); - DRW_shgroup_uniform_vec4_copy(grp, "color", color); + DRW_shgroup_uniform_vec4_copy(grp, "ucolor", color); DRW_shgroup_call(grp, geom, nullptr); break; case PART_DRAW_AXIS: case PART_DRAW_CIRC: case PART_DRAW_CROSS: grp = DRW_shgroup_create_sub(pd->particle_shapes_grp); - DRW_shgroup_uniform_vec4_copy(grp, "color", color); + DRW_shgroup_uniform_vec4_copy(grp, "ucolor", color); shape = DRW_cache_particles_get_prim(draw_as); DRW_shgroup_call_instances_with_attrs(grp, nullptr, shape, geom); break; -- cgit v1.2.3 From 728451f01ad5eec6abdc4f54364fe82490b151c5 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 17 Oct 2022 12:21:30 -0500 Subject: Fix T101871: Realize instances node can skip material indices The node only created a material index attribute on the result mesh if it existed on any of the input meshes. But the input meshes might not have the attribute if they had a single material or no materials. As a fix, also create the attribute if the result has more than one material. --- source/blender/geometry/intern/realize_instances.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index daafe0e4aa7..c649bde06ca 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -859,6 +859,7 @@ static AllMeshesInfo preprocess_meshes(const GeometrySet &geometry_set, } } } + info.create_material_index_attribute |= info.materials.size() > 1; info.realize_info.reinitialize(info.order.size()); for (const int mesh_index : info.realize_info.index_range()) { MeshRealizeInfo &mesh_info = info.realize_info[mesh_index]; -- cgit v1.2.3 From 603a534f09b0f94f599c607240a4934f7c1a2ef6 Mon Sep 17 00:00:00 2001 From: Aras Pranckevicius Date: Mon, 17 Oct 2022 21:03:17 +0300 Subject: Fix T101850: Cycles DDS oversaturation when alpha is in use DDS files coming through OIIO needed a similar treatment as TGA in T99565; just for DDS OIIO just never set the "unassociated alpha" attribute. Fixes T101850. Reviewed By: Brecht Van Lommel Differential Revision: https://developer.blender.org/D16270 --- intern/cycles/scene/image_oiio.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/intern/cycles/scene/image_oiio.cpp b/intern/cycles/scene/image_oiio.cpp index d59359970c6..7bcf1ccb073 100644 --- a/intern/cycles/scene/image_oiio.cpp +++ b/intern/cycles/scene/image_oiio.cpp @@ -196,11 +196,16 @@ bool OIIOImageLoader::load_pixels(const ImageMetaData &metadata, if (associate_alpha) { do_associate_alpha = spec.get_int_attribute("oiio:UnassociatedAlpha", 0); - /* Workaround OIIO not detecting TGA file alpha the same as Blender (since #3019). - * We want anything not marked as premultiplied alpha to get associated. */ - if (!do_associate_alpha && spec.alpha_channel != -1 && - strcmp(in->format_name(), "targa") == 0) { - do_associate_alpha = spec.get_int_attribute("targa:alpha_type", -1) != 4; + if (!do_associate_alpha && spec.alpha_channel != -1) { + /* Workaround OIIO not detecting TGA file alpha the same as Blender (since #3019). + * We want anything not marked as premultiplied alpha to get associated. */ + if (strcmp(in->format_name(), "targa") == 0) { + do_associate_alpha = spec.get_int_attribute("targa:alpha_type", -1) != 4; + } + /* OIIO DDS reader never sets UnassociatedAlpha attribute. */ + if (strcmp(in->format_name(), "dds") == 0) { + do_associate_alpha = true; + } } } -- cgit v1.2.3 From 23ea72f051028c8980736eee157f3fabc0615dd5 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 17 Oct 2022 13:00:37 -0500 Subject: Cleanup: Move versioning_defaults.c to C++ --- source/blender/blenloader/CMakeLists.txt | 2 +- .../blenloader/intern/versioning_defaults.c | 760 -------------------- .../blenloader/intern/versioning_defaults.cc | 788 +++++++++++++++++++++ 3 files changed, 789 insertions(+), 761 deletions(-) delete mode 100644 source/blender/blenloader/intern/versioning_defaults.c create mode 100644 source/blender/blenloader/intern/versioning_defaults.cc diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt index f0209d1337c..86793d38b0b 100644 --- a/source/blender/blenloader/CMakeLists.txt +++ b/source/blender/blenloader/CMakeLists.txt @@ -47,7 +47,7 @@ set(SRC intern/versioning_400.cc intern/versioning_common.cc intern/versioning_cycles.c - intern/versioning_defaults.c + intern/versioning_defaults.cc intern/versioning_dna.c intern/versioning_legacy.c intern/versioning_userdef.c diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c deleted file mode 100644 index 06903865381..00000000000 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ /dev/null @@ -1,760 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup blenloader - * - * This file handles updating the `startup.blend`, this is used when reading old files. - * - * Unlike regular versioning this makes changes that ensure the startup file - * has brushes and other presets setup to take advantage of newer features. - * - * To update preference defaults see `userdef_default.c`. - */ - -#include "MEM_guardedalloc.h" - -#include "BLI_listbase.h" -#include "BLI_math.h" -#include "BLI_string.h" -#include "BLI_system.h" -#include "BLI_utildefines.h" - -#include "DNA_camera_types.h" -#include "DNA_curveprofile_types.h" -#include "DNA_gpencil_types.h" -#include "DNA_light_types.h" -#include "DNA_mask_types.h" -#include "DNA_material_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_screen_types.h" -#include "DNA_space_types.h" -#include "DNA_userdef_types.h" -#include "DNA_windowmanager_types.h" -#include "DNA_workspace_types.h" - -#include "BKE_appdir.h" -#include "BKE_brush.h" -#include "BKE_colortools.h" -#include "BKE_curveprofile.h" -#include "BKE_customdata.h" -#include "BKE_gpencil.h" -#include "BKE_idprop.h" -#include "BKE_layer.h" -#include "BKE_lib_id.h" -#include "BKE_main.h" -#include "BKE_main_namemap.h" -#include "BKE_material.h" -#include "BKE_mesh.h" -#include "BKE_node.h" -#include "BKE_node_tree_update.h" -#include "BKE_paint.h" -#include "BKE_screen.h" -#include "BKE_workspace.h" - -#include "BLO_readfile.h" - -#include "BLT_translation.h" - -#include "versioning_common.h" - -/* Make preferences read-only, use versioning_userdef.c. */ -#define U (*((const UserDef *)&U)) - -static bool blo_is_builtin_template(const char *app_template) -{ - /* For all builtin templates shipped with Blender. */ - return ( - !app_template || - STR_ELEM(app_template, N_("2D_Animation"), N_("Sculpting"), N_("VFX"), N_("Video_Editing"))); -} - -static void blo_update_defaults_screen(bScreen *screen, - const char *app_template, - const char *workspace_name) -{ - /* For all app templates. */ - LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { - LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { - /* Some toolbars have been saved as initialized, - * we don't want them to have odd zoom-level or scrolling set, see: T47047 */ - if (ELEM(region->regiontype, RGN_TYPE_UI, RGN_TYPE_TOOLS, RGN_TYPE_TOOL_PROPS)) { - region->v2d.flag &= ~V2D_IS_INIT; - } - } - - /* Set default folder. */ - LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { - if (sl->spacetype == SPACE_FILE) { - SpaceFile *sfile = (SpaceFile *)sl; - if (sfile->params) { - const char *dir_default = BKE_appdir_folder_default(); - if (dir_default) { - STRNCPY(sfile->params->dir, dir_default); - sfile->params->file[0] = '\0'; - } - } - } - } - } - - /* For builtin templates only. */ - if (!blo_is_builtin_template(app_template)) { - return; - } - - LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { - LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { - /* Remove all stored panels, we want to use defaults - * (order, open/closed) as defined by UI code here! */ - BKE_area_region_panels_free(®ion->panels); - BLI_freelistN(®ion->panels_category_active); - - /* Reset size so it uses consistent defaults from the region types. */ - region->sizex = 0; - region->sizey = 0; - } - - if (area->spacetype == SPACE_IMAGE) { - if (STREQ(workspace_name, "UV Editing")) { - SpaceImage *sima = area->spacedata.first; - if (sima->mode == SI_MODE_VIEW) { - sima->mode = SI_MODE_UV; - } - } - } - else if (area->spacetype == SPACE_ACTION) { - /* Show markers region, hide channels and collapse summary in timelines. */ - SpaceAction *saction = area->spacedata.first; - saction->flag |= SACTION_SHOW_MARKERS; - if (saction->mode == SACTCONT_TIMELINE) { - saction->ads.flag |= ADS_FLAG_SUMMARY_COLLAPSED; - - LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { - if (region->regiontype == RGN_TYPE_CHANNELS) { - region->flag |= RGN_FLAG_HIDDEN; - } - } - } - else { - /* Open properties panel by default. */ - LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { - if (region->regiontype == RGN_TYPE_UI) { - region->flag &= ~RGN_FLAG_HIDDEN; - } - } - } - } - else if (area->spacetype == SPACE_GRAPH) { - SpaceGraph *sipo = area->spacedata.first; - sipo->flag |= SIPO_SHOW_MARKERS; - } - else if (area->spacetype == SPACE_NLA) { - SpaceNla *snla = area->spacedata.first; - snla->flag |= SNLA_SHOW_MARKERS; - } - else if (area->spacetype == SPACE_SEQ) { - SpaceSeq *seq = area->spacedata.first; - seq->flag |= SEQ_SHOW_MARKERS | SEQ_ZOOM_TO_FIT | SEQ_USE_PROXIES | SEQ_SHOW_OVERLAY; - seq->render_size = SEQ_RENDER_SIZE_PROXY_100; - seq->timeline_overlay.flag |= SEQ_TIMELINE_SHOW_STRIP_SOURCE | SEQ_TIMELINE_SHOW_STRIP_NAME | - SEQ_TIMELINE_SHOW_STRIP_DURATION | SEQ_TIMELINE_SHOW_GRID | - SEQ_TIMELINE_SHOW_STRIP_COLOR_TAG; - seq->preview_overlay.flag |= SEQ_PREVIEW_SHOW_OUTLINE_SELECTED; - } - else if (area->spacetype == SPACE_TEXT) { - /* Show syntax and line numbers in Script workspace text editor. */ - SpaceText *stext = area->spacedata.first; - stext->showsyntax = true; - stext->showlinenrs = true; - } - else if (area->spacetype == SPACE_VIEW3D) { - View3D *v3d = area->spacedata.first; - /* Screen space cavity by default for faster performance. */ - v3d->shading.cavity_type = V3D_SHADING_CAVITY_CURVATURE; - v3d->shading.flag |= V3D_SHADING_SPECULAR_HIGHLIGHT; - v3d->overlay.texture_paint_mode_opacity = 1.0f; - v3d->overlay.weight_paint_mode_opacity = 1.0f; - v3d->overlay.vertex_paint_mode_opacity = 1.0f; - /* Use dimmed selected edges. */ - v3d->overlay.edit_flag &= ~V3D_OVERLAY_EDIT_EDGES; - /* grease pencil settings */ - v3d->vertex_opacity = 1.0f; - v3d->gp_flag |= V3D_GP_SHOW_EDIT_LINES; - /* Remove dither pattern in wireframe mode. */ - v3d->shading.xray_alpha_wire = 0.0f; - v3d->clip_start = 0.01f; - /* Skip startups that use the viewport color by default. */ - if (v3d->shading.background_type != V3D_SHADING_BACKGROUND_VIEWPORT) { - copy_v3_fl(v3d->shading.background_color, 0.05f); - } - /* Disable Curve Normals. */ - v3d->overlay.edit_flag &= ~V3D_OVERLAY_EDIT_CU_NORMALS; - v3d->overlay.normals_constant_screen_size = 7.0f; - } - else if (area->spacetype == SPACE_CLIP) { - SpaceClip *sclip = area->spacedata.first; - sclip->around = V3D_AROUND_CENTER_MEDIAN; - sclip->mask_info.blend_factor = 0.7f; - sclip->mask_info.draw_flag = MASK_DRAWFLAG_SPLINE; - } - } - - /* Show tool-header by default (for most cases at least, hide for others). */ - const bool hide_image_tool_header = STREQ(workspace_name, "Rendering"); - LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { - LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { - ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase : &sl->regionbase; - - LISTBASE_FOREACH (ARegion *, region, regionbase) { - if (region->regiontype == RGN_TYPE_TOOL_HEADER) { - if (((sl->spacetype == SPACE_IMAGE) && hide_image_tool_header) || - sl->spacetype == SPACE_SEQ) { - region->flag |= RGN_FLAG_HIDDEN; - } - else { - region->flag &= ~(RGN_FLAG_HIDDEN | RGN_FLAG_HIDDEN_BY_USER); - } - } - } - } - } - - /* 2D animation template. */ - if (app_template && STREQ(app_template, "2D_Animation")) { - LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { - if (area->spacetype == SPACE_ACTION) { - SpaceAction *saction = area->spacedata.first; - /* Enable Sliders. */ - saction->flag |= SACTION_SLIDERS; - } - else if (area->spacetype == SPACE_VIEW3D) { - View3D *v3d = area->spacedata.first; - /* Set Material Color by default. */ - v3d->shading.color_type = V3D_SHADING_MATERIAL_COLOR; - /* Enable Annotations. */ - v3d->flag2 |= V3D_SHOW_ANNOTATION; - } - } - } -} - -void BLO_update_defaults_workspace(WorkSpace *workspace, const char *app_template) -{ - LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) { - if (layout->screen) { - blo_update_defaults_screen(layout->screen, app_template, workspace->id.name + 2); - } - } - - if (blo_is_builtin_template(app_template)) { - /* Clear all tools to use default options instead, ignore the tool saved in the file. */ - while (!BLI_listbase_is_empty(&workspace->tools)) { - BKE_workspace_tool_remove(workspace, workspace->tools.first); - } - - /* For 2D animation template. */ - if (STREQ(workspace->id.name + 2, "Drawing")) { - workspace->object_mode = OB_MODE_PAINT_GPENCIL; - } - - /* For Sculpting template. */ - if (STREQ(workspace->id.name + 2, "Sculpting")) { - LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) { - bScreen *screen = layout->screen; - if (screen) { - LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { - LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { - if (area->spacetype == SPACE_VIEW3D) { - View3D *v3d = area->spacedata.first; - v3d->shading.flag &= ~V3D_SHADING_CAVITY; - copy_v3_fl(v3d->shading.single_color, 1.0f); - STRNCPY(v3d->shading.matcap, "basic_1"); - } - } - } - } - } - } - } -} - -static void blo_update_defaults_scene(Main *bmain, Scene *scene) -{ - BLI_strncpy(scene->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(scene->r.engine)); - - scene->r.cfra = 1.0f; - - /* Don't enable compositing nodes. */ - if (scene->nodetree) { - ntreeFreeEmbeddedTree(scene->nodetree); - MEM_freeN(scene->nodetree); - scene->nodetree = NULL; - scene->use_nodes = false; - } - - /* Rename render layers. */ - BKE_view_layer_rename(bmain, scene, scene->view_layers.first, "ViewLayer"); - - /* Disable Z pass by default. */ - LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { - view_layer->passflag &= ~SCE_PASS_Z; - } - - /* New EEVEE defaults. */ - scene->eevee.bloom_intensity = 0.05f; - scene->eevee.bloom_clamp = 0.0f; - scene->eevee.motion_blur_shutter = 0.5f; - - copy_v3_v3(scene->display.light_direction, (float[3]){M_SQRT1_3, M_SQRT1_3, M_SQRT1_3}); - copy_v2_fl2(scene->safe_areas.title, 0.1f, 0.05f); - copy_v2_fl2(scene->safe_areas.action, 0.035f, 0.035f); - - /* Change default cube-map quality. */ - scene->eevee.gi_filter_quality = 3.0f; - - /* Enable Soft Shadows by default. */ - scene->eevee.flag |= SCE_EEVEE_SHADOW_SOFT; - - /* Be sure `curfalloff` and primitive are initialized. */ - ToolSettings *ts = scene->toolsettings; - if (ts->gp_sculpt.cur_falloff == NULL) { - ts->gp_sculpt.cur_falloff = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); - CurveMapping *gp_falloff_curve = ts->gp_sculpt.cur_falloff; - BKE_curvemapping_init(gp_falloff_curve); - BKE_curvemap_reset(gp_falloff_curve->cm, - &gp_falloff_curve->clipr, - CURVE_PRESET_GAUSS, - CURVEMAP_SLOPE_POSITIVE); - } - if (ts->gp_sculpt.cur_primitive == NULL) { - ts->gp_sculpt.cur_primitive = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); - CurveMapping *gp_primitive_curve = ts->gp_sculpt.cur_primitive; - BKE_curvemapping_init(gp_primitive_curve); - BKE_curvemap_reset(gp_primitive_curve->cm, - &gp_primitive_curve->clipr, - CURVE_PRESET_BELL, - CURVEMAP_SLOPE_POSITIVE); - } - - if (ts->sculpt) { - ts->sculpt->paint.symmetry_flags |= PAINT_SYMMETRY_FEATHER; - } - - /* Correct default startup UV's. */ - Mesh *me = BLI_findstring(&bmain->meshes, "Cube", offsetof(ID, name) + 2); - if (me && (me->totloop == 24) && CustomData_has_layer(&me->ldata, CD_MLOOPUV)) { - MLoopUV *mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV); - const float uv_values[24][2] = { - {0.625, 0.50}, {0.875, 0.50}, {0.875, 0.75}, {0.625, 0.75}, {0.375, 0.75}, {0.625, 0.75}, - {0.625, 1.00}, {0.375, 1.00}, {0.375, 0.00}, {0.625, 0.00}, {0.625, 0.25}, {0.375, 0.25}, - {0.125, 0.50}, {0.375, 0.50}, {0.375, 0.75}, {0.125, 0.75}, {0.375, 0.50}, {0.625, 0.50}, - {0.625, 0.75}, {0.375, 0.75}, {0.375, 0.25}, {0.625, 0.25}, {0.625, 0.50}, {0.375, 0.50}, - }; - for (int i = 0; i < ARRAY_SIZE(uv_values); i++) { - copy_v2_v2(mloopuv[i].uv, uv_values[i]); - } - } - - /* Make sure that the curve profile is initialized */ - if (ts->custom_bevel_profile_preset == NULL) { - ts->custom_bevel_profile_preset = BKE_curveprofile_add(PROF_PRESET_LINE); - } - - /* Clear ID properties so Cycles gets defaults. */ - IDProperty *idprop = IDP_GetProperties(&scene->id, false); - if (idprop) { - IDP_ClearProperty(idprop); - } -} - -void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) -{ - /* For all app templates. */ - for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { - BLO_update_defaults_workspace(workspace, app_template); - } - - /* New grease pencil brushes and vertex paint setup. */ - { - /* Update Grease Pencil brushes. */ - Brush *brush; - - /* Pencil brush. */ - do_versions_rename_id(bmain, ID_BR, "Draw Pencil", "Pencil"); - - /* Pen brush. */ - do_versions_rename_id(bmain, ID_BR, "Draw Pen", "Pen"); - - /* Pen Soft brush. */ - brush = (Brush *)do_versions_rename_id(bmain, ID_BR, "Draw Soft", "Pencil Soft"); - if (brush) { - brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PEN; - } - - /* Ink Pen brush. */ - do_versions_rename_id(bmain, ID_BR, "Draw Ink", "Ink Pen"); - - /* Ink Pen Rough brush. */ - do_versions_rename_id(bmain, ID_BR, "Draw Noise", "Ink Pen Rough"); - - /* Marker Bold brush. */ - do_versions_rename_id(bmain, ID_BR, "Draw Marker", "Marker Bold"); - - /* Marker Chisel brush. */ - do_versions_rename_id(bmain, ID_BR, "Draw Block", "Marker Chisel"); - - /* Remove useless Fill Area.001 brush. */ - brush = BLI_findstring(&bmain->brushes, "Fill Area.001", offsetof(ID, name) + 2); - if (brush) { - BKE_id_delete(bmain, brush); - } - - /* Rename and fix materials and enable default object lights on. */ - if (app_template && STREQ(app_template, "2D_Animation")) { - Material *ma = NULL; - do_versions_rename_id(bmain, ID_MA, "Black", "Solid Stroke"); - do_versions_rename_id(bmain, ID_MA, "Red", "Squares Stroke"); - do_versions_rename_id(bmain, ID_MA, "Grey", "Solid Fill"); - do_versions_rename_id(bmain, ID_MA, "Black Dots", "Dots Stroke"); - - /* Dots Stroke. */ - ma = BLI_findstring(&bmain->materials, "Dots Stroke", offsetof(ID, name) + 2); - if (ma == NULL) { - ma = BKE_gpencil_material_add(bmain, "Dots Stroke"); - } - ma->gp_style->mode = GP_MATERIAL_MODE_DOT; - - /* Squares Stroke. */ - ma = BLI_findstring(&bmain->materials, "Squares Stroke", offsetof(ID, name) + 2); - if (ma == NULL) { - ma = BKE_gpencil_material_add(bmain, "Squares Stroke"); - } - ma->gp_style->mode = GP_MATERIAL_MODE_SQUARE; - - /* Change Solid Stroke settings. */ - ma = BLI_findstring(&bmain->materials, "Solid Stroke", offsetof(ID, name) + 2); - if (ma != NULL) { - ma->gp_style->mix_rgba[3] = 1.0f; - ma->gp_style->texture_offset[0] = -0.5f; - ma->gp_style->mix_factor = 0.5f; - } - - /* Change Solid Fill settings. */ - ma = BLI_findstring(&bmain->materials, "Solid Fill", offsetof(ID, name) + 2); - if (ma != NULL) { - ma->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW; - ma->gp_style->mix_rgba[3] = 1.0f; - ma->gp_style->texture_offset[0] = -0.5f; - ma->gp_style->mix_factor = 0.5f; - } - - Object *ob = BLI_findstring(&bmain->objects, "Stroke", offsetof(ID, name) + 2); - if (ob && ob->type == OB_GPENCIL) { - ob->dtx |= OB_USE_GPENCIL_LIGHTS; - } - } - - /* Reset all grease pencil brushes. */ - Scene *scene = bmain->scenes.first; - BKE_brush_gpencil_paint_presets(bmain, scene->toolsettings, true); - BKE_brush_gpencil_sculpt_presets(bmain, scene->toolsettings, true); - BKE_brush_gpencil_vertex_presets(bmain, scene->toolsettings, true); - BKE_brush_gpencil_weight_presets(bmain, scene->toolsettings, true); - - /* Ensure new Paint modes. */ - BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_VERTEX_GPENCIL); - BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_SCULPT_GPENCIL); - BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_WEIGHT_GPENCIL); - - /* Enable cursor. */ - GpPaint *gp_paint = scene->toolsettings->gp_paint; - gp_paint->paint.flags |= PAINT_SHOW_BRUSH; - - /* Ensure Palette by default. */ - BKE_gpencil_palette_ensure(bmain, scene); - } - - /* For builtin templates only. */ - if (!blo_is_builtin_template(app_template)) { - return; - } - - /* Workspaces. */ - LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) { - LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { - LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) { - WorkSpaceLayout *layout = BKE_workspace_active_layout_for_workspace_get( - win->workspace_hook, workspace); - /* Name all screens by their workspaces (avoids 'Default.###' names). */ - /* Default only has one window. */ - if (layout->screen) { - bScreen *screen = layout->screen; - if (!STREQ(screen->id.name + 2, workspace->id.name + 2)) { - BKE_main_namemap_remove_name(bmain, &screen->id, screen->id.name + 2); - BLI_strncpy(screen->id.name + 2, workspace->id.name + 2, sizeof(screen->id.name) - 2); - BLI_libblock_ensure_unique_name(bmain, screen->id.name); - } - } - - /* For some reason we have unused screens, needed until re-saving. - * Clear unused layouts because they're visible in the outliner & Python API. */ - LISTBASE_FOREACH_MUTABLE (WorkSpaceLayout *, layout_iter, &workspace->layouts) { - if (layout != layout_iter) { - BKE_workspace_layout_remove(bmain, workspace, layout_iter); - } - } - } - } - } - - /* Scenes */ - for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { - blo_update_defaults_scene(bmain, scene); - - if (app_template && STREQ(app_template, "Video_Editing")) { - /* Filmic is too slow, use standard until it is optimized. */ - STRNCPY(scene->view_settings.view_transform, "Standard"); - STRNCPY(scene->view_settings.look, "None"); - } - else { - /* AV Sync break physics sim caching, disable until that is fixed. */ - scene->audio.flag &= ~AUDIO_SYNC; - scene->flag &= ~SCE_FRAME_DROP; - } - - /* Change default selection mode for Grease Pencil. */ - if (app_template && STREQ(app_template, "2D_Animation")) { - ToolSettings *ts = scene->toolsettings; - ts->gpencil_selectmode_edit = GP_SELECTMODE_STROKE; - } - } - - /* Objects */ - do_versions_rename_id(bmain, ID_OB, "Lamp", "Light"); - do_versions_rename_id(bmain, ID_LA, "Lamp", "Light"); - - if (app_template && STREQ(app_template, "2D_Animation")) { - for (Object *object = bmain->objects.first; object; object = object->id.next) { - if (object->type == OB_GPENCIL) { - /* Set grease pencil object in drawing mode */ - bGPdata *gpd = (bGPdata *)object->data; - object->mode = OB_MODE_PAINT_GPENCIL; - gpd->flag |= GP_DATA_STROKE_PAINTMODE; - break; - } - } - } - - for (Mesh *mesh = bmain->meshes.first; mesh; mesh = mesh->id.next) { - /* Match default for new meshes. */ - mesh->smoothresh = DEG2RADF(30); - /* Match voxel remesher options for all existing meshes in templates. */ - mesh->flag |= ME_REMESH_REPROJECT_VOLUME | ME_REMESH_REPROJECT_PAINT_MASK | - ME_REMESH_REPROJECT_SCULPT_FACE_SETS | ME_REMESH_REPROJECT_VERTEX_COLORS; - - /* For Sculpting template. */ - if (app_template && STREQ(app_template, "Sculpting")) { - mesh->remesh_voxel_size = 0.035f; - BKE_mesh_smooth_flag_set(mesh, false); - } - else { - /* Remove sculpt-mask data in default mesh objects for all non-sculpt templates. */ - CustomData_free_layers(&mesh->vdata, CD_PAINT_MASK, mesh->totvert); - CustomData_free_layers(&mesh->ldata, CD_GRID_PAINT_MASK, mesh->totloop); - } - } - - for (Camera *camera = bmain->cameras.first; camera; camera = camera->id.next) { - /* Initialize to a useful value. */ - camera->dof.focus_distance = 10.0f; - camera->dof.aperture_fstop = 2.8f; - } - - for (Light *light = bmain->lights.first; light; light = light->id.next) { - /* Fix lights defaults. */ - light->clipsta = 0.05f; - light->att_dist = 40.0f; - } - - /* Materials */ - for (Material *ma = bmain->materials.first; ma; ma = ma->id.next) { - /* Update default material to be a bit more rough. */ - ma->roughness = 0.5f; - - if (ma->nodetree) { - LISTBASE_FOREACH (bNode *, node, &ma->nodetree->nodes) { - if (node->type == SH_NODE_BSDF_PRINCIPLED) { - bNodeSocket *roughness_socket = nodeFindSocket(node, SOCK_IN, "Roughness"); - bNodeSocketValueFloat *roughness_data = roughness_socket->default_value; - roughness_data->value = 0.5f; - node->custom2 = SHD_SUBSURFACE_RANDOM_WALK; - BKE_ntree_update_tag_node_property(ma->nodetree, node); - } - else if (node->type == SH_NODE_SUBSURFACE_SCATTERING) { - node->custom1 = SHD_SUBSURFACE_RANDOM_WALK; - BKE_ntree_update_tag_node_property(ma->nodetree, node); - } - } - } - } - - /* Brushes */ - { - /* Enable for UV sculpt (other brush types will be created as needed), - * without this the grab brush will be active but not selectable from the list. */ - const char *brush_name = "Grab"; - Brush *brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); - if (brush) { - brush->ob_mode |= OB_MODE_EDIT; - } - } - - for (Brush *brush = bmain->brushes.first; brush; brush = brush->id.next) { - brush->blur_kernel_radius = 2; - - /* Use full strength for all non-sculpt brushes, - * when painting we want to use full color/weight always. - * - * Note that sculpt is an exception, - * its values are overwritten by #BKE_brush_sculpt_reset below. */ - brush->alpha = 1.0; - - /* Enable antialiasing by default */ - brush->sampling_flag |= BRUSH_PAINT_ANTIALIASING; - } - - { - /* Change the spacing of the Smear brush to 3.0% */ - const char *brush_name; - Brush *brush; - - brush_name = "Smear"; - brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); - if (brush) { - brush->spacing = 3.0; - } - - brush_name = "Draw Sharp"; - brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); - if (!brush) { - brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); - id_us_min(&brush->id); - brush->sculpt_tool = SCULPT_TOOL_DRAW_SHARP; - } - - brush_name = "Elastic Deform"; - brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); - if (!brush) { - brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); - id_us_min(&brush->id); - brush->sculpt_tool = SCULPT_TOOL_ELASTIC_DEFORM; - } - - brush_name = "Pose"; - brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); - if (!brush) { - brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); - id_us_min(&brush->id); - brush->sculpt_tool = SCULPT_TOOL_POSE; - } - - brush_name = "Multi-plane Scrape"; - brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); - if (!brush) { - brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); - id_us_min(&brush->id); - brush->sculpt_tool = SCULPT_TOOL_MULTIPLANE_SCRAPE; - } - - brush_name = "Clay Thumb"; - brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); - if (!brush) { - brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); - id_us_min(&brush->id); - brush->sculpt_tool = SCULPT_TOOL_CLAY_THUMB; - } - - brush_name = "Cloth"; - brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); - if (!brush) { - brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); - id_us_min(&brush->id); - brush->sculpt_tool = SCULPT_TOOL_CLOTH; - } - - brush_name = "Slide Relax"; - brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); - if (!brush) { - brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); - id_us_min(&brush->id); - brush->sculpt_tool = SCULPT_TOOL_SLIDE_RELAX; - } - - brush_name = "Paint"; - brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); - if (!brush) { - brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); - id_us_min(&brush->id); - brush->sculpt_tool = SCULPT_TOOL_PAINT; - } - - brush_name = "Smear"; - brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); - if (!brush) { - brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); - id_us_min(&brush->id); - brush->sculpt_tool = SCULPT_TOOL_SMEAR; - } - - brush_name = "Boundary"; - brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); - if (!brush) { - brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); - id_us_min(&brush->id); - brush->sculpt_tool = SCULPT_TOOL_BOUNDARY; - } - - brush_name = "Simplify"; - brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); - if (!brush) { - brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); - id_us_min(&brush->id); - brush->sculpt_tool = SCULPT_TOOL_SIMPLIFY; - } - - brush_name = "Draw Face Sets"; - brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); - if (!brush) { - brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); - id_us_min(&brush->id); - brush->sculpt_tool = SCULPT_TOOL_DRAW_FACE_SETS; - } - - brush_name = "Multires Displacement Eraser"; - brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); - if (!brush) { - brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); - id_us_min(&brush->id); - brush->sculpt_tool = SCULPT_TOOL_DISPLACEMENT_ERASER; - } - - brush_name = "Multires Displacement Smear"; - brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); - if (!brush) { - brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); - id_us_min(&brush->id); - brush->sculpt_tool = SCULPT_TOOL_DISPLACEMENT_SMEAR; - } - - /* Use the same tool icon color in the brush cursor */ - for (brush = bmain->brushes.first; brush; brush = brush->id.next) { - if (brush->ob_mode & OB_MODE_SCULPT) { - BLI_assert(brush->sculpt_tool != 0); - BKE_brush_sculpt_reset(brush); - } - } - } -} diff --git a/source/blender/blenloader/intern/versioning_defaults.cc b/source/blender/blenloader/intern/versioning_defaults.cc new file mode 100644 index 00000000000..8917654de85 --- /dev/null +++ b/source/blender/blenloader/intern/versioning_defaults.cc @@ -0,0 +1,788 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup blenloader + * + * This file handles updating the `startup.blend`, this is used when reading old files. + * + * Unlike regular versioning this makes changes that ensure the startup file + * has brushes and other presets setup to take advantage of newer features. + * + * To update preference defaults see `userdef_default.c`. + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_math_vec_types.hh" +#include "BLI_string.h" +#include "BLI_system.h" +#include "BLI_utildefines.h" + +#include "DNA_camera_types.h" +#include "DNA_curveprofile_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_light_types.h" +#include "DNA_mask_types.h" +#include "DNA_material_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_userdef_types.h" +#include "DNA_windowmanager_types.h" +#include "DNA_workspace_types.h" + +#include "BKE_appdir.h" +#include "BKE_brush.h" +#include "BKE_colortools.h" +#include "BKE_curveprofile.h" +#include "BKE_customdata.h" +#include "BKE_gpencil.h" +#include "BKE_idprop.h" +#include "BKE_layer.h" +#include "BKE_lib_id.h" +#include "BKE_main.h" +#include "BKE_main_namemap.h" +#include "BKE_material.h" +#include "BKE_mesh.h" +#include "BKE_node.h" +#include "BKE_node_tree_update.h" +#include "BKE_paint.h" +#include "BKE_screen.h" +#include "BKE_workspace.h" + +#include "BLO_readfile.h" + +#include "BLT_translation.h" + +#include "versioning_common.h" + +/* Make preferences read-only, use versioning_userdef.c. */ +#define U (*((const UserDef *)&U)) + +static bool blo_is_builtin_template(const char *app_template) +{ + /* For all builtin templates shipped with Blender. */ + return ( + !app_template || + STR_ELEM(app_template, N_("2D_Animation"), N_("Sculpting"), N_("VFX"), N_("Video_Editing"))); +} + +static void blo_update_defaults_screen(bScreen *screen, + const char *app_template, + const char *workspace_name) +{ + /* For all app templates. */ + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + /* Some toolbars have been saved as initialized, + * we don't want them to have odd zoom-level or scrolling set, see: T47047 */ + if (ELEM(region->regiontype, RGN_TYPE_UI, RGN_TYPE_TOOLS, RGN_TYPE_TOOL_PROPS)) { + region->v2d.flag &= ~V2D_IS_INIT; + } + } + + /* Set default folder. */ + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + if (sl->spacetype == SPACE_FILE) { + SpaceFile *sfile = (SpaceFile *)sl; + if (sfile->params) { + const char *dir_default = BKE_appdir_folder_default(); + if (dir_default) { + STRNCPY(sfile->params->dir, dir_default); + sfile->params->file[0] = '\0'; + } + } + } + } + } + + /* For builtin templates only. */ + if (!blo_is_builtin_template(app_template)) { + return; + } + + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + /* Remove all stored panels, we want to use defaults + * (order, open/closed) as defined by UI code here! */ + BKE_area_region_panels_free(®ion->panels); + BLI_freelistN(®ion->panels_category_active); + + /* Reset size so it uses consistent defaults from the region types. */ + region->sizex = 0; + region->sizey = 0; + } + + if (area->spacetype == SPACE_IMAGE) { + if (STREQ(workspace_name, "UV Editing")) { + SpaceImage *sima = static_cast(area->spacedata.first); + if (sima->mode == SI_MODE_VIEW) { + sima->mode = SI_MODE_UV; + } + } + } + else if (area->spacetype == SPACE_ACTION) { + /* Show markers region, hide channels and collapse summary in timelines. */ + SpaceAction *saction = static_cast(area->spacedata.first); + saction->flag |= SACTION_SHOW_MARKERS; + if (saction->mode == SACTCONT_TIMELINE) { + saction->ads.flag |= ADS_FLAG_SUMMARY_COLLAPSED; + + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + if (region->regiontype == RGN_TYPE_CHANNELS) { + region->flag |= RGN_FLAG_HIDDEN; + } + } + } + else { + /* Open properties panel by default. */ + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + if (region->regiontype == RGN_TYPE_UI) { + region->flag &= ~RGN_FLAG_HIDDEN; + } + } + } + } + else if (area->spacetype == SPACE_GRAPH) { + SpaceGraph *sipo = static_cast(area->spacedata.first); + sipo->flag |= SIPO_SHOW_MARKERS; + } + else if (area->spacetype == SPACE_NLA) { + SpaceNla *snla = static_cast(area->spacedata.first); + snla->flag |= SNLA_SHOW_MARKERS; + } + else if (area->spacetype == SPACE_SEQ) { + SpaceSeq *seq = static_cast(area->spacedata.first); + seq->flag |= SEQ_SHOW_MARKERS | SEQ_ZOOM_TO_FIT | SEQ_USE_PROXIES | SEQ_SHOW_OVERLAY; + seq->render_size = SEQ_RENDER_SIZE_PROXY_100; + seq->timeline_overlay.flag |= SEQ_TIMELINE_SHOW_STRIP_SOURCE | SEQ_TIMELINE_SHOW_STRIP_NAME | + SEQ_TIMELINE_SHOW_STRIP_DURATION | SEQ_TIMELINE_SHOW_GRID | + SEQ_TIMELINE_SHOW_STRIP_COLOR_TAG; + seq->preview_overlay.flag |= SEQ_PREVIEW_SHOW_OUTLINE_SELECTED; + } + else if (area->spacetype == SPACE_TEXT) { + /* Show syntax and line numbers in Script workspace text editor. */ + SpaceText *stext = static_cast(area->spacedata.first); + stext->showsyntax = true; + stext->showlinenrs = true; + } + else if (area->spacetype == SPACE_VIEW3D) { + View3D *v3d = static_cast(area->spacedata.first); + /* Screen space cavity by default for faster performance. */ + v3d->shading.cavity_type = V3D_SHADING_CAVITY_CURVATURE; + v3d->shading.flag |= V3D_SHADING_SPECULAR_HIGHLIGHT; + v3d->overlay.texture_paint_mode_opacity = 1.0f; + v3d->overlay.weight_paint_mode_opacity = 1.0f; + v3d->overlay.vertex_paint_mode_opacity = 1.0f; + /* Use dimmed selected edges. */ + v3d->overlay.edit_flag &= ~V3D_OVERLAY_EDIT_EDGES; + /* grease pencil settings */ + v3d->vertex_opacity = 1.0f; + v3d->gp_flag |= V3D_GP_SHOW_EDIT_LINES; + /* Remove dither pattern in wireframe mode. */ + v3d->shading.xray_alpha_wire = 0.0f; + v3d->clip_start = 0.01f; + /* Skip startups that use the viewport color by default. */ + if (v3d->shading.background_type != V3D_SHADING_BACKGROUND_VIEWPORT) { + copy_v3_fl(v3d->shading.background_color, 0.05f); + } + /* Disable Curve Normals. */ + v3d->overlay.edit_flag &= ~V3D_OVERLAY_EDIT_CU_NORMALS; + v3d->overlay.normals_constant_screen_size = 7.0f; + } + else if (area->spacetype == SPACE_CLIP) { + SpaceClip *sclip = static_cast(area->spacedata.first); + sclip->around = V3D_AROUND_CENTER_MEDIAN; + sclip->mask_info.blend_factor = 0.7f; + sclip->mask_info.draw_flag = MASK_DRAWFLAG_SPLINE; + } + } + + /* Show tool-header by default (for most cases at least, hide for others). */ + const bool hide_image_tool_header = STREQ(workspace_name, "Rendering"); + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + ListBase *regionbase = (sl == static_cast(area->spacedata.first)) ? + &area->regionbase : + &sl->regionbase; + + LISTBASE_FOREACH (ARegion *, region, regionbase) { + if (region->regiontype == RGN_TYPE_TOOL_HEADER) { + if (((sl->spacetype == SPACE_IMAGE) && hide_image_tool_header) || + sl->spacetype == SPACE_SEQ) { + region->flag |= RGN_FLAG_HIDDEN; + } + else { + region->flag &= ~(RGN_FLAG_HIDDEN | RGN_FLAG_HIDDEN_BY_USER); + } + } + } + } + } + + /* 2D animation template. */ + if (app_template && STREQ(app_template, "2D_Animation")) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + if (area->spacetype == SPACE_ACTION) { + SpaceAction *saction = static_cast(area->spacedata.first); + /* Enable Sliders. */ + saction->flag |= SACTION_SLIDERS; + } + else if (area->spacetype == SPACE_VIEW3D) { + View3D *v3d = static_cast(area->spacedata.first); + /* Set Material Color by default. */ + v3d->shading.color_type = V3D_SHADING_MATERIAL_COLOR; + /* Enable Annotations. */ + v3d->flag2 |= V3D_SHOW_ANNOTATION; + } + } + } +} + +void BLO_update_defaults_workspace(WorkSpace *workspace, const char *app_template) +{ + LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) { + if (layout->screen) { + blo_update_defaults_screen(layout->screen, app_template, workspace->id.name + 2); + } + } + + if (blo_is_builtin_template(app_template)) { + /* Clear all tools to use default options instead, ignore the tool saved in the file. */ + while (!BLI_listbase_is_empty(&workspace->tools)) { + BKE_workspace_tool_remove(workspace, static_cast(workspace->tools.first)); + } + + /* For 2D animation template. */ + if (STREQ(workspace->id.name + 2, "Drawing")) { + workspace->object_mode = OB_MODE_PAINT_GPENCIL; + } + + /* For Sculpting template. */ + if (STREQ(workspace->id.name + 2, "Sculpting")) { + LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) { + bScreen *screen = layout->screen; + if (screen) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + if (area->spacetype == SPACE_VIEW3D) { + View3D *v3d = static_cast(area->spacedata.first); + v3d->shading.flag &= ~V3D_SHADING_CAVITY; + copy_v3_fl(v3d->shading.single_color, 1.0f); + STRNCPY(v3d->shading.matcap, "basic_1"); + } + } + } + } + } + } + } +} + +static void blo_update_defaults_scene(Main *bmain, Scene *scene) +{ + BLI_strncpy(scene->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(scene->r.engine)); + + scene->r.cfra = 1.0f; + + /* Don't enable compositing nodes. */ + if (scene->nodetree) { + ntreeFreeEmbeddedTree(scene->nodetree); + MEM_freeN(scene->nodetree); + scene->nodetree = NULL; + scene->use_nodes = false; + } + + /* Rename render layers. */ + BKE_view_layer_rename( + bmain, scene, static_cast(scene->view_layers.first), "ViewLayer"); + + /* Disable Z pass by default. */ + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { + view_layer->passflag &= ~SCE_PASS_Z; + } + + /* New EEVEE defaults. */ + scene->eevee.bloom_intensity = 0.05f; + scene->eevee.bloom_clamp = 0.0f; + scene->eevee.motion_blur_shutter = 0.5f; + + copy_v3_v3(scene->display.light_direction, blender::float3(M_SQRT1_3)); + copy_v2_fl2(scene->safe_areas.title, 0.1f, 0.05f); + copy_v2_fl2(scene->safe_areas.action, 0.035f, 0.035f); + + /* Change default cube-map quality. */ + scene->eevee.gi_filter_quality = 3.0f; + + /* Enable Soft Shadows by default. */ + scene->eevee.flag |= SCE_EEVEE_SHADOW_SOFT; + + /* Be sure `curfalloff` and primitive are initialized. */ + ToolSettings *ts = scene->toolsettings; + if (ts->gp_sculpt.cur_falloff == NULL) { + ts->gp_sculpt.cur_falloff = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + CurveMapping *gp_falloff_curve = ts->gp_sculpt.cur_falloff; + BKE_curvemapping_init(gp_falloff_curve); + BKE_curvemap_reset(gp_falloff_curve->cm, + &gp_falloff_curve->clipr, + CURVE_PRESET_GAUSS, + CURVEMAP_SLOPE_POSITIVE); + } + if (ts->gp_sculpt.cur_primitive == NULL) { + ts->gp_sculpt.cur_primitive = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + CurveMapping *gp_primitive_curve = ts->gp_sculpt.cur_primitive; + BKE_curvemapping_init(gp_primitive_curve); + BKE_curvemap_reset(gp_primitive_curve->cm, + &gp_primitive_curve->clipr, + CURVE_PRESET_BELL, + CURVEMAP_SLOPE_POSITIVE); + } + + if (ts->sculpt) { + ts->sculpt->paint.symmetry_flags |= PAINT_SYMMETRY_FEATHER; + } + + /* Correct default startup UV's. */ + Mesh *me = static_cast(BLI_findstring(&bmain->meshes, "Cube", offsetof(ID, name) + 2)); + if (me && (me->totloop == 24) && CustomData_has_layer(&me->ldata, CD_MLOOPUV)) { + MLoopUV *mloopuv = static_cast(CustomData_get_layer(&me->ldata, CD_MLOOPUV)); + const float uv_values[24][2] = { + {0.625, 0.50}, {0.875, 0.50}, {0.875, 0.75}, {0.625, 0.75}, {0.375, 0.75}, {0.625, 0.75}, + {0.625, 1.00}, {0.375, 1.00}, {0.375, 0.00}, {0.625, 0.00}, {0.625, 0.25}, {0.375, 0.25}, + {0.125, 0.50}, {0.375, 0.50}, {0.375, 0.75}, {0.125, 0.75}, {0.375, 0.50}, {0.625, 0.50}, + {0.625, 0.75}, {0.375, 0.75}, {0.375, 0.25}, {0.625, 0.25}, {0.625, 0.50}, {0.375, 0.50}, + }; + for (int i = 0; i < ARRAY_SIZE(uv_values); i++) { + copy_v2_v2(mloopuv[i].uv, uv_values[i]); + } + } + + /* Make sure that the curve profile is initialized */ + if (ts->custom_bevel_profile_preset == NULL) { + ts->custom_bevel_profile_preset = BKE_curveprofile_add(PROF_PRESET_LINE); + } + + /* Clear ID properties so Cycles gets defaults. */ + IDProperty *idprop = IDP_GetProperties(&scene->id, false); + if (idprop) { + IDP_ClearProperty(idprop); + } +} + +void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) +{ + /* For all app templates. */ + LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) { + BLO_update_defaults_workspace(workspace, app_template); + } + + /* New grease pencil brushes and vertex paint setup. */ + { + /* Update Grease Pencil brushes. */ + Brush *brush; + + /* Pencil brush. */ + do_versions_rename_id(bmain, ID_BR, "Draw Pencil", "Pencil"); + + /* Pen brush. */ + do_versions_rename_id(bmain, ID_BR, "Draw Pen", "Pen"); + + /* Pen Soft brush. */ + brush = reinterpret_cast( + do_versions_rename_id(bmain, ID_BR, "Draw Soft", "Pencil Soft")); + if (brush) { + brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PEN; + } + + /* Ink Pen brush. */ + do_versions_rename_id(bmain, ID_BR, "Draw Ink", "Ink Pen"); + + /* Ink Pen Rough brush. */ + do_versions_rename_id(bmain, ID_BR, "Draw Noise", "Ink Pen Rough"); + + /* Marker Bold brush. */ + do_versions_rename_id(bmain, ID_BR, "Draw Marker", "Marker Bold"); + + /* Marker Chisel brush. */ + do_versions_rename_id(bmain, ID_BR, "Draw Block", "Marker Chisel"); + + /* Remove useless Fill Area.001 brush. */ + brush = static_cast( + BLI_findstring(&bmain->brushes, "Fill Area.001", offsetof(ID, name) + 2)); + if (brush) { + BKE_id_delete(bmain, brush); + } + + /* Rename and fix materials and enable default object lights on. */ + if (app_template && STREQ(app_template, "2D_Animation")) { + Material *ma = NULL; + do_versions_rename_id(bmain, ID_MA, "Black", "Solid Stroke"); + do_versions_rename_id(bmain, ID_MA, "Red", "Squares Stroke"); + do_versions_rename_id(bmain, ID_MA, "Grey", "Solid Fill"); + do_versions_rename_id(bmain, ID_MA, "Black Dots", "Dots Stroke"); + + /* Dots Stroke. */ + ma = static_cast( + BLI_findstring(&bmain->materials, "Dots Stroke", offsetof(ID, name) + 2)); + if (ma == NULL) { + ma = BKE_gpencil_material_add(bmain, "Dots Stroke"); + } + ma->gp_style->mode = GP_MATERIAL_MODE_DOT; + + /* Squares Stroke. */ + ma = static_cast( + BLI_findstring(&bmain->materials, "Squares Stroke", offsetof(ID, name) + 2)); + if (ma == NULL) { + ma = BKE_gpencil_material_add(bmain, "Squares Stroke"); + } + ma->gp_style->mode = GP_MATERIAL_MODE_SQUARE; + + /* Change Solid Stroke settings. */ + ma = static_cast( + BLI_findstring(&bmain->materials, "Solid Stroke", offsetof(ID, name) + 2)); + if (ma != NULL) { + ma->gp_style->mix_rgba[3] = 1.0f; + ma->gp_style->texture_offset[0] = -0.5f; + ma->gp_style->mix_factor = 0.5f; + } + + /* Change Solid Fill settings. */ + ma = static_cast( + BLI_findstring(&bmain->materials, "Solid Fill", offsetof(ID, name) + 2)); + if (ma != NULL) { + ma->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW; + ma->gp_style->mix_rgba[3] = 1.0f; + ma->gp_style->texture_offset[0] = -0.5f; + ma->gp_style->mix_factor = 0.5f; + } + + Object *ob = static_cast( + BLI_findstring(&bmain->objects, "Stroke", offsetof(ID, name) + 2)); + if (ob && ob->type == OB_GPENCIL) { + ob->dtx |= OB_USE_GPENCIL_LIGHTS; + } + } + + /* Reset all grease pencil brushes. */ + Scene *scene = static_cast(bmain->scenes.first); + BKE_brush_gpencil_paint_presets(bmain, scene->toolsettings, true); + BKE_brush_gpencil_sculpt_presets(bmain, scene->toolsettings, true); + BKE_brush_gpencil_vertex_presets(bmain, scene->toolsettings, true); + BKE_brush_gpencil_weight_presets(bmain, scene->toolsettings, true); + + /* Ensure new Paint modes. */ + BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_VERTEX_GPENCIL); + BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_SCULPT_GPENCIL); + BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_WEIGHT_GPENCIL); + + /* Enable cursor. */ + GpPaint *gp_paint = scene->toolsettings->gp_paint; + gp_paint->paint.flags |= PAINT_SHOW_BRUSH; + + /* Ensure Palette by default. */ + BKE_gpencil_palette_ensure(bmain, scene); + } + + /* For builtin templates only. */ + if (!blo_is_builtin_template(app_template)) { + return; + } + + /* Workspaces. */ + LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) { + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { + LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) { + WorkSpaceLayout *layout = BKE_workspace_active_layout_for_workspace_get( + win->workspace_hook, workspace); + /* Name all screens by their workspaces (avoids 'Default.###' names). */ + /* Default only has one window. */ + if (layout->screen) { + bScreen *screen = layout->screen; + if (!STREQ(screen->id.name + 2, workspace->id.name + 2)) { + BKE_main_namemap_remove_name(bmain, &screen->id, screen->id.name + 2); + BLI_strncpy(screen->id.name + 2, workspace->id.name + 2, sizeof(screen->id.name) - 2); + BLI_libblock_ensure_unique_name(bmain, screen->id.name); + } + } + + /* For some reason we have unused screens, needed until re-saving. + * Clear unused layouts because they're visible in the outliner & Python API. */ + LISTBASE_FOREACH_MUTABLE (WorkSpaceLayout *, layout_iter, &workspace->layouts) { + if (layout != layout_iter) { + BKE_workspace_layout_remove(bmain, workspace, layout_iter); + } + } + } + } + } + + /* Scenes */ + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + blo_update_defaults_scene(bmain, scene); + + if (app_template && STREQ(app_template, "Video_Editing")) { + /* Filmic is too slow, use standard until it is optimized. */ + STRNCPY(scene->view_settings.view_transform, "Standard"); + STRNCPY(scene->view_settings.look, "None"); + } + else { + /* AV Sync break physics sim caching, disable until that is fixed. */ + scene->audio.flag &= ~AUDIO_SYNC; + scene->flag &= ~SCE_FRAME_DROP; + } + + /* Change default selection mode for Grease Pencil. */ + if (app_template && STREQ(app_template, "2D_Animation")) { + ToolSettings *ts = scene->toolsettings; + ts->gpencil_selectmode_edit = GP_SELECTMODE_STROKE; + } + } + + /* Objects */ + do_versions_rename_id(bmain, ID_OB, "Lamp", "Light"); + do_versions_rename_id(bmain, ID_LA, "Lamp", "Light"); + + if (app_template && STREQ(app_template, "2D_Animation")) { + LISTBASE_FOREACH (Object *, object, &bmain->objects) { + if (object->type == OB_GPENCIL) { + /* Set grease pencil object in drawing mode */ + bGPdata *gpd = (bGPdata *)object->data; + object->mode = OB_MODE_PAINT_GPENCIL; + gpd->flag |= GP_DATA_STROKE_PAINTMODE; + break; + } + } + } + + LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) { + /* Match default for new meshes. */ + mesh->smoothresh = DEG2RADF(30); + /* Match voxel remesher options for all existing meshes in templates. */ + mesh->flag |= ME_REMESH_REPROJECT_VOLUME | ME_REMESH_REPROJECT_PAINT_MASK | + ME_REMESH_REPROJECT_SCULPT_FACE_SETS | ME_REMESH_REPROJECT_VERTEX_COLORS; + + /* For Sculpting template. */ + if (app_template && STREQ(app_template, "Sculpting")) { + mesh->remesh_voxel_size = 0.035f; + BKE_mesh_smooth_flag_set(mesh, false); + } + else { + /* Remove sculpt-mask data in default mesh objects for all non-sculpt templates. */ + CustomData_free_layers(&mesh->vdata, CD_PAINT_MASK, mesh->totvert); + CustomData_free_layers(&mesh->ldata, CD_GRID_PAINT_MASK, mesh->totloop); + } + } + + LISTBASE_FOREACH (Camera *, camera, &bmain->cameras) { + /* Initialize to a useful value. */ + camera->dof.focus_distance = 10.0f; + camera->dof.aperture_fstop = 2.8f; + } + + LISTBASE_FOREACH (Light *, light, &bmain->lights) { + /* Fix lights defaults. */ + light->clipsta = 0.05f; + light->att_dist = 40.0f; + } + + /* Materials */ + LISTBASE_FOREACH (Material *, ma, &bmain->materials) { + /* Update default material to be a bit more rough. */ + ma->roughness = 0.5f; + + if (ma->nodetree) { + LISTBASE_FOREACH (bNode *, node, &ma->nodetree->nodes) { + if (node->type == SH_NODE_BSDF_PRINCIPLED) { + bNodeSocket *roughness_socket = nodeFindSocket(node, SOCK_IN, "Roughness"); + bNodeSocketValueFloat *roughness_data = static_cast( + roughness_socket->default_value); + roughness_data->value = 0.5f; + node->custom2 = SHD_SUBSURFACE_RANDOM_WALK; + BKE_ntree_update_tag_node_property(ma->nodetree, node); + } + else if (node->type == SH_NODE_SUBSURFACE_SCATTERING) { + node->custom1 = SHD_SUBSURFACE_RANDOM_WALK; + BKE_ntree_update_tag_node_property(ma->nodetree, node); + } + } + } + } + + /* Brushes */ + { + /* Enable for UV sculpt (other brush types will be created as needed), + * without this the grab brush will be active but not selectable from the list. */ + const char *brush_name = "Grab"; + Brush *brush = static_cast( + BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2)); + if (brush) { + brush->ob_mode |= OB_MODE_EDIT; + } + } + + LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) { + brush->blur_kernel_radius = 2; + + /* Use full strength for all non-sculpt brushes, + * when painting we want to use full color/weight always. + * + * Note that sculpt is an exception, + * its values are overwritten by #BKE_brush_sculpt_reset below. */ + brush->alpha = 1.0; + + /* Enable antialiasing by default */ + brush->sampling_flag |= BRUSH_PAINT_ANTIALIASING; + } + + { + /* Change the spacing of the Smear brush to 3.0% */ + const char *brush_name; + Brush *brush; + + brush_name = "Smear"; + brush = static_cast( + BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2)); + if (brush) { + brush->spacing = 3.0; + } + + brush_name = "Draw Sharp"; + brush = static_cast( + BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2)); + if (!brush) { + brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); + id_us_min(&brush->id); + brush->sculpt_tool = SCULPT_TOOL_DRAW_SHARP; + } + + brush_name = "Elastic Deform"; + brush = static_cast( + BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2)); + if (!brush) { + brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); + id_us_min(&brush->id); + brush->sculpt_tool = SCULPT_TOOL_ELASTIC_DEFORM; + } + + brush_name = "Pose"; + brush = static_cast( + BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2)); + if (!brush) { + brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); + id_us_min(&brush->id); + brush->sculpt_tool = SCULPT_TOOL_POSE; + } + + brush_name = "Multi-plane Scrape"; + brush = static_cast( + BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2)); + if (!brush) { + brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); + id_us_min(&brush->id); + brush->sculpt_tool = SCULPT_TOOL_MULTIPLANE_SCRAPE; + } + + brush_name = "Clay Thumb"; + brush = static_cast( + BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2)); + if (!brush) { + brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); + id_us_min(&brush->id); + brush->sculpt_tool = SCULPT_TOOL_CLAY_THUMB; + } + + brush_name = "Cloth"; + brush = static_cast( + BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2)); + if (!brush) { + brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); + id_us_min(&brush->id); + brush->sculpt_tool = SCULPT_TOOL_CLOTH; + } + + brush_name = "Slide Relax"; + brush = static_cast( + BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2)); + if (!brush) { + brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); + id_us_min(&brush->id); + brush->sculpt_tool = SCULPT_TOOL_SLIDE_RELAX; + } + + brush_name = "Paint"; + brush = static_cast( + BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2)); + if (!brush) { + brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); + id_us_min(&brush->id); + brush->sculpt_tool = SCULPT_TOOL_PAINT; + } + + brush_name = "Smear"; + brush = static_cast( + BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2)); + if (!brush) { + brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); + id_us_min(&brush->id); + brush->sculpt_tool = SCULPT_TOOL_SMEAR; + } + + brush_name = "Boundary"; + brush = static_cast( + BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2)); + if (!brush) { + brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); + id_us_min(&brush->id); + brush->sculpt_tool = SCULPT_TOOL_BOUNDARY; + } + + brush_name = "Simplify"; + brush = static_cast( + BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2)); + if (!brush) { + brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); + id_us_min(&brush->id); + brush->sculpt_tool = SCULPT_TOOL_SIMPLIFY; + } + + brush_name = "Draw Face Sets"; + brush = static_cast( + BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2)); + if (!brush) { + brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); + id_us_min(&brush->id); + brush->sculpt_tool = SCULPT_TOOL_DRAW_FACE_SETS; + } + + brush_name = "Multires Displacement Eraser"; + brush = static_cast( + BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2)); + if (!brush) { + brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); + id_us_min(&brush->id); + brush->sculpt_tool = SCULPT_TOOL_DISPLACEMENT_ERASER; + } + + brush_name = "Multires Displacement Smear"; + brush = static_cast( + BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2)); + if (!brush) { + brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); + id_us_min(&brush->id); + brush->sculpt_tool = SCULPT_TOOL_DISPLACEMENT_SMEAR; + } + + /* Use the same tool icon color in the brush cursor */ + LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) { + if (brush->ob_mode & OB_MODE_SCULPT) { + BLI_assert(brush->sculpt_tool != 0); + BKE_brush_sculpt_reset(brush); + } + } + } +} -- cgit v1.2.3 From e8291f4504d320ea1eac0601a9b99263fbf305e8 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 17 Oct 2022 13:11:50 -0500 Subject: Sculpt: Remove face sets from default cube As discussed in T101623, since face sets have become optionally stored, (see b5f7af31d6d474c3b4) the default cube shouldn't have face sets-- they should be created explicitly by the user instead. This may improve performance when modifying the default cube mesh. --- source/blender/blenloader/intern/versioning_defaults.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/blenloader/intern/versioning_defaults.cc b/source/blender/blenloader/intern/versioning_defaults.cc index 8917654de85..da23e9cb49f 100644 --- a/source/blender/blenloader/intern/versioning_defaults.cc +++ b/source/blender/blenloader/intern/versioning_defaults.cc @@ -37,6 +37,7 @@ #include "DNA_workspace_types.h" #include "BKE_appdir.h" +#include "BKE_attribute.hh" #include "BKE_brush.h" #include "BKE_colortools.h" #include "BKE_curveprofile.h" @@ -576,6 +577,7 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) CustomData_free_layers(&mesh->vdata, CD_PAINT_MASK, mesh->totvert); CustomData_free_layers(&mesh->ldata, CD_GRID_PAINT_MASK, mesh->totloop); } + mesh->attributes_for_write().remove(".sculpt_face_set"); } LISTBASE_FOREACH (Camera *, camera, &bmain->cameras) { -- cgit v1.2.3 From 161aa5e0d039577964d7080817e3df229aa153c0 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 17 Oct 2022 16:51:42 -0500 Subject: Fix T101882: Division by zero in mesh topology nodes A vertex might be connected to no edges or no faces. Most of these nodes worked fine in that case, but we might as well make that explicit and skip the sorting anyway. --- .../nodes/geometry/nodes/node_geo_mesh_topology_corners_of_vertex.cc | 4 ++++ .../nodes/geometry/nodes/node_geo_mesh_topology_edges_of_vertex.cc | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_vertex.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_vertex.cc index cce3f4e3648..036af2d3b93 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_vertex.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_vertex.cc @@ -93,6 +93,10 @@ class CornersOfVertInput final : public bke::MeshFieldInput { } const Span corners = vert_to_loop_map[vert_i]; + if (corners.is_empty()) { + corner_of_vertex[selection_i] = 0; + continue; + } /* Retrieve the connected edge indices as 64 bit integers for #materialize_compressed. */ corner_indices.reinitialize(corners.size()); diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_vertex.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_vertex.cc index 053ef61deed..f0cc191e217 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_vertex.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_vertex.cc @@ -93,6 +93,10 @@ class EdgesOfVertInput final : public bke::MeshFieldInput { } const Span edges = vert_to_edge_map[vert_i]; + if (edges.is_empty()) { + edge_of_vertex[selection_i] = 0; + continue; + } /* Retrieve the connected edge indices as 64 bit integers for #materialize_compressed. */ edge_indices.reinitialize(edges.size()); -- cgit v1.2.3 From 85875455b9171a602f57102bb4575f6e2c2a9b7f Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 17 Oct 2022 17:08:09 -0500 Subject: Fix T101872: Curves sculpt deform node crash with changed curve count There might be more or fewer curves in the input to the deform curves on surface node than the original, so the curve's surface UV coordinates need to be retrieved from the original curves. --- .../nodes/node_geo_deform_curves_on_surface.cc | 29 ++++++++++++---------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc index a12ae9bbb92..0932624bdc3 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc @@ -379,19 +379,22 @@ static void node_geo_exec(GeoNodeExecParams params) invalid_uv_count); /* Then also deform edit curve information for use in sculpt mode. */ const CurvesGeometry &curves_orig = CurvesGeometry::wrap(edit_hints->curves_id_orig.geometry); - deform_curves(curves_orig, - *surface_mesh_orig, - *surface_mesh_eval, - surface_uv_coords, - reverse_uv_sampler_orig, - reverse_uv_sampler_eval, - corner_normals_orig, - corner_normals_eval, - rest_positions, - transforms.surface_to_curves, - edit_hint_positions, - edit_hint_rotations, - invalid_uv_count); + const Span surface_uv_coords_orig = curves_orig.surface_uv_coords(); + if (!surface_uv_coords_orig.is_empty()) { + deform_curves(curves_orig, + *surface_mesh_orig, + *surface_mesh_eval, + surface_uv_coords_orig, + reverse_uv_sampler_orig, + reverse_uv_sampler_eval, + corner_normals_orig, + corner_normals_eval, + rest_positions, + transforms.surface_to_curves, + edit_hint_positions, + edit_hint_rotations, + invalid_uv_count); + } } curves.tag_positions_changed(); -- cgit v1.2.3 From c7051192e217a89cceb9117776b62d45a9f8da38 Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Mon, 17 Oct 2022 22:57:01 -0400 Subject: UI: Improve tooltip for texture shading mode Pointed out in T98506 --- source/blender/makesrna/intern/rna_space.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 3cd8020ca6c..5c192b80dc1 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -426,7 +426,11 @@ static const EnumPropertyItem rna_enum_shading_color_type_items[] = { {V3D_SHADING_OBJECT_COLOR, "OBJECT", 0, "Object", "Show object color"}, {V3D_SHADING_RANDOM_COLOR, "RANDOM", 0, "Random", "Show random object color"}, {V3D_SHADING_VERTEX_COLOR, "VERTEX", 0, "Attribute", "Show active color attribute"}, - {V3D_SHADING_TEXTURE_COLOR, "TEXTURE", 0, "Texture", "Show texture"}, + {V3D_SHADING_TEXTURE_COLOR, + "TEXTURE", + 0, + "Texture", + "Show the texture from the active image texture node using the active UV map coordinates"}, {0, NULL, 0, NULL, NULL}, }; -- cgit v1.2.3 From 1edebb794b76326e06b527fd0a04eba34d51ab7c Mon Sep 17 00:00:00 2001 From: Chris Blackbourn Date: Tue, 18 Oct 2022 15:59:35 +1300 Subject: UV: support snapping on non-uniform grids Part of a wider set of changes to Grid and Pixel snapping in the UV Editor. This change fixes snapping behavior for non-uniform grids, either manually specified Fixed grids, or pixel grids where the underlying image is non-square. See a24fc6bbc1ae for visual changes. Maniphest Tasks: T78391 Differential Revision: https://developer.blender.org/D16275 --- source/blender/editors/transform/transform.c | 19 +++++-------- source/blender/editors/transform/transform.h | 4 ++- .../editors/transform/transform_mode_translate.c | 2 +- source/blender/editors/transform/transform_snap.c | 33 +++++++++++++--------- 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 93e99f97387..34e5b78c48f 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -60,8 +60,6 @@ * and being able to set it to zero is handy. */ /* #define USE_NUM_NO_ZERO */ -static void initSnapSpatial(TransInfo *t, float r_snap[2]); - bool transdata_check_local_islands(TransInfo *t, short around) { if (t->options & (CTX_CURSOR | CTX_TEXTURE_SPACE)) { @@ -1723,7 +1721,7 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) } } -static void initSnapSpatial(TransInfo *t, float r_snap[2]) +static void initSnapSpatial(TransInfo *t, float r_snap[2], float r_snap_y[2]) { if (t->spacetype == SPACE_VIEW3D) { if (t->region->regiondata) { @@ -1737,18 +1735,15 @@ static void initSnapSpatial(TransInfo *t, float r_snap[2]) View2D *v2d = &t->region->v2d; int grid_size = SI_GRID_STEPS_LEN; float zoom_factor = ED_space_image_zoom_level(v2d, grid_size); - float grid_steps[SI_GRID_STEPS_LEN]; + float grid_steps_x[SI_GRID_STEPS_LEN]; float grid_steps_y[SI_GRID_STEPS_LEN]; - ED_space_image_grid_steps(sima, grid_steps, grid_steps_y, grid_size); + ED_space_image_grid_steps(sima, grid_steps_x, grid_steps_y, grid_size); /* Snapping value based on what type of grid is used (adaptive-subdividing or custom-grid). */ - r_snap[0] = ED_space_image_increment_snap_value(grid_size, grid_steps, zoom_factor); + r_snap[0] = ED_space_image_increment_snap_value(grid_size, grid_steps_x, zoom_factor); r_snap[1] = r_snap[0] / 2.0f; - - /* TODO: Implement snapping for custom grid sizes with `grid_steps[0] != grid_steps_y[0]`. - * r_snap_y[0] = ED_space_image_increment_snap_value(grid_size, grid_steps_y, zoom_factor); - * r_snap_y[1] = r_snap_y[0] / 2.0f; - */ + r_snap_y[0] = ED_space_image_increment_snap_value(grid_size, grid_steps_y, zoom_factor); + r_snap_y[1] = r_snap_y[0] / 2.0f; } else if (t->spacetype == SPACE_CLIP) { r_snap[0] = 0.125f; @@ -1903,7 +1898,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve initSnapping(t, op); /* Initialize snapping data AFTER mode flags */ - initSnapSpatial(t, t->snap_spatial); + initSnapSpatial(t, t->snap_spatial_x, t->snap_spatial_y); /* EVIL! posemode code can switch translation to rotate when 1 bone is selected. * will be removed (ton) */ diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index e2bab378cad..95686f12fe2 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -555,7 +555,9 @@ typedef struct TransInfo { /** Snapping Gears. */ float snap[2]; /** Spatial snapping gears(even when rotating, scaling... etc). */ - float snap_spatial[2]; + float snap_spatial_x[2]; + /** Spatial snapping in the Y coordinate, for non-uniform grid in UV Editor. */ + float snap_spatial_y[2]; /** Mouse side of the current frame, 'L', 'R' or 'B' */ char frame_side; diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index 8f6ec7bd98f..91388ecd661 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -590,7 +590,7 @@ void initTranslation(TransInfo *t) t->num.flag = 0; t->num.idx_max = t->idx_max; - copy_v2_v2(t->snap, t->snap_spatial); + copy_v2_v2(t->snap, t->snap_spatial_x); copy_v3_fl(t->num.val_inc, t->snap[0]); t->num.unit_sys = t->scene->unit.system; diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 3f9cca55138..553202b5798 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -519,10 +519,12 @@ void applyGridAbsolute(TransInfo *t) return; } - float grid_size = (t->modifiers & MOD_PRECISION) ? t->snap_spatial[1] : t->snap_spatial[0]; + float grid_size_x = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_x[1] : t->snap_spatial_x[0]; + float grid_size_y = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_y[1] : t->snap_spatial_y[0]; + float grid_size_z = grid_size_x; - /* early exit on unusable grid size */ - if (grid_size == 0.0f) { + /* Early exit on unusable grid size. */ + if (grid_size_x == 0.0f || grid_size_y == 0.0f || grid_size_z == 0.0f) { return; } @@ -548,11 +550,9 @@ void applyGridAbsolute(TransInfo *t) copy_v3_v3(iloc, td->ob->obmat[3]); } - mul_v3_v3fl(loc, iloc, 1.0f / grid_size); - loc[0] = roundf(loc[0]); - loc[1] = roundf(loc[1]); - loc[2] = roundf(loc[2]); - mul_v3_fl(loc, grid_size); + loc[0] = roundf(iloc[0] / grid_size_x) * grid_size_x; + loc[1] = roundf(iloc[1] / grid_size_y) * grid_size_y; + loc[2] = roundf(iloc[2] / grid_size_z) * grid_size_z; sub_v3_v3v3(tvec, loc, iloc); mul_m3_v3(td->smtx, tvec); @@ -1654,8 +1654,12 @@ bool snapNodesTransform( /** \name snap Grid * \{ */ -static void snap_grid_apply( - TransInfo *t, const int max_index, const float grid_dist, const float loc[3], float r_out[3]) +static void snap_grid_apply(TransInfo *t, + const int max_index, + const float grid_dist_x, + const float grid_dist_y, + const float loc[3], + float r_out[3]) { BLI_assert(max_index <= 2); snap_target_grid_ensure(t); @@ -1672,7 +1676,7 @@ static void snap_grid_apply( } for (int i = 0; i <= max_index; i++) { - const float iter_fac = grid_dist * asp[i]; + const float iter_fac = ((i == 1) ? grid_dist_y : grid_dist_x) * asp[i]; r_out[i] = iter_fac * roundf((in[i] + center_global[i]) / iter_fac) - center_global[i]; } } @@ -1697,14 +1701,15 @@ bool transform_snap_grid(TransInfo *t, float *val) return false; } - float grid_dist = (t->modifiers & MOD_PRECISION) ? t->snap[1] : t->snap[0]; + float grid_dist_x = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_x[1] : t->snap_spatial_x[0]; + float grid_dist_y = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_y[1] : t->snap_spatial_y[0]; /* Early bailing out if no need to snap */ - if (grid_dist == 0.0f) { + if (grid_dist_x == 0.0f || grid_dist_y == 0.0f) { return false; } - snap_grid_apply(t, t->idx_max, grid_dist, val, val); + snap_grid_apply(t, t->idx_max, grid_dist_x, grid_dist_y, val, val); t->tsnap.snapElem = SCE_SNAP_MODE_GRID; return true; } -- cgit v1.2.3 From e47bf05e8527c77700aea24b90d5fa7fc66990cf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 18 Oct 2022 13:44:23 +1100 Subject: NDOF: use logging for GHOST so users can enable event logging Previously this was only available as a build options, making it difficult to get user feedback when NDOF events didn't work as expected. Now logging can be enabled with: blender --log "ghost.ndof.*" --log-level 2 --log-show-basename --- intern/ghost/GHOST_Types.h | 2 +- intern/ghost/intern/GHOST_NDOFManager.cpp | 213 +++++++++++++++++++----------- intern/ghost/intern/GHOST_NDOFManager.h | 5 +- 3 files changed, 135 insertions(+), 85 deletions(-) diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 182eb6eb7d2..2645ce448b0 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -526,7 +526,7 @@ typedef struct { } GHOST_TStringArray; typedef enum { - GHOST_kNotStarted, + GHOST_kNotStarted = 0, GHOST_kStarting, GHOST_kInProgress, GHOST_kFinishing, diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index b1bd5287d24..f4c726c7450 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -7,18 +7,23 @@ #include "GHOST_WindowManager.h" #include "GHOST_utildefines.h" +/* Logging, use `ghost.ndof.*` prefix. */ +#include "CLG_log.h" + #include #include #include /* For error/info reporting. */ #include /* For memory functions. */ -#ifdef DEBUG_NDOF_MOTION /* Printable version of each GHOST_TProgress value. */ static const char *progress_string[] = { - "not started", "starting", "in progress", "finishing", "finished"}; -#endif + "not started", + "starting", + "in progress", + "finishing", + "finished", +}; -#ifdef DEBUG_NDOF_BUTTONS static const char *ndof_button_names[] = { /* used internally, never sent */ "NDOF_BUTTON_NONE", @@ -69,8 +74,8 @@ static const char *ndof_button_names[] = { "NDOF_BUTTON_B", "NDOF_BUTTON_C", /* the end */ - "NDOF_BUTTON_LAST"}; -#endif + "NDOF_BUTTON_LAST", +}; /* Shared by the latest 3Dconnexion hardware * SpacePilotPro uses all of these @@ -150,6 +155,13 @@ GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System &sys) memset(m_rotation, 0, sizeof(m_rotation)); } +/* -------------------------------------------------------------------- */ +/** \name NDOF Device Setup + * \{ */ + +static CLG_LogRef LOG_NDOF_DEVICE = {"ghost.ndof.device"}; +#define LOG (&LOG_NDOF_DEVICE) + bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) { /* Call this function until it returns true @@ -260,13 +272,19 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) m_buttonMask = int(~(UINT_MAX << m_buttonCount)); } -#ifdef DEBUG_NDOF_BUTTONS - printf("ndof: %d buttons -> hex:%X\n", m_buttonCount, m_buttonMask); -#endif + CLOG_INFO(LOG, 2, "%d buttons -> hex:%X", m_buttonCount, (uint)m_buttonMask); return m_deviceType != NDOF_UnknownDevice; } +#undef LOG + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name NDOF Update State + * \{ */ + void GHOST_NDOFManager::updateTranslation(const int t[3], uint64_t time) { memcpy(m_translation, t, sizeof(m_translation)); @@ -281,6 +299,36 @@ void GHOST_NDOFManager::updateRotation(const int r[3], uint64_t time) m_motionEventPending = true; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name NDOF Buttons + * \{ */ + +static CLG_LogRef LOG_NDOF_BUTTONS = {"ghost.ndof.buttons"}; +#define LOG (&LOG_NDOF_BUTTONS) + +static GHOST_TKey ghost_map_keyboard_from_ndof_buttom(const NDOF_ButtonT button) +{ + switch (button) { + case NDOF_BUTTON_ESC: { + return GHOST_kKeyEsc; + } + case NDOF_BUTTON_ALT: { + return GHOST_kKeyLeftAlt; + } + case NDOF_BUTTON_SHIFT: { + return GHOST_kKeyLeftShift; + } + case NDOF_BUTTON_CTRL: { + return GHOST_kKeyLeftControl; + } + default: { + return GHOST_kKeyUnknown; + } + } +} + void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button, bool press, uint64_t time, @@ -295,10 +343,6 @@ void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button, data->action = press ? GHOST_kPress : GHOST_kRelease; data->button = button; -#ifdef DEBUG_NDOF_BUTTONS - printf("%s %s\n", ndof_button_names[button], press ? "pressed" : "released"); -#endif - m_system.pushEvent(event); } @@ -310,44 +354,41 @@ void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key, GHOST_TEventType type = press ? GHOST_kEventKeyDown : GHOST_kEventKeyUp; GHOST_EventKey *event = new GHOST_EventKey(time, type, window, key, false); -#ifdef DEBUG_NDOF_BUTTONS - printf("keyboard %s\n", press ? "down" : "up"); -#endif - m_system.pushEvent(event); } void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t time) { - GHOST_IWindow *window = m_system.getWindowManager()->getActiveWindow(); - -#ifdef DEBUG_NDOF_BUTTONS - printf("ndof: button %d -> ", button_number); -#endif + if (button_number >= m_buttonCount) { + CLOG_INFO(LOG, + 2, + "button=%d, press=%d (out of range %d, ignoring!)", + button_number, + (int)press, + m_buttonCount); + return; + } + const NDOF_ButtonT button = m_hidMap[button_number]; + if (button == NDOF_BUTTON_NONE) { + CLOG_INFO( + LOG, 2, "button=%d, press=%d (mapped to none, ignoring!)", button_number, (int)press); + return; + } - NDOF_ButtonT button = (button_number < m_buttonCount) ? m_hidMap[button_number] : - NDOF_BUTTON_NONE; + CLOG_INFO(LOG, + 2, + "button=%d, press=%d, name=%s", + button_number, + (int)press, + ndof_button_names[button]); - switch (button) { - case NDOF_BUTTON_NONE: -#ifdef DEBUG_NDOF_BUTTONS - printf("discarded\n"); -#endif - break; - case NDOF_BUTTON_ESC: - sendKeyEvent(GHOST_kKeyEsc, press, time, window); - break; - case NDOF_BUTTON_ALT: - sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); - break; - case NDOF_BUTTON_SHIFT: - sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); - break; - case NDOF_BUTTON_CTRL: - sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); - break; - default: - sendButtonEvent(button, press, time, window); + GHOST_IWindow *window = m_system.getWindowManager()->getActiveWindow(); + const GHOST_TKey key = ghost_map_keyboard_from_ndof_buttom(button); + if (key != GHOST_kKeyUnknown) { + sendKeyEvent(key, press, time, window); + } + else { + sendButtonEvent(button, press, time, window); } int mask = 1 << button_number; @@ -375,19 +416,27 @@ void GHOST_NDOFManager::updateButtons(int button_bits, uint64_t time) } } +#undef LOG + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name NDOF Motion + * \{ */ + +static CLG_LogRef LOG_NDOF_MOTION = {"ghost.ndof.motion"}; +#define LOG (&LOG_NDOF_MOTION) + void GHOST_NDOFManager::setDeadZone(float dz) { if (dz < 0.0f) { /* Negative values don't make sense, so clamp at zero. */ dz = 0.0f; } - else if (dz > 0.5f) { - /* Warn the rogue user/developer, but allow it. */ - GHOST_PRINTF("ndof: dead zone of %.2f is rather high...\n", dz); - } m_deadZone = dz; - GHOST_PRINTF("ndof: dead zone set to %.2f\n", dz); + /* Warn the rogue user/developer about high dead-zone, but allow it. */ + CLOG_INFO(LOG, 2, "dead zone set to %.2f%s", dz, (dz > 0.5f) ? " (unexpectedly high)" : ""); } static bool atHomePosition(GHOST_TEventNDOFMotionData *ndof) @@ -402,11 +451,9 @@ static bool nearHomePosition(GHOST_TEventNDOFMotionData *ndof, float threshold) if (threshold == 0.0f) { return atHomePosition(ndof); } - else { #define HOME(foo) (fabsf(ndof->foo) < threshold) - return HOME(tx) && HOME(ty) && HOME(tz) && HOME(rx) && HOME(ry) && HOME(rz); + return HOME(tx) && HOME(ty) && HOME(tz) && HOME(rx) && HOME(ry) && HOME(rz); #undef HOME - } } bool GHOST_NDOFManager::sendMotionEvent() @@ -419,7 +466,7 @@ bool GHOST_NDOFManager::sendMotionEvent() GHOST_IWindow *window = m_system.getWindowManager()->getActiveWindow(); - if (window == NULL) { + if (window == nullptr) { m_motionState = GHOST_kNotStarted; /* Avoid large `dt` times when changing windows. */ return false; /* Delivery will fail, so don't bother sending. */ } @@ -439,7 +486,6 @@ bool GHOST_NDOFManager::sendMotionEvent() data->rx = scale * m_rotation[0]; data->ry = scale * m_rotation[1]; data->rz = scale * m_rotation[2]; - data->dt = 0.001f * (m_motionTime - m_prevMotionTime); /* In seconds. */ m_prevMotionTime = m_motionTime; @@ -449,7 +495,7 @@ bool GHOST_NDOFManager::sendMotionEvent() * and where that leaves this NDOF manager `(NotStarted, InProgress, Finished)`. */ switch (m_motionState) { case GHOST_kNotStarted: - case GHOST_kFinished: + case GHOST_kFinished: { if (weHaveMotion) { data->progress = GHOST_kStarting; m_motionState = GHOST_kInProgress; @@ -458,14 +504,13 @@ bool GHOST_NDOFManager::sendMotionEvent() } else { /* Send no event and keep current state. */ -#ifdef DEBUG_NDOF_MOTION - printf("ndof motion ignored -- %s\n", progress_string[data->progress]); -#endif + CLOG_INFO(LOG, 2, "motion ignored"); delete event; return false; } break; - case GHOST_kInProgress: + } + case GHOST_kInProgress: { if (weHaveMotion) { data->progress = GHOST_kInProgress; /* Remain 'InProgress'. */ @@ -475,33 +520,41 @@ bool GHOST_NDOFManager::sendMotionEvent() m_motionState = GHOST_kFinished; } break; - default: + } + default: { /* Will always be one of the above. */ break; + } } -#ifdef DEBUG_NDOF_MOTION - printf("ndof motion sent -- %s\n", progress_string[data->progress]); - - /* Show details about this motion event. */ - printf(" T=(%d,%d,%d) R=(%d,%d,%d) raw\n", - m_translation[0], - m_translation[1], - m_translation[2], - m_rotation[0], - m_rotation[1], - m_rotation[2]); - printf(" T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", - data->tx, - data->ty, - data->tz, - data->rx, - data->ry, - data->rz, - data->dt); +#if 1 + CLOG_INFO(LOG, + 2, + "motion sent, T=(%.2f,%.2f,%.2f), R=(%.2f,%.2f,%.2f) dt=%.3f, status=%s", + data->tx, + data->ty, + data->tz, + data->rx, + data->ry, + data->rz, + data->dt, + progress_string[data->progress]); +#else + /* Raw values, may be useful for debugging. */ + CLOG_INFO(LOG, + 2, + "motion sent, T=(%d,%d,%d) R=(%d,%d,%d) status=%s", + m_translation[0], + m_translation[1], + m_translation[2], + m_rotation[0], + m_rotation[1], + m_rotation[2], + progress_string[data->progress]); #endif - m_system.pushEvent(event); return true; } + +/** \} */ diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index d49e6326722..73c1b17f891 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -8,9 +8,6 @@ #include "GHOST_System.h" -// #define DEBUG_NDOF_MOTION -// #define DEBUG_NDOF_BUTTONS - typedef enum { NDOF_UnknownDevice, @@ -33,7 +30,7 @@ typedef enum { /* NDOF device button event types */ typedef enum { /* Used internally, never sent. */ - NDOF_BUTTON_NONE, + NDOF_BUTTON_NONE = 0, /* These two are available from any 3Dconnexion device. */ NDOF_BUTTON_MENU, NDOF_BUTTON_FIT, -- cgit v1.2.3 From aed301704aa1cd02b8868396d36ce78bc292850e Mon Sep 17 00:00:00 2001 From: Jason Fielder Date: Tue, 18 Oct 2022 12:18:25 +0200 Subject: Metal: MTLBatch and MTLDrawList implementation. MTLBatch and MTLDrawList implementation enables use of Metal Viewport for UI and Workbench. Includes Vertex descriptor caching and SSBO Vertex Fetch mode draw call submission. Authored by Apple: Michael Parkin-White Ref T96261 Reviewed By: fclem Maniphest Tasks: T96261 Differential Revision: https://developer.blender.org/D16101 --- .../overlay_motion_path_line_vert_no_geom.glsl | 12 +- source/blender/draw/intern/draw_manager_data.cc | 37 +- source/blender/gpu/CMakeLists.txt | 2 + source/blender/gpu/intern/gpu_texture_private.hh | 7 +- source/blender/gpu/intern/gpu_viewport.c | 4 + source/blender/gpu/metal/mtl_backend.mm | 3 +- source/blender/gpu/metal/mtl_batch.hh | 115 ++- source/blender/gpu/metal/mtl_batch.mm | 995 +++++++++++++++++++++ source/blender/gpu/metal/mtl_context.mm | 10 +- source/blender/gpu/metal/mtl_drawlist.hh | 58 +- source/blender/gpu/metal/mtl_drawlist.mm | 282 ++++++ source/blender/gpu/metal/mtl_immediate.mm | 3 + .../blender/gpu/metal/mtl_pso_descriptor_state.hh | 13 + source/blender/gpu/metal/mtl_shader_interface.mm | 10 +- source/blender/gpu/metal/mtl_texture.hh | 4 +- source/blender/gpu/metal/mtl_texture.mm | 97 +- 16 files changed, 1566 insertions(+), 86 deletions(-) create mode 100644 source/blender/gpu/metal/mtl_batch.mm create mode 100644 source/blender/gpu/metal/mtl_drawlist.mm diff --git a/source/blender/draw/engines/overlay/shaders/overlay_motion_path_line_vert_no_geom.glsl b/source/blender/draw/engines/overlay/shaders/overlay_motion_path_line_vert_no_geom.glsl index e3ddeb5c6a4..abaa814a4dc 100644 --- a/source/blender/draw/engines/overlay/shaders/overlay_motion_path_line_vert_no_geom.glsl +++ b/source/blender/draw/engines/overlay/shaders/overlay_motion_path_line_vert_no_geom.glsl @@ -108,8 +108,8 @@ void main() vec3 in_pos0 = vertex_fetch_attribute(base_vertex_id, pos, vec3); vec3 in_pos1 = vertex_fetch_attribute(base_vertex_id + 1, pos, vec3); - vec4 out_pos0 = ProjectionMatrix * (ViewMatrix * vec4(in_pos0, 1.0)); - vec4 out_pos1 = ProjectionMatrix * (ViewMatrix * vec4(in_pos1, 1.0)); + vec4 out_pos0 = drw_view.winmat * (drw_view.viewmat * vec4(in_pos0, 1.0)); + vec4 out_pos1 = drw_view.winmat * (drw_view.viewmat * vec4(in_pos1, 1.0)); /* Final calculations required for Geometry Shader alternative. * We need to calculate values for each vertex position to correctly determine the final output @@ -130,28 +130,28 @@ void main() float line_size = float(lineThickness) * sizePixel; if (quad_vertex_id == 0) { - view_clipping_distances(out_pos0); + view_clipping_distances(out_pos0.xyz); interp.color = finalColor_geom[0]; t = edge_dir * (line_size * (is_persp ? out_pos0.w : 1.0)); gl_Position = out_pos0 + vec4(t, 0.0, 0.0); } else if (quad_vertex_id == 1 || quad_vertex_id == 3) { - view_clipping_distances(out_pos0); + view_clipping_distances(out_pos0.xyz); interp.color = finalColor_geom[0]; t = edge_dir * (line_size * (is_persp ? out_pos0.w : 1.0)); gl_Position = out_pos0 - vec4(t, 0.0, 0.0); } else if (quad_vertex_id == 2 || quad_vertex_id == 5) { - view_clipping_distances(out_pos1); + view_clipping_distances(out_pos1.xyz); interp.color = finalColor_geom[1]; t = edge_dir * (line_size * (is_persp ? out_pos1.w : 1.0)); gl_Position = out_pos1 + vec4(t, 0.0, 0.0); } else if (quad_vertex_id == 4) { - view_clipping_distances(out_pos1); + view_clipping_distances(out_pos1.xyz); interp.color = finalColor_geom[1]; t = edge_dir * (line_size * (is_persp ? out_pos1.w : 1.0)); diff --git a/source/blender/draw/intern/draw_manager_data.cc b/source/blender/draw/intern/draw_manager_data.cc index 9768f1ce9e7..981206e56fe 100644 --- a/source/blender/draw/intern/draw_manager_data.cc +++ b/source/blender/draw/intern/draw_manager_data.cc @@ -1714,23 +1714,32 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader) } #ifdef DEBUG - int debug_print_location = GPU_shader_get_builtin_ssbo(shader, GPU_STORAGE_BUFFER_DEBUG_PRINT); - if (debug_print_location != -1) { - GPUStorageBuf *buf = drw_debug_gpu_print_buf_get(); - drw_shgroup_uniform_create_ex( - shgroup, debug_print_location, DRW_UNIFORM_STORAGE_BLOCK, buf, GPU_SAMPLER_DEFAULT, 0, 1); + /* TODO(Metal): Support Shader debug print. + * This is not currently supported by Metal Backend. */ + if (GPU_backend_get_type() != GPU_BACKEND_METAL) { + int debug_print_location = GPU_shader_get_builtin_ssbo(shader, GPU_STORAGE_BUFFER_DEBUG_PRINT); + if (debug_print_location != -1) { + GPUStorageBuf *buf = drw_debug_gpu_print_buf_get(); + drw_shgroup_uniform_create_ex(shgroup, + debug_print_location, + DRW_UNIFORM_STORAGE_BLOCK, + buf, + GPU_SAMPLER_DEFAULT, + 0, + 1); # ifndef DISABLE_DEBUG_SHADER_PRINT_BARRIER - /* Add a barrier to allow multiple shader writing to the same buffer. */ - DRW_shgroup_barrier(shgroup, GPU_BARRIER_SHADER_STORAGE); + /* Add a barrier to allow multiple shader writing to the same buffer. */ + DRW_shgroup_barrier(shgroup, GPU_BARRIER_SHADER_STORAGE); # endif - } + } - int debug_draw_location = GPU_shader_get_builtin_ssbo(shader, GPU_STORAGE_BUFFER_DEBUG_VERTS); - if (debug_draw_location != -1) { - GPUStorageBuf *buf = drw_debug_gpu_draw_buf_get(); - drw_shgroup_uniform_create_ex( - shgroup, debug_draw_location, DRW_UNIFORM_STORAGE_BLOCK, buf, GPU_SAMPLER_DEFAULT, 0, 1); - /* NOTE(fclem): No barrier as ordering is not important. */ + int debug_draw_location = GPU_shader_get_builtin_ssbo(shader, GPU_STORAGE_BUFFER_DEBUG_VERTS); + if (debug_draw_location != -1) { + GPUStorageBuf *buf = drw_debug_gpu_draw_buf_get(); + drw_shgroup_uniform_create_ex( + shgroup, debug_draw_location, DRW_UNIFORM_STORAGE_BLOCK, buf, GPU_SAMPLER_DEFAULT, 0, 1); + /* NOTE(fclem): No barrier as ordering is not important. */ + } } #endif diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index f387a4588b6..5a1e0cde1d8 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -186,9 +186,11 @@ set(OPENGL_SRC set(METAL_SRC metal/mtl_backend.mm + metal/mtl_batch.mm metal/mtl_command_buffer.mm metal/mtl_context.mm metal/mtl_debug.mm + metal/mtl_drawlist.mm metal/mtl_framebuffer.mm metal/mtl_immediate.mm metal/mtl_index_buffer.mm diff --git a/source/blender/gpu/intern/gpu_texture_private.hh b/source/blender/gpu/intern/gpu_texture_private.hh index b96a9b870e5..2ad31183206 100644 --- a/source/blender/gpu/intern/gpu_texture_private.hh +++ b/source/blender/gpu/intern/gpu_texture_private.hh @@ -431,15 +431,16 @@ inline bool validate_data_format(eGPUTextureFormat tex_format, eGPUDataFormat da case GPU_DEPTH_COMPONENT24: case GPU_DEPTH_COMPONENT16: case GPU_DEPTH_COMPONENT32F: - return data_format == GPU_DATA_FLOAT; + return ELEM(data_format, GPU_DATA_FLOAT, GPU_DATA_UINT); case GPU_DEPTH24_STENCIL8: case GPU_DEPTH32F_STENCIL8: - return data_format == GPU_DATA_UINT_24_8; + return ELEM(data_format, GPU_DATA_UINT_24_8, GPU_DATA_UINT); case GPU_R8UI: case GPU_R16UI: case GPU_RG16UI: case GPU_R32UI: return data_format == GPU_DATA_UINT; + case GPU_R32I: case GPU_RG16I: case GPU_R16I: return data_format == GPU_DATA_INT; @@ -453,6 +454,8 @@ inline bool validate_data_format(eGPUTextureFormat tex_format, eGPUDataFormat da return ELEM(data_format, GPU_DATA_2_10_10_10_REV, GPU_DATA_FLOAT); case GPU_R11F_G11F_B10F: return ELEM(data_format, GPU_DATA_10_11_11_REV, GPU_DATA_FLOAT); + case GPU_RGBA16F: + return ELEM(data_format, GPU_DATA_HALF_FLOAT, GPU_DATA_FLOAT); default: return data_format == GPU_DATA_FLOAT; } diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 71bdf9e336b..e267d5a2f12 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -147,6 +147,10 @@ static void gpu_viewport_textures_create(GPUViewport *viewport) if (viewport->depth_tx == NULL) { viewport->depth_tx = GPU_texture_create_2d( "dtxl_depth", UNPACK2(size), 1, GPU_DEPTH24_STENCIL8, NULL); + if (GPU_clear_viewport_workaround()) { + static int depth_clear = 0; + GPU_texture_clear(viewport->depth_tx, GPU_DATA_UINT_24_8, &depth_clear); + } } if (!viewport->depth_tx || !viewport->color_render_tx[0] || !viewport->color_overlay_tx[0]) { diff --git a/source/blender/gpu/metal/mtl_backend.mm b/source/blender/gpu/metal/mtl_backend.mm index 2ca1fd3f3d0..240951c1ebd 100644 --- a/source/blender/gpu/metal/mtl_backend.mm +++ b/source/blender/gpu/metal/mtl_backend.mm @@ -47,13 +47,11 @@ Context *MTLBackend::context_alloc(void *ghost_window, void *ghost_context) Batch *MTLBackend::batch_alloc() { - /* TODO(Metal): Full MTLBatch implementation. */ return new MTLBatch(); }; DrawList *MTLBackend::drawlist_alloc(int list_length) { - /* TODO(Metal): Full MTLDrawList implementation. */ return new MTLDrawList(list_length); }; @@ -420,6 +418,7 @@ void MTLBackend::capabilities_init(MTLContext *ctx) GCaps.depth_blitting_workaround = false; GCaps.use_main_context_workaround = false; GCaps.broken_amd_driver = false; + GCaps.clear_viewport_workaround = true; /* Metal related workarounds. */ /* Minimum per-vertex stride is 4 bytes in Metal. diff --git a/source/blender/gpu/metal/mtl_batch.hh b/source/blender/gpu/metal/mtl_batch.hh index 236367bf5a4..9e179e662b5 100644 --- a/source/blender/gpu/metal/mtl_batch.hh +++ b/source/blender/gpu/metal/mtl_batch.hh @@ -10,31 +10,126 @@ #pragma once #include "MEM_guardedalloc.h" - #include "gpu_batch_private.hh" +#include "mtl_index_buffer.hh" +#include "mtl_primitive.hh" +#include "mtl_shader.hh" +#include "mtl_vertex_buffer.hh" + +namespace blender::gpu { + +class MTLContext; +class MTLShaderInterface; + +#define GPU_VAO_STATIC_LEN 64 -namespace blender { -namespace gpu { +struct VertexBufferID { + uint32_t id : 16; + uint32_t is_instance : 15; + uint32_t used : 1; +}; -/* Pass-through MTLBatch. TODO(Metal): Implement. */ class MTLBatch : public Batch { + + /* Vertex Bind-state Caching for a given shader interface used with the Batch. */ + struct VertexDescriptorShaderInterfacePair { + MTLVertexDescriptor vertex_descriptor{}; + const ShaderInterface *interface = nullptr; + uint16_t attr_mask{}; + int num_buffers{}; + VertexBufferID bufferIds[GPU_BATCH_VBO_MAX_LEN] = {}; + /* Cache life index compares a cache entry with the active MTLBatch state. + * This is initially set to the cache life index of MTLBatch. If the batch has been modified, + * this index is incremented to cheaply invalidate existing cache entries. */ + uint32_t cache_life_index = 0; + }; + + class MTLVertexDescriptorCache { + + private: + MTLBatch *batch_; + + VertexDescriptorShaderInterfacePair cache_[GPU_VAO_STATIC_LEN] = {}; + MTLContext *cache_context_ = nullptr; + uint32_t cache_life_index_ = 0; + + public: + MTLVertexDescriptorCache(MTLBatch *batch) : batch_(batch){}; + VertexDescriptorShaderInterfacePair *find(const ShaderInterface *interface); + bool insert(VertexDescriptorShaderInterfacePair &data); + + private: + void vertex_descriptor_cache_init(MTLContext *ctx); + void vertex_descriptor_cache_clear(); + void vertex_descriptor_cache_ensure(); + }; + + private: + MTLShader *active_shader_ = nullptr; + bool shader_in_use_ = false; + MTLVertexDescriptorCache vao_cache = {this}; + + /* Topology emulation. */ + gpu::MTLBuffer *emulated_topology_buffer_ = nullptr; + GPUPrimType emulated_topology_type_; + uint32_t topology_buffer_input_v_count_ = 0; + uint32_t topology_buffer_output_v_count_ = 0; + public: - void draw(int v_first, int v_count, int i_first, int i_count) override - { - } + MTLBatch(){}; + ~MTLBatch(){}; + void draw(int v_first, int v_count, int i_first, int i_count) override; void draw_indirect(GPUStorageBuf *indirect_buf, intptr_t offset) override { + /* TODO(Metal): Support indirect draw commands. */ } - void multi_draw_indirect(GPUStorageBuf *indirect_buf, int count, intptr_t offset, intptr_t stride) override { + /* TODO(Metal): Support indirect draw commands. */ + } + + /* Returns an initialized RenderComandEncoder for drawing if all is good. + * Otherwise, nil. */ + id bind(uint v_first, uint v_count, uint i_first, uint i_count); + void unbind(); + + /* Convenience getters. */ + MTLIndexBuf *elem_() const + { + return static_cast(unwrap(elem)); + } + MTLVertBuf *verts_(const int index) const + { + return static_cast(unwrap(verts[index])); } + MTLVertBuf *inst_(const int index) const + { + return static_cast(unwrap(inst[index])); + } + MTLShader *active_shader_get() const + { + return active_shader_; + } + + private: + void shader_bind(); + void draw_advanced(int v_first, int v_count, int i_first, int i_count); + int prepare_vertex_binding(MTLVertBuf *verts, + MTLRenderPipelineStateDescriptor &desc, + const MTLShaderInterface *interface, + uint16_t &attr_mask, + bool instanced); + + id get_emulated_toplogy_buffer(GPUPrimType &in_out_prim_type, uint32_t &v_count); + + void prepare_vertex_descriptor_and_bindings( + MTLVertBuf **buffers, int &num_buffers, int v_first, int v_count, int i_first, int i_count); + MEM_CXX_CLASS_ALLOC_FUNCS("MTLBatch"); }; -} // namespace gpu -} // namespace blender +} // namespace blender::gpu diff --git a/source/blender/gpu/metal/mtl_batch.mm b/source/blender/gpu/metal/mtl_batch.mm new file mode 100644 index 00000000000..e9804d4be77 --- /dev/null +++ b/source/blender/gpu/metal/mtl_batch.mm @@ -0,0 +1,995 @@ + +/** \file + * \ingroup gpu + * + * Metal implementation of GPUBatch. + */ + +#include "BLI_assert.h" +#include "BLI_span.hh" + +#include "BKE_global.h" + +#include "GPU_common.h" +#include "gpu_batch_private.hh" +#include "gpu_shader_private.hh" + +#include "mtl_batch.hh" +#include "mtl_context.hh" +#include "mtl_debug.hh" +#include "mtl_index_buffer.hh" +#include "mtl_shader.hh" +#include "mtl_vertex_buffer.hh" + +#include + +namespace blender::gpu { + +/* -------------------------------------------------------------------- */ +/** \name Creation & Deletion + * \{ */ +void MTLBatch::draw(int v_first, int v_count, int i_first, int i_count) +{ + if (this->flag & GPU_BATCH_INVALID) { + this->shader_in_use_ = false; + } + this->draw_advanced(v_first, v_count, i_first, i_count); +} + +void MTLBatch::shader_bind() +{ + if (active_shader_ && active_shader_->is_valid()) { + active_shader_->bind(); + shader_in_use_ = true; + } +} + +void MTLBatch::MTLVertexDescriptorCache::vertex_descriptor_cache_init(MTLContext *ctx) +{ + BLI_assert(ctx != nullptr); + this->vertex_descriptor_cache_clear(); + cache_context_ = ctx; +} + +void MTLBatch::MTLVertexDescriptorCache::vertex_descriptor_cache_clear() +{ + cache_life_index_++; + cache_context_ = nullptr; +} + +void MTLBatch::MTLVertexDescriptorCache::vertex_descriptor_cache_ensure() +{ + if (this->cache_context_ != nullptr) { + + /* Invalidate vertex descriptor bindings cache if batch has changed. */ + if (batch_->flag & GPU_BATCH_DIRTY) { + batch_->flag &= ~GPU_BATCH_DIRTY; + this->vertex_descriptor_cache_clear(); + } + } + + /* Initialise cache if not ready. */ + if (cache_context_ == nullptr) { + this->vertex_descriptor_cache_init(MTLContext::get()); + } +} + +MTLBatch::VertexDescriptorShaderInterfacePair *MTLBatch::MTLVertexDescriptorCache::find( + const ShaderInterface *interface) +{ + this->vertex_descriptor_cache_ensure(); + for (int i = 0; i < GPU_VAO_STATIC_LEN; ++i) { + if (cache_[i].interface == interface && cache_[i].cache_life_index == cache_life_index_) { + return &cache_[i]; + } + } + return nullptr; +} + +bool MTLBatch::MTLVertexDescriptorCache::insert( + MTLBatch::VertexDescriptorShaderInterfacePair &data) +{ + vertex_descriptor_cache_ensure(); + for (int i = 0; i < GPU_VAO_STATIC_LEN; ++i) { + if (cache_[i].interface == nullptr || cache_[i].cache_life_index != cache_life_index_) { + cache_[i] = data; + cache_[i].cache_life_index = cache_life_index_; + return true; + } + } + return false; +} + +int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts, + MTLRenderPipelineStateDescriptor &desc, + const MTLShaderInterface *interface, + uint16_t &attr_mask, + bool instanced) +{ + + const GPUVertFormat *format = &verts->format; + /* Whether the current vertex buffer has been added to the buffer layout descriptor. */ + bool buffer_added = false; + /* Per-vertex stride of current vertex buffer. */ + int buffer_stride = format->stride; + /* Buffer binding index of the vertex buffer once added to the buffer layout descriptor. */ + int buffer_index = -1; + int attribute_offset = 0; + + if (!active_shader_->get_uses_ssbo_vertex_fetch()) { + BLI_assert( + buffer_stride >= 4 && + "In Metal, Vertex buffer stride should be 4. SSBO Vertex fetch is not affected by this"); + } + + /* Iterate over GPUVertBuf vertex format and find attributes matching those in the active + * shader's interface. */ + for (uint32_t a_idx = 0; a_idx < format->attr_len; a_idx++) { + const GPUVertAttr *a = &format->attrs[a_idx]; + + if (format->deinterleaved) { + attribute_offset += ((a_idx == 0) ? 0 : format->attrs[a_idx - 1].size) * verts->vertex_len; + buffer_stride = a->size; + } + else { + attribute_offset = a->offset; + } + + /* Find attribute with the matching name. Attributes may have multiple compatible + * name aliases. */ + for (uint32_t n_idx = 0; n_idx < a->name_len; n_idx++) { + const char *name = GPU_vertformat_attr_name_get(format, a, n_idx); + const ShaderInput *input = interface->attr_get(name); + + if (input == nullptr || input->location == -1) { + /* Vertex/instance buffers provided have attribute data for attributes which are not needed + * by this particular shader. This shader only needs binding information for the attributes + * has in the shader interface. */ + MTL_LOG_WARNING( + "MTLBatch: Could not find attribute with name '%s' (defined in active vertex format) " + "in the shader interface for shader '%s'\n", + name, + interface->get_name()); + continue; + } + + /* Fetch metal attribute information. */ + const MTLShaderInputAttribute &mtl_attr = interface->get_attribute(input->location); + BLI_assert(mtl_attr.location >= 0); + /* Verify that the attribute location from the shader interface + * matches the attribute location returned. */ + BLI_assert(mtl_attr.location == input->location); + + /* Check if attribute is already present in the given slot. */ + if ((~attr_mask) & (1 << mtl_attr.location)) { + MTL_LOG_INFO( + " -- [Batch] Skipping attribute with input location %d (As one is already bound)\n", + mtl_attr.location); + } + else { + + /* Update attribute used-slot mask. */ + attr_mask &= ~(1 << mtl_attr.location); + + /* Add buffer layout entry in descriptor if it has not yet been added + * for current vertex buffer. */ + if (!buffer_added) { + buffer_index = desc.vertex_descriptor.num_vert_buffers; + desc.vertex_descriptor.buffer_layouts[buffer_index].step_function = + (instanced) ? MTLVertexStepFunctionPerInstance : MTLVertexStepFunctionPerVertex; + desc.vertex_descriptor.buffer_layouts[buffer_index].step_rate = 1; + desc.vertex_descriptor.buffer_layouts[buffer_index].stride = buffer_stride; + desc.vertex_descriptor.num_vert_buffers++; + buffer_added = true; + + MTL_LOG_INFO(" -- [Batch] Adding source %s buffer (Index: %d, Stride: %d)\n", + (instanced) ? "instance" : "vertex", + buffer_index, + buffer_stride); + } + else { + /* Ensure stride is correct for de-interlevaed attributes. */ + desc.vertex_descriptor.buffer_layouts[buffer_index].stride = buffer_stride; + } + + /* Handle Matrix/Array vertex attribute types. + * Metal does not natively support these as attribute types, so we handle these cases + * by stacking together compatible types (e.g. 4xVec4 for Mat4) and combining + * the data in the shader. + * The generated Metal shader will contain a generated input binding, which reads + * in individual attributes and merges them into the desired type after vertex + * assembly. e.g. a Mat4 (Float4x4) will generate 4 Float4 attributes. */ + if (a->comp_len == 16 || a->comp_len == 12 || a->comp_len == 8) { + BLI_assert_msg( + a->comp_len == 16, + "only mat4 attributes currently supported -- Not ready to handle other long " + "component length attributes yet"); + + /* SSBO Vertex Fetch Attribute safety checks. */ + if (active_shader_->get_uses_ssbo_vertex_fetch()) { + /* When using SSBO vertex fetch, we do not need to expose split attributes, + * A matrix can be read directly as a whole block of contiguous data. */ + MTLSSBOAttribute ssbo_attr(mtl_attr.index, + buffer_index, + attribute_offset, + buffer_stride, + GPU_SHADER_ATTR_TYPE_MAT4, + instanced); + active_shader_->ssbo_vertex_fetch_bind_attribute(ssbo_attr); + desc.vertex_descriptor.ssbo_attributes[desc.vertex_descriptor.num_ssbo_attributes] = + ssbo_attr; + desc.vertex_descriptor.num_ssbo_attributes++; + } + else { + + /* Handle Mat4 attributes. */ + if (a->comp_len == 16) { + /* Debug safety checks. */ + BLI_assert_msg(mtl_attr.matrix_element_count == 4, + "mat4 type expected but there are fewer components"); + BLI_assert_msg(mtl_attr.size == 16, "Expecting subtype 'vec4' with 16 bytes"); + BLI_assert_msg( + mtl_attr.format == MTLVertexFormatFloat4, + "Per-attribute vertex format MUST be float4 for an input type of 'mat4'"); + + /* We have found the 'ROOT' attribute. A mat4 contains 4 consecutive float4 attribute + * locations we must map to. */ + for (int i = 0; i < a->comp_len / 4; i++) { + desc.vertex_descriptor.attributes[mtl_attr.location + i].format = + MTLVertexFormatFloat4; + /* Data is consecutive in the buffer for the whole matrix, each float4 will shift + * the offset by 16 bytes. */ + desc.vertex_descriptor.attributes[mtl_attr.location + i].offset = + attribute_offset + i * 16; + /* All source data for a matrix is in the same singular buffer. */ + desc.vertex_descriptor.attributes[mtl_attr.location + i].buffer_index = + buffer_index; + + /* Update total attribute account. */ + desc.vertex_descriptor.num_attributes = max_ii( + mtl_attr.location + i + 1, desc.vertex_descriptor.num_attributes); + MTL_LOG_INFO("-- Sub-Attrib Location: %d, offset: %d, buffer index: %d\n", + mtl_attr.location + i, + attribute_offset + i * 16, + buffer_index); + } + MTL_LOG_INFO( + "Float4x4 attribute type added for '%s' at attribute locations: %d to %d\n", + name, + mtl_attr.location, + mtl_attr.location + 3); + } + + /* Ensure we are not exceeding the attribute limit. */ + BLI_assert(desc.vertex_descriptor.num_attributes <= MTL_MAX_VERTEX_INPUT_ATTRIBUTES); + } + } + else { + + /* Handle Any required format conversions. + * NOTE(Metal): If there is a mis-match between the format of an attribute + * in the shader interface, and the specified format in the VertexBuffer VertexFormat, + * we need to perform a format conversion. + * + * The Metal API can perform certain conversions internally during vertex assembly: + * - Type Normalization e.g short2 to float2 between 0.0 to 1.0. + * - Type Truncation e.g. Float4 to Float2. + * - Type expansion e,g, Float3 to Float4 (Following 0,0,0,1 for assignment to empty + * elements). + * + * Certain conversion cannot be performed however, and in these cases, we need to + * instruct the shader to generate a specialised version with a conversion routine upon + * attribute read. + * - This handles cases such as conversion between types e.g. Integer to float without + * normalization. + * + * For more information on the supported and unsupported conversions, see: + * https://developer.apple.com/documentation/metal/mtlvertexattributedescriptor/1516081-format?language=objc + */ + MTLVertexFormat converted_format; + bool can_use_internal_conversion = mtl_convert_vertex_format( + mtl_attr.format, + (GPUVertCompType)a->comp_type, + a->comp_len, + (GPUVertFetchMode)a->fetch_mode, + &converted_format); + bool is_floating_point_format = (a->comp_type == GPU_COMP_F32); + + if (can_use_internal_conversion) { + desc.vertex_descriptor.attributes[mtl_attr.location].format = converted_format; + desc.vertex_descriptor.attributes[mtl_attr.location].format_conversion_mode = + is_floating_point_format ? (GPUVertFetchMode)GPU_FETCH_FLOAT : + (GPUVertFetchMode)GPU_FETCH_INT; + BLI_assert(converted_format != MTLVertexFormatInvalid); + } + else { + /* The internal implicit conversion is not supported. + * In this case, we need to handle conversion inside the shader. + * This is handled using `format_conversion_mode`. + * `format_conversion_mode` is assigned the blender-specified fetch mode (GPU_FETCH_*). + * This then controls how a given attribute is interpreted. The data will be read + * as specified and then converted appropriately to the correct form. + * + * e.g. if `GPU_FETCH_INT_TO_FLOAT` is specified, the specialised read-routine + * in the shader will read the data as an int, and cast this to floating point + * representation. (Rather than reading the source data as float). + * + * NOTE: Even if full conversion is not supported, we may still partially perform an + * implicit conversion where possible, such as vector truncation or expansion. */ + MTLVertexFormat converted_format; + bool can_convert = mtl_vertex_format_resize( + mtl_attr.format, a->comp_len, &converted_format); + desc.vertex_descriptor.attributes[mtl_attr.location].format = can_convert ? + converted_format : + mtl_attr.format; + desc.vertex_descriptor.attributes[mtl_attr.location].format_conversion_mode = + (GPUVertFetchMode)a->fetch_mode; + BLI_assert(desc.vertex_descriptor.attributes[mtl_attr.location].format != + MTLVertexFormatInvalid); + } + desc.vertex_descriptor.attributes[mtl_attr.location].offset = attribute_offset; + desc.vertex_descriptor.attributes[mtl_attr.location].buffer_index = buffer_index; + desc.vertex_descriptor.num_attributes = ((mtl_attr.location + 1) > + desc.vertex_descriptor.num_attributes) ? + (mtl_attr.location + 1) : + desc.vertex_descriptor.num_attributes; + + /* SSBO Vertex Fetch attribute bind. */ + if (active_shader_->get_uses_ssbo_vertex_fetch()) { + BLI_assert_msg(desc.vertex_descriptor.attributes[mtl_attr.location].format == + mtl_attr.format, + "SSBO Vertex Fetch does not support attribute conversion."); + + MTLSSBOAttribute ssbo_attr( + mtl_attr.index, + buffer_index, + attribute_offset, + buffer_stride, + MTLShader::ssbo_vertex_type_to_attr_type( + desc.vertex_descriptor.attributes[mtl_attr.location].format), + instanced); + + active_shader_->ssbo_vertex_fetch_bind_attribute(ssbo_attr); + desc.vertex_descriptor.ssbo_attributes[desc.vertex_descriptor.num_ssbo_attributes] = + ssbo_attr; + desc.vertex_descriptor.num_ssbo_attributes++; + } + + /* NOTE: We are setting num_attributes to be up to the maximum found index, because of + * this, it is possible that we may skip over certain attributes if they were not in the + * source GPUVertFormat. */ + MTL_LOG_INFO( + " -- Batch Attribute(%d): ORIG Shader Format: %d, ORIG Vert format: %d, Vert " + "components: %d, Fetch Mode %d --> FINAL FORMAT: %d\n", + mtl_attr.location, + (int)mtl_attr.format, + (int)a->comp_type, + (int)a->comp_len, + (int)a->fetch_mode, + (int)desc.vertex_descriptor.attributes[mtl_attr.location].format); + + MTL_LOG_INFO( + " -- [Batch] matching %s attribute '%s' (Attribute Index: %d, Buffer index: %d, " + "offset: %d)\n", + (instanced) ? "instance" : "vertex", + name, + mtl_attr.location, + buffer_index, + attribute_offset); + } + } + } + } + if (buffer_added) { + return buffer_index; + } + return -1; +} + +id MTLBatch::bind(uint v_first, uint v_count, uint i_first, uint i_count) +{ + /* Setup draw call and render pipeline state here. Called by every draw, but setup here so that + * MTLDrawList only needs to perform setup a single time. */ + BLI_assert(this); + + /* Fetch Metal device. */ + MTLContext *ctx = MTLContext::get(); + if (!ctx) { + BLI_assert_msg(false, "No context available for rendering."); + return nil; + } + + /* Verify Shader. */ + active_shader_ = (shader) ? static_cast(unwrap(shader)) : nullptr; + + if (active_shader_ == nullptr || !active_shader_->is_valid()) { + /* Skip drawing if there is no vaid Metal shader. + * This will occur if the path through which the shader is prepared + * is invalid (e.g. Python without create-info), or, the source shader uses a geometry pass. */ + BLI_assert_msg(false, "No valid Metal shader!"); + return nil; + } + + /* Check if using SSBO Fetch Mode. + * This is an alternative drawing mode to geometry shaders, wherein vertex buffers + * are bound as readable (random-access) GPU buffers and certain descriptor properties + * are passed using Shader uniforms. */ + bool uses_ssbo_fetch = active_shader_->get_uses_ssbo_vertex_fetch(); + + /* Prepare Vertex Descriptor and extract VertexBuffers to bind. */ + MTLVertBuf *buffers[GPU_BATCH_VBO_MAX_LEN] = {nullptr}; + int num_buffers = 0; + + /* Ensure Index Buffer is ready. */ + MTLIndexBuf *mtl_elem = static_cast(reinterpret_cast(this->elem)); + if (mtl_elem != NULL) { + mtl_elem->upload_data(); + } + + /* Populate vertex descriptor with attribute binding information. + * The vertex descriptor and buffer layout descriptors describe + * how vertex data from bound vertex buffers maps to the + * shader's input. + * A unique vertex descriptor will result in a new PipelineStateObject + * being generated for the currently bound shader. */ + prepare_vertex_descriptor_and_bindings(buffers, num_buffers, v_first, v_count, i_first, i_count); + + /* Prepare Vertex Buffers - Run before RenderCommandEncoder in case BlitCommandEncoder buffer + * data operations are required. */ + for (int i = 0; i < num_buffers; i++) { + MTLVertBuf *buf_at_index = buffers[i]; + if (buf_at_index == NULL) { + BLI_assert_msg( + false, + "Total buffer count does not match highest buffer index, could be gaps in bindings"); + continue; + } + + MTLVertBuf *mtlvbo = static_cast(reinterpret_cast(buf_at_index)); + mtlvbo->bind(); + } + + /* Ensure render pass is active and fetch active RenderCommandEncoder. */ + id rec = ctx->ensure_begin_render_pass(); + + /* Fetch RenderPassState to enable resource binding for active pass. */ + MTLRenderPassState &rps = ctx->main_command_buffer.get_render_pass_state(); + + /* Debug Check: Ensure Framebuffer instance is not dirty. */ + BLI_assert(!ctx->main_command_buffer.get_active_framebuffer()->get_dirty()); + + /* Bind Shader. */ + this->shader_bind(); + + /* GPU debug markers. */ + if (G.debug & G_DEBUG_GPU) { + [rec pushDebugGroup:[NSString stringWithFormat:@"batch_bind%@(shader: %s)", + this->elem ? @"(indexed)" : @"", + active_shader_->get_interface()->get_name()]]; + [rec insertDebugSignpost:[NSString + stringWithFormat:@"batch_bind%@(shader: %s)", + this->elem ? @"(indexed)" : @"", + active_shader_->get_interface()->get_name()]]; + } + + /* Ensure Context Render Pipeline State is fully setup and ready to execute the draw. */ + MTLPrimitiveType mtl_prim_type = gpu_prim_type_to_metal(this->prim_type); + if (!ctx->ensure_render_pipeline_state(mtl_prim_type)) { + printf("FAILED TO ENSURE RENDER PIPELINE STATE"); + BLI_assert(false); + + if (G.debug & G_DEBUG_GPU) { + [rec popDebugGroup]; + } + return nil; + } + + /*** Bind Vertex Buffers and Index Buffers **/ + + /* SSBO Vertex Fetch Buffer bindings. */ + if (uses_ssbo_fetch) { + + /* SSBO Vertex Fetch - Bind Index Buffer to appropriate slot -- if used. */ + id idx_buffer = nil; + GPUPrimType final_prim_type = this->prim_type; + + if (mtl_elem != nullptr) { + + /* Fetch index buffer. This function can situationally return an optimised + * index buffer of a different primtiive type. If this is the case, `final_prim_type` + * and `v_count` will be updated with the new format. + * NOTE: For indexed rendering, v_count represents the number of indices. */ + idx_buffer = mtl_elem->get_index_buffer(final_prim_type, v_count); + BLI_assert(idx_buffer != nil); + + /* Update uniforms for SSBO-vertex-fetch-mode indexed rendering to flag usage. */ + int &uniform_ssbo_index_mode_u16 = active_shader_->uni_ssbo_uses_index_mode_u16; + BLI_assert(uniform_ssbo_index_mode_u16 != -1); + int uses_index_mode_u16 = (mtl_elem->index_type_ == GPU_INDEX_U16) ? 1 : 0; + active_shader_->uniform_int(uniform_ssbo_index_mode_u16, 1, 1, &uses_index_mode_u16); + } + else { + idx_buffer = ctx->get_null_buffer(); + } + rps.bind_vertex_buffer(idx_buffer, 0, MTL_SSBO_VERTEX_FETCH_IBO_INDEX); + + /* Ensure all attributes are set */ + active_shader_->ssbo_vertex_fetch_bind_attributes_end(rec); + + /* Bind NULL Buffers for unused vertex data slots. */ + id null_buffer = ctx->get_null_buffer(); + BLI_assert(null_buffer != nil); + for (int i = num_buffers; i < MTL_SSBO_VERTEX_FETCH_MAX_VBOS; i++) { + if (rps.cached_vertex_buffer_bindings[i].metal_buffer == nil) { + rps.bind_vertex_buffer(null_buffer, 0, i); + } + } + + /* Flag whether Indexed rendering is used or not. */ + int &uniform_ssbo_use_indexed = active_shader_->uni_ssbo_uses_indexed_rendering; + BLI_assert(uniform_ssbo_use_indexed != -1); + int uses_indexed_rendering = (mtl_elem != NULL) ? 1 : 0; + active_shader_->uniform_int(uniform_ssbo_use_indexed, 1, 1, &uses_indexed_rendering); + + /* Set SSBO-fetch-mode status uniforms. */ + BLI_assert(active_shader_->uni_ssbo_input_prim_type_loc != -1); + BLI_assert(active_shader_->uni_ssbo_input_vert_count_loc != -1); + GPU_shader_uniform_vector_int(reinterpret_cast(wrap(active_shader_)), + active_shader_->uni_ssbo_input_prim_type_loc, + 1, + 1, + (const int *)(&final_prim_type)); + GPU_shader_uniform_vector_int(reinterpret_cast(wrap(active_shader_)), + active_shader_->uni_ssbo_input_vert_count_loc, + 1, + 1, + (const int *)(&v_count)); + } + + /* Bind Vertex Buffers. */ + for (int i = 0; i < num_buffers; i++) { + MTLVertBuf *buf_at_index = buffers[i]; + if (buf_at_index == NULL) { + BLI_assert_msg( + false, + "Total buffer count does not match highest buffer index, could be gaps in bindings"); + continue; + } + /* Buffer handle. */ + MTLVertBuf *mtlvbo = static_cast(reinterpret_cast(buf_at_index)); + mtlvbo->flag_used(); + + /* Fetch buffer from MTLVertexBuffer and bind. */ + id mtl_buffer = mtlvbo->get_metal_buffer(); + + BLI_assert(mtl_buffer != nil); + rps.bind_vertex_buffer(mtl_buffer, 0, i); + } + + if (G.debug & G_DEBUG_GPU) { + [rec popDebugGroup]; + } + + /* Return Render Command Encoder used with setup. */ + return rec; +} + +void MTLBatch::unbind() +{ +} + +void MTLBatch::prepare_vertex_descriptor_and_bindings( + MTLVertBuf **buffers, int &num_buffers, int v_first, int v_count, int i_first, int i_count) +{ + + /* Here we populate the MTLContext vertex descriptor and resolve which buffers need to be bound. + */ + MTLStateManager *state_manager = static_cast( + MTLContext::get()->state_manager); + MTLRenderPipelineStateDescriptor &desc = state_manager->get_pipeline_descriptor(); + const MTLShaderInterface *interface = active_shader_->get_interface(); + uint16_t attr_mask = interface->get_enabled_attribute_mask(); + + /* Reset vertex descriptor to default state. */ + desc.reset_vertex_descriptor(); + + /* Fetch Vertex and Instance Buffers. */ + Span mtl_verts(reinterpret_cast(this->verts), GPU_BATCH_VBO_MAX_LEN); + Span mtl_inst(reinterpret_cast(this->inst), GPU_BATCH_INST_VBO_MAX_LEN); + + /* SSBO Vertex fetch also passes vertex descriptor information into the shader. */ + if (active_shader_->get_uses_ssbo_vertex_fetch()) { + active_shader_->ssbo_vertex_fetch_bind_attributes_begin(); + } + + /* Resolve Metal vertex buffer bindings. */ + /* Vertex Descriptors + * ------------------ + * Vertex Descriptors are required to generate a pipeline state, based on the current Batch's + * buffer bindings. These bindings are a unique matching, depending on what input attributes a + * batch has in its buffers, and those which are supported by the shader interface. + + * We iterate through the buffers and resolve which attributes satisfy the requirements of the + * currently bound shader. We cache this data, for a given Batch<->ShderInterface pairing in a + * VAO cache to avoid the need to recalculate this data. */ + bool buffer_is_instanced[GPU_BATCH_VBO_MAX_LEN] = {false}; + + VertexDescriptorShaderInterfacePair *descriptor = this->vao_cache.find(interface); + if (descriptor) { + desc.vertex_descriptor = descriptor->vertex_descriptor; + attr_mask = descriptor->attr_mask; + num_buffers = descriptor->num_buffers; + + for (int bid = 0; bid < GPU_BATCH_VBO_MAX_LEN; ++bid) { + if (descriptor->bufferIds[bid].used) { + if (descriptor->bufferIds[bid].is_instance) { + buffers[bid] = mtl_inst[descriptor->bufferIds[bid].id]; + buffer_is_instanced[bid] = true; + } + else { + buffers[bid] = mtl_verts[descriptor->bufferIds[bid].id]; + buffer_is_instanced[bid] = false; + } + } + } + + /* Use cached ssbo attribute binding data. */ + if (active_shader_->get_uses_ssbo_vertex_fetch()) { + BLI_assert(desc.vertex_descriptor.uses_ssbo_vertex_fetch); + for (int attr_id = 0; attr_id < desc.vertex_descriptor.num_ssbo_attributes; attr_id++) { + active_shader_->ssbo_vertex_fetch_bind_attribute( + desc.vertex_descriptor.ssbo_attributes[attr_id]); + } + } + } + else { + VertexDescriptorShaderInterfacePair pair{}; + pair.interface = interface; + + for (int i = 0; i < GPU_BATCH_VBO_MAX_LEN; ++i) { + pair.bufferIds[i].id = -1; + pair.bufferIds[i].is_instance = 0; + pair.bufferIds[i].used = 0; + } + /* NOTE: Attribute extraction order from buffer is the reverse of the OpenGL as we flag once an + * attribute is found, rather than pre-setting the mask. */ + /* Extract Instance attributes (These take highest priority). */ + for (int v = 0; v < GPU_BATCH_INST_VBO_MAX_LEN; v++) { + if (mtl_inst[v]) { + MTL_LOG_INFO(" -- [Batch] Checking bindings for bound instance buffer %p\n", mtl_inst[v]); + int buffer_ind = this->prepare_vertex_binding( + mtl_inst[v], desc, interface, attr_mask, true); + if (buffer_ind >= 0) { + buffers[buffer_ind] = mtl_inst[v]; + buffer_is_instanced[buffer_ind] = true; + + pair.bufferIds[buffer_ind].id = v; + pair.bufferIds[buffer_ind].used = 1; + pair.bufferIds[buffer_ind].is_instance = 1; + num_buffers = ((buffer_ind + 1) > num_buffers) ? (buffer_ind + 1) : num_buffers; + } + } + } + + /* Extract Vertex attribues (First-bound vertex buffer takes priority). */ + for (int v = 0; v < GPU_BATCH_VBO_MAX_LEN; v++) { + if (mtl_verts[v] != NULL) { + MTL_LOG_INFO(" -- [Batch] Checking bindings for bound vertex buffer %p\n", mtl_verts[v]); + int buffer_ind = this->prepare_vertex_binding( + mtl_verts[v], desc, interface, attr_mask, false); + if (buffer_ind >= 0) { + buffers[buffer_ind] = mtl_verts[v]; + buffer_is_instanced[buffer_ind] = false; + + pair.bufferIds[buffer_ind].id = v; + pair.bufferIds[buffer_ind].used = 1; + pair.bufferIds[buffer_ind].is_instance = 0; + num_buffers = ((buffer_ind + 1) > num_buffers) ? (buffer_ind + 1) : num_buffers; + } + } + } + + /* Add to VertexDescriptor cache */ + desc.vertex_descriptor.uses_ssbo_vertex_fetch = active_shader_->get_uses_ssbo_vertex_fetch(); + pair.attr_mask = attr_mask; + pair.vertex_descriptor = desc.vertex_descriptor; + pair.num_buffers = num_buffers; + if (!this->vao_cache.insert(pair)) { + printf( + "[Performance Warning] cache is full (Size: %d), vertex descriptor will not be cached\n", + GPU_VAO_STATIC_LEN); + } + } + +/* DEBUG: verify if our attribute bindings have been fully provided as expected. */ +#if MTL_DEBUG_SHADER_ATTRIBUTES == 1 + if (attr_mask != 0) { + for (uint16_t mask = 1, a = 0; a < 16; a++, mask <<= 1) { + if (attr_mask & mask) { + /* Fallback for setting default attributes, for missed slots. Attributes flagged with + * 'MTLVertexFormatInvalid' in the vertex descriptor are bound to a NULL buffer during PSO + * creation. */ + MTL_LOG_WARNING("MTLBatch: Missing expected attribute '%s' at index '%d' for shader: %s\n", + this->active_shader->interface->attributes[a].name, + a, + interface->name); + /* Ensure any assigned attribute has not been given an invalid format. This should not + * occur and may be the result of an unsupported attribute type conversion. */ + BLI_assert(desc.attributes[a].format == MTLVertexFormatInvalid); + } + } + } +#endif +} + +void MTLBatch::draw_advanced(int v_first, int v_count, int i_first, int i_count) +{ + +#if TRUST_NO_ONE + BLI_assert(v_count > 0 && i_count > 0); +#endif + + /* Setup RenderPipelineState for batch. */ + MTLContext *ctx = reinterpret_cast(GPU_context_active_get()); + id rec = this->bind(v_first, v_count, i_first, i_count); + if (rec == nil) { + return; + } + + /* Fetch IndexBuffer and resolve primitive type. */ + MTLIndexBuf *mtl_elem = static_cast(reinterpret_cast(this->elem)); + MTLPrimitiveType mtl_prim_type = gpu_prim_type_to_metal(this->prim_type); + + /* Render using SSBO Vertex Fetch. */ + if (active_shader_->get_uses_ssbo_vertex_fetch()) { + + /* Submit draw call with modified vertex count, which reflects vertices per primitive defined + * in the USE_SSBO_VERTEX_FETCH pragma. */ + int num_input_primitives = gpu_get_prim_count_from_type(v_count, this->prim_type); + int output_num_verts = num_input_primitives * + active_shader_->get_ssbo_vertex_fetch_output_num_verts(); + BLI_assert_msg( + mtl_vertex_count_fits_primitive_type( + output_num_verts, active_shader_->get_ssbo_vertex_fetch_output_prim_type()), + "Output Vertex count is not compatible with the requested output vertex primitive type"); + [rec drawPrimitives:active_shader_->get_ssbo_vertex_fetch_output_prim_type() + vertexStart:0 + vertexCount:output_num_verts + instanceCount:i_count + baseInstance:i_first]; + ctx->main_command_buffer.register_draw_counters(output_num_verts * i_count); + } + /* Perform regular draw. */ + else if (mtl_elem == NULL) { + + /* Primitive Type toplogy emulation. */ + if (mtl_needs_topology_emulation(this->prim_type)) { + + /* Generate index buffer for primitive types requiring emulation. */ + GPUPrimType emulated_prim_type = this->prim_type; + uint32_t emulated_v_count = v_count; + id generated_index_buffer = this->get_emulated_toplogy_buffer(emulated_prim_type, + emulated_v_count); + BLI_assert(generated_index_buffer != nil); + + MTLPrimitiveType emulated_mtl_prim_type = gpu_prim_type_to_metal(emulated_prim_type); + + /* Temp: Disable culling for emulated primitive types. + * TODO(Metal): Support face winding in topology buffer. */ + [rec setCullMode:MTLCullModeNone]; + + if (generated_index_buffer != nil) { + BLI_assert(emulated_mtl_prim_type == MTLPrimitiveTypeTriangle || + emulated_mtl_prim_type == MTLPrimitiveTypeLine); + if (emulated_mtl_prim_type == MTLPrimitiveTypeTriangle) { + BLI_assert(emulated_v_count % 3 == 0); + } + if (emulated_mtl_prim_type == MTLPrimitiveTypeLine) { + BLI_assert(emulated_v_count % 2 == 0); + } + + /* Set depth stencil state (requires knowledge of primitive type). */ + ctx->ensure_depth_stencil_state(emulated_mtl_prim_type); + + [rec drawIndexedPrimitives:emulated_mtl_prim_type + indexCount:emulated_v_count + indexType:MTLIndexTypeUInt32 + indexBuffer:generated_index_buffer + indexBufferOffset:0 + instanceCount:i_count + baseVertex:v_first + baseInstance:i_first]; + } + else { + printf("[Note] Cannot draw batch -- Emulated Topology mode: %u not yet supported\n", + this->prim_type); + } + } + else { + /* Set depth stencil state (requires knowledge of primitive type). */ + ctx->ensure_depth_stencil_state(mtl_prim_type); + + /* Issue draw call. */ + [rec drawPrimitives:mtl_prim_type + vertexStart:v_first + vertexCount:v_count + instanceCount:i_count + baseInstance:i_first]; + } + ctx->main_command_buffer.register_draw_counters(v_count * i_count); + } + /* Perform indexed draw. */ + else { + + MTLIndexType index_type = MTLIndexBuf::gpu_index_type_to_metal(mtl_elem->index_type_); + uint32_t base_index = mtl_elem->index_base_; + uint32_t index_size = (mtl_elem->index_type_ == GPU_INDEX_U16) ? 2 : 4; + uint32_t v_first_ofs = ((v_first + mtl_elem->index_start_) * index_size); + BLI_assert_msg((v_first_ofs % index_size) == 0, + "Index offset is not 2/4-byte aligned as per METAL spec"); + + /* Fetch index buffer. May return an index buffer of a differing format, + * if index buffer optimisation is used. In these cases, final_prim_type and + * index_count get updated with the new properties. */ + GPUPrimType final_prim_type = this->prim_type; + uint index_count = v_count; + + id index_buffer = mtl_elem->get_index_buffer(final_prim_type, index_count); + mtl_prim_type = gpu_prim_type_to_metal(final_prim_type); + BLI_assert(index_buffer != nil); + + if (index_buffer != nil) { + + /* Set depth stencil state (requires knowledge of primitive type). */ + ctx->ensure_depth_stencil_state(mtl_prim_type); + + /* Issue draw call. */ + [rec drawIndexedPrimitives:mtl_prim_type + indexCount:index_count + indexType:index_type + indexBuffer:index_buffer + indexBufferOffset:v_first_ofs + instanceCount:i_count + baseVertex:base_index + baseInstance:i_first]; + ctx->main_command_buffer.register_draw_counters(index_count * i_count); + } + else { + BLI_assert_msg(false, "Index buffer does not have backing Metal buffer"); + } + } + + /* End of draw. */ + this->unbind(); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Topology emulation and optimization + * \{ */ + +id MTLBatch::get_emulated_toplogy_buffer(GPUPrimType &in_out_prim_type, + uint32_t &in_out_v_count) +{ + + BLI_assert(in_out_v_count > 0); + /* Determine emulated primitive types. */ + GPUPrimType input_prim_type = in_out_prim_type; + uint32_t v_count = in_out_v_count; + GPUPrimType output_prim_type; + switch (input_prim_type) { + case GPU_PRIM_POINTS: + case GPU_PRIM_LINES: + case GPU_PRIM_TRIS: + BLI_assert_msg(false, "Optimal primitive types should not reach here."); + return nil; + break; + case GPU_PRIM_LINES_ADJ: + case GPU_PRIM_TRIS_ADJ: + BLI_assert_msg(false, "Adjacency primitive types should not reach here."); + return nil; + break; + case GPU_PRIM_LINE_STRIP: + case GPU_PRIM_LINE_LOOP: + case GPU_PRIM_LINE_STRIP_ADJ: + output_prim_type = GPU_PRIM_LINES; + break; + case GPU_PRIM_TRI_STRIP: + case GPU_PRIM_TRI_FAN: + output_prim_type = GPU_PRIM_TRIS; + break; + default: + BLI_assert_msg(false, "Invalid primitive type."); + return nil; + } + + /* Check if topology buffer exists and is valid. */ + if (this->emulated_topology_buffer_ != nullptr && + (emulated_topology_type_ != input_prim_type || topology_buffer_input_v_count_ != v_count)) { + + /* Release existing topology buffer. */ + emulated_topology_buffer_->free(); + emulated_topology_buffer_ = nullptr; + } + + /* Generate new topology index buffer. */ + if (this->emulated_topology_buffer_ == nullptr) { + /* Calculate IB len. */ + uint32_t output_prim_count = 0; + switch (input_prim_type) { + case GPU_PRIM_LINE_STRIP: + case GPU_PRIM_LINE_STRIP_ADJ: + output_prim_count = v_count - 1; + break; + case GPU_PRIM_LINE_LOOP: + output_prim_count = v_count; + break; + case GPU_PRIM_TRI_STRIP: + case GPU_PRIM_TRI_FAN: + output_prim_count = v_count - 2; + break; + default: + BLI_assert_msg(false, "Cannot generate optimized topology buffer for other types."); + break; + } + uint32_t output_IB_elems = output_prim_count * ((output_prim_type == GPU_PRIM_TRIS) ? 3 : 2); + + /* Allocate buffer. */ + uint32_t buffer_bytes = output_IB_elems * 4; + BLI_assert(buffer_bytes > 0); + this->emulated_topology_buffer_ = MTLContext::get_global_memory_manager().allocate( + buffer_bytes, true); + + /* Populate. */ + uint32_t *data = (uint32_t *)this->emulated_topology_buffer_->get_host_ptr(); + BLI_assert(data != nullptr); + + /* TODO(Metal): Support inverse winding modes. */ + bool winding_clockwise = false; + UNUSED_VARS(winding_clockwise); + + switch (input_prim_type) { + /* Line Loop. */ + case GPU_PRIM_LINE_LOOP: { + int line = 0; + for (line = 0; line < output_prim_count - 1; line++) { + data[line * 3 + 0] = line + 0; + data[line * 3 + 1] = line + 1; + } + /* Closing line. */ + data[line * 2 + 0] = line + 0; + data[line * 2 + 1] = 0; + } break; + + /* Triangle Fan. */ + case GPU_PRIM_TRI_FAN: { + for (int triangle = 0; triangle < output_prim_count; triangle++) { + data[triangle * 3 + 0] = 0; /* Always 0 */ + data[triangle * 3 + 1] = triangle + 1; + data[triangle * 3 + 2] = triangle + 2; + } + } break; + + default: + BLI_assert_msg(false, "Other primitive types do not require emulation."); + return nil; + } + + /* Flush. */ + this->emulated_topology_buffer_->flush(); + /* Assign members relating to current cached IB. */ + topology_buffer_input_v_count_ = v_count; + topology_buffer_output_v_count_ = output_IB_elems; + emulated_topology_type_ = input_prim_type; + } + + /* Return. */ + in_out_v_count = topology_buffer_output_v_count_; + in_out_prim_type = output_prim_type; + return (emulated_topology_buffer_) ? emulated_topology_buffer_->get_metal_buffer() : nil; +} + +/** \} */ + +} // blender::gpu diff --git a/source/blender/gpu/metal/mtl_context.mm b/source/blender/gpu/metal/mtl_context.mm index ef66a1f2111..50576379f0d 100644 --- a/source/blender/gpu/metal/mtl_context.mm +++ b/source/blender/gpu/metal/mtl_context.mm @@ -995,19 +995,21 @@ bool MTLContext::ensure_uniform_buffer_bindings( if (ubo.buffer_index >= 0) { - const uint32_t buffer_index = ubo.buffer_index; + /* Uniform Buffer index offset by 1 as the first shader buffer binding slot is reserved for + * the uniform PushConstantBlock. */ + const uint32_t buffer_index = ubo.buffer_index + 1; int ubo_offset = 0; id ubo_buffer = nil; int ubo_size = 0; bool bind_dummy_buffer = false; - if (this->pipeline_state.ubo_bindings[buffer_index].bound) { + if (this->pipeline_state.ubo_bindings[ubo_index].bound) { /* Fetch UBO global-binding properties from slot. */ ubo_offset = 0; - ubo_buffer = this->pipeline_state.ubo_bindings[buffer_index].ubo->get_metal_buffer( + ubo_buffer = this->pipeline_state.ubo_bindings[ubo_index].ubo->get_metal_buffer( &ubo_offset); - ubo_size = this->pipeline_state.ubo_bindings[buffer_index].ubo->get_size(); + ubo_size = this->pipeline_state.ubo_bindings[ubo_index].ubo->get_size(); /* Use dummy zero buffer if no buffer assigned -- this is an optimization to avoid * allocating zero buffers. */ diff --git a/source/blender/gpu/metal/mtl_drawlist.hh b/source/blender/gpu/metal/mtl_drawlist.hh index ed99c76faa7..47055f3d7f4 100644 --- a/source/blender/gpu/metal/mtl_drawlist.hh +++ b/source/blender/gpu/metal/mtl_drawlist.hh @@ -9,34 +9,50 @@ #pragma once -#pragma once - +#include "BLI_sys_types.h" +#include "GPU_batch.h" +#include "MEM_guardedalloc.h" #include "gpu_drawlist_private.hh" -namespace blender { -namespace gpu { +#include "mtl_batch.hh" +#include "mtl_context.hh" + +namespace blender::gpu { /** - * TODO(Metal): MTLDrawList Implementation. Included as temporary stub. - */ + * Implementation of Multi Draw Indirect using OpenGL. + **/ class MTLDrawList : public DrawList { + + private: + /** Batch for which we are recording commands for. */ + MTLBatch *batch_; + /** Mapped memory bounds. */ + void *data_; + /** Length of the mapped buffer (in byte). */ + size_t data_size_; + /** Current offset inside the mapped buffer (in byte). */ + size_t command_offset_; + /** Current number of command recorded inside the mapped buffer. */ + uint32_t command_len_; + /** Is UINT_MAX if not drawing indexed geom. Also Avoid dereferencing batch. */ + uint32_t base_index_; + /** Also Avoid dereferencing batch. */ + uint32_t v_first_, v_count_; + /** Length of whole the buffer (in byte). */ + uint32_t buffer_size_; + public: - MTLDrawList(int length) - { - } - ~MTLDrawList() - { - } - - void append(GPUBatch *batch, int i_first, int i_count) override - { - } - void submit() override - { - } + MTLDrawList(int length); + ~MTLDrawList(); + + void append(GPUBatch *batch, int i_first, int i_count) override; + void submit() override; + + private: + void init(); MEM_CXX_CLASS_ALLOC_FUNCS("MTLDrawList"); }; -} // namespace gpu -} // namespace blender +} // namespace blender::gpu diff --git a/source/blender/gpu/metal/mtl_drawlist.mm b/source/blender/gpu/metal/mtl_drawlist.mm new file mode 100644 index 00000000000..76e2abb4ea6 --- /dev/null +++ b/source/blender/gpu/metal/mtl_drawlist.mm @@ -0,0 +1,282 @@ +/** \file + * \ingroup gpu + * + * Implementation of Multi Draw Indirect using OpenGL. + * Fallback if the needed extensions are not supported. + */ + +#include "BLI_assert.h" + +#include "GPU_batch.h" +#include "mtl_common.hh" +#include "mtl_drawlist.hh" +#include "mtl_primitive.hh" + +using namespace blender::gpu; + +namespace blender::gpu { + +/* Indirect draw call structure for reference. */ +/* MTLDrawPrimitivesIndirectArguments -- + * https://developer.apple.com/documentation/metal/mtldrawprimitivesindirectarguments?language=objc + */ +/* struct MTLDrawPrimitivesIndirectArguments { + * uint32_t vertexCount; + * uint32_t instanceCount; + * uint32_t vertexStart; + * uint32_t baseInstance; +};*/ + +/* MTLDrawIndexedPrimitivesIndirectArguments -- + * https://developer.apple.com/documentation/metal/mtldrawindexedprimitivesindirectarguments?language=objc + */ +/* struct MTLDrawIndexedPrimitivesIndirectArguments { + * uint32_t indexCount; + * uint32_t instanceCount; + * uint32_t indexStart; + * uint32_t baseVertex; + * uint32_t baseInstance; +};*/ + +#define MDI_ENABLED (buffer_size_ != 0) +#define MDI_DISABLED (buffer_size_ == 0) +#define MDI_INDEXED (base_index_ != UINT_MAX) + +MTLDrawList::MTLDrawList(int length) +{ + BLI_assert(length > 0); + batch_ = nullptr; + command_len_ = 0; + base_index_ = 0; + command_offset_ = 0; + data_size_ = 0; + buffer_size_ = sizeof(MTLDrawIndexedPrimitivesIndirectArguments) * length; + data_ = (void *)MEM_mallocN(buffer_size_, __func__); +} + +MTLDrawList::~MTLDrawList() +{ + if (data_) { + MEM_freeN(data_); + data_ = nullptr; + } +} + +void MTLDrawList::init() +{ + MTLContext *ctx = reinterpret_cast(GPU_context_active_get()); + BLI_assert(ctx); + BLI_assert(MDI_ENABLED); + BLI_assert(data_ == nullptr); + UNUSED_VARS_NDEBUG(ctx); + + batch_ = nullptr; + command_len_ = 0; + BLI_assert(data_); + + command_offset_ = 0; +} + +void MTLDrawList::append(GPUBatch *gpu_batch, int i_first, int i_count) +{ + /* Fallback when MultiDrawIndirect is not supported/enabled. */ + MTLShader *shader = static_cast(unwrap(gpu_batch->shader)); + bool requires_ssbo = (shader->get_uses_ssbo_vertex_fetch()); + bool requires_emulation = mtl_needs_topology_emulation(gpu_batch->prim_type); + if (MDI_DISABLED || requires_ssbo || requires_emulation) { + GPU_batch_draw_advanced(gpu_batch, 0, 0, i_first, i_count); + return; + } + + if (data_ == nullptr) { + this->init(); + } + BLI_assert(data_); + + MTLBatch *mtl_batch = static_cast(gpu_batch); + BLI_assert(mtl_batch); + if (mtl_batch != batch_) { + /* Submit existing calls. */ + this->submit(); + + /* Begin new batch. */ + batch_ = mtl_batch; + + /* Cached for faster access. */ + MTLIndexBuf *el = batch_->elem_(); + base_index_ = el ? el->index_base_ : UINT_MAX; + v_first_ = el ? el->index_start_ : 0; + v_count_ = el ? el->index_len_ : batch_->verts_(0)->vertex_len; + } + + if (v_count_ == 0) { + /* Nothing to draw. */ + return; + } + + if (MDI_INDEXED) { + MTLDrawIndexedPrimitivesIndirectArguments *cmd = + reinterpret_cast((char *)data_ + + command_offset_); + cmd->indexStart = v_first_; + cmd->indexCount = v_count_; + cmd->instanceCount = i_count; + cmd->baseVertex = base_index_; + cmd->baseInstance = i_first; + } + else { + MTLDrawPrimitivesIndirectArguments *cmd = + reinterpret_cast((char *)data_ + command_offset_); + cmd->vertexStart = v_first_; + cmd->vertexCount = v_count_; + cmd->instanceCount = i_count; + cmd->baseInstance = i_first; + } + + size_t command_size = MDI_INDEXED ? sizeof(MTLDrawIndexedPrimitivesIndirectArguments) : + sizeof(MTLDrawPrimitivesIndirectArguments); + + command_offset_ += command_size; + command_len_++; + + /* Check if we can fit at least one other command. */ + if (command_offset_ + command_size > buffer_size_) { + this->submit(); + } + + return; +} + +void MTLDrawList::submit() +{ + /* Metal does not support MDI from the host side, but we still benefit from only executing the + * batch bind a single time, rather than per-draw. + * NOTE(Metal): Consider using MTLIndirectCommandBuffer to achieve similar behaviour. */ + if (command_len_ == 0) { + return; + } + + /* Something's wrong if we get here without MDI support. */ + BLI_assert(MDI_ENABLED); + BLI_assert(data_); + + /* Host-side MDI Currently unsupported on Metal. */ + bool can_use_MDI = false; + + /* Verify context. */ + MTLContext *ctx = reinterpret_cast(GPU_context_active_get()); + BLI_assert(ctx); + + /* Execute indirect draw calls. */ + MTLShader *shader = static_cast(unwrap(batch_->shader)); + bool SSBO_MODE = (shader->get_uses_ssbo_vertex_fetch()); + if (SSBO_MODE) { + can_use_MDI = false; + BLI_assert(false); + return; + } + + /* Heuristic to determine whether using indirect drawing is more efficient. */ + size_t command_size = MDI_INDEXED ? sizeof(MTLDrawIndexedPrimitivesIndirectArguments) : + sizeof(MTLDrawPrimitivesIndirectArguments); + const bool is_finishing_a_buffer = (command_offset_ + command_size > buffer_size_); + can_use_MDI = can_use_MDI && (is_finishing_a_buffer || command_len_ > 2); + + /* Bind Batch to setup render pipeline state. */ + id rec = batch_->bind(0, 0, 0, 0); + if (!rec) { + BLI_assert_msg(false, "A RenderCommandEncoder should always be available!\n"); + return; + } + + /* Common properties. */ + MTLPrimitiveType mtl_prim_type = gpu_prim_type_to_metal(batch_->prim_type); + + /* Execute multidraw indirect. */ + if (can_use_MDI && false) { + /* Metal Doesn't support MDI -- Singular Indirect draw calls are supported, + * but Multidraw is not. + * TODO(Metal): Consider using IndirectCommandBuffers to provide similar + * behaviour. */ + } + else { + + /* Execute draws manually. */ + if (MDI_INDEXED) { + MTLDrawIndexedPrimitivesIndirectArguments *cmd = + (MTLDrawIndexedPrimitivesIndirectArguments *)data_; + MTLIndexBuf *mtl_elem = static_cast( + reinterpret_cast(batch_->elem)); + BLI_assert(mtl_elem); + MTLIndexType index_type = MTLIndexBuf::gpu_index_type_to_metal(mtl_elem->index_type_); + uint32_t index_size = (mtl_elem->index_type_ == GPU_INDEX_U16) ? 2 : 4; + uint32_t v_first_ofs = (mtl_elem->index_start_ * index_size); + uint32_t index_count = cmd->indexCount; + + /* Fetch index buffer. May return an index buffer of a differing format, + * if index buffer optimisation is used. In these cases, mtl_prim_type and + * index_count get updated with the new properties. */ + GPUPrimType final_prim_type = batch_->prim_type; + id index_buffer = mtl_elem->get_index_buffer(final_prim_type, index_count); + BLI_assert(index_buffer != nil); + + /* Final primitive type. */ + mtl_prim_type = gpu_prim_type_to_metal(final_prim_type); + + if (index_buffer != nil) { + + /* Set depth stencil state (requires knowledge of primitive type). */ + ctx->ensure_depth_stencil_state(mtl_prim_type); + + for (int i = 0; i < command_len_; i++, cmd++) { + [rec drawIndexedPrimitives:mtl_prim_type + indexCount:index_count + indexType:index_type + indexBuffer:index_buffer + indexBufferOffset:v_first_ofs + instanceCount:cmd->instanceCount + baseVertex:cmd->baseVertex + baseInstance:cmd->baseInstance]; + ctx->main_command_buffer.register_draw_counters(cmd->indexCount * cmd->instanceCount); + } + } + else { + BLI_assert_msg(false, "Index buffer does not have backing Metal buffer"); + } + } + else { + MTLDrawPrimitivesIndirectArguments *cmd = (MTLDrawPrimitivesIndirectArguments *)data_; + + /* Verify if topology emulation is required. */ + if (mtl_needs_topology_emulation(batch_->prim_type)) { + BLI_assert_msg(false, "topology emulation cases should use fallback."); + } + else { + + /* Set depth stencil state (requires knowledge of primitive type). */ + ctx->ensure_depth_stencil_state(mtl_prim_type); + + for (int i = 0; i < command_len_; i++, cmd++) { + [rec drawPrimitives:mtl_prim_type + vertexStart:cmd->vertexStart + vertexCount:cmd->vertexCount + instanceCount:cmd->instanceCount + baseInstance:cmd->baseInstance]; + ctx->main_command_buffer.register_draw_counters(cmd->vertexCount * cmd->instanceCount); + } + } + } + } + + /* Unbind batch. */ + batch_->unbind(); + + /* Reset command offsets. */ + command_len_ = 0; + command_offset_ = 0; + + /* Avoid keeping reference to the batch. */ + batch_ = nullptr; +} + +} // namespace blender::gpu diff --git a/source/blender/gpu/metal/mtl_immediate.mm b/source/blender/gpu/metal/mtl_immediate.mm index 4b63a3b1ce2..ee48bdd6ee1 100644 --- a/source/blender/gpu/metal/mtl_immediate.mm +++ b/source/blender/gpu/metal/mtl_immediate.mm @@ -99,6 +99,9 @@ void MTLImmediate::end() MTLRenderPipelineStateDescriptor &desc = state_manager->get_pipeline_descriptor(); const MTLShaderInterface *interface = active_mtl_shader->get_interface(); + /* Reset vertex descriptor to default state. */ + desc.reset_vertex_descriptor(); + desc.vertex_descriptor.num_attributes = interface->get_total_attributes(); desc.vertex_descriptor.num_vert_buffers = 1; diff --git a/source/blender/gpu/metal/mtl_pso_descriptor_state.hh b/source/blender/gpu/metal/mtl_pso_descriptor_state.hh index 198d309874b..04ceb5bdf03 100644 --- a/source/blender/gpu/metal/mtl_pso_descriptor_state.hh +++ b/source/blender/gpu/metal/mtl_pso_descriptor_state.hh @@ -243,6 +243,19 @@ struct MTLRenderPipelineStateDescriptor { return hash; } + + /* Reset the Vertex Descriptor to default. */ + void reset_vertex_descriptor() + { + vertex_descriptor.num_attributes = 0; + vertex_descriptor.num_vert_buffers = 0; + for (int i = 0; i < GPU_VERT_ATTR_MAX_LEN; i++) { + vertex_descriptor.attributes[i].format = MTLVertexFormatInvalid; + vertex_descriptor.attributes[i].offset = 0; + } + vertex_descriptor.uses_ssbo_vertex_fetch = false; + vertex_descriptor.num_ssbo_attributes = 0; + } }; } // namespace blender::gpu diff --git a/source/blender/gpu/metal/mtl_shader_interface.mm b/source/blender/gpu/metal/mtl_shader_interface.mm index 3703d5b5684..97a82345761 100644 --- a/source/blender/gpu/metal/mtl_shader_interface.mm +++ b/source/blender/gpu/metal/mtl_shader_interface.mm @@ -117,9 +117,7 @@ uint32_t MTLShaderInterface::add_uniform_block(uint32_t name_offset, MTLShaderUniformBlock &uni_block = ubos_[total_uniform_blocks_]; uni_block.name_offset = name_offset; - /* We offset the buffer binding index by one, as the first slot is reserved for push constant - * data. */ - uni_block.buffer_index = buffer_index + 1; + uni_block.buffer_index = buffer_index; uni_block.size = size; uni_block.current_offset = 0; uni_block.stage_mask = ShaderStage::BOTH; @@ -297,8 +295,10 @@ void MTLShaderInterface::prepare_common_shader_inputs() current_input->name_hash = BLI_hash_string(this->get_name_at_offset(shd_ubo.name_offset)); /* Location refers to the index in the ubos_ array. */ current_input->location = ubo_index; - /* Final binding location refers to the buffer binding index within the shader (Relative to - * MTL_uniform_buffer_base_index). */ + /* Binding location refers to the UBO bind slot in + * #MTLContextGlobalShaderPipelineState::ubo_bindings. The buffer bind index [[buffer(N)]] + * within the shader will apply an offset for bound vertex buffers and the default uniform + * PushConstantBlock. */ current_input->binding = shd_ubo.buffer_index; current_input++; } diff --git a/source/blender/gpu/metal/mtl_texture.hh b/source/blender/gpu/metal/mtl_texture.hh index ebc9eb2e00e..28b55306707 100644 --- a/source/blender/gpu/metal/mtl_texture.hh +++ b/source/blender/gpu/metal/mtl_texture.hh @@ -51,9 +51,9 @@ struct TextureUpdateRoutineSpecialisation { uint64_t hash() const { blender::DefaultHash string_hasher; - return uint64_t(string_hasher( + return (uint64_t)string_hasher( this->input_data_type + this->output_data_type + - std::to_string((this->component_count_input << 8) + this->component_count_output))); + std::to_string((this->component_count_input << 8) + this->component_count_output)); } }; diff --git a/source/blender/gpu/metal/mtl_texture.mm b/source/blender/gpu/metal/mtl_texture.mm index 32029db6fd9..4931f8a4f52 100644 --- a/source/blender/gpu/metal/mtl_texture.mm +++ b/source/blender/gpu/metal/mtl_texture.mm @@ -337,20 +337,6 @@ void gpu::MTLTexture::blit(gpu::MTLTexture *dst, GPU_batch_draw(quad); - /* TMP draw with IMM TODO(Metal): Remove this once GPUBatch is supported. */ - GPUVertFormat *imm_format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(imm_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - immBindShader(shader); - immBegin(GPU_PRIM_TRI_STRIP, 4); - immVertex2f(pos, 1, 0); - immVertex2f(pos, 0, 0); - immVertex2f(pos, 1, 1); - immVertex2f(pos, 0, 1); - immEnd(); - immUnbindProgram(); - /**********************/ - /* restoring old pipeline state. */ GPU_depth_mask(depth_write_prev); GPU_stencil_write_mask_set(stencil_mask_prev); @@ -1472,10 +1458,82 @@ bool gpu::MTLTexture::init_internal() bool gpu::MTLTexture::init_internal(GPUVertBuf *vbo) { - /* Not a valid vertex buffer format, though verifying texture is not set as such - * as this is not supported on Apple Silicon. */ - BLI_assert_msg(this->format_ != GPU_DEPTH24_STENCIL8, - "Apple silicon does not support GPU_DEPTH24_S8"); + if (this->format_ == GPU_DEPTH24_STENCIL8) { + /* Apple Silicon requires GPU_DEPTH32F_STENCIL8 instead of GPU_DEPTH24_STENCIL8. */ + this->format_ = GPU_DEPTH32F_STENCIL8; + } + + MTLPixelFormat mtl_format = gpu_texture_format_to_metal(this->format_); + mtl_max_mips_ = 1; + mipmaps_ = 0; + this->mip_range_set(0, 0); + + /* Create texture from GPUVertBuf's buffer. */ + MTLVertBuf *mtl_vbo = static_cast(unwrap(vbo)); + mtl_vbo->bind(); + mtl_vbo->flag_used(); + + /* Get Metal Buffer. */ + id source_buffer = mtl_vbo->get_metal_buffer(); + BLI_assert(source_buffer); + + /* Verify size. */ + if (w_ <= 0) { + MTL_LOG_WARNING("Allocating texture buffer of width 0!\n"); + w_ = 1; + } + + /* Verify Texture and vertex buffer alignment. */ + int bytes_per_pixel = get_mtl_format_bytesize(mtl_format); + int bytes_per_row = bytes_per_pixel * w_; + + MTLContext *mtl_ctx = MTLContext::get(); + uint32_t align_requirement = static_cast( + [mtl_ctx->device minimumLinearTextureAlignmentForPixelFormat:mtl_format]); + + /* Verify per-vertex size aligns with texture size. */ + const GPUVertFormat *format = GPU_vertbuf_get_format(vbo); + BLI_assert(bytes_per_pixel == format->stride && + "Pixel format stride MUST match the texture format stride -- These being different " + "is likely caused by Metal's VBO padding to a minimum of 4-bytes per-vertex"); + UNUSED_VARS_NDEBUG(format); + + /* Create texture descriptor. */ + BLI_assert(type_ == GPU_TEXTURE_BUFFER); + texture_descriptor_ = [[MTLTextureDescriptor alloc] init]; + texture_descriptor_.pixelFormat = mtl_format; + texture_descriptor_.textureType = MTLTextureTypeTextureBuffer; + texture_descriptor_.width = w_; + texture_descriptor_.height = 1; + texture_descriptor_.depth = 1; + texture_descriptor_.arrayLength = 1; + texture_descriptor_.mipmapLevelCount = mtl_max_mips_; + texture_descriptor_.usage = + MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite | + MTLTextureUsagePixelFormatView; /* TODO(Metal): Optimise usage flags. */ + texture_descriptor_.storageMode = [source_buffer storageMode]; + texture_descriptor_.sampleCount = 1; + texture_descriptor_.cpuCacheMode = [source_buffer cpuCacheMode]; + texture_descriptor_.hazardTrackingMode = [source_buffer hazardTrackingMode]; + + texture_ = [source_buffer + newTextureWithDescriptor:texture_descriptor_ + offset:0 + bytesPerRow:ceil_to_multiple_u(bytes_per_row, align_requirement)]; + aligned_w_ = bytes_per_row / bytes_per_pixel; + + BLI_assert(texture_); + texture_.label = [NSString stringWithUTF8String:this->get_name()]; + is_baked_ = true; + is_dirty_ = false; + resource_mode_ = MTL_TEXTURE_MODE_VBO; + + /* Track Status. */ + vert_buffer_ = mtl_vbo; + vert_buffer_mtl_ = source_buffer; + /* Cleanup. */ + [texture_descriptor_ release]; + texture_descriptor_ = nullptr; return true; } @@ -1522,7 +1580,6 @@ bool gpu::MTLTexture::texture_is_baked() /* Prepare texture parameters after initialization, but before baking. */ void gpu::MTLTexture::prepare_internal() { - /* Derive implicit usage flags for Depth/Stencil attachments. */ if (format_flag_ & GPU_FORMAT_DEPTH || format_flag_ & GPU_FORMAT_STENCIL) { gpu_image_usage_flags_ |= GPU_TEXTURE_USAGE_ATTACHMENT; @@ -1687,7 +1744,7 @@ void gpu::MTLTexture::ensure_baked() /* Determine Resource Mode. */ resource_mode_ = MTL_TEXTURE_MODE_DEFAULT; - /* Create texture. */ + /* Standard texture allocation. */ texture_ = [ctx->device newTextureWithDescriptor:texture_descriptor_]; [texture_descriptor_ release]; -- cgit v1.2.3 From 2006c3ed106d7d7931c6f76704765b3842c34fec Mon Sep 17 00:00:00 2001 From: Sebastian Herholz Date: Tue, 18 Oct 2022 13:59:12 +0200 Subject: Fix T101529: Blender crashes when using Path Guiding --- intern/cycles/integrator/path_trace.cpp | 1 + intern/cycles/kernel/integrator/state_flow.h | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/intern/cycles/integrator/path_trace.cpp b/intern/cycles/integrator/path_trace.cpp index 506d962f13d..8e8fbd86be0 100644 --- a/intern/cycles/integrator/path_trace.cpp +++ b/intern/cycles/integrator/path_trace.cpp @@ -1296,6 +1296,7 @@ void PathTrace::set_guiding_params(const GuidingParams &guiding_params, const bo # if OPENPGL_VERSION_MINOR >= 4 field_args.deterministic = guiding_params.deterministic; # endif + reinterpret_cast(field_args.spatialSturctureArguments)->maxDepth = 16; openpgl::cpp::Device *guiding_device = static_cast( device_->get_guiding_device()); if (guiding_device) { diff --git a/intern/cycles/kernel/integrator/state_flow.h b/intern/cycles/kernel/integrator/state_flow.h index 4b03c665e17..40961b1c5fb 100644 --- a/intern/cycles/kernel/integrator/state_flow.h +++ b/intern/cycles/kernel/integrator/state_flow.h @@ -76,6 +76,9 @@ ccl_device_forceinline IntegratorShadowState integrator_shadow_path_init( &kernel_integrator_state.next_shadow_path_index[0], 1); atomic_fetch_and_add_uint32(&kernel_integrator_state.queue_counter->num_queued[next_kernel], 1); INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, queued_kernel) = next_kernel; +# ifdef __PATH_GUIDING__ + INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, path_segment) = nullptr; +# endif return shadow_state; } @@ -181,6 +184,9 @@ ccl_device_forceinline IntegratorShadowState integrator_shadow_path_init( { IntegratorShadowState shadow_state = (is_ao) ? &state->ao : &state->shadow; INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, queued_kernel) = next_kernel; +# ifdef __PATH_GUIDING__ + INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, path_segment) = nullptr; +# endif return shadow_state; } -- cgit v1.2.3 From c2fe3872445d96325c2accb654b1c39a195a31d1 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 3 Oct 2022 16:47:03 +0200 Subject: Build: get make deps working with Xcode command line tools Deduplicating code with Xcode detection for Blender builds. --- build_files/build_environment/cmake/options.cmake | 36 ++++++----------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/build_files/build_environment/cmake/options.cmake b/build_files/build_environment/cmake/options.cmake index 299b82f6d05..6e5f9df20b4 100644 --- a/build_files/build_environment/cmake/options.cmake +++ b/build_files/build_environment/cmake/options.cmake @@ -101,34 +101,16 @@ else() set(LIBPREFIX "lib") if(APPLE) - # Let's get the current Xcode dir, to support xcode-select - execute_process( - COMMAND xcode-select --print-path - OUTPUT_VARIABLE XCODE_DEV_PATH OUTPUT_STRIP_TRAILING_WHITESPACE - ) - execute_process( - COMMAND xcodebuild -version -sdk macosx SDKVersion - OUTPUT_VARIABLE MACOSX_SDK_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) - - if(NOT CMAKE_OSX_ARCHITECTURES) - execute_process(COMMAND uname -m OUTPUT_VARIABLE ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE) - message(STATUS "Detected native architecture ${ARCHITECTURE}.") - set(CMAKE_OSX_ARCHITECTURES "${ARCHITECTURE}") - endif() - if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64") - set(OSX_DEPLOYMENT_TARGET 10.13) - else() - set(OSX_DEPLOYMENT_TARGET 11.00) - endif() - set(OSX_SYSROOT ${XCODE_DEV_PATH}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk) + # Use same Xcode detection as Blender itself. + include(../cmake/platform/platform_apple_xcode.cmake) if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64") set(BLENDER_PLATFORM_ARM ON) endif() - set(PLATFORM_CFLAGS "-isysroot ${OSX_SYSROOT} -mmacosx-version-min=${OSX_DEPLOYMENT_TARGET} -arch ${CMAKE_OSX_ARCHITECTURES}") - set(PLATFORM_CXXFLAGS "-isysroot ${OSX_SYSROOT} -mmacosx-version-min=${OSX_DEPLOYMENT_TARGET} -std=c++11 -stdlib=libc++ -arch ${CMAKE_OSX_ARCHITECTURES}") - set(PLATFORM_LDFLAGS "-isysroot ${OSX_SYSROOT} -mmacosx-version-min=${OSX_DEPLOYMENT_TARGET} -arch ${CMAKE_OSX_ARCHITECTURES}") + set(PLATFORM_CFLAGS "-isysroot ${CMAKE_OSX_SYSROOT} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} -arch ${CMAKE_OSX_ARCHITECTURES}") + set(PLATFORM_CXXFLAGS "-isysroot ${CMAKE_OSX_SYSROOT} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} -std=c++11 -stdlib=libc++ -arch ${CMAKE_OSX_ARCHITECTURES}") + set(PLATFORM_LDFLAGS "-isysroot ${CMAKE_OSX_SYSROOT} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} -arch ${CMAKE_OSX_ARCHITECTURES}") if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64") set(PLATFORM_BUILD_TARGET --build=x86_64-apple-darwin17.0.0) # OS X 10.13 else() @@ -136,8 +118,8 @@ else() endif() set(PLATFORM_CMAKE_FLAGS -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES} - -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${OSX_DEPLOYMENT_TARGET} - -DCMAKE_OSX_SYSROOT:PATH=${OSX_SYSROOT} + -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET} + -DCMAKE_OSX_SYSROOT:PATH=${CMAKE_OSX_SYSROOT} ) else() if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64") @@ -171,8 +153,8 @@ else() set(BLENDER_CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DNDEBUG ${PLATFORM_CXXFLAGS}") set(CONFIGURE_ENV - export MACOSX_DEPLOYMENT_TARGET=${OSX_DEPLOYMENT_TARGET} && - export MACOSX_SDK_VERSION=${OSX_DEPLOYMENT_TARGET} && + export MACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} && + export MACOSX_SDK_VERSION=${CMAKE_OSX_DEPLOYMENT_TARGET} && export CFLAGS=${PLATFORM_CFLAGS} && export CXXFLAGS=${PLATFORM_CXXFLAGS} && export LDFLAGS=${PLATFORM_LDFLAGS} -- cgit v1.2.3 From 489260198e9654aaf5922e64fbe36b335bcb8e1b Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 18 Oct 2022 15:05:53 +0200 Subject: File Browser: Fix slowdown with non-existing ID previews in big files When the File (or Asset) Browser would display data-blocks without previews in a heavy .blend file, there would be a drastic slowdown. See patch for details and comparison videos. Differential Revision: https://developer.blender.org/D16273 Reviewed by: Bastien Montagne --- source/blender/blenloader/BLO_readfile.h | 5 +++++ source/blender/blenloader/intern/readblenentry.cc | 15 +++++++++++++ source/blender/editors/space_file/filelist.cc | 27 +++++++++++++++++++---- source/blender/makesdna/DNA_space_types.h | 4 ++++ 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index 93040fa01ee..75a1956ce12 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -182,6 +182,11 @@ void BLO_blendfiledata_free(BlendFileData *bfd); typedef struct BLODataBlockInfo { char name[64]; /* MAX_NAME */ struct AssetMetaData *asset_data; + /* Optimization: Tag data-blocks for which we know there is no preview. + * Knowing this can be used to skip the (potentially expensive) preview loading process. If this + * is set to true it means we looked for a preview and couldn't find one. False may mean that + * either no preview was found, or that it wasn't looked for in the first place. */ + bool no_preview_found; } BLODataBlockInfo; /** diff --git a/source/blender/blenloader/intern/readblenentry.cc b/source/blender/blenloader/intern/readblenentry.cc index 55ac2d31277..ead796c0e28 100644 --- a/source/blender/blenloader/intern/readblenentry.cc +++ b/source/blender/blenloader/intern/readblenentry.cc @@ -138,11 +138,15 @@ LinkNode *BLO_blendhandle_get_datablock_info(BlendHandle *bh, BHead *bhead; int tot = 0; + const int sdna_nr_preview_image = DNA_struct_find_nr(fd->filesdna, "PreviewImage"); + for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) { if (bhead->code == ENDB) { break; } if (bhead->code == ofblocktype) { + BHead *id_bhead = bhead; + const char *name = blo_bhead_id_name(fd, bhead) + 2; AssetMetaData *asset_meta_data = blo_bhead_id_asset_data_address(fd, bhead); @@ -165,6 +169,17 @@ LinkNode *BLO_blendhandle_get_datablock_info(BlendHandle *bh, STRNCPY(info->name, name); info->asset_data = asset_meta_data; + bool has_preview = false; + /* See if we can find a preview in the data of this ID. */ + for (BHead *data_bhead = blo_bhead_next(fd, id_bhead); data_bhead->code == DATA; + data_bhead = blo_bhead_next(fd, data_bhead)) { + if (data_bhead->SDNAnr == sdna_nr_preview_image) { + has_preview = true; + break; + } + } + info->no_preview_found = !has_preview; + BLI_linklist_prepend(&infos, info); tot++; } diff --git a/source/blender/editors/space_file/filelist.cc b/source/blender/editors/space_file/filelist.cc index b6f6ab39438..f177eebf6f2 100644 --- a/source/blender/editors/space_file/filelist.cc +++ b/source/blender/editors/space_file/filelist.cc @@ -115,6 +115,9 @@ struct FileListInternEntry { * Owning pointer. */ AssetMetaData *imported_asset_data; + /* See #FILE_ENTRY_BLENDERLIB_NO_PREVIEW. */ + bool blenderlib_has_no_preview; + /** Defined in BLI_fileops.h */ eFileAttributes attributes; BLI_stat_t st; @@ -1575,6 +1578,14 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry return; } + /* If we know this is an external ID without a preview, skip loading the preview. Can save quite + * some time in heavy files, because otherwise for each missing preview and for each preview + * reload, we'd reopen the .blend to look for the preview. */ + if ((entry->typeflag & FILE_TYPE_BLENDERLIB) && + (entry->flags & FILE_ENTRY_BLENDERLIB_NO_PREVIEW)) { + return; + } + FileListInternEntry *intern_entry = filelist->filelist_intern.filtered[index]; PreviewImage *preview_in_memory = intern_entry->local_data.preview_image; if (preview_in_memory && !BKE_previewimg_is_finished(preview_in_memory, ICON_SIZE_PREVIEW)) { @@ -2042,6 +2053,9 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in ret->preview_icon_id = BKE_icon_imbuf_create(ibuf); } } + if (entry->blenderlib_has_no_preview) { + ret->flags |= FILE_ENTRY_BLENDERLIB_NO_PREVIEW; + } BLI_addtail(&cache->cached_entries, ret); return ret; } @@ -2995,10 +3009,15 @@ static void filelist_readjob_list_lib_add_datablock(ListBase *entries, entry->relpath = BLI_strdup(datablock_info->name); } entry->typeflag |= FILE_TYPE_BLENDERLIB; - if (datablock_info && datablock_info->asset_data) { - entry->typeflag |= FILE_TYPE_ASSET; - /* Moves ownership! */ - entry->imported_asset_data = datablock_info->asset_data; + + if (datablock_info) { + entry->blenderlib_has_no_preview = datablock_info->no_preview_found; + + if (datablock_info->asset_data) { + entry->typeflag |= FILE_TYPE_ASSET; + /* Moves ownership! */ + entry->imported_asset_data = datablock_info->asset_data; + } } entry->blentype = idcode; BLI_addtail(entries, entry); diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 809c8be7bc4..d2d20bcde78 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -1169,6 +1169,10 @@ enum { FILE_ENTRY_NAME_FREE = 1 << 1, /* The preview for this entry is being loaded on another thread. */ FILE_ENTRY_PREVIEW_LOADING = 1 << 2, + /** For #FILE_TYPE_BLENDERLIB only: Denotes that the ID is known to not have a preview (none was + * found in the .blend). Stored so we don't keep trying to find non-existent previews every time + * we reload previews. When dealing with heavy files this can have quite an impact. */ + FILE_ENTRY_BLENDERLIB_NO_PREVIEW = 1 << 3, }; /** \} */ -- cgit v1.2.3 From 619ce8392b2122e326dcfad4fe195de8f01cedca Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 18 Oct 2022 15:48:50 +0200 Subject: Depsgraph: wrong copy-on-write update after depsgraph rebuild Differential Revision: https://developer.blender.org/D16268 --- source/blender/depsgraph/intern/builder/deg_builder_nodes.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index f95c0700a47..6cb0b985d3d 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -453,6 +453,11 @@ static int foreach_id_cow_detect_need_for_update_callback(LibraryIDLinkCallbackD if (id == nullptr) { return IDWALK_RET_NOP; } + if (!ID_TYPE_IS_COW(GS(id->name))) { + /* No need to go further if thte id never had a cow copy in the depsgraph. This function is + * only concerned with keeping the mapping between original and cow ids intact. */ + return IDWALK_RET_NOP; + } DepsgraphNodeBuilder *builder = static_cast(cb_data->user_data); ID *id_cow_self = cb_data->id_self; -- cgit v1.2.3 From 5c1d2c5a9d336b7b41617139e04ace23229e8d1f Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 18 Oct 2022 13:50:04 +0200 Subject: Brush: Wrap mtex/mask_tex around functions. `Brush` has two attributes for holding texture information (`MTex`). One for color textures (`mtex`) and one for mask textures (`mask_mtex`). Unfortunately sculpt mode due to reasons used `mtex` to store mask textures. Changes like brush asset/paint mode require modes/tools to read the mask/color texture from one place. To start sanatizing this we isolate the attributes in functions. `BKE_brush_color_texture_get` and `BKE_brush_mask_texture_get`. All object paint modes should use these functions. --- source/blender/blenkernel/BKE_brush.h | 21 +++++++++++++++++++++ source/blender/blenkernel/intern/brush.cc | 22 ++++++++++++++++++++-- .../blender/editors/sculpt_paint/paint_image_2d.c | 6 ++++-- .../editors/sculpt_paint/paint_image_proj.c | 5 +++-- .../blender/editors/sculpt_paint/paint_vertex.cc | 9 +++++---- source/blender/editors/sculpt_paint/sculpt.c | 16 ++++++++-------- .../blender/editors/sculpt_paint/sculpt_expand.c | 7 ++++--- 7 files changed, 65 insertions(+), 21 deletions(-) diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 4d728002c87..8f069841fbc 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -18,7 +18,9 @@ extern "C" { struct Brush; struct ImBuf; struct ImagePool; +struct Object; struct Main; +struct MTex; struct Scene; struct ToolSettings; struct UnifiedPaintSettings; @@ -109,6 +111,7 @@ float BKE_brush_curve_strength(const struct Brush *br, float p, float len); */ float BKE_brush_sample_tex_3d(const struct Scene *scene, const struct Brush *br, + const struct MTex *mtex, const float point[3], float rgba[4], int thread, @@ -119,6 +122,24 @@ float BKE_brush_sample_masktex(const struct Scene *scene, int thread, struct ImagePool *pool); +/** + * Get the mask texture for this given object mode. + * + * This is preferred above using mtex/mask_mtex attributes directly as due to legacy these + * attributes got switched in sculpt mode. + */ +const struct MTex *BKE_brush_mask_texture_get(const struct Brush *brush, + const eObjectMode object_mode); + +/** + * Get the color texture for this given object mode. + * + * This is preferred above using mtex/mask_mtex attributes directly as due to legacy these + * attributes got switched in sculpt mode. + */ +const struct MTex *BKE_brush_color_texture_get(const struct Brush *brush, + const eObjectMode object_mode); + /** * Radial control. */ diff --git a/source/blender/blenkernel/intern/brush.cc b/source/blender/blenkernel/intern/brush.cc index 20d86ea5a2d..6f1435e90b8 100644 --- a/source/blender/blenkernel/intern/brush.cc +++ b/source/blender/blenkernel/intern/brush.cc @@ -1974,19 +1974,37 @@ void BKE_brush_curve_preset(Brush *b, eCurveMappingPreset preset) BKE_curvemapping_changed(cumap, false); } +const struct MTex *BKE_brush_mask_texture_get(const struct Brush *brush, + const eObjectMode object_mode) +{ + if (object_mode == OB_MODE_SCULPT) { + return &brush->mtex; + } + return &brush->mask_mtex; +} + +const struct MTex *BKE_brush_color_texture_get(const struct Brush *brush, + const eObjectMode object_mode) +{ + if (object_mode == OB_MODE_SCULPT) { + return &brush->mask_mtex; + } + return &brush->mtex; +} + float BKE_brush_sample_tex_3d(const Scene *scene, const Brush *br, + const MTex *mtex, const float point[3], float rgba[4], const int thread, struct ImagePool *pool) { UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; - const MTex *mtex = &br->mtex; float intensity = 1.0; bool hasrgb = false; - if (!mtex->tex) { + if (mtex == nullptr || mtex->tex == nullptr) { intensity = 1; } else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) { diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index 79316361e53..b7ce4b2973c 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -402,7 +402,8 @@ static ImBuf *brush_painter_imbuf_new( if (is_texbrush) { brush_imbuf_tex_co(&tex_mapping, x, y, texco); - BKE_brush_sample_tex_3d(scene, brush, texco, rgba, thread, pool); + const MTex *mtex = &brush->mtex; + BKE_brush_sample_tex_3d(scene, brush, mtex, texco, rgba, thread, pool); /* TODO(sergey): Support texture paint color space. */ if (!use_float) { IMB_colormanagement_scene_linear_to_display_v3(rgba, display); @@ -446,6 +447,7 @@ static void brush_painter_imbuf_update(BrushPainter *painter, { Scene *scene = painter->scene; Brush *brush = painter->brush; + const MTex *mtex = &brush->mtex; BrushPainterCache *cache = &tile->cache; const char *display_device = scene->display_settings.display_device; @@ -485,7 +487,7 @@ static void brush_painter_imbuf_update(BrushPainter *painter, if (!use_texture_old) { if (is_texbrush) { brush_imbuf_tex_co(&tex_mapping, x, y, texco); - BKE_brush_sample_tex_3d(scene, brush, texco, rgba, thread, pool); + BKE_brush_sample_tex_3d(scene, brush, mtex, texco, rgba, thread, pool); /* TODO(sergey): Support texture paint color space. */ if (!use_float) { IMB_colormanagement_scene_linear_to_display_v3(rgba, display); diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 41d5090b38c..d9aa11a2847 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -5370,7 +5370,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v /* Color texture (alpha used as mask). */ if (ps->is_texbrush) { - MTex *mtex = &brush->mtex; + const MTex *mtex = BKE_brush_color_texture_get(brush, OB_MODE_TEXTURE_PAINT); float samplecos[3]; float texrgba[4]; @@ -5386,7 +5386,8 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v /* NOTE: for clone and smear, * we only use the alpha, could be a special function */ - BKE_brush_sample_tex_3d(ps->scene, brush, samplecos, texrgba, thread_index, pool); + BKE_brush_sample_tex_3d( + ps->scene, brush, mtex, samplecos, texrgba, thread_index, pool); copy_v3_v3(texrgb, texrgba); custom_mask *= texrgba[3]; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.cc b/source/blender/editors/sculpt_paint/paint_vertex.cc index 6e3504332ed..acd8b1a6bb1 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex.cc @@ -433,9 +433,10 @@ static void paint_and_tex_color_alpha_intern(VPaint *vp, float r_rgba[4]) { const Brush *brush = BKE_paint_brush(&vp->paint); - BLI_assert(brush->mtex.tex != nullptr); - if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) { - BKE_brush_sample_tex_3d(vc->scene, brush, co, r_rgba, 0, nullptr); + const MTex *mtex = BKE_brush_mask_texture_get(brush, OB_MODE_SCULPT); + BLI_assert(mtex->tex != nullptr); + if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) { + BKE_brush_sample_tex_3d(vc->scene, brush, mtex, co, r_rgba, 0, nullptr); } else { float co_ss[2]; /* screenspace */ @@ -445,7 +446,7 @@ static void paint_and_tex_color_alpha_intern(VPaint *vp, co_ss, (eV3DProjTest)(V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR)) == V3D_PROJ_RET_OK) { const float co_ss_3d[3] = {co_ss[0], co_ss[1], 0.0f}; /* we need a 3rd empty value */ - BKE_brush_sample_tex_3d(vc->scene, brush, co_ss_3d, r_rgba, 0, nullptr); + BKE_brush_sample_tex_3d(vc->scene, brush, mtex, co_ss_3d, r_rgba, 0, nullptr); } else { zero_v4(r_rgba); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 0f71acd3698..95192114429 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -2458,7 +2458,7 @@ float SCULPT_brush_strength_factor(SculptSession *ss, { StrokeCache *cache = ss->cache; const Scene *scene = cache->vc->scene; - const MTex *mtex = &br->mtex; + const MTex *mtex = BKE_brush_mask_texture_get(br, OB_MODE_SCULPT); float avg = 1.0f; float rgba[4]; float point[3]; @@ -2470,7 +2470,7 @@ float SCULPT_brush_strength_factor(SculptSession *ss, } else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) { /* Get strength by feeding the vertex location directly into a texture. */ - avg = BKE_brush_sample_tex_3d(scene, br, point, rgba, 0, ss->tex_pool); + avg = BKE_brush_sample_tex_3d(scene, br, mtex, point, rgba, 0, ss->tex_pool); } else { float symm_point[3], point_2d[2]; @@ -2499,19 +2499,19 @@ float SCULPT_brush_strength_factor(SculptSession *ss, x = symm_point[0]; y = symm_point[1]; - x *= br->mtex.size[0]; - y *= br->mtex.size[1]; + x *= mtex->size[0]; + y *= mtex->size[1]; - x += br->mtex.ofs[0]; - y += br->mtex.ofs[1]; + x += mtex->ofs[0]; + y += mtex->ofs[1]; - avg = paint_get_tex_pixel(&br->mtex, x, y, ss->tex_pool, thread_id); + avg = paint_get_tex_pixel(mtex, x, y, ss->tex_pool, thread_id); avg += br->texture_sample_bias; } else { const float point_3d[3] = {point_2d[0], point_2d[1], 0.0f}; - avg = BKE_brush_sample_tex_3d(scene, br, point_3d, rgba, 0, ss->tex_pool); + avg = BKE_brush_sample_tex_3d(scene, br, mtex, point_3d, rgba, 0, ss->tex_pool); } } diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.c b/source/blender/editors/sculpt_paint/sculpt_expand.c index 655b03bbb36..3133bb2007e 100644 --- a/source/blender/editors/sculpt_paint/sculpt_expand.c +++ b/source/blender/editors/sculpt_paint/sculpt_expand.c @@ -167,15 +167,16 @@ static float sculpt_expand_falloff_value_vertex_get(SculptSession *ss, if (expand_cache->texture_distortion_strength == 0.0f) { return expand_cache->vert_falloff[v_i]; } - - if (!expand_cache->brush->mtex.tex) { + const Brush *brush = expand_cache->brush; + const MTex *mtex = BKE_brush_mask_texture_get(brush, OB_MODE_SCULPT); + if (!mtex->tex) { return expand_cache->vert_falloff[v_i]; } float rgba[4]; const float *vertex_co = SCULPT_vertex_co_get(ss, v); const float avg = BKE_brush_sample_tex_3d( - expand_cache->scene, expand_cache->brush, vertex_co, rgba, 0, ss->tex_pool); + expand_cache->scene, brush, mtex, vertex_co, rgba, 0, ss->tex_pool); const float distortion = (avg - 0.5f) * expand_cache->texture_distortion_strength * expand_cache->max_vert_falloff; -- cgit v1.2.3 From 7abd79398d712be54935c01f1d2eefb5eaba64a9 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 18 Oct 2022 16:15:12 +0200 Subject: Fix T101642: crash when deleting group output inside node group --- source/blender/nodes/intern/geometry_nodes_lazy_function.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc index 5bf245f1832..197f0997160 100644 --- a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc +++ b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc @@ -604,6 +604,7 @@ class LazyFunctionForGroupNode : public LazyFunction { private: const bNode &group_node_; bool has_many_nodes_ = false; + bool use_fallback_outputs_ = false; std::optional lf_logger_; std::optional lf_side_effect_provider_; std::optional graph_executor_; @@ -640,6 +641,9 @@ class LazyFunctionForGroupNode : public LazyFunction { } } } + else { + use_fallback_outputs_ = true; + } lf_logger_.emplace(lf_graph_info); lf_side_effect_provider_.emplace(); @@ -660,6 +664,11 @@ class LazyFunctionForGroupNode : public LazyFunction { * if every individual node is very small. */ lazy_threading::send_hint(); } + if (use_fallback_outputs_) { + /* The node group itself does not have an output node, so use default values as outputs. + * The group should still be executed in case it has side effects. */ + params.set_default_remaining_outputs(); + } /* The compute context changes when entering a node group. */ bke::NodeGroupComputeContext compute_context{user_data->compute_context, group_node_.name}; -- cgit v1.2.3 From a2fcfcabd74294d261bc76ed18d6591e4b9ea8fb Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 18 Oct 2022 16:50:42 +0200 Subject: Cleanup: add missing CPPType for MStringProperty --- source/blender/blenkernel/intern/customdata.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index 6f2390fc28f..03a0f17a4bb 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -19,6 +19,7 @@ #include "BLI_bitmap.h" #include "BLI_color.hh" +#include "BLI_cpp_type_make.hh" #include "BLI_endian_switch.h" #include "BLI_index_range.hh" #include "BLI_math.h" @@ -5387,6 +5388,8 @@ const blender::CPPType *custom_data_type_to_cpp_type(const eCustomDataType type) return &CPPType::get(); case CD_PROP_BYTE_COLOR: return &CPPType::get(); + case CD_PROP_STRING: + return &CPPType::get(); default: return nullptr; } @@ -5419,6 +5422,9 @@ eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type) if (type.is()) { return CD_PROP_BYTE_COLOR; } + if (type.is()) { + return CD_PROP_STRING; + } return static_cast(-1); } @@ -5430,3 +5436,5 @@ size_t CustomData_get_elem_size(CustomDataLayer *layer) { return LAYERTYPEINFO[layer->type].size; } + +BLI_CPP_TYPE_MAKE(MStringProperty, MStringProperty, CPPTypeFlags::None); -- cgit v1.2.3 From 91ecf47b2c6b884aadb5550adeda03d5700988d4 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 18 Oct 2022 10:07:32 -0500 Subject: Fix: Sample nearest surface node crash with empty mesh --- .../blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc index 44851a0ade5..95bf7199d63 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc @@ -240,7 +240,11 @@ static void node_geo_exec(GeoNodeExecParams params) params.set_default_remaining_outputs(); return; } - if (mesh->totpoly == 0 && mesh->totvert != 0) { + if (mesh->totvert == 0) { + params.set_default_remaining_outputs(); + return; + } + if (mesh->totpoly == 0) { params.error_message_add(NodeWarningType::Error, TIP_("The source mesh must have faces")); params.set_default_remaining_outputs(); return; -- cgit v1.2.3 From 91e85230f9c1b490f7424b9da7bbd65b7c0c4068 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 18 Oct 2022 17:16:51 +0200 Subject: Fix T101660: crash when trying to propagate string attributes in some nodes String attributes are intentionally not fully supported in geometry nodes yet because more design work is necessary to decide how they should behave. For now just disable handling string attributes to avoid crashes. --- source/blender/blenkernel/intern/curve_to_mesh_convert.cc | 10 +++++++--- source/blender/blenkernel/intern/curves_geometry.cc | 3 +++ source/blender/blenkernel/intern/geometry_set.cc | 5 ++++- source/blender/geometry/intern/resample_curves.cc | 3 +++ source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc | 12 ++++++++++++ source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc | 3 +++ .../blender/nodes/geometry/nodes/node_geo_join_geometry.cc | 3 +++ 7 files changed, 35 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc index b9fea2a27b8..ecf3be9bd81 100644 --- a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc +++ b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc @@ -332,7 +332,8 @@ static eAttrDomain get_attribute_domain_for_mesh(const AttributeAccessor &mesh_a static bool should_add_attribute_to_mesh(const AttributeAccessor &curve_attributes, const AttributeAccessor &mesh_attributes, - const AttributeIDRef &id) + const AttributeIDRef &id, + const AttributeMetaData &meta_data) { /* The position attribute has special non-generic evaluation. */ @@ -346,6 +347,9 @@ static bool should_add_attribute_to_mesh(const AttributeAccessor &curve_attribut if (!id.should_be_kept()) { return false; } + if (meta_data.data_type == CD_PROP_STRING) { + return false; + } return true; } @@ -714,7 +718,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main, MutableAttributeAccessor mesh_attributes = mesh->attributes_for_write(); main_attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) { - if (!should_add_attribute_to_mesh(main_attributes, mesh_attributes, id)) { + if (!should_add_attribute_to_mesh(main_attributes, mesh_attributes, id, meta_data)) { return true; } main_attributes_set.add_new(id); @@ -751,7 +755,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main, if (main_attributes.contains(id)) { return true; } - if (!should_add_attribute_to_mesh(profile_attributes, mesh_attributes, id)) { + if (!should_add_attribute_to_mesh(profile_attributes, mesh_attributes, id, meta_data)) { return true; } const eAttrDomain src_domain = meta_data.domain; diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc index f5c845443f1..29f8d62545f 100644 --- a/source/blender/blenkernel/intern/curves_geometry.cc +++ b/source/blender/blenkernel/intern/curves_geometry.cc @@ -1402,6 +1402,9 @@ void CurvesGeometry::reverse_curves(const IndexMask curves_to_reverse) if (meta_data.domain != ATTR_DOMAIN_POINT) { return true; } + if (meta_data.data_type == CD_PROP_STRING) { + return true; + } if (id.is_named() && bezier_handle_names.contains(id.name())) { return true; } diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc index 90568a8a080..ee4c398c3d6 100644 --- a/source/blender/blenkernel/intern/geometry_set.cc +++ b/source/blender/blenkernel/intern/geometry_set.cc @@ -607,7 +607,10 @@ void GeometrySet::gather_attributes_for_propagation( return; } } - + if (meta_data.data_type == CD_PROP_STRING) { + /* Propagating string attributes is not supported yet. */ + return; + } if (!attribute_id.should_be_kept()) { return; } diff --git a/source/blender/geometry/intern/resample_curves.cc b/source/blender/geometry/intern/resample_curves.cc index a7f6ac16f8d..3be850ec097 100644 --- a/source/blender/geometry/intern/resample_curves.cc +++ b/source/blender/geometry/intern/resample_curves.cc @@ -139,6 +139,9 @@ static void gather_point_attributes_to_interpolate( if (meta_data.domain != ATTR_DOMAIN_POINT) { return true; } + if (meta_data.data_type == CD_PROP_STRING) { + return true; + } if (!interpolate_attribute_to_curves(id, dst_curves.curve_type_counts())) { return true; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index 1d8c9d6312c..d348d886ad6 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -260,6 +260,9 @@ static void extrude_mesh_vertices(Mesh &mesh, if (!ELEM(meta_data.domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE)) { return true; } + if (meta_data.data_type == CD_PROP_STRING) { + return true; + } GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span( id, meta_data.domain, meta_data.data_type); attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { @@ -506,6 +509,9 @@ static void extrude_mesh_edges(Mesh &mesh, MutableAttributeAccessor attributes = mesh.attributes_for_write(); attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) { + if (meta_data.data_type == CD_PROP_STRING) { + return true; + } GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span( id, meta_data.domain, meta_data.data_type); if (!attribute) { @@ -889,6 +895,9 @@ static void extrude_mesh_face_regions(Mesh &mesh, MutableAttributeAccessor attributes = mesh.attributes_for_write(); attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) { + if (meta_data.data_type == CD_PROP_STRING) { + return true; + } GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span( id, meta_data.domain, meta_data.data_type); if (!attribute) { @@ -1143,6 +1152,9 @@ static void extrude_individual_mesh_faces(Mesh &mesh, MutableAttributeAccessor attributes = mesh.attributes_for_write(); attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) { + if (meta_data.data_type == CD_PROP_STRING) { + return true; + } GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span( id, meta_data.domain, meta_data.data_type); if (!attribute) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc index 613425716d4..95a0013a9e1 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc @@ -47,6 +47,9 @@ static void mesh_flip_faces(Mesh &mesh, const Field &selection_field) MutableAttributeAccessor attributes = mesh.attributes_for_write(); attributes.for_all( [&](const bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { + if (meta_data.data_type == CD_PROP_STRING) { + return true; + } if (meta_data.domain == ATTR_DOMAIN_CORNER) { GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span( attribute_id, ATTR_DOMAIN_CORNER, meta_data.data_type); diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc index ec9b9faf4ec..ea2646a9786 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc @@ -31,6 +31,9 @@ static Map get_final_attribute_info( if (attribute_id.is_named() && ignored_attributes.contains(attribute_id.name())) { return true; } + if (meta_data.data_type == CD_PROP_STRING) { + return true; + } info.add_or_modify( attribute_id, [&](AttributeMetaData *meta_data_final) { *meta_data_final = meta_data; }, -- cgit v1.2.3 From d57352b1147642660c13aeb17a0c603593fc0dea Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Tue, 18 Oct 2022 12:50:11 -0300 Subject: Fix T101893: Auto merge affecting edge crease and bevel weight None of the special transformations in `special_aftertrans_update__mesh` are really applicable or useful for edge crease and bevel weight. --- source/blender/editors/transform/transform_convert.h | 2 -- source/blender/editors/transform/transform_convert_mesh.c | 2 +- source/blender/editors/transform/transform_convert_mesh_edge.c | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h index 8466fd88e1d..4798d666d70 100644 --- a/source/blender/editors/transform/transform_convert.h +++ b/source/blender/editors/transform/transform_convert.h @@ -226,8 +226,6 @@ void transform_convert_mesh_crazyspace_transdata_set(const float mtx[3][3], struct TransData *r_td); void transform_convert_mesh_crazyspace_free(struct TransMeshDataCrazySpace *r_crazyspace_data); -void special_aftertrans_update__mesh(bContext *C, TransInfo *t); - /* transform_convert_mesh_edge.c */ extern TransConvertTypeInfo TransConvertType_MeshEdge; diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index af7982f862a..7e237c9eb32 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -2068,7 +2068,7 @@ static void recalcData_mesh(TransInfo *t) /** \name Special After Transform Mesh * \{ */ -void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t) +static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t) { const bool is_canceling = (t->state == TRANS_CANCEL); const bool use_automerge = !is_canceling && (t->flag & (T_AUTOMERGE | T_AUTOSPLIT)) != 0; diff --git a/source/blender/editors/transform/transform_convert_mesh_edge.c b/source/blender/editors/transform/transform_convert_mesh_edge.c index 7f26029850b..0ce4c592f53 100644 --- a/source/blender/editors/transform/transform_convert_mesh_edge.c +++ b/source/blender/editors/transform/transform_convert_mesh_edge.c @@ -125,5 +125,5 @@ TransConvertTypeInfo TransConvertType_MeshEdge = { /* flags */ T_EDIT, /* createTransData */ createTransEdge, /* recalcData */ recalcData_mesh_edge, - /* special_aftertrans_update */ special_aftertrans_update__mesh, + /* special_aftertrans_update */ NULL, }; -- cgit v1.2.3 From be32882e1c40eb1cb72deab0bb6ee54fff917ca2 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 18 Oct 2022 15:57:47 -0500 Subject: Fix T101883: Issue applying modifier to mesh with shape keys Caused by 21f2bacad977d3fd83d which misunderstood the logic handling shape keys in this function. The shape key on the original mesh in the main data-base should be cleared if the "no-main" mesh doesn't have any shape key layers and the vertex count has changed. The complexity is necessary because shape keys are stored differently on original and evaluated meshes. Also change to "Warn" because this is expected behavior in some cases, like when applying a geometry nodes modifier that creates a new mesh from scratch. --- source/blender/blenkernel/intern/mesh_convert.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc index 027423f5774..784d35a8d65 100644 --- a/source/blender/blenkernel/intern/mesh_convert.cc +++ b/source/blender/blenkernel/intern/mesh_convert.cc @@ -1313,6 +1313,7 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob) CustomData_duplicate_referenced_layers(&mesh_src->pdata, mesh_src->totpoly); CustomData_duplicate_referenced_layers(&mesh_src->ldata, mesh_src->totloop); + const bool verts_num_changed = mesh_dst->totvert != mesh_src->totvert; mesh_dst->totvert = mesh_src->totvert; mesh_dst->totedge = mesh_src->totedge; mesh_dst->totpoly = mesh_src->totpoly; @@ -1339,11 +1340,10 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob) const int uid_active = ob ? find_object_active_key_uid(*key_dst, *ob) : -1; move_shapekey_layers_to_keyblocks(*mesh_dst, mesh_src->vdata, *key_dst, uid_active); } - else if (mesh_src->totvert != mesh_dst->totvert) { - CLOG_ERROR(&LOG, "Mesh in Main '%s' lost shape keys", mesh_src->id.name); - if (mesh_src->key) { - id_us_min(&mesh_src->key->id); - } + else if (verts_num_changed) { + CLOG_WARN(&LOG, "Shape key data lost when replacing mesh '%s' in Main", mesh_src->id.name); + id_us_min(&mesh_dst->key->id); + mesh_dst->key = nullptr; } } -- cgit v1.2.3 From 8115d30dcaddeb399ea9a557694788b03505b2bd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 12:52:54 +1100 Subject: License headers: add missing license identifiers --- source/blender/gpu/metal/mtl_batch.mm | 1 + source/blender/gpu/metal/mtl_drawlist.mm | 2 ++ 2 files changed, 3 insertions(+) diff --git a/source/blender/gpu/metal/mtl_batch.mm b/source/blender/gpu/metal/mtl_batch.mm index e9804d4be77..3961e7a71a0 100644 --- a/source/blender/gpu/metal/mtl_batch.mm +++ b/source/blender/gpu/metal/mtl_batch.mm @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /** \file * \ingroup gpu diff --git a/source/blender/gpu/metal/mtl_drawlist.mm b/source/blender/gpu/metal/mtl_drawlist.mm index 76e2abb4ea6..dc3e4665dcf 100644 --- a/source/blender/gpu/metal/mtl_drawlist.mm +++ b/source/blender/gpu/metal/mtl_drawlist.mm @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + /** \file * \ingroup gpu * -- cgit v1.2.3 From 8aca40652a5729895f1ba6efd2d03829785ae43f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 12:52:55 +1100 Subject: Cleanup: spelling in comments --- source/blender/blenkernel/BKE_instances.hh | 2 +- source/blender/blenkernel/intern/instances.cc | 2 +- source/blender/blenkernel/intern/volume.cc | 4 ++-- .../depsgraph/intern/builder/deg_builder_nodes.cc | 4 ++-- source/blender/gpu/metal/mtl_batch.mm | 20 ++++++++++---------- source/blender/gpu/metal/mtl_drawlist.mm | 12 ++++++------ source/blender/gpu/metal/mtl_texture.mm | 2 +- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/source/blender/blenkernel/BKE_instances.hh b/source/blender/blenkernel/BKE_instances.hh index 6502fefec88..f17ebba0dfa 100644 --- a/source/blender/blenkernel/BKE_instances.hh +++ b/source/blender/blenkernel/BKE_instances.hh @@ -5,7 +5,7 @@ /** \file * \ingroup bke * - * #Instances is a container for geometry instances. It fullfills some key requirements: + * #Instances is a container for geometry instances. It fulfills some key requirements: * - Support nested instances. * - Support instance attributes. * - Support referencing different kinds of instances (objects, collections, geometry sets). diff --git a/source/blender/blenkernel/intern/instances.cc b/source/blender/blenkernel/intern/instances.cc index dd759453630..2f8acf477e2 100644 --- a/source/blender/blenkernel/intern/instances.cc +++ b/source/blender/blenkernel/intern/instances.cc @@ -266,7 +266,7 @@ bool Instances::owns_direct_data() const void Instances::ensure_owns_direct_data() { for (const InstanceReference &const_reference : references_) { - /* Const cast is fine because we are not changing anything that would change the hash of the + /* `const` cast is fine because we are not changing anything that would change the hash of the * reference. */ InstanceReference &reference = const_cast(const_reference); reference.ensure_owns_direct_data(); diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index 7c54b4d3f2f..e81657f9ef0 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -445,7 +445,7 @@ struct VolumeGrid { * may actually be loaded by another user while this is false. But only after * calling load() and is_loaded changes to true is it safe to access. * - * Const write access to this must be protected by `entry->mutex`. + * `const` write access to this must be protected by `entry->mutex`. */ mutable bool is_loaded; }; @@ -480,7 +480,7 @@ struct VolumeGridVector : public std::list { metadata.reset(); } - /* Mutex for file loading of grids list. Const write access to the fields after this must be + /* Mutex for file loading of grids list. `const` write access to the fields after this must be * protected by locking with this mutex. */ mutable std::mutex mutex; /* Absolute file path that grids have been loaded from. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 6cb0b985d3d..c84852788fd 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -454,8 +454,8 @@ static int foreach_id_cow_detect_need_for_update_callback(LibraryIDLinkCallbackD return IDWALK_RET_NOP; } if (!ID_TYPE_IS_COW(GS(id->name))) { - /* No need to go further if thte id never had a cow copy in the depsgraph. This function is - * only concerned with keeping the mapping between original and cow ids intact. */ + /* No need to go further if the id never had a cow copy in the depsgraph. This function is + * only concerned with keeping the mapping between original and COW ids intact. */ return IDWALK_RET_NOP; } diff --git a/source/blender/gpu/metal/mtl_batch.mm b/source/blender/gpu/metal/mtl_batch.mm index 3961e7a71a0..0d9a3225a51 100644 --- a/source/blender/gpu/metal/mtl_batch.mm +++ b/source/blender/gpu/metal/mtl_batch.mm @@ -69,7 +69,7 @@ void MTLBatch::MTLVertexDescriptorCache::vertex_descriptor_cache_ensure() } } - /* Initialise cache if not ready. */ + /* Initialize cache if not ready. */ if (cache_context_ == nullptr) { this->vertex_descriptor_cache_init(MTLContext::get()); } @@ -189,7 +189,7 @@ int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts, buffer_stride); } else { - /* Ensure stride is correct for de-interlevaed attributes. */ + /* Ensure stride is correct for de-interleaved attributes. */ desc.vertex_descriptor.buffer_layouts[buffer_index].stride = buffer_stride; } @@ -279,7 +279,7 @@ int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts, * elements). * * Certain conversion cannot be performed however, and in these cases, we need to - * instruct the shader to generate a specialised version with a conversion routine upon + * instruct the shader to generate a specialized version with a conversion routine upon * attribute read. * - This handles cases such as conversion between types e.g. Integer to float without * normalization. @@ -311,7 +311,7 @@ int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts, * This then controls how a given attribute is interpreted. The data will be read * as specified and then converted appropriately to the correct form. * - * e.g. if `GPU_FETCH_INT_TO_FLOAT` is specified, the specialised read-routine + * e.g. if `GPU_FETCH_INT_TO_FLOAT` is specified, the specialized read-routine * in the shader will read the data as an int, and cast this to floating point * representation. (Rather than reading the source data as float). * @@ -404,7 +404,7 @@ id MTLBatch::bind(uint v_first, uint v_count, uint i_fi active_shader_ = (shader) ? static_cast(unwrap(shader)) : nullptr; if (active_shader_ == nullptr || !active_shader_->is_valid()) { - /* Skip drawing if there is no vaid Metal shader. + /* Skip drawing if there is no valid Metal shader. * This will occur if the path through which the shader is prepared * is invalid (e.g. Python without create-info), or, the source shader uses a geometry pass. */ BLI_assert_msg(false, "No valid Metal shader!"); @@ -456,7 +456,7 @@ id MTLBatch::bind(uint v_first, uint v_count, uint i_fi /* Fetch RenderPassState to enable resource binding for active pass. */ MTLRenderPassState &rps = ctx->main_command_buffer.get_render_pass_state(); - /* Debug Check: Ensure Framebuffer instance is not dirty. */ + /* Debug Check: Ensure Frame-buffer instance is not dirty. */ BLI_assert(!ctx->main_command_buffer.get_active_framebuffer()->get_dirty()); /* Bind Shader. */ @@ -496,8 +496,8 @@ id MTLBatch::bind(uint v_first, uint v_count, uint i_fi if (mtl_elem != nullptr) { - /* Fetch index buffer. This function can situationally return an optimised - * index buffer of a different primtiive type. If this is the case, `final_prim_type` + /* Fetch index buffer. This function can situationally return an optimized + * index buffer of a different primitive type. If this is the case, `final_prim_type` * and `v_count` will be updated with the new format. * NOTE: For indexed rendering, v_count represents the number of indices. */ idx_buffer = mtl_elem->get_index_buffer(final_prim_type, v_count); @@ -672,7 +672,7 @@ void MTLBatch::prepare_vertex_descriptor_and_bindings( } } - /* Extract Vertex attribues (First-bound vertex buffer takes priority). */ + /* Extract Vertex attributes (First-bound vertex buffer takes priority). */ for (int v = 0; v < GPU_BATCH_VBO_MAX_LEN; v++) { if (mtl_verts[v] != NULL) { MTL_LOG_INFO(" -- [Batch] Checking bindings for bound vertex buffer %p\n", mtl_verts[v]); @@ -830,7 +830,7 @@ void MTLBatch::draw_advanced(int v_first, int v_count, int i_first, int i_count) "Index offset is not 2/4-byte aligned as per METAL spec"); /* Fetch index buffer. May return an index buffer of a differing format, - * if index buffer optimisation is used. In these cases, final_prim_type and + * if index buffer optimization is used. In these cases, final_prim_type and * index_count get updated with the new properties. */ GPUPrimType final_prim_type = this->prim_type; uint index_count = v_count; diff --git a/source/blender/gpu/metal/mtl_drawlist.mm b/source/blender/gpu/metal/mtl_drawlist.mm index dc3e4665dcf..99194d2b72c 100644 --- a/source/blender/gpu/metal/mtl_drawlist.mm +++ b/source/blender/gpu/metal/mtl_drawlist.mm @@ -153,7 +153,7 @@ void MTLDrawList::submit() { /* Metal does not support MDI from the host side, but we still benefit from only executing the * batch bind a single time, rather than per-draw. - * NOTE(Metal): Consider using MTLIndirectCommandBuffer to achieve similar behaviour. */ + * NOTE(Metal): Consider using #MTLIndirectCommandBuffer to achieve similar behavior. */ if (command_len_ == 0) { return; } @@ -194,12 +194,12 @@ void MTLDrawList::submit() /* Common properties. */ MTLPrimitiveType mtl_prim_type = gpu_prim_type_to_metal(batch_->prim_type); - /* Execute multidraw indirect. */ + /* Execute multi-draw indirect. */ if (can_use_MDI && false) { /* Metal Doesn't support MDI -- Singular Indirect draw calls are supported, - * but Multidraw is not. - * TODO(Metal): Consider using IndirectCommandBuffers to provide similar - * behaviour. */ + * but Multi-draw is not. + * TODO(Metal): Consider using #IndirectCommandBuffers to provide similar + * behavior. */ } else { @@ -216,7 +216,7 @@ void MTLDrawList::submit() uint32_t index_count = cmd->indexCount; /* Fetch index buffer. May return an index buffer of a differing format, - * if index buffer optimisation is used. In these cases, mtl_prim_type and + * if index buffer optimization is used. In these cases, mtl_prim_type and * index_count get updated with the new properties. */ GPUPrimType final_prim_type = batch_->prim_type; id index_buffer = mtl_elem->get_index_buffer(final_prim_type, index_count); diff --git a/source/blender/gpu/metal/mtl_texture.mm b/source/blender/gpu/metal/mtl_texture.mm index 4931f8a4f52..29dcc8d32ee 100644 --- a/source/blender/gpu/metal/mtl_texture.mm +++ b/source/blender/gpu/metal/mtl_texture.mm @@ -1510,7 +1510,7 @@ bool gpu::MTLTexture::init_internal(GPUVertBuf *vbo) texture_descriptor_.mipmapLevelCount = mtl_max_mips_; texture_descriptor_.usage = MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite | - MTLTextureUsagePixelFormatView; /* TODO(Metal): Optimise usage flags. */ + MTLTextureUsagePixelFormatView; /* TODO(Metal): Optimize usage flags. */ texture_descriptor_.storageMode = [source_buffer storageMode]; texture_descriptor_.sampleCount = 1; texture_descriptor_.cpuCacheMode = [source_buffer cpuCacheMode]; -- cgit v1.2.3 From ecda118be407163096641db36b6ee8bf1d88ee55 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 12:52:58 +1100 Subject: Fix T101866: Incorrect buttons for space-mouse enterprise Use key from spacenavd's wiki. Also add keys: ENTER, DELETE, TAB, SPACE & Views 1-3. --- intern/ghost/intern/GHOST_NDOFManager.cpp | 67 ++++++++++++++++++++++++--- intern/ghost/intern/GHOST_NDOFManager.h | 18 +++++-- source/blender/makesrna/intern/rna_wm.c | 22 ++++++--- source/blender/windowmanager/wm_event_types.h | 51 +++++++++++--------- 4 files changed, 118 insertions(+), 40 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index f4c726c7450..2754b9c8a6f 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -53,11 +53,6 @@ static const char *ndof_button_names[] = { "NDOF_BUTTON_DOMINANT", "NDOF_BUTTON_PLUS", "NDOF_BUTTON_MINUS", - /* keyboard emulation */ - "NDOF_BUTTON_ESC", - "NDOF_BUTTON_ALT", - "NDOF_BUTTON_SHIFT", - "NDOF_BUTTON_CTRL", /* general-purpose buttons */ "NDOF_BUTTON_1", "NDOF_BUTTON_2", @@ -73,6 +68,19 @@ static const char *ndof_button_names[] = { "NDOF_BUTTON_A", "NDOF_BUTTON_B", "NDOF_BUTTON_C", + /* Stored views. */ + "NDOF_BUTTON_V1", + "NDOF_BUTTON_V2", + "NDOF_BUTTON_V3", + /* Keyboard emulation. */ + "NDOF_BUTTON_ESC", + "NDOF_BUTTON_ENTER", + "NDOF_BUTTON_DELETE", + "NDOF_BUTTON_TAB", + "NDOF_BUTTON_SPACE", + "NDOF_BUTTON_ALT", + "NDOF_BUTTON_SHIFT", + "NDOF_BUTTON_CTRL", /* the end */ "NDOF_BUTTON_LAST", }; @@ -134,6 +142,41 @@ static const NDOF_ButtonT Generic_HID_map[] = { NDOF_BUTTON_C, }; +/* Values taken from: https://github.com/FreeSpacenav/spacenavd/wiki/Device-button-names */ +static const NDOF_ButtonT SpaceMouseEnterprise_HID_map[] = { + NDOF_BUTTON_1, /* (0) */ + NDOF_BUTTON_2, /* (1) */ + NDOF_BUTTON_3, /* (2) */ + NDOF_BUTTON_4, /* (3) */ + NDOF_BUTTON_5, /* (4) */ + NDOF_BUTTON_6, /* (5) */ + NDOF_BUTTON_7, /* (6) */ + NDOF_BUTTON_8, /* (7) */ + NDOF_BUTTON_9, /* (8) */ + NDOF_BUTTON_A, /* Labeled "10" (9). */ + NDOF_BUTTON_B, /* Labeled "11" (10). */ + NDOF_BUTTON_C, /* Labeled "12" (11). */ + NDOF_BUTTON_MENU, /* (12). */ + NDOF_BUTTON_FIT, /* (13). */ + NDOF_BUTTON_TOP, /* (14). */ + NDOF_BUTTON_RIGHT, /* (15). */ + NDOF_BUTTON_FRONT, /* (16). */ + NDOF_BUTTON_ROLL_CW, /* (17). */ + NDOF_BUTTON_ESC, /* (18). */ + NDOF_BUTTON_ALT, /* (19). */ + NDOF_BUTTON_SHIFT, /* (20). */ + NDOF_BUTTON_CTRL, /* (21). */ + NDOF_BUTTON_ROTATE, /* Labeled "Lock Rotate" (22). */ + NDOF_BUTTON_ENTER, /* Labeled "Enter" (23). */ + NDOF_BUTTON_DELETE, /* (24). */ + NDOF_BUTTON_TAB, /* (25). */ + NDOF_BUTTON_SPACE, /* (26). */ + NDOF_BUTTON_V1, /* Labeled "V1" (27). */ + NDOF_BUTTON_V2, /* Labeled "V2" (28). */ + NDOF_BUTTON_V3, /* Labeled "V3" (29). */ + NDOF_BUTTON_ISO1, /* Labeled "ISO1" (30). */ +}; + static const int genericButtonCount = ARRAY_SIZE(Generic_HID_map); GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System &sys) @@ -257,7 +300,7 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) puts("ndof: using SpaceMouse Enterprise"); m_deviceType = NDOF_SpaceMouseEnterprise; m_buttonCount = 31; - m_hidMap = Modern3Dx_HID_map; + m_hidMap = SpaceMouseEnterprise_HID_map; break; default: @@ -314,6 +357,18 @@ static GHOST_TKey ghost_map_keyboard_from_ndof_buttom(const NDOF_ButtonT button) case NDOF_BUTTON_ESC: { return GHOST_kKeyEsc; } + case NDOF_BUTTON_ENTER: { + return GHOST_kKeyEnter; + } + case NDOF_BUTTON_DELETE: { + return GHOST_kKeyDelete; + } + case NDOF_BUTTON_TAB: { + return GHOST_kKeyTab; + } + case NDOF_BUTTON_SPACE: { + return GHOST_kKeySpace; + } case NDOF_BUTTON_ALT: { return GHOST_kKeyLeftAlt; } diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 73c1b17f891..58371826527 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -58,11 +58,6 @@ typedef enum { NDOF_BUTTON_DOMINANT, NDOF_BUTTON_PLUS, NDOF_BUTTON_MINUS, - /* Keyboard emulation. */ - NDOF_BUTTON_ESC, - NDOF_BUTTON_ALT, - NDOF_BUTTON_SHIFT, - NDOF_BUTTON_CTRL, /* General-purpose buttons. * Users can assign functions via keymap editor. */ NDOF_BUTTON_1, @@ -79,6 +74,19 @@ typedef enum { NDOF_BUTTON_A, NDOF_BUTTON_B, NDOF_BUTTON_C, + /* Store Views. */ + NDOF_BUTTON_V1, + NDOF_BUTTON_V2, + NDOF_BUTTON_V3, + /* Keyboard emulation. */ + NDOF_BUTTON_ESC, + NDOF_BUTTON_ENTER, + NDOF_BUTTON_DELETE, + NDOF_BUTTON_TAB, + NDOF_BUTTON_SPACE, + NDOF_BUTTON_ALT, + NDOF_BUTTON_SHIFT, + NDOF_BUTTON_CTRL, /* The end. */ NDOF_BUTTON_LAST } NDOF_ButtonT; diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 5b5544120a1..eebe595820e 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -99,13 +99,6 @@ static const EnumPropertyItem event_ndof_type_items[] = { {NDOF_BUTTON_DOMINANT, "NDOF_BUTTON_DOMINANT", 0, "Dominant", ""}, {NDOF_BUTTON_PLUS, "NDOF_BUTTON_PLUS", 0, "Plus", ""}, {NDOF_BUTTON_MINUS, "NDOF_BUTTON_MINUS", 0, "Minus", ""}, -# if 0 /* Never used (converted to keyboard events by GHOST). */ - /* keyboard emulation */ - {NDOF_BUTTON_ESC, "NDOF_BUTTON_ESC", 0, "Esc"}, - {NDOF_BUTTON_ALT, "NDOF_BUTTON_ALT", 0, "Alt"}, - {NDOF_BUTTON_SHIFT, "NDOF_BUTTON_SHIFT", 0, "Shift"}, - {NDOF_BUTTON_CTRL, "NDOF_BUTTON_CTRL", 0, "Ctrl"}, -# endif /* general-purpose buttons */ {NDOF_BUTTON_1, "NDOF_BUTTON_1", 0, "Button 1", ""}, {NDOF_BUTTON_2, "NDOF_BUTTON_2", 0, "Button 2", ""}, @@ -120,6 +113,21 @@ static const EnumPropertyItem event_ndof_type_items[] = { {NDOF_BUTTON_A, "NDOF_BUTTON_A", 0, "Button A", ""}, {NDOF_BUTTON_B, "NDOF_BUTTON_B", 0, "Button B", ""}, {NDOF_BUTTON_C, "NDOF_BUTTON_C", 0, "Button C", ""}, + /* View buttons. */ + {NDOF_BUTTON_V1, "NDOF_BUTTON_V1", 0, "View 1", ""}, + {NDOF_BUTTON_V2, "NDOF_BUTTON_V2", 0, "View 2", ""}, + {NDOF_BUTTON_V3, "NDOF_BUTTON_V3", 0, "View 3", ""}, +# if 0 /* Never used (converted to keyboard events by GHOST). */ + /* keyboard emulation */ + {NDOF_BUTTON_ESC, "NDOF_BUTTON_ESC", 0, "Esc"}, + {NDOF_BUTTON_ENTER, "NDOF_BUTTON_ENTER", 0, "Enter"}, + {NDOF_BUTTON_DELETE, "NDOF_BUTTON_DELETE", 0, "Delete"}, + {NDOF_BUTTON_TAB, "NDOF_BUTTON_TAB", 0, "Tab"}, + {NDOF_BUTTON_SPACE, "NDOF_BUTTON_SPACE", 0, "Space"}, + {NDOF_BUTTON_ALT, "NDOF_BUTTON_ALT", 0, "Alt"}, + {NDOF_BUTTON_SHIFT, "NDOF_BUTTON_SHIFT", 0, "Shift"}, + {NDOF_BUTTON_CTRL, "NDOF_BUTTON_CTRL", 0, "Ctrl"}, +# endif {0, NULL, 0, NULL, NULL}, }; #endif /* RNA_RUNTIME */ diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index 405b7225bd5..10536a00501 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -281,35 +281,42 @@ enum { NDOF_BUTTON_DOMINANT = 0x01a3, /* 419 */ NDOF_BUTTON_PLUS = 0x01a4, /* 420 */ NDOF_BUTTON_MINUS = 0x01a5, /* 421 */ + /* General-purpose buttons. */ + NDOF_BUTTON_1 = 0x01a6, /* 422 */ + NDOF_BUTTON_2 = 0x01a7, /* 423 */ + NDOF_BUTTON_3 = 0x01a8, /* 424 */ + NDOF_BUTTON_4 = 0x01a9, /* 425 */ + NDOF_BUTTON_5 = 0x01aa, /* 426 */ + NDOF_BUTTON_6 = 0x01ab, /* 427 */ + NDOF_BUTTON_7 = 0x01ac, /* 428 */ + NDOF_BUTTON_8 = 0x01ad, /* 429 */ + NDOF_BUTTON_9 = 0x01ae, /* 430 */ + NDOF_BUTTON_10 = 0x01af, /* 431 */ + /* more general-purpose buttons */ + NDOF_BUTTON_A = 0x01b0, /* 432 */ + NDOF_BUTTON_B = 0x01b1, /* 433 */ + NDOF_BUTTON_C = 0x01b2, /* 434 */ + /* Store/restore views. */ + NDOF_BUTTON_V1 = 0x01b3, /* 435 */ + NDOF_BUTTON_V2 = 0x01b4, /* 436 */ + NDOF_BUTTON_V3 = 0x01b5, /* 437 */ /* Disabled as GHOST converts these to keyboard events * which use regular keyboard event handling logic. */ #if 0 /* keyboard emulation */ - NDOF_BUTTON_ESC = 0x01a6, /* 422 */ - NDOF_BUTTON_ALT = 0x01a7, /* 423 */ - NDOF_BUTTON_SHIFT = 0x01a8, /* 424 */ - NDOF_BUTTON_CTRL = 0x01a9, /* 425 */ + NDOF_BUTTON_ESC = 0x01b6, /* 438 */ + NDOF_BUTTON_ENTER = 0x01b7, /* 439 */ + NDOF_BUTTON_DELETE = 0x01b8, /* 440 */ + NDOF_BUTTON_TAB = 0x01b9, /* 441 */ + NDOF_BUTTON_SPACE = 0x01ba, /* 442 */ + NDOF_BUTTON_ALT = 0x01bb, /* 443 */ + NDOF_BUTTON_SHIFT = 0x01bc, /* 444 */ + NDOF_BUTTON_CTRL = 0x01bd, /* 445 */ #endif - /* general-purpose buttons */ - NDOF_BUTTON_1 = 0x01aa, /* 426 */ - NDOF_BUTTON_2 = 0x01ab, /* 427 */ - NDOF_BUTTON_3 = 0x01ac, /* 428 */ - NDOF_BUTTON_4 = 0x01ad, /* 429 */ - NDOF_BUTTON_5 = 0x01ae, /* 430 */ - NDOF_BUTTON_6 = 0x01af, /* 431 */ - NDOF_BUTTON_7 = 0x01b0, /* 432 */ - NDOF_BUTTON_8 = 0x01b1, /* 433 */ - NDOF_BUTTON_9 = 0x01b2, /* 434 */ - NDOF_BUTTON_10 = 0x01b3, /* 435 */ - /* more general-purpose buttons */ - NDOF_BUTTON_A = 0x01b4, /* 436 */ - NDOF_BUTTON_B = 0x01b5, /* 437 */ - NDOF_BUTTON_C = 0x01b6, /* 438 */ - -#define _NDOF_MAX NDOF_BUTTON_C -#define _NDOF_BUTTON_MAX NDOF_BUTTON_C +#define _NDOF_MAX NDOF_BUTTON_V3 +#define _NDOF_BUTTON_MAX NDOF_BUTTON_V3 /* ********** End of Input devices. ********** */ -- cgit v1.2.3 From ab28abcb6baaa728d8e2c30c4c98fef3655aa4dd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 12:58:36 +1100 Subject: Cleanup: remove the last button from NDOF button enum values This is only used for comparison, no need to make it part of the enum. --- intern/ghost/intern/GHOST_NDOFManager.cpp | 4 +--- intern/ghost/intern/GHOST_NDOFManager.h | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 2754b9c8a6f..555e22dadbb 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -81,8 +81,6 @@ static const char *ndof_button_names[] = { "NDOF_BUTTON_ALT", "NDOF_BUTTON_SHIFT", "NDOF_BUTTON_CTRL", - /* the end */ - "NDOF_BUTTON_LAST", }; /* Shared by the latest 3Dconnexion hardware @@ -389,7 +387,7 @@ void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button, uint64_t time, GHOST_IWindow *window) { - GHOST_ASSERT(button > NDOF_BUTTON_NONE && button < NDOF_BUTTON_LAST, + GHOST_ASSERT(button > NDOF_BUTTON_NONE && button < NDOF_BUTTON_NUM, "rogue button trying to escape NDOF manager"); GHOST_EventNDOFButton *event = new GHOST_EventNDOFButton(time, window); diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 58371826527..c883c2dce65 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -87,8 +87,7 @@ typedef enum { NDOF_BUTTON_ALT, NDOF_BUTTON_SHIFT, NDOF_BUTTON_CTRL, - /* The end. */ - NDOF_BUTTON_LAST +#define NDOF_BUTTON_NUM (NDOF_BUTTON_CTRL + 1) } NDOF_ButtonT; class GHOST_NDOFManager { -- cgit v1.2.3 From c247562b0703841ba5f9f651dbd77a3d448a93c1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 13:19:31 +1100 Subject: GHOST/NDOF: various minor changes to NDOF manager - Use logging for NDOF device output (this removes printing on startup buy default). - Use `ndof_` prefix for button maps. - Use full sentences. --- intern/ghost/intern/GHOST_NDOFManager.cpp | 157 +++++++++++++++++------------- intern/ghost/intern/GHOST_NDOFManager.h | 2 +- 2 files changed, 93 insertions(+), 66 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 555e22dadbb..e0913753e5b 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -12,11 +12,14 @@ #include #include -#include /* For error/info reporting. */ #include /* For memory functions. */ -/* Printable version of each GHOST_TProgress value. */ -static const char *progress_string[] = { +/* -------------------------------------------------------------------- */ +/** \name NDOF Enum Strings + * \{ */ + +/* Printable values for #GHOST_TProgress enum (keep aligned). */ +static const char *ndof_progress_string[] = { "not started", "starting", "in progress", @@ -24,36 +27,31 @@ static const char *progress_string[] = { "finished", }; +/* Printable values for #NDOF_ButtonT enum (keep aligned) */ static const char *ndof_button_names[] = { - /* used internally, never sent */ "NDOF_BUTTON_NONE", - /* these two are available from any 3Dconnexion device */ + /* Real button values. */ "NDOF_BUTTON_MENU", "NDOF_BUTTON_FIT", - /* standard views */ "NDOF_BUTTON_TOP", "NDOF_BUTTON_BOTTOM", "NDOF_BUTTON_LEFT", "NDOF_BUTTON_RIGHT", "NDOF_BUTTON_FRONT", "NDOF_BUTTON_BACK", - /* more views */ "NDOF_BUTTON_ISO1", "NDOF_BUTTON_ISO2", - /* 90 degree rotations */ "NDOF_BUTTON_ROLL_CW", "NDOF_BUTTON_ROLL_CCW", "NDOF_BUTTON_SPIN_CW", "NDOF_BUTTON_SPIN_CCW", "NDOF_BUTTON_TILT_CW", "NDOF_BUTTON_TILT_CCW", - /* device control */ "NDOF_BUTTON_ROTATE", "NDOF_BUTTON_PANZOOM", "NDOF_BUTTON_DOMINANT", "NDOF_BUTTON_PLUS", "NDOF_BUTTON_MINUS", - /* general-purpose buttons */ "NDOF_BUTTON_1", "NDOF_BUTTON_2", "NDOF_BUTTON_3", @@ -64,15 +62,12 @@ static const char *ndof_button_names[] = { "NDOF_BUTTON_8", "NDOF_BUTTON_9", "NDOF_BUTTON_10", - /* more general-purpose buttons */ "NDOF_BUTTON_A", "NDOF_BUTTON_B", "NDOF_BUTTON_C", - /* Stored views. */ "NDOF_BUTTON_V1", "NDOF_BUTTON_V2", "NDOF_BUTTON_V3", - /* Keyboard emulation. */ "NDOF_BUTTON_ESC", "NDOF_BUTTON_ENTER", "NDOF_BUTTON_DELETE", @@ -83,10 +78,30 @@ static const char *ndof_button_names[] = { "NDOF_BUTTON_CTRL", }; +static const char *ndof_device_names[] = { + "UnknownDevice", + "SpaceNavigator", + "SpaceExplorer", + "SpacePilotPro", + "SpaceMousePro", + "SpaceMouseWireless", + "SpaceMouseProWireless", + "SpaceMouseEnterprise", + "SpacePilot", + "Spaceball5000", + "SpaceTraveler", +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name NDOF Button Maps + * \{ */ + /* Shared by the latest 3Dconnexion hardware * SpacePilotPro uses all of these * smaller devices use only some, based on button mask. */ -static const NDOF_ButtonT Modern3Dx_HID_map[] = { +static const NDOF_ButtonT ndof_HID_map_Modern3Dx[] = { NDOF_BUTTON_MENU, NDOF_BUTTON_FIT, NDOF_BUTTON_TOP, NDOF_BUTTON_LEFT, NDOF_BUTTON_RIGHT, NDOF_BUTTON_FRONT, NDOF_BUTTON_BOTTOM, NDOF_BUTTON_BACK, NDOF_BUTTON_ROLL_CW, NDOF_BUTTON_ROLL_CCW, NDOF_BUTTON_ISO1, NDOF_BUTTON_ISO2, @@ -96,7 +111,7 @@ static const NDOF_ButtonT Modern3Dx_HID_map[] = { NDOF_BUTTON_SHIFT, NDOF_BUTTON_CTRL, NDOF_BUTTON_ROTATE, NDOF_BUTTON_PANZOOM, NDOF_BUTTON_DOMINANT, NDOF_BUTTON_PLUS, NDOF_BUTTON_MINUS}; -static const NDOF_ButtonT SpaceExplorer_HID_map[] = { +static const NDOF_ButtonT ndof_HID_map_SpaceExplorer[] = { NDOF_BUTTON_1, NDOF_BUTTON_2, NDOF_BUTTON_TOP, @@ -114,9 +129,8 @@ static const NDOF_ButtonT SpaceExplorer_HID_map[] = { NDOF_BUTTON_ROTATE, }; -/* This is the older SpacePilot (sans Pro) - * thanks to polosson for info about this device. */ -static const NDOF_ButtonT SpacePilot_HID_map[] = { +/* This is the older SpacePilot (sans Pro). */ +static const NDOF_ButtonT ndof_HID_map_SpacePilot[] = { NDOF_BUTTON_1, NDOF_BUTTON_2, NDOF_BUTTON_3, NDOF_BUTTON_4, NDOF_BUTTON_5, NDOF_BUTTON_6, NDOF_BUTTON_TOP, NDOF_BUTTON_LEFT, NDOF_BUTTON_RIGHT, NDOF_BUTTON_FRONT, NDOF_BUTTON_ESC, NDOF_BUTTON_ALT, @@ -125,7 +139,7 @@ static const NDOF_ButtonT SpacePilot_HID_map[] = { NDOF_BUTTON_NONE /* the CONFIG button -- what does it do? */ }; -static const NDOF_ButtonT Generic_HID_map[] = { +static const NDOF_ButtonT ndof_HID_map_Generic[] = { NDOF_BUTTON_1, NDOF_BUTTON_2, NDOF_BUTTON_3, @@ -141,7 +155,7 @@ static const NDOF_ButtonT Generic_HID_map[] = { }; /* Values taken from: https://github.com/FreeSpacenav/spacenavd/wiki/Device-button-names */ -static const NDOF_ButtonT SpaceMouseEnterprise_HID_map[] = { +static const NDOF_ButtonT ndof_HID_map_SpaceMouseEnterprise[] = { NDOF_BUTTON_1, /* (0) */ NDOF_BUTTON_2, /* (1) */ NDOF_BUTTON_3, /* (2) */ @@ -175,14 +189,20 @@ static const NDOF_ButtonT SpaceMouseEnterprise_HID_map[] = { NDOF_BUTTON_ISO1, /* Labeled "ISO1" (30). */ }; -static const int genericButtonCount = ARRAY_SIZE(Generic_HID_map); +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name NDOF Manager Class + * \{ */ + +static const int genericButtonCount = ARRAY_SIZE(ndof_HID_map_Generic); GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System &sys) : m_system(sys), m_deviceType(NDOF_UnknownDevice), /* Each platform has its own device detection code. */ m_buttonCount(genericButtonCount), m_buttonMask(0), - m_hidMap(Generic_HID_map), + m_hidMap(ndof_HID_map_Generic), m_buttons(0), m_motionTime(0), m_prevMotionTime(0), @@ -196,6 +216,8 @@ GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System &sys) memset(m_rotation, 0, sizeof(m_rotation)); } +/** \} */ + /* -------------------------------------------------------------------- */ /** \name NDOF Device Setup * \{ */ @@ -207,14 +229,14 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) { /* Call this function until it returns true * it's a good idea to stop calling it after that, as it will "forget" - * whichever device it already found */ + * whichever device it already found. */ /* Default to safe generic behavior for "unknown" devices * unidentified devices will emit motion events like normal * rogue buttons do nothing by default, but can be customized by the user. */ m_deviceType = NDOF_UnknownDevice; - m_hidMap = Generic_HID_map; + m_hidMap = ndof_HID_map_Generic; m_buttonCount = genericButtonCount; m_buttonMask = 0; @@ -226,87 +248,92 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) case 0x046D: /* Logitech (3Dconnexion was a subsidiary). */ switch (product_id) { /* -- current devices -- */ - case 0xC626: /* full-size SpaceNavigator */ - case 0xC628: /* the "for Notebooks" one */ - puts("ndof: using SpaceNavigator"); + case 0xC626: /* Full-size SpaceNavigator. */ + case 0xC628: /* The "for Notebooks" one. */ + { m_deviceType = NDOF_SpaceNavigator; m_buttonCount = 2; - m_hidMap = Modern3Dx_HID_map; + m_hidMap = ndof_HID_map_Modern3Dx; break; - case 0xC627: - puts("ndof: using SpaceExplorer"); + } + case 0xC627: { m_deviceType = NDOF_SpaceExplorer; m_buttonCount = 15; - m_hidMap = SpaceExplorer_HID_map; + m_hidMap = ndof_HID_map_SpaceExplorer; break; - case 0xC629: - puts("ndof: using SpacePilot Pro"); + } + case 0xC629: { m_deviceType = NDOF_SpacePilotPro; m_buttonCount = 31; - m_hidMap = Modern3Dx_HID_map; + m_hidMap = ndof_HID_map_Modern3Dx; break; - case 0xC62B: - puts("ndof: using SpaceMouse Pro"); + } + case 0xC62B: { m_deviceType = NDOF_SpaceMousePro; - m_buttonCount = 27; - /* ^^ actually has 15 buttons, but their HID codes range from 0 to 26 */ + m_buttonCount = 27; /* Actually has 15 buttons, but HID codes range from 0 to 26. */ m_buttonMask = 0x07C0F137; - m_hidMap = Modern3Dx_HID_map; + m_hidMap = ndof_HID_map_Modern3Dx; break; + } /* -- older devices -- */ - case 0xC625: - puts("ndof: using SpacePilot"); + case 0xC625: { m_deviceType = NDOF_SpacePilot; m_buttonCount = 21; - m_hidMap = SpacePilot_HID_map; + m_hidMap = ndof_HID_map_SpacePilot; break; - case 0xC621: - puts("ndof: using Spaceball 5000"); + } + case 0xC621: { m_deviceType = NDOF_Spaceball5000; m_buttonCount = 12; break; - case 0xC623: - puts("ndof: using SpaceTraveler"); + } + case 0xC623: { m_deviceType = NDOF_SpaceTraveler; m_buttonCount = 8; break; - - default: - printf("ndof: unknown Logitech product %04hx\n", product_id); + } + default: { + CLOG_INFO(LOG, 2, "unknown Logitech product %04hx", product_id); + } } break; - case 0x256F: /* 3Dconnexion */ + case 0x256F: /* 3Dconnexion. */ switch (product_id) { case 0xC62E: /* Plugged in. */ case 0xC62F: /* Wireless. */ - puts("ndof: using SpaceMouse Wireless"); + { m_deviceType = NDOF_SpaceMouseWireless; m_buttonCount = 2; - m_hidMap = Modern3Dx_HID_map; + m_hidMap = ndof_HID_map_Modern3Dx; break; + } case 0xC631: /* Plugged in. */ case 0xC632: /* Wireless. */ - puts("ndof: using SpaceMouse Pro Wireless"); + { m_deviceType = NDOF_SpaceMouseProWireless; - m_buttonCount = 27; - /* ^^ actually has 15 buttons, but their HID codes range from 0 to 26. */ + m_buttonCount = 27; /* Actually has 15 buttons, but HID codes range from 0 to 26. */ m_buttonMask = 0x07C0F137; - m_hidMap = Modern3Dx_HID_map; + m_hidMap = ndof_HID_map_Modern3Dx; break; - case 0xC633: - puts("ndof: using SpaceMouse Enterprise"); + } + case 0xC633: { m_deviceType = NDOF_SpaceMouseEnterprise; m_buttonCount = 31; - m_hidMap = SpaceMouseEnterprise_HID_map; + m_hidMap = ndof_HID_map_SpaceMouseEnterprise; break; - - default: - printf("ndof: unknown 3Dconnexion product %04hx\n", product_id); + } + default: { + CLOG_INFO(LOG, 2, "unknown 3Dconnexion product %04hx", product_id); + } } break; default: - printf("ndof: unknown device %04hx:%04hx\n", vendor_id, product_id); + CLOG_INFO(LOG, 2, "unknown device %04hx:%04hx", vendor_id, product_id); + } + + if (m_deviceType != NDOF_UnknownDevice) { + CLOG_INFO(LOG, 2, "using %s", ndof_device_names[m_deviceType]); } if (m_buttonMask == 0) { @@ -591,7 +618,7 @@ bool GHOST_NDOFManager::sendMotionEvent() data->ry, data->rz, data->dt, - progress_string[data->progress]); + ndof_progress_string[data->progress]); #else /* Raw values, may be useful for debugging. */ CLOG_INFO(LOG, @@ -603,7 +630,7 @@ bool GHOST_NDOFManager::sendMotionEvent() m_rotation[0], m_rotation[1], m_rotation[2], - progress_string[data->progress]); + ndof_progress_string[data->progress]); #endif m_system.pushEvent(event); diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index c883c2dce65..2a1d94b052e 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -9,7 +9,7 @@ #include "GHOST_System.h" typedef enum { - NDOF_UnknownDevice, + NDOF_UnknownDevice = 0, /* Current devices. */ NDOF_SpaceNavigator, -- cgit v1.2.3 From c9f13788639790aba02acb3376dc505043dae175 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 13:52:51 +1100 Subject: Cleanup: use '_' suffix for private members for NDOF Manager --- intern/ghost/intern/GHOST_NDOFManager.cpp | 190 +++++++++++++------------- intern/ghost/intern/GHOST_NDOFManager.h | 26 ++-- intern/ghost/intern/GHOST_NDOFManagerUnix.cpp | 16 +-- intern/ghost/intern/GHOST_NDOFManagerUnix.h | 2 +- 4 files changed, 117 insertions(+), 117 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index e0913753e5b..882443ae839 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -198,22 +198,22 @@ static const NDOF_ButtonT ndof_HID_map_SpaceMouseEnterprise[] = { static const int genericButtonCount = ARRAY_SIZE(ndof_HID_map_Generic); GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System &sys) - : m_system(sys), - m_deviceType(NDOF_UnknownDevice), /* Each platform has its own device detection code. */ - m_buttonCount(genericButtonCount), - m_buttonMask(0), - m_hidMap(ndof_HID_map_Generic), - m_buttons(0), - m_motionTime(0), - m_prevMotionTime(0), - m_motionState(GHOST_kNotStarted), - m_motionEventPending(false), - m_deadZone(0.0f) + : system_(sys), + device_type_(NDOF_UnknownDevice), /* Each platform has its own device detection code. */ + hid_map_button_num_(genericButtonCount), + hid_map_button_mask_(0), + hid_map_(ndof_HID_map_Generic), + button_depressed_(0), + motion_time_(0), + motion_time_prev_(0), + motion_state_(GHOST_kNotStarted), + motion_event_pending_(false), + motion_dead_zone_(0.0f) { /* To avoid the rare situation where one triple is updated and * the other is not, initialize them both here: */ - memset(m_translation, 0, sizeof(m_translation)); - memset(m_rotation, 0, sizeof(m_rotation)); + memset(translation_, 0, sizeof(translation_)); + memset(rotation_, 0, sizeof(rotation_)); } /** \} */ @@ -235,10 +235,10 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) * unidentified devices will emit motion events like normal * rogue buttons do nothing by default, but can be customized by the user. */ - m_deviceType = NDOF_UnknownDevice; - m_hidMap = ndof_HID_map_Generic; - m_buttonCount = genericButtonCount; - m_buttonMask = 0; + device_type_ = NDOF_UnknownDevice; + hid_map_ = ndof_HID_map_Generic; + hid_map_button_num_ = genericButtonCount; + hid_map_button_mask_ = 0; /* "mystery device" owners can help build a HID_map for their hardware * A few users have already contributed information about several older devices @@ -251,46 +251,46 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) case 0xC626: /* Full-size SpaceNavigator. */ case 0xC628: /* The "for Notebooks" one. */ { - m_deviceType = NDOF_SpaceNavigator; - m_buttonCount = 2; - m_hidMap = ndof_HID_map_Modern3Dx; + device_type_ = NDOF_SpaceNavigator; + hid_map_button_num_ = 2; + hid_map_ = ndof_HID_map_Modern3Dx; break; } case 0xC627: { - m_deviceType = NDOF_SpaceExplorer; - m_buttonCount = 15; - m_hidMap = ndof_HID_map_SpaceExplorer; + device_type_ = NDOF_SpaceExplorer; + hid_map_button_num_ = 15; + hid_map_ = ndof_HID_map_SpaceExplorer; break; } case 0xC629: { - m_deviceType = NDOF_SpacePilotPro; - m_buttonCount = 31; - m_hidMap = ndof_HID_map_Modern3Dx; + device_type_ = NDOF_SpacePilotPro; + hid_map_button_num_ = 31; + hid_map_ = ndof_HID_map_Modern3Dx; break; } case 0xC62B: { - m_deviceType = NDOF_SpaceMousePro; - m_buttonCount = 27; /* Actually has 15 buttons, but HID codes range from 0 to 26. */ - m_buttonMask = 0x07C0F137; - m_hidMap = ndof_HID_map_Modern3Dx; + device_type_ = NDOF_SpaceMousePro; + hid_map_button_num_ = 27; /* Actually has 15 buttons, but HID codes range from 0 to 26. */ + hid_map_button_mask_ = 0x07C0F137; + hid_map_ = ndof_HID_map_Modern3Dx; break; } /* -- older devices -- */ case 0xC625: { - m_deviceType = NDOF_SpacePilot; - m_buttonCount = 21; - m_hidMap = ndof_HID_map_SpacePilot; + device_type_ = NDOF_SpacePilot; + hid_map_button_num_ = 21; + hid_map_ = ndof_HID_map_SpacePilot; break; } case 0xC621: { - m_deviceType = NDOF_Spaceball5000; - m_buttonCount = 12; + device_type_ = NDOF_Spaceball5000; + hid_map_button_num_ = 12; break; } case 0xC623: { - m_deviceType = NDOF_SpaceTraveler; - m_buttonCount = 8; + device_type_ = NDOF_SpaceTraveler; + hid_map_button_num_ = 8; break; } default: { @@ -303,24 +303,24 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) case 0xC62E: /* Plugged in. */ case 0xC62F: /* Wireless. */ { - m_deviceType = NDOF_SpaceMouseWireless; - m_buttonCount = 2; - m_hidMap = ndof_HID_map_Modern3Dx; + device_type_ = NDOF_SpaceMouseWireless; + hid_map_button_num_ = 2; + hid_map_ = ndof_HID_map_Modern3Dx; break; } case 0xC631: /* Plugged in. */ case 0xC632: /* Wireless. */ { - m_deviceType = NDOF_SpaceMouseProWireless; - m_buttonCount = 27; /* Actually has 15 buttons, but HID codes range from 0 to 26. */ - m_buttonMask = 0x07C0F137; - m_hidMap = ndof_HID_map_Modern3Dx; + device_type_ = NDOF_SpaceMouseProWireless; + hid_map_button_num_ = 27; /* Actually has 15 buttons, but HID codes range from 0 to 26. */ + hid_map_button_mask_ = 0x07C0F137; + hid_map_ = ndof_HID_map_Modern3Dx; break; } case 0xC633: { - m_deviceType = NDOF_SpaceMouseEnterprise; - m_buttonCount = 31; - m_hidMap = ndof_HID_map_SpaceMouseEnterprise; + device_type_ = NDOF_SpaceMouseEnterprise; + hid_map_button_num_ = 31; + hid_map_ = ndof_HID_map_SpaceMouseEnterprise; break; } default: { @@ -332,17 +332,17 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) CLOG_INFO(LOG, 2, "unknown device %04hx:%04hx", vendor_id, product_id); } - if (m_deviceType != NDOF_UnknownDevice) { - CLOG_INFO(LOG, 2, "using %s", ndof_device_names[m_deviceType]); + if (device_type_ != NDOF_UnknownDevice) { + CLOG_INFO(LOG, 2, "using %s", ndof_device_names[device_type_]); } - if (m_buttonMask == 0) { - m_buttonMask = int(~(UINT_MAX << m_buttonCount)); + if (hid_map_button_mask_ == 0) { + hid_map_button_mask_ = int(~(UINT_MAX << hid_map_button_num_)); } - CLOG_INFO(LOG, 2, "%d buttons -> hex:%X", m_buttonCount, (uint)m_buttonMask); + CLOG_INFO(LOG, 2, "%d buttons -> hex:%X", hid_map_button_num_, (uint)hid_map_button_mask_); - return m_deviceType != NDOF_UnknownDevice; + return device_type_ != NDOF_UnknownDevice; } #undef LOG @@ -355,16 +355,16 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) void GHOST_NDOFManager::updateTranslation(const int t[3], uint64_t time) { - memcpy(m_translation, t, sizeof(m_translation)); - m_motionTime = time; - m_motionEventPending = true; + memcpy(translation_, t, sizeof(translation_)); + motion_time_ = time; + motion_event_pending_ = true; } void GHOST_NDOFManager::updateRotation(const int r[3], uint64_t time) { - memcpy(m_rotation, r, sizeof(m_rotation)); - m_motionTime = time; - m_motionEventPending = true; + memcpy(rotation_, r, sizeof(rotation_)); + motion_time_ = time; + motion_event_pending_ = true; } /** \} */ @@ -423,7 +423,7 @@ void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button, data->action = press ? GHOST_kPress : GHOST_kRelease; data->button = button; - m_system.pushEvent(event); + system_.pushEvent(event); } void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key, @@ -434,21 +434,21 @@ void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key, GHOST_TEventType type = press ? GHOST_kEventKeyDown : GHOST_kEventKeyUp; GHOST_EventKey *event = new GHOST_EventKey(time, type, window, key, false); - m_system.pushEvent(event); + system_.pushEvent(event); } void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t time) { - if (button_number >= m_buttonCount) { + if (button_number >= hid_map_button_num_) { CLOG_INFO(LOG, 2, "button=%d, press=%d (out of range %d, ignoring!)", button_number, (int)press, - m_buttonCount); + hid_map_button_num_); return; } - const NDOF_ButtonT button = m_hidMap[button_number]; + const NDOF_ButtonT button = hid_map_[button_number]; if (button == NDOF_BUTTON_NONE) { CLOG_INFO( LOG, 2, "button=%d, press=%d (mapped to none, ignoring!)", button_number, (int)press); @@ -462,7 +462,7 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t tim (int)press, ndof_button_names[button]); - GHOST_IWindow *window = m_system.getWindowManager()->getActiveWindow(); + GHOST_IWindow *window = system_.getWindowManager()->getActiveWindow(); const GHOST_TKey key = ghost_map_keyboard_from_ndof_buttom(button); if (key != GHOST_kKeyUnknown) { sendKeyEvent(key, press, time, window); @@ -473,20 +473,20 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t tim int mask = 1 << button_number; if (press) { - m_buttons |= mask; /* Set this button's bit. */ + button_depressed_ |= mask; /* Set this button's bit. */ } else { - m_buttons &= ~mask; /* Clear this button's bit. */ + button_depressed_ &= ~mask; /* Clear this button's bit. */ } } void GHOST_NDOFManager::updateButtons(int button_bits, uint64_t time) { - button_bits &= m_buttonMask; /* Discard any "garbage" bits. */ + button_bits &= hid_map_button_mask_; /* Discard any "garbage" bits. */ - int diff = m_buttons ^ button_bits; + int diff = button_depressed_ ^ button_bits; - for (int button_number = 0; button_number < m_buttonCount; ++button_number) { + for (int button_number = 0; button_number < hid_map_button_num_; ++button_number) { int mask = 1 << button_number; if (diff & mask) { @@ -513,7 +513,7 @@ void GHOST_NDOFManager::setDeadZone(float dz) /* Negative values don't make sense, so clamp at zero. */ dz = 0.0f; } - m_deadZone = dz; + motion_dead_zone_ = dz; /* Warn the rogue user/developer about high dead-zone, but allow it. */ CLOG_INFO(LOG, 2, "dead zone set to %.2f%s", dz, (dz > 0.5f) ? " (unexpectedly high)" : ""); @@ -538,20 +538,20 @@ static bool nearHomePosition(GHOST_TEventNDOFMotionData *ndof, float threshold) bool GHOST_NDOFManager::sendMotionEvent() { - if (!m_motionEventPending) { + if (!motion_event_pending_) { return false; } - m_motionEventPending = false; /* Any pending motion is handled right now. */ + motion_event_pending_ = false; /* Any pending motion is handled right now. */ - GHOST_IWindow *window = m_system.getWindowManager()->getActiveWindow(); + GHOST_IWindow *window = system_.getWindowManager()->getActiveWindow(); if (window == nullptr) { - m_motionState = GHOST_kNotStarted; /* Avoid large `dt` times when changing windows. */ + motion_state_ = GHOST_kNotStarted; /* Avoid large `dt` times when changing windows. */ return false; /* Delivery will fail, so don't bother sending. */ } - GHOST_EventNDOFMotion *event = new GHOST_EventNDOFMotion(m_motionTime, window); + GHOST_EventNDOFMotion *event = new GHOST_EventNDOFMotion(motion_time_, window); GHOST_TEventNDOFMotionData *data = (GHOST_TEventNDOFMotionData *)event->getData(); /* Scale axis values here to normalize them to around +/- 1 @@ -559,26 +559,26 @@ bool GHOST_NDOFManager::sendMotionEvent() const float scale = 1.0f / 350.0f; /* 3Dconnexion devices send +/- 350 usually */ - data->tx = scale * m_translation[0]; - data->ty = scale * m_translation[1]; - data->tz = scale * m_translation[2]; + data->tx = scale * translation_[0]; + data->ty = scale * translation_[1]; + data->tz = scale * translation_[2]; - data->rx = scale * m_rotation[0]; - data->ry = scale * m_rotation[1]; - data->rz = scale * m_rotation[2]; - data->dt = 0.001f * (m_motionTime - m_prevMotionTime); /* In seconds. */ - m_prevMotionTime = m_motionTime; + data->rx = scale * rotation_[0]; + data->ry = scale * rotation_[1]; + data->rz = scale * rotation_[2]; + data->dt = 0.001f * (motion_time_ - motion_time_prev_); /* In seconds. */ + motion_time_prev_ = motion_time_; - bool weHaveMotion = !nearHomePosition(data, m_deadZone); + bool weHaveMotion = !nearHomePosition(data, motion_dead_zone_); /* Determine what kind of motion event to send `(Starting, InProgress, Finishing)` * and where that leaves this NDOF manager `(NotStarted, InProgress, Finished)`. */ - switch (m_motionState) { + switch (motion_state_) { case GHOST_kNotStarted: case GHOST_kFinished: { if (weHaveMotion) { data->progress = GHOST_kStarting; - m_motionState = GHOST_kInProgress; + motion_state_ = GHOST_kInProgress; /* Previous motion time will be ancient, so just make up a reasonable time delta. */ data->dt = 0.0125f; } @@ -597,7 +597,7 @@ bool GHOST_NDOFManager::sendMotionEvent() } else { data->progress = GHOST_kFinishing; - m_motionState = GHOST_kFinished; + motion_state_ = GHOST_kFinished; } break; } @@ -624,15 +624,15 @@ bool GHOST_NDOFManager::sendMotionEvent() CLOG_INFO(LOG, 2, "motion sent, T=(%d,%d,%d) R=(%d,%d,%d) status=%s", - m_translation[0], - m_translation[1], - m_translation[2], - m_rotation[0], - m_rotation[1], - m_rotation[2], + translation_[0], + translation_[1], + translation_[2], + rotation_[0], + rotation_[1], + rotation_[2], ndof_progress_string[data->progress]); #endif - m_system.pushEvent(event); + system_.pushEvent(event); return true; } diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 2a1d94b052e..6dadeee1fcc 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -147,25 +147,25 @@ class GHOST_NDOFManager { bool sendMotionEvent(); protected: - GHOST_System &m_system; + GHOST_System &system_; private: void sendButtonEvent(NDOF_ButtonT, bool press, uint64_t time, GHOST_IWindow *); void sendKeyEvent(GHOST_TKey, bool press, uint64_t time, GHOST_IWindow *); - NDOF_DeviceT m_deviceType; - int m_buttonCount; - int m_buttonMask; - const NDOF_ButtonT *m_hidMap; + NDOF_DeviceT device_type_; + int hid_map_button_num_; + int hid_map_button_mask_; + const NDOF_ButtonT *hid_map_; - int m_translation[3]; - int m_rotation[3]; - int m_buttons; /* Bit field. */ + int translation_[3]; + int rotation_[3]; + int button_depressed_; /* Bit field. */ - uint64_t m_motionTime; /* In milliseconds. */ - uint64_t m_prevMotionTime; /* Time of most recent motion event sent. */ + uint64_t motion_time_; /* In milliseconds. */ + uint64_t motion_time_prev_; /* Time of most recent motion event sent. */ - GHOST_TProgress m_motionState; - bool m_motionEventPending; - float m_deadZone; /* Discard motion with each component < this. */ + GHOST_TProgress motion_state_; + bool motion_event_pending_; + float motion_dead_zone_; /* Discard motion with each component < this. */ }; diff --git a/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp b/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp index 94bf0337371..0ccf4dc9bfb 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp @@ -10,7 +10,7 @@ #define SPNAV_SOCK_PATH "/var/run/spnav.sock" GHOST_NDOFManagerUnix::GHOST_NDOFManagerUnix(GHOST_System &sys) - : GHOST_NDOFManager(sys), m_available(false) + : GHOST_NDOFManager(sys), available_(false) { if (access(SPNAV_SOCK_PATH, F_OK) != 0) { #ifdef DEBUG @@ -20,7 +20,7 @@ GHOST_NDOFManagerUnix::GHOST_NDOFManagerUnix(GHOST_System &sys) #endif } else if (spnav_open() != -1) { - m_available = true; + available_ = true; /* determine exactly which device (if any) is plugged in */ @@ -45,14 +45,14 @@ GHOST_NDOFManagerUnix::GHOST_NDOFManagerUnix(GHOST_System &sys) GHOST_NDOFManagerUnix::~GHOST_NDOFManagerUnix() { - if (m_available) { + if (available_) { spnav_close(); } } bool GHOST_NDOFManagerUnix::available() { - return m_available; + return available_; } /* @@ -74,7 +74,7 @@ bool GHOST_NDOFManagerUnix::processEvents() { bool anyProcessed = false; - if (m_available) { + if (available_) { spnav_event e; #ifdef USE_FINISH_GLITCH_WORKAROUND @@ -85,7 +85,7 @@ bool GHOST_NDOFManagerUnix::processEvents() switch (e.type) { case SPNAV_EVENT_MOTION: { /* convert to blender view coords */ - uint64_t now = m_system.getMilliSeconds(); + uint64_t now = system_.getMilliSeconds(); const int t[3] = {int(e.motion.x), int(e.motion.y), int(-e.motion.z)}; const int r[3] = {int(-e.motion.rx), int(-e.motion.ry), int(e.motion.rz)}; @@ -97,7 +97,7 @@ bool GHOST_NDOFManagerUnix::processEvents() break; } case SPNAV_EVENT_BUTTON: - uint64_t now = m_system.getMilliSeconds(); + uint64_t now = system_.getMilliSeconds(); updateButton(e.button.bnum, e.button.press, now); break; } @@ -106,7 +106,7 @@ bool GHOST_NDOFManagerUnix::processEvents() #ifdef USE_FINISH_GLITCH_WORKAROUND if (motion_test_prev == true && motion_test == false) { - uint64_t now = m_system.getMilliSeconds(); + uint64_t now = system_.getMilliSeconds(); const int v[3] = {0, 0, 0}; updateTranslation(v, now); diff --git a/intern/ghost/intern/GHOST_NDOFManagerUnix.h b/intern/ghost/intern/GHOST_NDOFManagerUnix.h index fd603e3cb54..2b98fad974f 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerUnix.h +++ b/intern/ghost/intern/GHOST_NDOFManagerUnix.h @@ -15,5 +15,5 @@ class GHOST_NDOFManagerUnix : public GHOST_NDOFManager { bool processEvents(); private: - bool m_available; + bool available_; }; -- cgit v1.2.3 From e4c5a46c1294eefd7464395bca9551b9ca866aea Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 14:07:36 +1100 Subject: Cleanup: remove NDOF_BUTTON_NONE from the range of usable buttons This is used to represent unknown state, so there is no need to be able to store it's pressed state. --- intern/ghost/intern/GHOST_NDOFManager.cpp | 8 ++++---- intern/ghost/intern/GHOST_NDOFManager.h | 6 +++--- source/blender/blenkernel/BKE_brush.h | 2 +- source/blender/windowmanager/intern/wm_event_system.cc | 2 +- source/blender/windowmanager/wm_event_types.h | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 882443ae839..9e9b9f14c43 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -29,8 +29,7 @@ static const char *ndof_progress_string[] = { /* Printable values for #NDOF_ButtonT enum (keep aligned) */ static const char *ndof_button_names[] = { - "NDOF_BUTTON_NONE", - /* Real button values. */ + /* Exclude `NDOF_BUTTON_NONE` (-1). */ "NDOF_BUTTON_MENU", "NDOF_BUTTON_FIT", "NDOF_BUTTON_TOP", @@ -68,6 +67,7 @@ static const char *ndof_button_names[] = { "NDOF_BUTTON_V1", "NDOF_BUTTON_V2", "NDOF_BUTTON_V3", + /* Keyboard emulation. */ "NDOF_BUTTON_ESC", "NDOF_BUTTON_ENTER", "NDOF_BUTTON_DELETE", @@ -270,7 +270,7 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) } case 0xC62B: { device_type_ = NDOF_SpaceMousePro; - hid_map_button_num_ = 27; /* Actually has 15 buttons, but HID codes range from 0 to 26. */ + hid_map_button_num_ = 27; /* 15 physical buttons, but HID codes range from 0 to 26. */ hid_map_button_mask_ = 0x07C0F137; hid_map_ = ndof_HID_map_Modern3Dx; break; @@ -312,7 +312,7 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) case 0xC632: /* Wireless. */ { device_type_ = NDOF_SpaceMouseProWireless; - hid_map_button_num_ = 27; /* Actually has 15 buttons, but HID codes range from 0 to 26. */ + hid_map_button_num_ = 27; /* 15 physical buttons, but HID codes range from 0 to 26. */ hid_map_button_mask_ = 0x07C0F137; hid_map_ = ndof_HID_map_Modern3Dx; break; diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 6dadeee1fcc..2d5bba14aa4 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -29,8 +29,8 @@ typedef enum { /* NDOF device button event types */ typedef enum { - /* Used internally, never sent. */ - NDOF_BUTTON_NONE = 0, + /* Used internally, never sent or used as an index. */ + NDOF_BUTTON_NONE = -1, /* These two are available from any 3Dconnexion device. */ NDOF_BUTTON_MENU, NDOF_BUTTON_FIT, @@ -162,7 +162,7 @@ class GHOST_NDOFManager { int rotation_[3]; int button_depressed_; /* Bit field. */ - uint64_t motion_time_; /* In milliseconds. */ + uint64_t motion_time_; /* In milliseconds. */ uint64_t motion_time_prev_; /* Time of most recent motion event sent. */ GHOST_TProgress motion_state_; diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 8f069841fbc..a763b3d12c2 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -126,7 +126,7 @@ float BKE_brush_sample_masktex(const struct Scene *scene, * Get the mask texture for this given object mode. * * This is preferred above using mtex/mask_mtex attributes directly as due to legacy these - * attributes got switched in sculpt mode. + * attributes got switched in sculpt mode. */ const struct MTex *BKE_brush_mask_texture_get(const struct Brush *brush, const eObjectMode object_mode); diff --git a/source/blender/windowmanager/intern/wm_event_system.cc b/source/blender/windowmanager/intern/wm_event_system.cc index affe0bcf45a..181ec89cabd 100644 --- a/source/blender/windowmanager/intern/wm_event_system.cc +++ b/source/blender/windowmanager/intern/wm_event_system.cc @@ -5620,7 +5620,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void case GHOST_kEventNDOFButton: { GHOST_TEventNDOFButtonData *e = static_cast(customdata); - event.type = NDOF_BUTTON_NONE + e->button; + event.type = NDOF_BUTTON_INDEX_AS_EVENT(e->button); switch (e->action) { case GHOST_kPress: diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index 10536a00501..c36c57a12ae 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -252,8 +252,6 @@ enum { #define _NDOF_MIN NDOF_MOTION #define _NDOF_BUTTON_MIN NDOF_BUTTON_MENU - /* used internally, never sent */ - NDOF_BUTTON_NONE = NDOF_MOTION, /* these two are available from any 3Dconnexion device */ NDOF_BUTTON_MENU = 0x0191, /* 401 */ @@ -456,6 +454,8 @@ enum eEventType_Mask { (EVT_TYPE_MASK_KEYBOARD | EVT_TYPE_MASK_MOUSE | EVT_TYPE_MASK_NDOF) #define EVT_TYPE_MASK_HOTKEY_EXCLUDE EVT_TYPE_MASK_KEYBOARD_MODIFIER +#define NDOF_BUTTON_INDEX_AS_EVENT(i) (_NDOF_BUTTON_MIN + (i)) + bool WM_event_type_mask_test(int event_type, enum eEventType_Mask mask); /** \} */ -- cgit v1.2.3 From 42f37106c59e454764a5a2c5c03c02a71efab49e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 14:53:48 +1100 Subject: GHOST/Wayland: add listener for touch events (no touch support yet) Currently unused as my tablet isn't generating touch events. This may be useful for development as touch events are logged. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 95 ++++++++++++++++++++++ .../extern/wayland_dynload_client.h | 1 + 2 files changed, 96 insertions(+) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 04c7e103bde..83bbcd60b2f 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -416,6 +416,7 @@ struct GWL_Seat { std::string name; struct wl_seat *wl_seat = nullptr; struct wl_pointer *wl_pointer = nullptr; + struct wl_touch *wl_touch = nullptr; struct wl_keyboard *wl_keyboard = nullptr; struct zwp_tablet_seat_v2 *tablet_seat = nullptr; @@ -643,6 +644,11 @@ static void display_destroy(GWL_Display *display) wl_pointer_destroy(seat->wl_pointer); } } + + if (seat->wl_touch) { + wl_touch_destroy(seat->wl_touch); + } + if (seat->wl_keyboard) { if (seat->key_repeat.timer) { keyboard_handle_key_repeat_cancel(seat); @@ -1898,6 +1904,89 @@ static const struct wl_pointer_listener pointer_listener = { /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Listener (Touch Seat), #wl_touch_listener + * + * TODO(@campbellbarton): Only setup the callbacks for now as I don't have + * hardware that generates touch events. + * \{ */ + +static CLG_LogRef LOG_WL_TOUCH = {"ghost.wl.handle.touch"}; +#define LOG (&LOG_WL_TOUCH) + +static void touch_seat_handle_down(void * /*data*/, + struct wl_touch * /*wl_touch*/, + uint32_t /*serial*/, + uint32_t /*time*/, + struct wl_surface * /*wl_surface*/, + int32_t /*id*/, + wl_fixed_t /*x*/, + wl_fixed_t /*y*/) +{ + CLOG_INFO(LOG, 2, "down"); +} + +static void touch_seat_handle_up(void * /*data*/, + struct wl_touch * /*wl_touch*/, + uint32_t /*serial*/, + uint32_t /*time*/, + int32_t /*id*/) +{ + CLOG_INFO(LOG, 2, "up"); +} + +static void touch_seat_handle_motion(void * /*data*/, + struct wl_touch * /*wl_touch*/, + uint32_t /*time*/, + int32_t /*id*/, + wl_fixed_t /*x*/, + wl_fixed_t /*y*/) +{ + CLOG_INFO(LOG, 2, "motion"); +} + +static void touch_seat_handle_frame(void * /*data*/, struct wl_touch * /*wl_touch*/) +{ + CLOG_INFO(LOG, 2, "frame"); +} + +static void touch_seat_handle_cancel(void * /*data*/, struct wl_touch * /*wl_touch*/) +{ + + CLOG_INFO(LOG, 2, "cancel"); +} + +static void touch_seat_handle_shape(void * /*data*/, + struct wl_touch * /*touch*/, + int32_t /*id*/, + wl_fixed_t /*major*/, + wl_fixed_t /*minor*/) +{ + CLOG_INFO(LOG, 2, "shape"); +} + +static void touch_seat_handle_orientation(void * /*data*/, + struct wl_touch * /*touch*/, + int32_t /*id*/, + wl_fixed_t /*orientation*/) +{ + CLOG_INFO(LOG, 2, "orientation"); +} + +static const struct wl_touch_listener touch_seat_listener = { + touch_seat_handle_down, + touch_seat_handle_up, + touch_seat_handle_motion, + touch_seat_handle_frame, + touch_seat_handle_cancel, + touch_seat_handle_shape, + touch_seat_handle_orientation, +}; + +#undef LOG + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Listener (Tablet Tool), #zwp_tablet_tool_v2_listener * \{ */ @@ -2717,6 +2806,12 @@ static void seat_handle_capabilities(void *data, ghost_wl_surface_tag_cursor_pointer(seat->cursor.wl_surface); } + if (capabilities & WL_SEAT_CAPABILITY_TOUCH) { + seat->wl_touch = wl_seat_get_touch(wl_seat); + wl_touch_set_user_data(seat->wl_touch, seat); + wl_touch_add_listener(seat->wl_touch, &touch_seat_listener, seat); + } + if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { seat->wl_keyboard = wl_seat_get_keyboard(wl_seat); wl_keyboard_add_listener(seat->wl_keyboard, &keyboard_listener, data); diff --git a/intern/wayland_dynload/extern/wayland_dynload_client.h b/intern/wayland_dynload/extern/wayland_dynload_client.h index 8e9dddd91a3..d80ef5c9f0c 100644 --- a/intern/wayland_dynload/extern/wayland_dynload_client.h +++ b/intern/wayland_dynload/extern/wayland_dynload_client.h @@ -41,6 +41,7 @@ WAYLAND_DYNLOAD_IFACE(wl_seat_interface) WAYLAND_DYNLOAD_IFACE(wl_shm_interface) WAYLAND_DYNLOAD_IFACE(wl_shm_pool_interface) WAYLAND_DYNLOAD_IFACE(wl_surface_interface) +WAYLAND_DYNLOAD_IFACE(wl_touch_interface) #else /* Header guard. */ -- cgit v1.2.3 From da4bd24c3e6122c74fbc6dcc81604ee7a0dd3fe0 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 18 Oct 2022 23:44:07 -0500 Subject: Sculpt: Improve performance of face set creation from selection Skip BMesh conversion and read the selection attribute directly. With a Ryzen 3700x, my test face of a simple 4 million face grid became over 4000 times faster, from 2.6s to 0.6ms. --- .../editors/sculpt_paint/sculpt_face_set.cc | 29 ++++++++-------------- 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.cc b/source/blender/editors/sculpt_paint/sculpt_face_set.cc index ee1238e0f24..8fb4dea668e 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.cc +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.cc @@ -18,6 +18,7 @@ #include "BLI_math_vector.hh" #include "BLI_span.hh" #include "BLI_task.h" +#include "BLI_task.hh" #include "DNA_brush_types.h" #include "DNA_customdata_types.h" @@ -313,6 +314,7 @@ static EnumPropertyItem prop_sculpt_face_set_create_types[] = { static int sculpt_face_set_create_exec(bContext *C, wmOperator *op) { + using namespace blender; Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); @@ -396,25 +398,16 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op) } if (mode == SCULPT_FACE_SET_SELECTION) { - BMesh *bm; - const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh); - BMeshCreateParams create_params{}; - create_params.use_toolflags = true; - bm = BM_mesh_create(&allocsize, &create_params); - - BMeshFromMeshParams convert_params{}; - convert_params.calc_vert_normal = true; - convert_params.calc_face_normal = true; - BM_mesh_bm_from_me(bm, mesh, &convert_params); - - BMIter iter; - BMFace *f; - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - ss->face_sets[BM_elem_index_get(f)] = next_face_set; + const bke::AttributeAccessor attributes = mesh->attributes(); + const VArraySpan select_poly = attributes.lookup_or_default( + ".select_poly", ATTR_DOMAIN_FACE, false); + threading::parallel_for(IndexRange(mesh->totvert), 4096, [&](const IndexRange range) { + for (const int i : range) { + if (select_poly[i]) { + ss->face_sets[i] = next_face_set; + } } - } - BM_mesh_free(bm); + }); } for (int i = 0; i < totnode; i++) { -- cgit v1.2.3 From 30d9a6245f892492188318e92b85083ef8b301f2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 16:20:30 +1100 Subject: GHOST/Wayland: support high resolution 2D track-pad scroll events These events are interpreted as MOUSEPAN by Blender. Tested with a Wacom Intuos5. This isn't full touch support which is needed to support gestures such as Swipe, Rotate .. etc. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 99 +++++++++++++++++++++++++---- 1 file changed, 88 insertions(+), 11 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 83bbcd60b2f..09f51199047 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -10,6 +10,7 @@ #include "GHOST_EventCursor.h" #include "GHOST_EventDragnDrop.h" #include "GHOST_EventKey.h" +#include "GHOST_EventTrackpad.h" #include "GHOST_EventWheel.h" #include "GHOST_PathUtils.h" #include "GHOST_TimerManager.h" @@ -340,6 +341,11 @@ struct GWL_SeatStatePointer { */ wl_fixed_t xy[2] = {0, 0}; + /** Smooth scrolling (handled & reset with pointer "frame" callback). */ + wl_fixed_t scroll_xy[2] = {0, 0}; + /** Discrete scrolling (handled & reset with pointer "frame" callback). */ + int32_t scroll_discrete_xy[2] = {0, 0}; + /** Outputs on which the cursor is visible. */ std::unordered_set outputs; @@ -843,6 +849,21 @@ static GHOST_TKey xkb_map_gkey_or_scan_code(const xkb_keysym_t sym, const uint32 return gkey; } +static int pointer_axis_as_index(const uint32_t axis) +{ + switch (axis) { + case WL_POINTER_AXIS_HORIZONTAL_SCROLL: { + return 0; + } + case WL_POINTER_AXIS_VERTICAL_SCROLL: { + return 1; + } + default: { + return -1; + } + } +} + static GHOST_TTabletMode tablet_tool_map_type(enum zwp_tablet_tool_v2_type wl_tablet_tool_type) { switch (wl_tablet_tool_type) { @@ -1732,6 +1753,14 @@ static void pointer_handle_enter(void *data, seat->pointer.serial = serial; seat->pointer.xy[0] = surface_x; seat->pointer.xy[1] = surface_y; + + /* Resetting scroll events is likely unnecessary, + * do this to avoid any possible problems as it's harmless. */ + seat->pointer.scroll_xy[0] = 0; + seat->pointer.scroll_xy[1] = 0; + seat->pointer.scroll_discrete_xy[0] = 0; + seat->pointer.scroll_discrete_xy[1] = 0; + seat->pointer.wl_surface = wl_surface; win->setCursorShape(win->getCursorShape()); @@ -1843,18 +1872,69 @@ static void pointer_handle_button(void *data, } } -static void pointer_handle_axis(void * /*data*/, +static void pointer_handle_axis(void *data, struct wl_pointer * /*wl_pointer*/, const uint32_t /*time*/, const uint32_t axis, const wl_fixed_t value) { + /* NOTE: this is used for touch based scrolling - or other input that doesn't scroll with + * discrete "steps". This allows supporting smooth-scrolling without "touch" gesture support. */ CLOG_INFO(LOG, 2, "axis (axis=%u, value=%d)", axis, value); + const int index = pointer_axis_as_index(axis); + if (UNLIKELY(index == -1)) { + return; + } + GWL_Seat *seat = static_cast(data); + seat->pointer.scroll_xy[index] = value; } -static void pointer_handle_frame(void * /*data*/, struct wl_pointer * /*wl_pointer*/) +static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/) { CLOG_INFO(LOG, 2, "frame"); + GWL_Seat *seat = static_cast(data); + + /* Discrete steps may generate non-discrete scrolling, in this case, + * give the mouse wheel priority otherwise mouse wheel events would be recognized + * as touch-pad scrolling too. */ + if (seat->pointer.scroll_discrete_xy[0]) { + seat->pointer.scroll_xy[0] = 0; + } + if (seat->pointer.scroll_discrete_xy[1]) { + seat->pointer.scroll_xy[1] = 0; + } + + /* Discrete Y steps currently unsupported. */ + if (seat->pointer.scroll_discrete_xy[0]) { + if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { + GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); + const int32_t discrete = seat->pointer.scroll_discrete_xy[0]; + seat->system->pushEvent(new GHOST_EventWheel( + seat->system->getMilliSeconds(), win, std::signbit(discrete) ? +1 : -1)); + } + seat->pointer.scroll_discrete_xy[0] = 0; + seat->pointer.scroll_discrete_xy[1] = 0; + } + + if (seat->pointer.scroll_xy[0] || seat->pointer.scroll_xy[1]) { + if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { + GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); + const wl_fixed_t scale = win->scale(); + seat->system->pushEvent(new GHOST_EventTrackpad( + seat->system->getMilliSeconds(), + win, + GHOST_kTrackpadEventScroll, + wl_fixed_to_int(scale * seat->pointer.xy[0]), + wl_fixed_to_int(scale * seat->pointer.xy[1]), + wl_fixed_to_int(seat->pointer.scroll_xy[0]), + wl_fixed_to_int(seat->pointer.scroll_xy[1]), + /* TODO: investigate a way to request this configuration from the system. */ + true)); + } + + seat->pointer.scroll_xy[0] = 0; + seat->pointer.scroll_xy[1] = 0; + } } static void pointer_handle_axis_source(void * /*data*/, struct wl_pointer * /*wl_pointer*/, @@ -1874,18 +1954,15 @@ static void pointer_handle_axis_discrete(void *data, uint32_t axis, int32_t discrete) { + /* NOTE: a discrete axis are typically mouse wheel events. + * The non-discrete version of this function is used for touch-pad. */ CLOG_INFO(LOG, 2, "axis_discrete (axis=%u, discrete=%d)", axis, discrete); - - GWL_Seat *seat = static_cast(data); - if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) { + const int index = pointer_axis_as_index(axis); + if (UNLIKELY(index == -1)) { return; } - - if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { - GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); - seat->system->pushEvent(new GHOST_EventWheel( - seat->system->getMilliSeconds(), win, std::signbit(discrete) ? +1 : -1)); - } + GWL_Seat *seat = static_cast(data); + seat->pointer.scroll_discrete_xy[index] = discrete; } static const struct wl_pointer_listener pointer_listener = { -- cgit v1.2.3 From 760a6aa1f5d67d9638e44748dfd453729634b331 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 16:35:32 +1100 Subject: Fix error in 30d9a6245f892492188318e92b85083ef8b301f2 X/Y for mouse wheel events was unintentionally flipped. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 09f51199047..62f96e4e620 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1904,11 +1904,11 @@ static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/) seat->pointer.scroll_xy[1] = 0; } - /* Discrete Y steps currently unsupported. */ - if (seat->pointer.scroll_discrete_xy[0]) { + /* Discrete X axis currently unsupported. */ + if (seat->pointer.scroll_discrete_xy[1]) { if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); - const int32_t discrete = seat->pointer.scroll_discrete_xy[0]; + const int32_t discrete = seat->pointer.scroll_discrete_xy[1]; seat->system->pushEvent(new GHOST_EventWheel( seat->system->getMilliSeconds(), win, std::signbit(discrete) ? +1 : -1)); } -- cgit v1.2.3 From 96fa5e1e84d722fd9d4014ab5d100ec254d64cb5 Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Tue, 18 Oct 2022 14:42:35 +0200 Subject: Cleanup: remove unused 'VIEW3D_MT_brush_context_menu_paint_modes' This was added in rB4c9fe657458f, however that new code never used this menu (but the existing `VIEW3D_MT_brush_paint_modes` instead). Differential Revision: https://developer.blender.org/D16285 --- release/scripts/startup/bl_ui/space_view3d_toolbar.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 328e45f79b9..a28e93c34d1 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -81,22 +81,6 @@ class VIEW3D_MT_brush_gpencil_context_menu(Menu): layout.operator("gpencil.brush_reset_all") -class VIEW3D_MT_brush_context_menu_paint_modes(Menu): - bl_label = "Enabled Modes" - - def draw(self, context): - layout = self.layout - - settings = UnifiedPaintPanel.paint_settings(context) - brush = settings.brush - - layout.prop(brush, "use_paint_sculpt", text="Sculpt") - layout.prop(brush, "use_paint_uv_sculpt", text="UV Sculpt") - layout.prop(brush, "use_paint_vertex", text="Vertex Paint") - layout.prop(brush, "use_paint_weight", text="Weight Paint") - layout.prop(brush, "use_paint_image", text="Texture Paint") - - class View3DPanel: bl_space_type = 'VIEW_3D' bl_region_type = 'UI' @@ -2373,7 +2357,6 @@ class VIEW3D_PT_gpencil_brush_presets(Panel, PresetPanel): classes = ( VIEW3D_MT_brush_context_menu, VIEW3D_MT_brush_gpencil_context_menu, - VIEW3D_MT_brush_context_menu_paint_modes, VIEW3D_PT_tools_object_options, VIEW3D_PT_tools_object_options_transform, VIEW3D_PT_tools_meshedit_options, -- cgit v1.2.3 From 4d185921f6cee93a1d8b5f3178b6f1267b0fb53a Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Tue, 18 Oct 2022 14:57:57 +0200 Subject: Sculpt curves: Fix BKE_paint_object_mode_from_paintmode Currently harmless (since atm. it is not possible to trigger this part of the code from curves sculpting), but in a future fix (for T101518), it would be good to use `BKE_paint_init` (and having the correct ob_mode for the brush would be nice). Differential Revision: https://developer.blender.org/D16286 --- source/blender/blenkernel/intern/paint.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index 13243925b28..408cd117e32 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -1043,6 +1043,8 @@ eObjectMode BKE_paint_object_mode_from_paintmode(ePaintMode mode) return OB_MODE_TEXTURE_PAINT; case PAINT_MODE_SCULPT_UV: return OB_MODE_EDIT; + case PAINT_MODE_SCULPT_CURVES: + return OB_MODE_SCULPT_CURVES; case PAINT_MODE_INVALID: default: return OB_MODE_OBJECT; -- cgit v1.2.3 From 4163c63def98b46fe7ddba82ade997c818ab2b96 Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Tue, 18 Oct 2022 15:40:54 +0200 Subject: Curves sculptmode: fix missing mode and tool in Brush Specials For consistency with other brush based (paint) systems we should add these entries in the brushes context menu. For this, expose the brushes `ob_mode` to RNA and show this (along with the tool choice) to the appropriate menus. Differential Revision: https://developer.blender.org/D16287 --- release/scripts/startup/bl_ui/space_view3d.py | 1 + release/scripts/startup/bl_ui/space_view3d_toolbar.py | 2 ++ source/blender/makesrna/intern/rna_brush.c | 4 ++++ 3 files changed, 7 insertions(+) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index ea257498e11..39684aaf161 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -3018,6 +3018,7 @@ class VIEW3D_MT_brush_paint_modes(Menu): layout.prop(brush, "use_paint_vertex", text="Vertex Paint") layout.prop(brush, "use_paint_weight", text="Weight Paint") layout.prop(brush, "use_paint_image", text="Texture Paint") + layout.prop(brush, "use_paint_sculpt_curves", text="Sculpt Curves") class VIEW3D_MT_paint_vertex(Menu): diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index a28e93c34d1..fec156580cf 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -52,6 +52,8 @@ class VIEW3D_MT_brush_context_menu(Menu): elif context.sculpt_object: layout.prop_menu_enum(brush, "sculpt_tool") layout.operator("brush.reset") + elif context.tool_settings.curves_sculpt: + layout.prop_menu_enum(brush, "curves_sculpt_tool") class VIEW3D_MT_brush_gpencil_context_menu(Menu): diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 35e01be366b..137020ce3f8 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -3616,6 +3616,10 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Use Vertex", "Use this brush in grease pencil vertex color mode"); + prop = RNA_def_property(srna, "use_paint_sculpt_curves", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "ob_mode", OB_MODE_SCULPT_CURVES); + RNA_def_property_ui_text(prop, "Use Sculpt", "Use this brush in sculpt curves mode"); + /* texture */ prop = RNA_def_property(srna, "texture_slot", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "BrushTextureSlot"); -- cgit v1.2.3 From a450a2f2b288c5105f0d0522c440e82fb498e117 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 19 Oct 2022 09:18:47 +0200 Subject: Fix T101903: Crash when deleting library in some cases. Remapping in batch deletion could end up calling viewlayer resync code on partially invalid BMain (some IDs still in Main using IDs removed from Main). Think this code can actually be further optimized, but this fix should be safe enough for 3.3 (and potentially 2.93). Thanks to Jeroen (@jbakker) for the initial investigation. --- source/blender/blenkernel/intern/lib_id_delete.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index f4f5ca7a1d7..aaf932accf1 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -23,6 +23,7 @@ #include "BKE_idprop.h" #include "BKE_idtype.h" #include "BKE_key.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_lib_override.h" #include "BKE_lib_remap.h" @@ -217,6 +218,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) BKE_main_lock(bmain); if (do_tagged_deletion) { + BKE_layer_collection_resync_forbid(); /* Main idea of batch deletion is to remove all IDs to be deleted from Main database. * This means that we won't have to loop over all deleted IDs to remove usages * of other deleted IDs. @@ -279,6 +281,9 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) } } + BKE_layer_collection_resync_allow(); + BKE_main_collection_sync_remap(bmain); + /* Now we can safely mark that ID as not being in Main database anymore. */ /* NOTE: This needs to be done in a separate loop than above, otherwise some user-counts of * deleted IDs may not be properly decreased by the remappings (since `NO_MAIN` ID user-counts -- cgit v1.2.3 From 358155a8da60760acc9baf554a449bbaf277085e Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 19 Oct 2022 10:17:33 +0200 Subject: Make batch ID deletion 100 times faster. Simplify and optimize remapping handling in bacth ID deletion, by moving it outside of the initial loop gathering all IDs to be deleted, and and by using batch remapping code. Speedup can be over 100 times faster in complex production scenes using thousands of IDs, when e.g. deleting a whole library. Examples before/after times on my machine (deleting two different libraries): lib1: 5.55 sec/0.03 sec lib2: 13.60 sec/0.13 sec Found while investigating T101903. --- source/blender/blenkernel/intern/lib_id_delete.c | 64 +++++++++++++----------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index aaf932accf1..a2236089093 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -16,6 +16,7 @@ #include "BLI_utildefines.h" +#include "BLI_linklist.h" #include "BLI_listbase.h" #include "BKE_anim_data.h" @@ -27,7 +28,6 @@ #include "BKE_lib_id.h" #include "BKE_lib_override.h" #include "BKE_lib_remap.h" -#include "BKE_library.h" #include "BKE_main.h" #include "BKE_main_namemap.h" @@ -203,7 +203,6 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) { const int tag = LIB_TAG_DOIT; ListBase *lbarray[INDEX_ID_MAX]; - Link dummy_link = {0}; int base_count, i; /* Used by batch tagged deletion, when we call BKE_id_free then, id is no more in Main database, @@ -218,7 +217,8 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) BKE_main_lock(bmain); if (do_tagged_deletion) { - BKE_layer_collection_resync_forbid(); + struct IDRemapper *id_remapper = BKE_id_remapper_create(); + /* Main idea of batch deletion is to remove all IDs to be deleted from Main database. * This means that we won't have to loop over all deleted IDs to remove usages * of other deleted IDs. @@ -229,7 +229,6 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) bool keep_looping = true; while (keep_looping) { ID *id, *id_next; - ID *last_remapped_id = tagged_deleted_ids.last; keep_looping = false; /* First tag and remove from Main all datablocks directly from target lib. @@ -245,6 +244,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) BLI_remlink(lb, id); BKE_main_namemap_remove_name(bmain, id, id->name + 2); BLI_addtail(&tagged_deleted_ids, id); + BKE_id_remapper_add(id_remapper, id, NULL); /* Do not tag as no_main now, we want to unlink it first (lower-level ID management * code has some specific handling of 'no main' IDs that would be a problem in that * case). */ @@ -253,34 +253,38 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) } } } - if (last_remapped_id == NULL) { - dummy_link.next = tagged_deleted_ids.first; - last_remapped_id = (ID *)(&dummy_link); - } - for (id = last_remapped_id->next; id; id = id->next) { - /* Will tag 'never NULL' users of this ID too. - * - * NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect - * links, this can lead to nasty crashing here in second, actual deleting loop. - * Also, this will also flag users of deleted data that cannot be unlinked - * (object using deleted obdata, etc.), so that they also get deleted. */ - BKE_libblock_remap_locked(bmain, - id, - NULL, - (ID_REMAP_FLAG_NEVER_NULL_USAGE | - ID_REMAP_FORCE_NEVER_NULL_USAGE | - ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS)); - /* Since we removed ID from Main, - * we also need to unlink its own other IDs usages ourself. */ - BKE_libblock_relink_ex( - bmain, - id, - NULL, - NULL, - (ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS | ID_REMAP_SKIP_USER_CLEAR)); - } } + BKE_layer_collection_resync_forbid(); + + /* Will tag 'never NULL' users of this ID too. + * + * NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect + * links, this can lead to nasty crashing here in second, actual deleting loop. + * Also, this will also flag users of deleted data that cannot be unlinked + * (object using deleted obdata, etc.), so that they also get deleted. */ + BKE_libblock_remap_multiple_locked(bmain, + id_remapper, + ID_REMAP_FLAG_NEVER_NULL_USAGE | + ID_REMAP_FORCE_NEVER_NULL_USAGE | + ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS); + BKE_id_remapper_clear(id_remapper); + + /* Since we removed IDs from Main, their own other IDs usages need to be removed 'manually'. */ + LinkNode *cleanup_ids = NULL; + for (ID *id = tagged_deleted_ids.first; id; id = id->next) { + BLI_linklist_prepend(&cleanup_ids, id); + } + BKE_libblock_relink_multiple(bmain, + cleanup_ids, + ID_REMAP_TYPE_CLEANUP, + id_remapper, + ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS | + ID_REMAP_SKIP_USER_CLEAR); + + BKE_id_remapper_free(id_remapper); + BLI_linklist_free(cleanup_ids, NULL); + BKE_layer_collection_resync_allow(); BKE_main_collection_sync_remap(bmain); -- cgit v1.2.3 From e5782df4aba90ca70fca9a949e5b546abdb12ec3 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 19 Oct 2022 10:27:56 +0200 Subject: Fix (unreported) error messages about invalid ID usercount when batch-deleting IDs. Batch-delete by-passes a lot of ID usages handling in to-be-deleted IDs, so usercount of deleted IDs needs to be manually reset to avoid the annoying error messages in the console. --- source/blender/blenkernel/intern/lib_id_delete.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index a2236089093..ae5dc75c36a 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -294,6 +294,10 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) * is never affected). */ for (ID *id = tagged_deleted_ids.first; id; id = id->next) { id->tag |= LIB_TAG_NO_MAIN; + /* Usercount needs to be reset artificially, since some usages may not be cleared in batch + * deletion (typically, if one deleted ID uses another deleted ID, this may not be cleared by + * remapping code, depending on order in which these are handled). */ + id->us = ID_FAKE_USERS(id); } } else { -- cgit v1.2.3 From 2180e6fc9ffb173e1a36e2668f048d18cf3940f2 Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Tue, 13 Sep 2022 13:19:15 +0200 Subject: Curves: make the "surface_uv_map" a searchable dropdown The users had to type in a name here, but we can also make it a dropdown choice with existing UV Maps for convenience: - dont have to remember a name or copy paste obviously - shows in red if it was removed / invalid Came up in T101028 Maniphest Tasks: T101028 Differential Revision: https://developer.blender.org/D15956 --- release/scripts/startup/bl_ui/properties_data_curves.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/release/scripts/startup/bl_ui/properties_data_curves.py b/release/scripts/startup/bl_ui/properties_data_curves.py index ff0eabeb7d9..df80bdb4552 100644 --- a/release/scripts/startup/bl_ui/properties_data_curves.py +++ b/release/scripts/startup/bl_ui/properties_data_curves.py @@ -44,7 +44,13 @@ class DATA_PT_curves_surface(DataButtonsPanel, Panel): layout.use_property_split = True layout.prop(ob.data, "surface") - layout.prop(ob.data, "surface_uv_map", text="UV Map") + has_surface = ob.data.surface is not None + if has_surface: + layout.prop_search(ob.data, "surface_uv_map", ob.data.surface.data, "uv_layers", text="UV Map") + else: + row = layout.row() + row.prop(ob.data, "surface_uv_map", text="UV Map") + row.enabled = has_surface class CURVES_MT_add_attribute(Menu): -- cgit v1.2.3 From b51763a773009d887460bac14e9f7b65cbf54e5b Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Tue, 18 Oct 2022 10:30:37 +0200 Subject: Fix T101888: Curves editmode: modifiers "Display in Edit mode" no effect Add the eModifierMode_Editmode to the required modes for curves modifier evaluation. Only this way the modifier can be skipped in evaluation. Maniphest Tasks: T101888 Differential Revision: https://developer.blender.org/D16280 --- source/blender/blenkernel/intern/curves.cc | 5 ++++- source/blender/blenkernel/intern/object.cc | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/curves.cc b/source/blender/blenkernel/intern/curves.cc index 01be22a57b0..72e53023d6d 100644 --- a/source/blender/blenkernel/intern/curves.cc +++ b/source/blender/blenkernel/intern/curves.cc @@ -287,7 +287,10 @@ static void curves_evaluate_modifiers(struct Depsgraph *depsgraph, { /* Modifier evaluation modes. */ const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); - const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; + int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; + if (BKE_object_is_in_editmode(object)) { + required_mode = (ModifierMode)(int(required_mode) | eModifierMode_Editmode); + } ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE; const ModifierEvalContext mectx = {depsgraph, object, apply_flag}; diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc index 2d949fb5c65..d98f5e85028 100644 --- a/source/blender/blenkernel/intern/object.cc +++ b/source/blender/blenkernel/intern/object.cc @@ -1902,6 +1902,7 @@ bool BKE_object_is_in_editmode(const Object *ob) /* Grease Pencil object has no edit mode data. */ return GPENCIL_EDIT_MODE((bGPdata *)ob->data); case OB_CURVES: + /* Curves object has no edit mode data. */ return ob->mode == OB_MODE_EDIT; default: return false; -- cgit v1.2.3 From d4b8e9b69fccf96a3c8035418a9fc1f00f43dee1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 17:02:40 +1100 Subject: Cleanup: format --- source/blender/gpu/metal/mtl_batch.mm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/blender/gpu/metal/mtl_batch.mm b/source/blender/gpu/metal/mtl_batch.mm index 0d9a3225a51..988fb9b793b 100644 --- a/source/blender/gpu/metal/mtl_batch.mm +++ b/source/blender/gpu/metal/mtl_batch.mm @@ -595,8 +595,10 @@ void MTLBatch::prepare_vertex_descriptor_and_bindings( desc.reset_vertex_descriptor(); /* Fetch Vertex and Instance Buffers. */ - Span mtl_verts(reinterpret_cast(this->verts), GPU_BATCH_VBO_MAX_LEN); - Span mtl_inst(reinterpret_cast(this->inst), GPU_BATCH_INST_VBO_MAX_LEN); + Span mtl_verts(reinterpret_cast(this->verts), + GPU_BATCH_VBO_MAX_LEN); + Span mtl_inst(reinterpret_cast(this->inst), + GPU_BATCH_INST_VBO_MAX_LEN); /* SSBO Vertex fetch also passes vertex descriptor information into the shader. */ if (active_shader_->get_uses_ssbo_vertex_fetch()) { -- cgit v1.2.3 From 89525fae59eaac8fe1d63a948b454ac9ce921f05 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 17:09:29 +1100 Subject: Cleanup: CMake include paths Remove redundant separators & redundant references to parent paths. --- intern/cycles/app/CMakeLists.txt | 5 ++++- intern/ghost/CMakeLists.txt | 2 +- source/blender/compositor/realtime_compositor/CMakeLists.txt | 2 +- source/blender/io/stl/CMakeLists.txt | 2 +- source/blender/io/wavefront_obj/CMakeLists.txt | 4 ++-- source/blender/makesdna/intern/CMakeLists.txt | 2 +- source/blender/makesrna/intern/CMakeLists.txt | 2 +- source/blender/nodes/texture/CMakeLists.txt | 2 +- 8 files changed, 12 insertions(+), 9 deletions(-) diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt index 0988b1c0ac4..1c7a861ea93 100644 --- a/intern/cycles/app/CMakeLists.txt +++ b/intern/cycles/app/CMakeLists.txt @@ -43,7 +43,10 @@ else() endif() if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI) - list(APPEND INC_SYS ${Epoxy_INCLUDE_DIRS} ${SDL2_INCLUDE_DIRS}) + list(APPEND INC_SYS + ${Epoxy_INCLUDE_DIRS} + ${SDL2_INCLUDE_DIRS} + ) list(APPEND LIB ${Epoxy_LIBRARIES} ${SDL2_LIBRARIES}) endif() diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 2f8ea1f9065..72621648608 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -268,7 +268,7 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND) if(WITH_GHOST_WAYLAND_DYNLOAD) list(APPEND INC_SYS - ../../intern/wayland_dynload/extern + ../wayland_dynload/extern ) list(APPEND LIB bf_intern_wayland_dynload diff --git a/source/blender/compositor/realtime_compositor/CMakeLists.txt b/source/blender/compositor/realtime_compositor/CMakeLists.txt index 90cbe0988ad..bab0b5385ec 100644 --- a/source/blender/compositor/realtime_compositor/CMakeLists.txt +++ b/source/blender/compositor/realtime_compositor/CMakeLists.txt @@ -2,7 +2,7 @@ set(INC . - ./algorithms + algorithms ../../blenkernel ../../blenlib ../../gpu diff --git a/source/blender/io/stl/CMakeLists.txt b/source/blender/io/stl/CMakeLists.txt index 3a21da5c579..f7eb933d198 100644 --- a/source/blender/io/stl/CMakeLists.txt +++ b/source/blender/io/stl/CMakeLists.txt @@ -2,7 +2,7 @@ set(INC . - ./importer + importer ../common ../../blenkernel ../../blenlib diff --git a/source/blender/io/wavefront_obj/CMakeLists.txt b/source/blender/io/wavefront_obj/CMakeLists.txt index f7958ef4ec6..bfbc715a45f 100644 --- a/source/blender/io/wavefront_obj/CMakeLists.txt +++ b/source/blender/io/wavefront_obj/CMakeLists.txt @@ -2,8 +2,8 @@ set(INC . - ./exporter - ./importer + exporter + importer ../common ../../blenkernel ../../blenlib diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt index 0d04d7df067..50fd51e88a1 100644 --- a/source/blender/makesdna/intern/CMakeLists.txt +++ b/source/blender/makesdna/intern/CMakeLists.txt @@ -116,8 +116,8 @@ blender_add_lib(bf_dna "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") # ----------------------------------------------------------------------------- # Build bf_dna_blenlib library set(INC + .. ../../blenlib - ../../makesdna ../../../../intern/atomic ../../../../intern/guardedalloc ) diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 2b06daf34e3..f028b199098 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -200,7 +200,7 @@ set(INC ../../imbuf ../../makesdna ../../modifiers - ../../nodes/ + ../../nodes ../../sequencer ../../simulation ../../windowmanager diff --git a/source/blender/nodes/texture/CMakeLists.txt b/source/blender/nodes/texture/CMakeLists.txt index 77db71d4b1a..2d704ac2228 100644 --- a/source/blender/nodes/texture/CMakeLists.txt +++ b/source/blender/nodes/texture/CMakeLists.txt @@ -2,7 +2,7 @@ set(INC . - ../ + .. ../intern ../../editors/include ../../blenkernel -- cgit v1.2.3 From ec638d3108a18f7f955d72290a9c246d54edb3ef Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 21:33:59 +1100 Subject: GHOST/Wayland: only prioritize discrete scroll for mouse wheel events Smooth & discrete scrolling may both be set, instead of always prioritizing discrete, use discrete scrolling when the source is a mouse wheel, otherwise prioritize smooth scrolling. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 84 ++++++++++++++++++----------- 1 file changed, 54 insertions(+), 30 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 62f96e4e620..37049e646bd 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -141,8 +141,7 @@ static bool use_gnome_confine_hack = false; * \{ */ /** - * The event codes are used to - * to differentiate from which mouse button an event comes from. + * The event codes are used to differentiate from which mouse button an event comes from. */ #define BTN_LEFT 0x110 #define BTN_RIGHT 0x111 @@ -341,11 +340,6 @@ struct GWL_SeatStatePointer { */ wl_fixed_t xy[2] = {0, 0}; - /** Smooth scrolling (handled & reset with pointer "frame" callback). */ - wl_fixed_t scroll_xy[2] = {0, 0}; - /** Discrete scrolling (handled & reset with pointer "frame" callback). */ - int32_t scroll_discrete_xy[2] = {0, 0}; - /** Outputs on which the cursor is visible. */ std::unordered_set outputs; @@ -363,6 +357,19 @@ struct GWL_SeatStatePointer { GHOST_Buttons buttons = GHOST_Buttons(); }; +/** + * Scroll state, applying to pointer (not tablet) events. + * Otherwise this would be part of #GWL_SeatStatePointer. + */ +struct GWL_SeatStatePointerScroll { + /** Smooth scrolling (handled & reset with pointer "frame" callback). */ + wl_fixed_t smooth_xy[2] = {0, 0}; + /** Discrete scrolling (handled & reset with pointer "frame" callback). */ + int32_t discrete_xy[2] = {0, 0}; + /** The source of scroll event. */ + enum wl_pointer_axis_source axis_source = WL_POINTER_AXIS_SOURCE_WHEEL; +}; + /** * State of the keyboard (in #GWL_Seat). */ @@ -433,6 +440,7 @@ struct GWL_Seat { uint32_t cursor_source_serial = 0; GWL_SeatStatePointer pointer; + GWL_SeatStatePointerScroll pointer_scroll; /** Mostly this can be interchanged with `pointer` however it can't be locked/confined. */ GWL_SeatStatePointer tablet; @@ -1756,10 +1764,11 @@ static void pointer_handle_enter(void *data, /* Resetting scroll events is likely unnecessary, * do this to avoid any possible problems as it's harmless. */ - seat->pointer.scroll_xy[0] = 0; - seat->pointer.scroll_xy[1] = 0; - seat->pointer.scroll_discrete_xy[0] = 0; - seat->pointer.scroll_discrete_xy[1] = 0; + seat->pointer_scroll.smooth_xy[0] = 0; + seat->pointer_scroll.smooth_xy[1] = 0; + seat->pointer_scroll.discrete_xy[0] = 0; + seat->pointer_scroll.discrete_xy[1] = 0; + seat->pointer_scroll.axis_source = WL_POINTER_AXIS_SOURCE_WHEEL; seat->pointer.wl_surface = wl_surface; @@ -1886,7 +1895,7 @@ static void pointer_handle_axis(void *data, return; } GWL_Seat *seat = static_cast(data); - seat->pointer.scroll_xy[index] = value; + seat->pointer_scroll.smooth_xy[index] = value; } static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/) @@ -1894,29 +1903,39 @@ static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/) CLOG_INFO(LOG, 2, "frame"); GWL_Seat *seat = static_cast(data); - /* Discrete steps may generate non-discrete scrolling, in this case, - * give the mouse wheel priority otherwise mouse wheel events would be recognized - * as touch-pad scrolling too. */ - if (seat->pointer.scroll_discrete_xy[0]) { - seat->pointer.scroll_xy[0] = 0; + /* Both discrete and smooth events may be set at once, never generate events for both + * as this will be handling the same event in to different ways. + * Prioritize discrete axis events for the mouse wheel, otherwise smooth scroll. */ + if (seat->pointer_scroll.axis_source == WL_POINTER_AXIS_SOURCE_WHEEL) { + if (seat->pointer_scroll.discrete_xy[0]) { + seat->pointer_scroll.smooth_xy[0] = 0; + } + if (seat->pointer_scroll.discrete_xy[1]) { + seat->pointer_scroll.smooth_xy[1] = 0; + } } - if (seat->pointer.scroll_discrete_xy[1]) { - seat->pointer.scroll_xy[1] = 0; + else { + if (seat->pointer_scroll.smooth_xy[0]) { + seat->pointer_scroll.discrete_xy[0] = 0; + } + if (seat->pointer_scroll.smooth_xy[1]) { + seat->pointer_scroll.discrete_xy[1] = 0; + } } /* Discrete X axis currently unsupported. */ - if (seat->pointer.scroll_discrete_xy[1]) { + if (seat->pointer_scroll.discrete_xy[1]) { if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); - const int32_t discrete = seat->pointer.scroll_discrete_xy[1]; + const int32_t discrete = seat->pointer_scroll.discrete_xy[1]; seat->system->pushEvent(new GHOST_EventWheel( seat->system->getMilliSeconds(), win, std::signbit(discrete) ? +1 : -1)); } - seat->pointer.scroll_discrete_xy[0] = 0; - seat->pointer.scroll_discrete_xy[1] = 0; + seat->pointer_scroll.discrete_xy[0] = 0; + seat->pointer_scroll.discrete_xy[1] = 0; } - if (seat->pointer.scroll_xy[0] || seat->pointer.scroll_xy[1]) { + if (seat->pointer_scroll.smooth_xy[0] || seat->pointer_scroll.smooth_xy[1]) { if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); const wl_fixed_t scale = win->scale(); @@ -1926,21 +1945,26 @@ static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/) GHOST_kTrackpadEventScroll, wl_fixed_to_int(scale * seat->pointer.xy[0]), wl_fixed_to_int(scale * seat->pointer.xy[1]), - wl_fixed_to_int(seat->pointer.scroll_xy[0]), - wl_fixed_to_int(seat->pointer.scroll_xy[1]), + /* NOTE: scaling the delta doesn't seem necessary. */ + wl_fixed_to_int(seat->pointer_scroll.smooth_xy[0]), + wl_fixed_to_int(seat->pointer_scroll.smooth_xy[1]), /* TODO: investigate a way to request this configuration from the system. */ true)); } - seat->pointer.scroll_xy[0] = 0; - seat->pointer.scroll_xy[1] = 0; + seat->pointer_scroll.smooth_xy[0] = 0; + seat->pointer_scroll.smooth_xy[1] = 0; } + + seat->pointer_scroll.axis_source = WL_POINTER_AXIS_SOURCE_WHEEL; } -static void pointer_handle_axis_source(void * /*data*/, +static void pointer_handle_axis_source(void *data, struct wl_pointer * /*wl_pointer*/, uint32_t axis_source) { CLOG_INFO(LOG, 2, "axis_source (axis_source=%u)", axis_source); + GWL_Seat *seat = static_cast(data); + seat->pointer_scroll.axis_source = (enum wl_pointer_axis_source)axis_source; } static void pointer_handle_axis_stop(void * /*data*/, struct wl_pointer * /*wl_pointer*/, @@ -1962,7 +1986,7 @@ static void pointer_handle_axis_discrete(void *data, return; } GWL_Seat *seat = static_cast(data); - seat->pointer.scroll_discrete_xy[index] = discrete; + seat->pointer_scroll.discrete_xy[index] = discrete; } static const struct wl_pointer_listener pointer_listener = { -- cgit v1.2.3 From f0fba1a2d8deb7e92ccb217361a378f8fcc29d9b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 21:48:42 +1100 Subject: GHOST/Wayland: invert touch-pad scrolling This should use the system preference for scroll direction eventually, for now default to a down-motion scrolling down (matching GTK & QT). --- intern/ghost/intern/GHOST_SystemWayland.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 37049e646bd..9f018d039b1 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1945,11 +1945,12 @@ static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/) GHOST_kTrackpadEventScroll, wl_fixed_to_int(scale * seat->pointer.xy[0]), wl_fixed_to_int(scale * seat->pointer.xy[1]), - /* NOTE: scaling the delta doesn't seem necessary. */ - wl_fixed_to_int(seat->pointer_scroll.smooth_xy[0]), - wl_fixed_to_int(seat->pointer_scroll.smooth_xy[1]), + /* NOTE: scaling the delta doesn't seem necessary. + * NOTE: inverting delta gives correct results, see: QTBUG-85767. */ + -wl_fixed_to_int(seat->pointer_scroll.smooth_xy[0]), + -wl_fixed_to_int(seat->pointer_scroll.smooth_xy[1]), /* TODO: investigate a way to request this configuration from the system. */ - true)); + false)); } seat->pointer_scroll.smooth_xy[0] = 0; -- cgit v1.2.3 From 3ac2f15a04c5c5425e086427170b5d1b2f559e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Wed, 19 Oct 2022 14:40:27 +0200 Subject: GL: Fix incorrect shader state after shader interface creation The interface needs to bind the shaders for some parameter setup. This program change wasn't reflected in the GPUContext. This was then conflicting with the next shader bind if the next shader was the same as the shader bound before the interface creation. Setting the state to the correct shader ensures a rebind if needed. Fix T101792 New hair curves do not render properly first time in EEVEE with motion blur enabled --- source/blender/gpu/opengl/gl_shader.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index dafcf4dbf33..f6f14932de7 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -1004,6 +1004,11 @@ bool GLShader::finalize(const shader::ShaderCreateInfo *info) else { interface = new GLShaderInterface(shader_program_); } + /** + * WORKAROUND: Creating the shader interface changes the active program. + * Make sure to update the context, otherwise we might have a missing bind. + */ + Context::get()->shader = this; return true; } -- cgit v1.2.3 From ead3fc4a075d24e3481dfebdc63d54e7143a027c Mon Sep 17 00:00:00 2001 From: Pratik Borhade Date: Wed, 19 Oct 2022 18:20:47 +0530 Subject: Fix T99997: Calling teleport without waiting for the previous event disables gravity During teleport event, gravity is disabled and WalkMethod is stored in `teleport.navigation_mode` which is used later to reset the status after execution. Calling teleport events consecutively will change the initial WalkMethod value. So update it only on the first call. Also remove `else condition` as it stops the previously running teleport when the new teleport call fails to find a hit point. Reviewed by: dfelinto, mano-wii Differential Revision: https://developer.blender.org/D15574 --- source/blender/editors/space_view3d/view3d_navigate_walk.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_navigate_walk.c b/source/blender/editors/space_view3d/view3d_navigate_walk.c index 3e0ce892b5a..aea322d73d9 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_walk.c +++ b/source/blender/editors/space_view3d/view3d_navigate_walk.c @@ -849,11 +849,15 @@ static void walkEvent(WalkInfo *walk, const wmEvent *event) if (ret) { WalkTeleport *teleport = &walk->teleport; + + /* Store the current navigation mode if we are not already teleporting. */ + if (teleport->state == WALK_TELEPORT_STATE_OFF) { + teleport->navigation_mode = walk->navigation_mode; + } teleport->state = WALK_TELEPORT_STATE_ON; teleport->initial_time = PIL_check_seconds_timer(); teleport->duration = U.walk_navigation.teleport_time; - teleport->navigation_mode = walk->navigation_mode; walk_navigation_mode_set(walk, WALK_MODE_FREE); copy_v3_v3(teleport->origin, walk->rv3d->viewinv[3]); @@ -864,9 +868,7 @@ static void walkEvent(WalkInfo *walk, const wmEvent *event) sub_v3_v3v3(teleport->direction, loc, teleport->origin); } - else { - walk->teleport.state = WALK_TELEPORT_STATE_OFF; - } + break; } -- cgit v1.2.3 From 3655eb7ff0e87c2cf6b17d0268253921fbeb8ea7 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 19 Oct 2022 15:13:15 +0200 Subject: Blender: Add command line argument to switch gpu backends. Add command line argument to switch gpu backend. Add `--gpu-backend` option to override the gpu backend selected by Blender. Values for this option that will be available in releases for now are: * opengl: Force blender to select OpenGL backend. During development and depending on compile options additional values can exist: * metal: Force Blender to select Metal backend. When this option isn't provided the internal logic for GPU backend selection will be used. Note that this is at the time of writing the same as always selecting the opengl backend. Reviewed By: fclem, brecht, MichaelPW Differential Revision: https://developer.blender.org/D16297 --- intern/ghost/GHOST_C-api.h | 2 - intern/ghost/GHOST_ISystem.h | 2 - intern/ghost/GHOST_Types.h | 12 ++++-- intern/ghost/intern/GHOST_C-api.cpp | 2 - intern/ghost/intern/GHOST_ContextCGL.h | 3 +- intern/ghost/intern/GHOST_ContextCGL.mm | 4 +- intern/ghost/intern/GHOST_System.cpp | 2 +- intern/ghost/intern/GHOST_SystemCocoa.h | 2 - intern/ghost/intern/GHOST_SystemCocoa.mm | 5 +-- intern/ghost/intern/GHOST_SystemHeadless.h | 3 +- intern/ghost/intern/GHOST_SystemSDL.cpp | 3 +- intern/ghost/intern/GHOST_SystemSDL.h | 1 - intern/ghost/intern/GHOST_SystemWayland.cpp | 3 +- intern/ghost/intern/GHOST_SystemWayland.h | 1 - intern/ghost/intern/GHOST_SystemWin32.cpp | 3 +- intern/ghost/intern/GHOST_SystemWin32.h | 2 - intern/ghost/intern/GHOST_SystemX11.cpp | 4 +- intern/ghost/intern/GHOST_SystemX11.h | 2 - intern/ghost/intern/GHOST_WindowCocoa.mm | 4 +- intern/ghost/test/gears/GHOST_Test.cpp | 21 +++------- source/blender/gpu/GPU_context.h | 2 + source/blender/gpu/intern/gpu_context.cc | 12 +++++- source/blender/gpu/intern/gpu_shader_builder.cc | 49 +++++++++++++++++++--- .../blender/gpu/intern/gpu_shader_builder_stubs.cc | 9 ++++ source/blender/windowmanager/intern/wm_playanim.c | 5 ++- source/blender/windowmanager/intern/wm_window.c | 21 +++++++++- .../windowmanager/intern/wm_window_private.h | 5 +++ source/creator/creator_args.c | 44 +++++++++++++++++++ 28 files changed, 166 insertions(+), 62 deletions(-) diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 7fda535a7ac..62984c762c1 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -162,7 +162,6 @@ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle, * \param height: The height the window. * \param state: The state of the window when opened. * \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized. - * \param type: The type of drawing context installed in this window. * \param glSettings: Misc OpenGL options. * \return A handle to the new window ( == NULL if creation failed). */ @@ -175,7 +174,6 @@ extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, uint32_t height, GHOST_TWindowState state, bool is_dialog, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings); /** diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 9fb94ed1525..64b5f4ee496 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -232,7 +232,6 @@ class GHOST_ISystem { * \param width: The width the window. * \param height: The height the window. * \param state: The state of the window when opened. - * \param type: The type of drawing context installed in this window. * \param glSettings: Misc OpenGL settings. * \param exclusive: Use to show the window on top and ignore others (used full-screen). * \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized. @@ -245,7 +244,6 @@ class GHOST_ISystem { uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive = false, const bool is_dialog = false, diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 2645ce448b0..db4eeff3122 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -60,10 +60,6 @@ typedef struct { int hot_spot[2]; } GHOST_CursorBitmapRef; -typedef struct { - int flags; -} GHOST_GLSettings; - typedef enum { GHOST_glStereoVisual = (1 << 0), GHOST_glDebugContext = (1 << 1), @@ -157,6 +153,9 @@ typedef enum { #ifdef WIN32 GHOST_kDrawingContextTypeD3D, #endif +#ifdef __APPLE__ + GHOST_kDrawingContextTypeMetal, +#endif } GHOST_TDrawingContextType; typedef enum { @@ -598,6 +597,11 @@ typedef struct { uint32_t frequency; } GHOST_DisplaySetting; +typedef struct { + int flags; + GHOST_TDrawingContextType context_type; +} GHOST_GLSettings; + typedef enum { /** Axis that cursor grab will wrap. */ GHOST_kDebugDefault = (1 << 1), diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 158e979cdf2..aa2363c10b3 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -161,7 +161,6 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, uint32_t height, GHOST_TWindowState state, bool is_dialog, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings) { GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; @@ -172,7 +171,6 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, width, height, state, - type, glSettings, false, is_dialog, diff --git a/intern/ghost/intern/GHOST_ContextCGL.h b/intern/ghost/intern/GHOST_ContextCGL.h index 130b926f25c..d19fffffb43 100644 --- a/intern/ghost/intern/GHOST_ContextCGL.h +++ b/intern/ghost/intern/GHOST_ContextCGL.h @@ -30,7 +30,8 @@ class GHOST_ContextCGL : public GHOST_Context { GHOST_ContextCGL(bool stereoVisual, NSView *metalView, CAMetalLayer *metalLayer, - NSOpenGLView *openglView); + NSOpenGLView *openglView, + GHOST_TDrawingContextType type); /** * Destructor. diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm index ff53ecdbbba..9dad337a5d6 100644 --- a/intern/ghost/intern/GHOST_ContextCGL.mm +++ b/intern/ghost/intern/GHOST_ContextCGL.mm @@ -46,8 +46,10 @@ int GHOST_ContextCGL::s_sharedCount = 0; GHOST_ContextCGL::GHOST_ContextCGL(bool stereoVisual, NSView *metalView, CAMetalLayer *metalLayer, - NSOpenGLView *openGLView) + NSOpenGLView *openGLView, + GHOST_TDrawingContextType type) : GHOST_Context(stereoVisual), + m_useMetalForRendering(type == GHOST_kDrawingContextTypeMetal), m_metalView(metalView), m_metalLayer(metalLayer), m_metalCmdQueue(nil), diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 94d021fd822..670ede35989 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -384,6 +384,7 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, if (stereoVisual) { glSettings.flags |= GHOST_glStereoVisual; } + glSettings.context_type = GHOST_kDrawingContextTypeOpenGL; /* NOTE: don't use #getCurrentDisplaySetting() because on X11 we may * be zoomed in and the desktop may be bigger than the viewport. */ GHOST_ASSERT(m_displayManager, @@ -395,7 +396,6 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, settings.xPixels, settings.yPixels, GHOST_kWindowStateNormal, - GHOST_kDrawingContextTypeOpenGL, glSettings, true /* exclusive */); return (*window == nullptr) ? GHOST_kFailure : GHOST_kSuccess; diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index dbb41c7fddf..0211694aad4 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -77,7 +77,6 @@ class GHOST_SystemCocoa : public GHOST_System { * \param width: The width the window. * \param height: The height the window. * \param state: The state of the window when opened. - * \param type: The type of drawing context installed in this window. * \param glSettings: Misc OpenGL settings. * \param exclusive: Use to show the window on top and ignore others (used full-screen). * \param parentWindow: Parent (embedder) window. @@ -89,7 +88,6 @@ class GHOST_SystemCocoa : public GHOST_System { uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive = false, const bool is_dialog = false, diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index bfa90114e4c..a1016dd4843 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -689,7 +689,6 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title, uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive, const bool is_dialog, @@ -719,7 +718,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title, width, height, state, - type, + glSettings.context_type, glSettings.flags & GHOST_glStereoVisual, glSettings.flags & GHOST_glDebugContext, is_dialog, @@ -751,7 +750,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title, */ GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSettings) { - GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL); + GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL, glSettings.context_type); if (context->initializeDrawingContext()) return context; else diff --git a/intern/ghost/intern/GHOST_SystemHeadless.h b/intern/ghost/intern/GHOST_SystemHeadless.h index b02a82fc9eb..66af65f763d 100644 --- a/intern/ghost/intern/GHOST_SystemHeadless.h +++ b/intern/ghost/intern/GHOST_SystemHeadless.h @@ -142,7 +142,6 @@ class GHOST_SystemHeadless : public GHOST_System { uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool /*exclusive*/, const bool /*is_dialog*/, @@ -155,7 +154,7 @@ class GHOST_SystemHeadless : public GHOST_System { height, state, parentWindow, - type, + glSettings.context_type, ((glSettings.flags & GHOST_glStereoVisual) != 0)); } diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp index ad5c4dc85fb..9174664adc4 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.cpp +++ b/intern/ghost/intern/GHOST_SystemSDL.cpp @@ -42,7 +42,6 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title, uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive, const bool /* is_dialog */, @@ -57,7 +56,7 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title, width, height, state, - type, + glSettings.context_type, ((glSettings.flags & GHOST_glStereoVisual) != 0), exclusive, parentWindow); diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h index bee277ba674..385bfb841e3 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.h +++ b/intern/ghost/intern/GHOST_SystemSDL.h @@ -71,7 +71,6 @@ class GHOST_SystemSDL : public GHOST_System { uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive = false, const bool is_dialog = false, diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 9f018d039b1..2d16fd4cff5 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -3813,7 +3813,6 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title, const uint32_t width, const uint32_t height, const GHOST_TWindowState state, - const GHOST_TDrawingContextType type, const GHOST_GLSettings glSettings, const bool exclusive, const bool is_dialog, @@ -3833,7 +3832,7 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title, height, state, parentWindow, - type, + glSettings.context_type, is_dialog, ((glSettings.flags & GHOST_glStereoVisual) != 0), exclusive); diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index 5d2cfe45582..ca78ccb89ab 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -128,7 +128,6 @@ class GHOST_SystemWayland : public GHOST_System { uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive, const bool is_dialog, diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 667198241f0..54c892d296e 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -213,7 +213,6 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title, uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive, const bool is_dialog, @@ -227,7 +226,7 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title, width, height, state, - type, + glSettings.context_type, ((glSettings.flags & GHOST_glStereoVisual) != 0), false, (GHOST_WindowWin32 *)parentWindow, diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index f5cd0055b34..98a7e5dfb35 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -103,7 +103,6 @@ class GHOST_SystemWin32 : public GHOST_System { * \param width: The width the window. * \param height: The height the window. * \param state: The state of the window when opened. - * \param type: The type of drawing context installed in this window. * \param glSettings: Misc OpenGL settings. * \param exclusive: Use to show the window on top and ignore others (used full-screen). * \param parentWindow: Parent window. @@ -115,7 +114,6 @@ class GHOST_SystemWin32 : public GHOST_System { uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive = false, const bool is_dialog = false, diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 4523f6fa37c..5c89febe97c 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -308,7 +308,6 @@ void GHOST_SystemX11::getAllDisplayDimensions(uint32_t &width, uint32_t &height) * \param width: The width the window. * \param height: The height the window. * \param state: The state of the window when opened. - * \param type: The type of drawing context installed in this window. * \param glSettings: Misc OpenGL settings. * \param exclusive: Use to show the window on top and ignore others (used full-screen). * \param parentWindow: Parent window. @@ -320,7 +319,6 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title, uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive, const bool is_dialog, @@ -341,7 +339,7 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title, height, state, (GHOST_WindowX11 *)parentWindow, - type, + glSettings.context_type, is_dialog, ((glSettings.flags & GHOST_glStereoVisual) != 0), exclusive, diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index 572be30174d..1f071da6da7 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -113,7 +113,6 @@ class GHOST_SystemX11 : public GHOST_System { * \param width: The width the window. * \param height: The height the window. * \param state: The state of the window when opened. - * \param type: The type of drawing context installed in this window. * \param stereoVisual: Create a stereo visual for quad buffered stereo. * \param exclusive: Use to show the window on top and ignore others (used full-screen). * \param parentWindow: Parent (embedder) window. @@ -125,7 +124,6 @@ class GHOST_SystemX11 : public GHOST_System { uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive = false, const bool is_dialog = false, diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 737fd64bdf0..bc1f1e99a3a 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -803,10 +803,10 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order) GHOST_Context *GHOST_WindowCocoa::newDrawingContext(GHOST_TDrawingContextType type) { - if (type == GHOST_kDrawingContextTypeOpenGL) { + if (type == GHOST_kDrawingContextTypeOpenGL || type == GHOST_kDrawingContextTypeMetal) { GHOST_Context *context = new GHOST_ContextCGL( - m_wantStereoVisual, m_metalView, m_metalLayer, m_openGLView); + m_wantStereoVisual, m_metalView, m_metalLayer, m_openGLView, type); if (context->initializeDrawingContext()) return context; diff --git a/intern/ghost/test/gears/GHOST_Test.cpp b/intern/ghost/test/gears/GHOST_Test.cpp index 1891f1eca77..3c9206b2010 100644 --- a/intern/ghost/test/gears/GHOST_Test.cpp +++ b/intern/ghost/test/gears/GHOST_Test.cpp @@ -407,17 +407,12 @@ Application::Application(GHOST_ISystem *system) stereo(false) { GHOST_GLSettings glSettings = {0}; + glSettings.context_type = GHOST_kDrawingContextTypeOpenGL; fApp = this; // Create the main window - m_mainWindow = system->createWindow("gears - main window", - 10, - 64, - 320, - 200, - GHOST_kWindowStateNormal, - GHOST_kDrawingContextTypeOpenGL, - glSettings); + m_mainWindow = system->createWindow( + "gears - main window", 10, 64, 320, 200, GHOST_kWindowStateNormal, glSettings); if (!m_mainWindow) { std::cout << "could not create main window\n"; @@ -425,14 +420,8 @@ Application::Application(GHOST_ISystem *system) } // Create a secondary window - m_secondaryWindow = system->createWindow("gears - secondary window", - 340, - 64, - 320, - 200, - GHOST_kWindowStateNormal, - GHOST_kDrawingContextTypeOpenGL, - glSettings); + m_secondaryWindow = system->createWindow( + "gears - secondary window", 340, 64, 320, 200, GHOST_kWindowStateNormal, glSettings); if (!m_secondaryWindow) { std::cout << "could not create secondary window\n"; exit(-1); diff --git a/source/blender/gpu/GPU_context.h b/source/blender/gpu/GPU_context.h index b59ea9e55d2..ac82774039a 100644 --- a/source/blender/gpu/GPU_context.h +++ b/source/blender/gpu/GPU_context.h @@ -21,6 +21,8 @@ extern "C" { * automatically initializes the back-end, and #GPU_context_discard frees it when there * are no more contexts. */ bool GPU_backend_supported(void); +void GPU_backend_type_selection_set(const eGPUBackendType backend); +eGPUBackendType GPU_backend_type_selection_get(void); eGPUBackendType GPU_backend_get_type(void); /** Opaque type hiding blender::gpu::Context. */ diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc index 48d7b2019c5..f6b88c4231c 100644 --- a/source/blender/gpu/intern/gpu_context.cc +++ b/source/blender/gpu/intern/gpu_context.cc @@ -223,9 +223,19 @@ void GPU_render_step() /* NOTE: To enable Metal API, we need to temporarily change this to `GPU_BACKEND_METAL`. * Until a global switch is added, Metal also needs to be enabled in GHOST_ContextCGL: * `m_useMetalForRendering = true`. */ -static const eGPUBackendType g_backend_type = GPU_BACKEND_OPENGL; +static eGPUBackendType g_backend_type = GPU_BACKEND_OPENGL; static GPUBackend *g_backend = nullptr; +void GPU_backend_type_selection_set(const eGPUBackendType backend) +{ + g_backend_type = backend; +} + +eGPUBackendType GPU_backend_type_selection_get() +{ + return g_backend_type; +} + bool GPU_backend_supported(void) { switch (g_backend_type) { diff --git a/source/blender/gpu/intern/gpu_shader_builder.cc b/source/blender/gpu/intern/gpu_shader_builder.cc index 3aa2963ecd0..9a67ddde5e6 100644 --- a/source/blender/gpu/intern/gpu_shader_builder.cc +++ b/source/blender/gpu/intern/gpu_shader_builder.cc @@ -15,6 +15,8 @@ #include "GPU_init_exit.h" #include "gpu_shader_create_info_private.hh" +#include "BLI_vector.hh" + #include "CLG_log.h" namespace blender::gpu::shader_builder { @@ -41,6 +43,22 @@ void ShaderBuilder::init() CLG_init(); GHOST_GLSettings glSettings = {0}; + switch (GPU_backend_type_selection_get()) { + case GPU_BACKEND_OPENGL: + glSettings.context_type = GHOST_kDrawingContextTypeOpenGL; + break; + +#ifdef WITH_METAL_BACKEND + case GPU_BACKEND_METAL: + glSettings.context_type = GHOST_kDrawingContextTypeMetal; + break; +#endif + + default: + BLI_assert_unreachable(); + break; + } + ghost_system_ = GHOST_CreateSystem(); ghost_context_ = GHOST_CreateOpenGLContext(ghost_system_, glSettings); GHOST_ActivateOpenGLContext(ghost_context_); @@ -73,13 +91,32 @@ int main(int argc, const char *argv[]) int exit_code = 0; - blender::gpu::shader_builder::ShaderBuilder builder; - builder.init(); - if (!builder.bake_create_infos()) { - exit_code = 1; + struct NamedBackend { + std::string name; + eGPUBackendType backend; + }; + + blender::Vector backends_to_validate; + backends_to_validate.append({"OpenGL", GPU_BACKEND_OPENGL}); +#ifdef WITH_METAL_BACKEND + backends_to_validate.append({"Metal", GPU_BACKEND_METAL}); +#endif + for (NamedBackend &backend : backends_to_validate) { + GPU_backend_type_selection_set(backend.backend); + if (!GPU_backend_supported()) { + printf("%s isn't supported on this platform. Shader compilation is skipped\n", + backend.name.c_str()); + continue; + } + blender::gpu::shader_builder::ShaderBuilder builder; + builder.init(); + if (!builder.bake_create_infos()) { + printf("Shader compilation failed for %s backend\n", backend.name.c_str()); + exit_code = 1; + } + builder.exit(); + exit(exit_code); } - builder.exit(); - exit(exit_code); return exit_code; } diff --git a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc index 7a06ede5c6d..65bda7ba858 100644 --- a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc +++ b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc @@ -46,6 +46,15 @@ void IMB_freeImBuf(ImBuf * /*ibuf*/) BLI_assert_unreachable(); } +struct ImBuf *IMB_allocImBuf(unsigned int /*x*/, + unsigned int /*y*/, + unsigned char /*planes*/, + unsigned int /*flags*/) +{ + BLI_assert_unreachable(); + return nullptr; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index bf793ee41a0..3e5399a6f56 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -59,6 +59,8 @@ #include "DEG_depsgraph.h" +#include "wm_window_private.h" + #include "WM_api.h" /* only for WM_main_playanim */ #ifdef WITH_AUDASPACE @@ -1340,6 +1342,8 @@ static bool ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) static void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey) { GHOST_GLSettings glsettings = {0}; + const eGPUBackendType gpu_backend = GPU_backend_type_selection_get(); + glsettings.context_type = wm_ghost_drawing_context_type(gpu_backend); uint32_t scr_w, scr_h; GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &scr_w, &scr_h); @@ -1356,7 +1360,6 @@ static void playanim_window_open(const char *title, int posx, int posy, int size /* Could optionally start full-screen. */ GHOST_kWindowStateNormal, false, - GHOST_kDrawingContextTypeOpenGL, glsettings); } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index b1b13390932..6b925b23dcb 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -556,6 +556,9 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, glSettings.flags |= GHOST_glDebugContext; } + eGPUBackendType gpu_backend = GPU_backend_type_selection_get(); + glSettings.context_type = wm_ghost_drawing_context_type(gpu_backend); + int scr_w, scr_h; wm_get_desktopsize(&scr_w, &scr_h); int posy = (scr_h - win->posy - win->sizey); @@ -573,7 +576,6 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, win->sizey, (GHOST_TWindowState)win->windowstate, is_dialog, - GHOST_kDrawingContextTypeOpenGL, glSettings); if (ghostwin) { @@ -1615,6 +1617,23 @@ const char *WM_ghost_backend(void) #endif } +GHOST_TDrawingContextType wm_ghost_drawing_context_type(const eGPUBackendType gpu_backend) +{ + switch (gpu_backend) { + case GPU_BACKEND_NONE: + return GHOST_kDrawingContextTypeNone; + case GPU_BACKEND_ANY: + case GPU_BACKEND_OPENGL: + return GHOST_kDrawingContextTypeOpenGL; +#ifdef WITH_METAL_BACKEND + case GPU_BACKEND_METAL: + return GHOST_kDrawingContextTypeMetal; +#endif + } + BLI_assert_unreachable(); + return GHOST_kDrawingContextTypeNone; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/windowmanager/intern/wm_window_private.h b/source/blender/windowmanager/intern/wm_window_private.h index f68d4e3e693..dad3e749817 100644 --- a/source/blender/windowmanager/intern/wm_window_private.h +++ b/source/blender/windowmanager/intern/wm_window_private.h @@ -7,8 +7,11 @@ #pragma once #include "BLI_sys_types.h" + #include "GHOST_Types.h" +#include "GPU_context.h" + /* *************** Message box *************** */ /* `WM_ghost_show_message_box` is implemented in `wm_windows.c` it is * defined here as it was implemented to be used for showing @@ -21,3 +24,5 @@ void WM_ghost_show_message_box(const char *title, const char *continue_label, const char *link, GHOST_DialogOptions dialog_options); + +GHOST_TDrawingContextType wm_ghost_drawing_context_type(const eGPUBackendType gpu_backend); diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index 06b898587bf..4144603555b 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -42,6 +42,8 @@ # include "BKE_scene.h" # include "BKE_sound.h" +# include "GPU_context.h" + # ifdef WITH_FFMPEG # include "IMB_imbuf.h" # endif @@ -1111,6 +1113,44 @@ static int arg_handle_debug_gpu_set(int UNUSED(argc), return 0; } +static const char arg_handle_gpu_backend_set_doc[] = + "\n" + "\tForce to use a specific GPU backend. Valid options: " +# ifdef WITH_METAL_BACKEND + "'metal', " +# endif + "'opengl')."; +static int arg_handle_gpu_backend_set(int argc, const char **argv, void *UNUSED(data)) +{ + if (argc == 0) { + printf("\nError: GPU backend must follow '--gpu-backend'.\n"); + return 0; + } + + eGPUBackendType gpu_backend = GPU_BACKEND_NONE; + + if (STREQ(argv[1], "opengl")) { + gpu_backend = GPU_BACKEND_OPENGL; + } +# ifdef WITH_METAL_BACKEND + else if (STREQ(argv[1], "metal")) { + gpu_backend = GPU_BACKEND_METAL; + } +# endif + else { + printf("\nError: Unrecognized GPU backend for '--gpu-backend'.\n"); + return 0; + } + + GPU_backend_type_selection_set(gpu_backend); + if (!GPU_backend_supported()) { + printf("\nError: GPU backend not supported.\n"); + return 0; + } + + return 1; +} + static const char arg_handle_debug_fpe_set_doc[] = "\n\t" "Enable floating-point exceptions."; @@ -2074,6 +2114,10 @@ void main_args_setup(bContext *C, bArgs *ba) BLI_args_add(ba, NULL, "--log-show-timestamp", CB(arg_handle_log_show_timestamp_set), ba); BLI_args_add(ba, NULL, "--log-file", CB(arg_handle_log_file_set), ba); + /* GPU backend selection should be part of ARG_PASS_ENVIRONMENT for correct GPU context selection + * for anim player. */ + BLI_args_add(ba, NULL, "--gpu-backend", CB(arg_handle_gpu_backend_set), NULL); + /* Pass: Background Mode & Settings * * Also and commands that exit after usage. */ -- cgit v1.2.3 From 6165395927cdd86a3ba48e53a4f3c2152cee2c0a Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Wed, 19 Oct 2022 11:33:19 +0200 Subject: Fix T101922: transforming surface points misses redraw Oversight in rBf8b1483566cc which resulted in fonts/surfaces not having their draw caches being tagged dirty. Not only OB_CURVES_LEGACY have their object data of type ID_CU_LEGACY, but also OB_SURF/OB_FONT objects. Maniphest Tasks: T101922 Differential Revision: https://developer.blender.org/D16298 --- source/blender/blenkernel/intern/object_update.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/blenkernel/intern/object_update.cc b/source/blender/blenkernel/intern/object_update.cc index ceef6404bf0..e53090bcffe 100644 --- a/source/blender/blenkernel/intern/object_update.cc +++ b/source/blender/blenkernel/intern/object_update.cc @@ -292,6 +292,8 @@ void BKE_object_batch_cache_dirty_tag(Object *ob) BKE_lattice_batch_cache_dirty_tag((struct Lattice *)ob->data, BKE_LATTICE_BATCH_DIRTY_ALL); break; case OB_CURVES_LEGACY: + case OB_SURF: + case OB_FONT: BKE_curve_batch_cache_dirty_tag((struct Curve *)ob->data, BKE_CURVE_BATCH_DIRTY_ALL); break; case OB_MBALL: { -- cgit v1.2.3 From 425e7ca3421d3a17651701d305140f490f5d2afc Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Wed, 19 Oct 2022 10:56:33 -0300 Subject: Fix T101928: transform operator properties saving wrong snap values The check for the flags should be `== 0` since they are describing a negative state. Thanks to @lone_noel for pointing out the error. --- source/blender/editors/transform/transform.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 34e5b78c48f..919f4e5b85c 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1594,9 +1594,9 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) RNA_enum_set(op->ptr, "snap_target", t->tsnap.source_select); eSnapTargetSelect target = t->tsnap.target_select; - RNA_boolean_set(op->ptr, "use_snap_self", (target & SCE_SNAP_TARGET_NOT_ACTIVE) != 0); - RNA_boolean_set(op->ptr, "use_snap_edit", (target & SCE_SNAP_TARGET_NOT_EDITED) != 0); - RNA_boolean_set(op->ptr, "use_snap_nonedit", (target & SCE_SNAP_TARGET_NOT_NONEDITED) != 0); + RNA_boolean_set(op->ptr, "use_snap_self", (target & SCE_SNAP_TARGET_NOT_ACTIVE) == 0); + RNA_boolean_set(op->ptr, "use_snap_edit", (target & SCE_SNAP_TARGET_NOT_EDITED) == 0); + RNA_boolean_set(op->ptr, "use_snap_nonedit", (target & SCE_SNAP_TARGET_NOT_NONEDITED) == 0); RNA_boolean_set( op->ptr, "use_snap_selectable", (target & SCE_SNAP_TARGET_ONLY_SELECTABLE) != 0); } -- cgit v1.2.3 From 5d67fb0f18291d3aa6ee2bde0972cf90881f187c Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Mon, 17 Oct 2022 10:06:28 +0200 Subject: Cycles: oneAPI: fix MSVC_TOOLS_DIR for some build environments MSVC Tools version doesn't match MSVC Redist version on some systems and it's not populated when using Ninja outside of Visual Studio shell, trying another way. --- intern/cycles/kernel/CMakeLists.txt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 36c8b23d983..dfd21c4e675 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -819,12 +819,17 @@ if(WITH_CYCLES_DEVICE_ONEAPI) -DONEAPI_EXPORT) string(REPLACE /Redist/ /Tools/ MSVC_TOOLS_DIR ${MSVC_REDIST_DIR}) - if(NOT CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION) # case for Ninja on Windows + # Version Folder between Redist and Tools can mismatch sometimes + if(NOT EXISTS ${MSVC_TOOLS_DIR}) + get_filename_component(cmake_ar_dir ${CMAKE_AR} DIRECTORY) + get_filename_component(MSVC_TOOLS_DIR "${cmake_ar_dir}/../../../" ABSOLUTE) + endif() + if(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION) + set(WINDOWS_KIT_DIR ${WINDOWS_KITS_DIR}/Lib/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}) + else() # case for Ninja on Windows get_filename_component(cmake_mt_dir ${CMAKE_MT} DIRECTORY) string(REPLACE /bin/ /Lib/ WINDOWS_KIT_DIR ${cmake_mt_dir}) get_filename_component(WINDOWS_KIT_DIR "${WINDOWS_KIT_DIR}/../" ABSOLUTE) - else() - set(WINDOWS_KIT_DIR ${WINDOWS_KITS_DIR}/Lib/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}) endif() list(APPEND sycl_compiler_flags -L "${MSVC_TOOLS_DIR}/lib/x64" -- cgit v1.2.3 From d816bae7bf38069ab3f6ad9043fde0294af79c82 Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Mon, 17 Oct 2022 10:15:57 +0200 Subject: Cycles: oneAPI: fix check_usm for debug builds --- intern/cycles/device/oneapi/device_impl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/intern/cycles/device/oneapi/device_impl.cpp b/intern/cycles/device/oneapi/device_impl.cpp index 91f53fd1eae..f14eada071d 100644 --- a/intern/cycles/device/oneapi/device_impl.cpp +++ b/intern/cycles/device/oneapi/device_impl.cpp @@ -432,7 +432,8 @@ void OneapiDevice::check_usm(SyclQueue *queue_, const void *usm_ptr, bool allow_ assert(usm_type == sycl::usm::alloc::device || ((device_type == sycl::info::device_type::host || device_type == sycl::info::device_type::cpu || allow_host) && - usm_type == sycl::usm::alloc::host)); + usm_type == sycl::usm::alloc::host || + usm_type == sycl::usm::alloc::unknown)); # else /* Silence warning about unused arguments. */ (void)queue_; -- cgit v1.2.3 From 2943997d2a09ab0dec8691b5cd155af2c655a049 Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Mon, 17 Oct 2022 11:03:01 +0200 Subject: Cycles: oneAPI: include sycl/sycl.hpp instead of CL/sycl.hpp Since SYCL 2020 API, sycl/sycl.hpp is the way. --- intern/cycles/device/oneapi/device_impl.h | 2 +- intern/cycles/kernel/device/oneapi/kernel.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/cycles/device/oneapi/device_impl.h b/intern/cycles/device/oneapi/device_impl.h index 62034150eac..197cf03d60d 100644 --- a/intern/cycles/device/oneapi/device_impl.h +++ b/intern/cycles/device/oneapi/device_impl.h @@ -3,7 +3,7 @@ #ifdef WITH_ONEAPI -# include +# include # include "device/device.h" # include "device/oneapi/device.h" diff --git a/intern/cycles/kernel/device/oneapi/kernel.cpp b/intern/cycles/kernel/device/oneapi/kernel.cpp index 40e0b1f0b2b..d15d6509d6a 100644 --- a/intern/cycles/kernel/device/oneapi/kernel.cpp +++ b/intern/cycles/kernel/device/oneapi/kernel.cpp @@ -8,7 +8,7 @@ # include # include -# include +# include # include "kernel/device/oneapi/compat.h" # include "kernel/device/oneapi/globals.h" -- cgit v1.2.3 From 86bb79e756fee32aa2dd1608b89a3fb3b36fda6f Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Mon, 17 Oct 2022 16:02:26 +0200 Subject: Cycles: oneAPI: update dg2 target to acm-g10 "dg2" target is deprecated from the GPU compiler/ocloc. We switch to targeting acm-g10 instead, for which generated binaries are compatible with other Arc GPUs. --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 408cf819ce8..bffd761f941 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -492,7 +492,8 @@ if(NOT APPLE) option(WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED "Enable use of SYCL host (CPU) device execution by oneAPI implementation. This option is for debugging purposes and impacts GPU execution." OFF) # https://www.intel.com/content/www/us/en/develop/documentation/oneapi-dpcpp-cpp-compiler-dev-guide-and-reference/top/compilation/ahead-of-time-compilation.html - set(CYCLES_ONEAPI_SPIR64_GEN_DEVICES "dg2" CACHE STRING "oneAPI Intel GPU architectures to build binaries for") + # acm-g10 is the architecture for the first Arc Alchemist GPUs. + set(CYCLES_ONEAPI_SPIR64_GEN_DEVICES "acm-g10" CACHE STRING "oneAPI Intel GPU architectures to build binaries for") set(CYCLES_ONEAPI_SYCL_TARGETS spir64 spir64_gen CACHE STRING "oneAPI targets to build AOT binaries for") mark_as_advanced(WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED) -- cgit v1.2.3 From 5bfce9a822efef9a841614156255030821df564c Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Wed, 19 Oct 2022 12:46:23 +0200 Subject: Cycles: oneAPI: preload kernels only when not using prebuilt binaries sycl::build triggers compilation even if prebuilt binaries are available, we'll have to find a better way in this case. --- intern/cycles/kernel/CMakeLists.txt | 2 ++ intern/cycles/kernel/device/oneapi/kernel.cpp | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index dfd21c4e675..e5d1c3d6563 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -767,6 +767,8 @@ if(WITH_CYCLES_DEVICE_ONEAPI) string(PREPEND CYCLES_ONEAPI_SYCL_OPTIONS_spir64_gen "-device ${CYCLES_ONEAPI_SPIR64_GEN_DEVICES} ") if (WITH_CYCLES_ONEAPI_BINARIES) + # AoT binaries aren't currently reused when calling sycl::build. + list (APPEND sycl_compiler_flags -DSYCL_SKIP_KERNELS_PRELOAD) # Iterate over all targest and their options list (JOIN CYCLES_ONEAPI_SYCL_TARGETS "," targets_string) list (APPEND sycl_compiler_flags -fsycl-targets=${targets_string}) diff --git a/intern/cycles/kernel/device/oneapi/kernel.cpp b/intern/cycles/kernel/device/oneapi/kernel.cpp index d15d6509d6a..1f32d3406ea 100644 --- a/intern/cycles/kernel/device/oneapi/kernel.cpp +++ b/intern/cycles/kernel/device/oneapi/kernel.cpp @@ -144,6 +144,10 @@ size_t oneapi_kernel_preferred_local_size(SyclQueue *queue, bool oneapi_load_kernels(SyclQueue *queue_, const uint requested_features) { +# ifdef SYCL_SKIP_KERNELS_PRELOAD + (void)queue_; + (void)requested_features; +# else assert(queue_); sycl::queue *queue = reinterpret_cast(queue_); @@ -175,7 +179,7 @@ bool oneapi_load_kernels(SyclQueue *queue_, const uint requested_features) sycl::kernel_bundle one_kernel_bundle = sycl::get_kernel_bundle(queue->get_context(), {kernel_id}); - sycl::build(one_kernel_bundle, {queue->get_device()}, sycl::property::queue::in_order()); + sycl::build(one_kernel_bundle); } } catch (sycl::exception const &e) { @@ -184,7 +188,7 @@ bool oneapi_load_kernels(SyclQueue *queue_, const uint requested_features) } return false; } - +# endif return true; } -- cgit v1.2.3 From 151b653bd5f3460363663a65eb389025e7f9c38a Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Wed, 19 Oct 2022 12:51:16 +0200 Subject: Cycles: oneAPI: fix clean Windows ninja builds Previously, a first build using ninja would throw "ninja: error: 'intern/cycles/kernel/cycles_kernel_oneapi.lib', needed by 'bin/blender.exe', missing and no known rule to make it". --- intern/cycles/kernel/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index e5d1c3d6563..6140e90042b 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -715,6 +715,7 @@ endif() if(WITH_CYCLES_DEVICE_ONEAPI) if(WIN32) set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi.dll) + set(cycles_kernel_oneapi_linker_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi.lib) else() set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/libcycles_kernel_oneapi.so) endif() @@ -851,7 +852,7 @@ if(WITH_CYCLES_DEVICE_ONEAPI) -Xclang --dependent-lib=${sycl_library_debug_name}) add_custom_command( - OUTPUT ${cycles_kernel_oneapi_lib} + OUTPUT ${cycles_kernel_oneapi_lib} ${cycles_kernel_oneapi_linker_lib} COMMAND ${CMAKE_COMMAND} -E env "LIB=${sycl_compiler_root}/../lib" # for compiler to find sycl.lib "PATH=${OCLOC_INSTALL_DIR}\;${sycl_compiler_root}" -- cgit v1.2.3 From d763e294fc68226af320b9fe17ad50e2b21287ce Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Wed, 19 Oct 2022 12:31:17 +0200 Subject: Cycles: oneAPI: fix libsycl.so files harvesting was missing libsycl.so.5.7.0-16 when using such version. --- build_files/cmake/platform/platform_unix.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake index 695ea3d773e..7f3acb142ce 100644 --- a/build_files/cmake/platform/platform_unix.cmake +++ b/build_files/cmake/platform/platform_unix.cmake @@ -341,10 +341,10 @@ if(WITH_CYCLES AND WITH_CYCLES_DEVICE_ONEAPI) endif() file(GLOB _sycl_runtime_libraries ${SYCL_ROOT_DIR}/lib/libsycl.so - ${SYCL_ROOT_DIR}/lib/libsycl.so.[0-9] - ${SYCL_ROOT_DIR}/lib/libsycl.so.[0-9].[0-9].[0-9]-[0-9] + ${SYCL_ROOT_DIR}/lib/libsycl.so.* ${SYCL_ROOT_DIR}/lib/libpi_level_zero.so ) + list(FILTER _sycl_runtime_libraries EXCLUDE REGEX ".*\.py") list(APPEND PLATFORM_BUNDLED_LIBRARIES ${_sycl_runtime_libraries}) unset(_sycl_runtime_libraries) endif() -- cgit v1.2.3 From ceb0e7fceae52d317833ed05e6ee0b2852ad170d Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 19 Oct 2022 16:47:57 +0200 Subject: Fix (devs-reported) mistake in batch delete code in recent change. Mistake in own rB358155a8da60, change ended up discarding the case where we need to also delete IDs using a tagged-to-be-deleted ID in a 'never NULL' way. Typical example: Whene deleting a Mesh ID, one also needs to delete all the Objects using that mesh, since obdata pointer is of type 'never NULL'. Note that luckily, this fix does not affect the performance improvements from rB358155a8da60. Noted by Brecht and Clement because of failing unittests, shame on me. --- source/blender/blenkernel/intern/lib_id_delete.c | 29 ++++++++++++------------ 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index ae5dc75c36a..1a80376f482 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -218,6 +218,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) BKE_main_lock(bmain); if (do_tagged_deletion) { struct IDRemapper *id_remapper = BKE_id_remapper_create(); + BKE_layer_collection_resync_forbid(); /* Main idea of batch deletion is to remove all IDs to be deleted from Main database. * This means that we won't have to loop over all deleted IDs to remove usages @@ -253,22 +254,20 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) } } } - } - - BKE_layer_collection_resync_forbid(); - /* Will tag 'never NULL' users of this ID too. - * - * NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect - * links, this can lead to nasty crashing here in second, actual deleting loop. - * Also, this will also flag users of deleted data that cannot be unlinked - * (object using deleted obdata, etc.), so that they also get deleted. */ - BKE_libblock_remap_multiple_locked(bmain, - id_remapper, - ID_REMAP_FLAG_NEVER_NULL_USAGE | - ID_REMAP_FORCE_NEVER_NULL_USAGE | - ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS); - BKE_id_remapper_clear(id_remapper); + /* Will tag 'never NULL' users of this ID too. + * + * NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect + * links, this can lead to nasty crashing here in second, actual deleting loop. + * Also, this will also flag users of deleted data that cannot be unlinked + * (object using deleted obdata, etc.), so that they also get deleted. */ + BKE_libblock_remap_multiple_locked(bmain, + id_remapper, + ID_REMAP_FLAG_NEVER_NULL_USAGE | + ID_REMAP_FORCE_NEVER_NULL_USAGE | + ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS); + BKE_id_remapper_clear(id_remapper); + } /* Since we removed IDs from Main, their own other IDs usages need to be removed 'manually'. */ LinkNode *cleanup_ids = NULL; -- cgit v1.2.3 From 3d878cd0df31ae89e1fc2a99b3f90e12c6db9c55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Wed, 19 Oct 2022 17:08:24 +0200 Subject: Fix T101896 Eevee: Custom object properties don't work in shader for Curves objects Move the material resources binding inside the `DRW_shgroup_curves_create_sub` so that `DRW_shgroup_call_no_cull` extracts the attributes. --- source/blender/draw/engines/eevee/eevee_materials.c | 6 ------ source/blender/draw/intern/draw_curves.cc | 5 +++++ source/blender/draw/intern/draw_hair.cc | 5 +++++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index b5f81f3a307..068b18f1117 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -924,17 +924,14 @@ void EEVEE_particle_hair_cache_populate(EEVEE_Data *vedata, if (matcache.depth_grp) { *matcache.depth_grp_p = DRW_shgroup_hair_create_sub( ob, psys, md, matcache.depth_grp, NULL); - DRW_shgroup_add_material_resources(*matcache.depth_grp_p, matcache.shading_gpumat); } if (matcache.shading_grp) { *matcache.shading_grp_p = DRW_shgroup_hair_create_sub( ob, psys, md, matcache.shading_grp, matcache.shading_gpumat); - DRW_shgroup_add_material_resources(*matcache.shading_grp_p, matcache.shading_gpumat); } if (matcache.shadow_grp) { *matcache.shadow_grp_p = DRW_shgroup_hair_create_sub( ob, psys, md, matcache.shadow_grp, NULL); - DRW_shgroup_add_material_resources(*matcache.shadow_grp_p, matcache.shading_gpumat); *cast_shadow = true; } @@ -954,16 +951,13 @@ void EEVEE_object_curves_cache_populate(EEVEE_Data *vedata, if (matcache.depth_grp) { *matcache.depth_grp_p = DRW_shgroup_curves_create_sub(ob, matcache.depth_grp, NULL); - DRW_shgroup_add_material_resources(*matcache.depth_grp_p, matcache.shading_gpumat); } if (matcache.shading_grp) { *matcache.shading_grp_p = DRW_shgroup_curves_create_sub( ob, matcache.shading_grp, matcache.shading_gpumat); - DRW_shgroup_add_material_resources(*matcache.shading_grp_p, matcache.shading_gpumat); } if (matcache.shadow_grp) { *matcache.shadow_grp_p = DRW_shgroup_curves_create_sub(ob, matcache.shadow_grp, NULL); - DRW_shgroup_add_material_resources(*matcache.shadow_grp_p, matcache.shading_gpumat); *cast_shadow = true; } diff --git a/source/blender/draw/intern/draw_curves.cc b/source/blender/draw/intern/draw_curves.cc index a61769e7a63..8847e3f6016 100644 --- a/source/blender/draw/intern/draw_curves.cc +++ b/source/blender/draw/intern/draw_curves.cc @@ -394,6 +394,11 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object, DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", hair_rad_root); DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", hair_rad_tip); DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip); + if (gpu_material) { + /* \note: This needs to happen before the drawcall to allow correct attribute extraction. + * (see T101896) */ + DRW_shgroup_add_material_resources(shgrp, gpu_material); + } /* TODO(fclem): Until we have a better way to cull the curves and render with orco, bypass * culling test. */ GPUBatch *geom = curves_cache->final[subdiv].proc_hairs[thickness_res - 1]; diff --git a/source/blender/draw/intern/draw_hair.cc b/source/blender/draw/intern/draw_hair.cc index 4e44967e5e9..281e58ea230 100644 --- a/source/blender/draw/intern/draw_hair.cc +++ b/source/blender/draw/intern/draw_hair.cc @@ -293,6 +293,11 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object, DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", hair_rad_root); DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", hair_rad_tip); DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip); + if (gpu_material) { + /* \note: This needs to happen before the drawcall to allow correct attribute extraction. + * (see T101896) */ + DRW_shgroup_add_material_resources(shgrp, gpu_material); + } /* TODO(fclem): Until we have a better way to cull the hair and render with orco, bypass * culling test. */ GPUBatch *geom = hair_cache->final[subdiv].proc_hairs[thickness_res - 1]; -- cgit v1.2.3 From 96c085d4af151f0ff20f23f1fe0428e2d8fbdee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Wed, 19 Oct 2022 17:19:18 +0200 Subject: Cleanup: WM: Fix missing enumerator case in switch --- source/blender/windowmanager/intern/wm_window.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 6b925b23dcb..ce573a9285b 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1625,13 +1625,14 @@ GHOST_TDrawingContextType wm_ghost_drawing_context_type(const eGPUBackendType gp case GPU_BACKEND_ANY: case GPU_BACKEND_OPENGL: return GHOST_kDrawingContextTypeOpenGL; -#ifdef WITH_METAL_BACKEND case GPU_BACKEND_METAL: +#ifdef WITH_METAL_BACKEND return GHOST_kDrawingContextTypeMetal; +#else + BLI_assert_unreachable(); + return GHOST_kDrawingContextTypeNone; #endif } - BLI_assert_unreachable(); - return GHOST_kDrawingContextTypeNone; } /** \} */ -- cgit v1.2.3 From bad734081180ed31417ea382d5093f8e6fd35129 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 19 Oct 2022 17:31:56 +0200 Subject: Fix control reaches end of non-void function error --- source/blender/windowmanager/intern/wm_window.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index ce573a9285b..2ca7b5f470d 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1633,6 +1633,11 @@ GHOST_TDrawingContextType wm_ghost_drawing_context_type(const eGPUBackendType gp return GHOST_kDrawingContextTypeNone; #endif } + + /* Avoid control reaches end of non-void function compilation warning, which could be promoted + * to error. */ + BLI_assert_unreachable(); + return GHOST_kDrawingContextTypeNone; } /** \} */ -- cgit v1.2.3 From 63aec82e8ae388c8ae0cf3717d18a1eb1e97395a Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Wed, 19 Oct 2022 17:47:21 +0200 Subject: Cycles: oneAPI: switch back target to dg2 Current version of IGC dependency doesn't yet support acm-g10 target. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bffd761f941..9134c7c1ed6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -492,8 +492,8 @@ if(NOT APPLE) option(WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED "Enable use of SYCL host (CPU) device execution by oneAPI implementation. This option is for debugging purposes and impacts GPU execution." OFF) # https://www.intel.com/content/www/us/en/develop/documentation/oneapi-dpcpp-cpp-compiler-dev-guide-and-reference/top/compilation/ahead-of-time-compilation.html - # acm-g10 is the architecture for the first Arc Alchemist GPUs. - set(CYCLES_ONEAPI_SPIR64_GEN_DEVICES "acm-g10" CACHE STRING "oneAPI Intel GPU architectures to build binaries for") + # acm-g10 is the architecture for the first Arc Alchemist GPUs but we'll keep using dg2 until IGC dependency is updated to support acm-g10. + set(CYCLES_ONEAPI_SPIR64_GEN_DEVICES "dg2" CACHE STRING "oneAPI Intel GPU architectures to build binaries for") set(CYCLES_ONEAPI_SYCL_TARGETS spir64 spir64_gen CACHE STRING "oneAPI targets to build AOT binaries for") mark_as_advanced(WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED) -- cgit v1.2.3 From 053fc35b01593dbfa83858bf5a0debea39c5f1ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Wed, 19 Oct 2022 17:55:18 +0200 Subject: EEVEE: Depth Of Field: Replace ambiguous select with manual check This is an attempt to remove a driver bug. --- .../blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl index 51a351babd3..5f04cdcebfa 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl @@ -95,7 +95,11 @@ void main() weights = dof_layer_weight(cocs) * dof_sample_weight(cocs); /* Filter NaNs. */ - weights = select(weights, vec4(0.0), equal(cocs, vec4(0.0))); + for (int i = 0; i < 4; i++) { + if (isnan(weights[i]) || isinf(weights[i])) { + weights[i] = 0.0; + } + } color1 = colors[0] * weights[0]; color2 = colors[1] * weights[1]; -- cgit v1.2.3 From e6902d19a0d8b034e65f28df6dba914a876b08df Mon Sep 17 00:00:00 2001 From: Morteza Mostajab Date: Wed, 19 Oct 2022 17:09:23 +0100 Subject: Cycles: Allow Intel GPUs under Metal Known Issues: - Command buffer failures when using binary archives (binary archives is disabled for Intel GPUs as a workaround) - Wrong texture sampler being applied (to be addressed in the future) Ref T92212 Reviewed By: brecht Maniphest Tasks: T92212 Differential Revision: https://developer.blender.org/D16253 --- intern/cycles/device/metal/device_impl.mm | 6 ++++ intern/cycles/device/metal/kernel.mm | 6 ++++ intern/cycles/device/metal/util.mm | 4 +++ intern/cycles/kernel/device/metal/context_begin.h | 37 ++++++++++++++++++++++- 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/intern/cycles/device/metal/device_impl.mm b/intern/cycles/device/metal/device_impl.mm index 6a16d4bb3b4..82ad5d55ecd 100644 --- a/intern/cycles/device/metal/device_impl.mm +++ b/intern/cycles/device/metal/device_impl.mm @@ -339,6 +339,12 @@ bool MetalDevice::compile_and_load(MetalPipelineType pso_type) MTLCompileOptions *options = [[MTLCompileOptions alloc] init]; + if (@available(macos 13.0, *)) { + if (device_vendor == METAL_GPU_INTEL) { + [options setOptimizationLevel:MTLLibraryOptimizationLevelSize]; + } + } + options.fastMathEnabled = YES; if (@available(macOS 12.0, *)) { options.languageVersion = MTLLanguageVersion2_4; diff --git a/intern/cycles/device/metal/kernel.mm b/intern/cycles/device/metal/kernel.mm index 5e0cb6d18f4..8ccc50e57a3 100644 --- a/intern/cycles/device/metal/kernel.mm +++ b/intern/cycles/device/metal/kernel.mm @@ -317,6 +317,12 @@ bool MetalKernelPipeline::should_use_binary_archive() const } } + /* Workaround for Intel GPU having issue using Binary Archives */ + MetalGPUVendor gpu_vendor = MetalInfo::get_device_vendor(mtlDevice); + if (gpu_vendor == METAL_GPU_INTEL) { + return false; + } + if (pso_type == PSO_GENERIC) { /* Archive the generic kernels. */ return true; diff --git a/intern/cycles/device/metal/util.mm b/intern/cycles/device/metal/util.mm index 65c67c400fe..eb77aeb6a54 100644 --- a/intern/cycles/device/metal/util.mm +++ b/intern/cycles/device/metal/util.mm @@ -110,6 +110,10 @@ vector> const &MetalInfo::get_usable_devices() usable |= (vendor == METAL_GPU_AMD); } + if (@available(macos 13.0, *)) { + usable |= (vendor == METAL_GPU_INTEL); + } + if (usable) { metal_printf("- %s\n", device_name.c_str()); [device retain]; diff --git a/intern/cycles/kernel/device/metal/context_begin.h b/intern/cycles/kernel/device/metal/context_begin.h index 99cb1e3826e..e75ec9cadec 100644 --- a/intern/cycles/kernel/device/metal/context_begin.h +++ b/intern/cycles/kernel/device/metal/context_begin.h @@ -34,21 +34,48 @@ class MetalKernelContext { kernel_assert(0); return 0; } - + +#ifdef __KERNEL_METAL_INTEL__ + template + inline __attribute__((__always_inline__)) + auto ccl_gpu_tex_object_read_intel_workaround(TextureType texture_array, + const uint tid, const uint sid, + CoordsType coords) const + { + switch(sid) { + default: + case 0: return texture_array[tid].tex.sample(sampler(address::repeat, filter::nearest), coords); + case 1: return texture_array[tid].tex.sample(sampler(address::clamp_to_edge, filter::nearest), coords); + case 2: return texture_array[tid].tex.sample(sampler(address::clamp_to_zero, filter::nearest), coords); + case 3: return texture_array[tid].tex.sample(sampler(address::repeat, filter::linear), coords); + case 4: return texture_array[tid].tex.sample(sampler(address::clamp_to_edge, filter::linear), coords); + case 5: return texture_array[tid].tex.sample(sampler(address::clamp_to_zero, filter::linear), coords); + } + } +#endif + // texture2d template<> inline __attribute__((__always_inline__)) float4 ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object_2D tex, float x, float y) const { const uint tid(tex); const uint sid(tex >> 32); +#ifndef __KERNEL_METAL_INTEL__ return metal_ancillaries->textures_2d[tid].tex.sample(metal_samplers[sid], float2(x, y)); +#else + return ccl_gpu_tex_object_read_intel_workaround(metal_ancillaries->textures_2d, tid, sid, float2(x, y)); +#endif } template<> inline __attribute__((__always_inline__)) float ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object_2D tex, float x, float y) const { const uint tid(tex); const uint sid(tex >> 32); +#ifndef __KERNEL_METAL_INTEL__ return metal_ancillaries->textures_2d[tid].tex.sample(metal_samplers[sid], float2(x, y)).x; +#else + return ccl_gpu_tex_object_read_intel_workaround(metal_ancillaries->textures_2d, tid, sid, float2(x, y)).x; +#endif } // texture3d @@ -57,14 +84,22 @@ class MetalKernelContext { float4 ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object_3D tex, float x, float y, float z) const { const uint tid(tex); const uint sid(tex >> 32); +#ifndef __KERNEL_METAL_INTEL__ return metal_ancillaries->textures_3d[tid].tex.sample(metal_samplers[sid], float3(x, y, z)); +#else + return ccl_gpu_tex_object_read_intel_workaround(metal_ancillaries->textures_3d, tid, sid, float3(x, y, z)); +#endif } template<> inline __attribute__((__always_inline__)) float ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object_3D tex, float x, float y, float z) const { const uint tid(tex); const uint sid(tex >> 32); +#ifndef __KERNEL_METAL_INTEL__ return metal_ancillaries->textures_3d[tid].tex.sample(metal_samplers[sid], float3(x, y, z)).x; +#else + return ccl_gpu_tex_object_read_intel_workaround(metal_ancillaries->textures_3d, tid, sid, float3(x, y, z)).x; +#endif } # include "kernel/device/gpu/image.h" -- cgit v1.2.3 From a803dbe7ed80df577b648f9e289aaed2a2cc1700 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 19 Oct 2022 12:38:48 -0500 Subject: Geometry Nodes: Use common utility for copying attribute data Attribute copying often uses identical logic for copying selected elements or copying with an index map. Instead of reimplementing this in each file, use the common implementation in the array_utils namespace. This makes the commonality more obvious, gives improved performance (this implementation is multithreaded), reduces binary size (I observed a 173KB reduction), and probably reduces compile time. --- .../blender/blenkernel/intern/curves_geometry.cc | 13 +---- source/blender/blenkernel/intern/instances.cc | 25 +++------ source/blender/blenlib/BLI_array_utils.hh | 5 ++ source/blender/blenlib/intern/array_utils.cc | 5 ++ .../geometry/nodes/node_geo_delete_geometry.cc | 40 +++---------- .../nodes/geometry/nodes/node_geo_dual_mesh.cc | 46 +++++++-------- .../geometry/nodes/node_geo_duplicate_elements.cc | 25 +++------ .../nodes/geometry/nodes/node_geo_extrude_mesh.cc | 65 ++++++++-------------- .../geometry/nodes/node_geo_instance_on_points.cc | 14 +---- 9 files changed, 80 insertions(+), 158 deletions(-) diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc index 29f8d62545f..d65c31139fc 100644 --- a/source/blender/blenkernel/intern/curves_geometry.cc +++ b/source/blender/blenkernel/intern/curves_geometry.cc @@ -9,6 +9,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_array_utils.hh" #include "BLI_bounds.hh" #include "BLI_index_mask_ops.hh" #include "BLI_length_parameterize.hh" @@ -1111,21 +1112,11 @@ static void copy_between_buffers(const CPPType &type, src_range.size()); } -template -static void copy_with_map(const Span src, const Span map, MutableSpan dst) -{ - threading::parallel_for(map.index_range(), 1024, [&](const IndexRange range) { - for (const int i : range) { - dst[i] = src[map[i]]; - } - }); -} - static void copy_with_map(const GSpan src, const Span map, GMutableSpan dst) { attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { using T = decltype(dummy); - copy_with_map(src.typed(), map, dst.typed()); + array_utils::gather(src.typed(), map, dst.typed()); }); } diff --git a/source/blender/blenkernel/intern/instances.cc b/source/blender/blenkernel/intern/instances.cc index 2f8acf477e2..4675562e927 100644 --- a/source/blender/blenkernel/intern/instances.cc +++ b/source/blender/blenkernel/intern/instances.cc @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BLI_array_utils.hh" #include "BLI_cpp_type_make.hh" #include "BLI_rand.hh" #include "BLI_task.hh" @@ -107,18 +108,6 @@ blender::Span Instances::references() const return references_; } -template -static void copy_data_based_on_mask(Span src, MutableSpan dst, IndexMask mask) -{ - BLI_assert(src.data() != dst.data()); - using namespace blender; - threading::parallel_for(mask.index_range(), 1024, [&](IndexRange range) { - for (const int i : range) { - dst[i] = src[mask[i]]; - } - }); -} - void Instances::remove(const IndexMask mask) { using namespace blender; @@ -129,11 +118,14 @@ void Instances::remove(const IndexMask mask) return; } + const Span old_handles = this->reference_handles(); Vector new_handles(mask.size()); - copy_data_based_on_mask(this->reference_handles(), new_handles, mask); + array_utils::gather(old_handles, mask.indices(), new_handles.as_mutable_span()); reference_handles_ = std::move(new_handles); + + const Span old_tansforms = this->transforms(); Vector new_transforms(mask.size()); - copy_data_based_on_mask(this->transforms(), new_transforms, mask); + array_utils::gather(old_tansforms, mask.indices(), new_transforms.as_mutable_span()); transforms_ = std::move(new_transforms); const bke::CustomDataAttributes &src_attributes = attributes_; @@ -150,11 +142,8 @@ void Instances::remove(const IndexMask mask) GSpan src = *src_attributes.get_for_read(id); dst_attributes.create(id, meta_data.data_type); GMutableSpan dst = *dst_attributes.get_for_write(id); + array_utils::gather(src, mask.indices(), dst); - attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { - using T = decltype(dummy); - copy_data_based_on_mask(src.typed(), dst.typed(), mask); - }); return true; }, ATTR_DOMAIN_INSTANCE); diff --git a/source/blender/blenlib/BLI_array_utils.hh b/source/blender/blenlib/BLI_array_utils.hh index 95b3bde10f4..264ac00e034 100644 --- a/source/blender/blenlib/BLI_array_utils.hh +++ b/source/blender/blenlib/BLI_array_utils.hh @@ -39,6 +39,11 @@ inline void copy(const Span src, */ void gather(const GVArray &src, IndexMask indices, GMutableSpan dst, int64_t grain_size = 4096); +/** + * Fill the destination span by gathering indexed values from the `src` array. + */ +void gather(GSpan src, IndexMask indices, GMutableSpan dst, int64_t grain_size = 4096); + /** * Fill the destination span by gathering indexed values from the `src` array. */ diff --git a/source/blender/blenlib/intern/array_utils.cc b/source/blender/blenlib/intern/array_utils.cc index a837d6aceec..2a231228dcb 100644 --- a/source/blender/blenlib/intern/array_utils.cc +++ b/source/blender/blenlib/intern/array_utils.cc @@ -28,4 +28,9 @@ void gather(const GVArray &src, }); } +void gather(const GSpan src, const IndexMask indices, GMutableSpan dst, const int64_t grain_size) +{ + gather(GVArray::ForSpan(src), indices, dst, grain_size); +} + } // namespace blender::array_utils diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc index a433a0df9b0..3e48a9fd923 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -4,6 +4,7 @@ #include "UI_resources.h" #include "BLI_array.hh" +#include "BLI_array_utils.hh" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -23,15 +24,9 @@ namespace blender::nodes::node_geo_delete_geometry_cc { using blender::bke::CustomDataAttributes; template -static void copy_data_based_on_mask(Span data, MutableSpan r_data, IndexMask mask) -{ - for (const int i_out : mask.index_range()) { - r_data[i_out] = data[mask[i_out]]; - } -} - -template -static void copy_data_based_on_map(Span src, MutableSpan dst, Span index_map) +static void copy_data_based_on_map(const Span src, + const Span index_map, + MutableSpan dst) { for (const int i_src : index_map.index_range()) { const int i_dst = index_map[i_src]; @@ -55,26 +50,17 @@ static void copy_attributes(const Map &attributes if (!attribute) { continue; } - /* Only copy if it is on a domain we want. */ if (!domains.contains(attribute.domain)) { continue; } const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type()); - GSpanAttributeWriter result_attribute = dst_attributes.lookup_or_add_for_write_only_span( attribute_id, attribute.domain, data_type); - if (!result_attribute) { continue; } - - attribute_math::convert_to_static_type(data_type, [&](auto dummy) { - using T = decltype(dummy); - VArraySpan span{attribute.varray.typed()}; - MutableSpan out_span = result_attribute.span.typed(); - out_span.copy_from(span); - }); + attribute.varray.materialize(result_attribute.span.data()); result_attribute.finish(); } } @@ -95,26 +81,19 @@ static void copy_attributes_based_on_mask(const Map span{attribute.varray.typed()}; - MutableSpan out_span = result_attribute.span.typed(); - copy_data_based_on_mask(span, out_span, mask); - }); + array_utils::gather(attribute.varray, mask, result_attribute.span); + result_attribute.finish(); } } @@ -131,16 +110,13 @@ static void copy_attributes_based_on_map(const Map span{attribute.varray.typed()}; MutableSpan out_span = result_attribute.span.typed(); - copy_data_based_on_map(span, out_span, index_map); + copy_data_based_on_map(span, index_map, out_span); }); result_attribute.finish(); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc index 84e63845b84..9b1c13bf563 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BLI_array_utils.hh" #include "BLI_task.hh" #include "DNA_mesh_types.h" @@ -105,18 +106,6 @@ static void copy_data_based_on_pairs(Span data, } } -/* Copy using the map. */ -template -static void copy_data_based_on_new_to_old_map(Span data, - MutableSpan r_data, - const Span new_to_old_map) -{ - for (const int i : r_data.index_range()) { - const int old_i = new_to_old_map[i]; - r_data[i] = data[old_i]; - } -} - /** * Transfers the attributes from the original mesh to the new mesh using the following logic: * - If the attribute was on the face domain it is now on the point domain, and this is true @@ -168,7 +157,6 @@ static void transfer_attributes( src_attribute.varray.type()); GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span( attribute_id, out_domain, data_type); - if (!dst_attribute) { continue; } @@ -177,20 +165,24 @@ static void transfer_attributes( using T = decltype(dummy); VArraySpan span{src_attribute.varray.typed()}; MutableSpan dst_span = dst_attribute.span.typed(); - if (src_attribute.domain == ATTR_DOMAIN_FACE) { - dst_span.take_front(span.size()).copy_from(span); - if (keep_boundaries) { - copy_data_based_on_pairs(span, dst_span, boundary_vertex_to_relevant_face_map); - } - } - else if (src_attribute.domain == ATTR_DOMAIN_POINT) { - copy_data_based_on_vertex_types(span, dst_span, vertex_types, keep_boundaries); - } - else if (src_attribute.domain == ATTR_DOMAIN_EDGE) { - copy_data_based_on_new_to_old_map(span, dst_span, new_to_old_edges_map); - } - else { - copy_data_based_on_new_to_old_map(span, dst_span, new_to_old_face_corners_map); + switch (src_attribute.domain) { + case ATTR_DOMAIN_POINT: + copy_data_based_on_vertex_types(span, dst_span, vertex_types, keep_boundaries); + break; + case ATTR_DOMAIN_EDGE: + array_utils::gather(span, new_to_old_edges_map, dst_span); + break; + case ATTR_DOMAIN_FACE: + dst_span.take_front(span.size()).copy_from(span); + if (keep_boundaries) { + copy_data_based_on_pairs(span, dst_span, boundary_vertex_to_relevant_face_map); + } + break; + case ATTR_DOMAIN_CORNER: + array_utils::gather(span, new_to_old_face_corners_map, dst_span); + break; + default: + BLI_assert_unreachable(); } }); dst_attribute.finish(); diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc index 70583625a7a..486f900aca5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BLI_array_utils.hh" #include "BLI_map.hh" #include "BLI_noise.hh" #include "BLI_span.hh" @@ -105,16 +106,6 @@ static void threaded_slice_fill(Span offsets, }); } -template -static void threaded_mapped_copy(const Span mapping, const Span src, MutableSpan dst) -{ - threading::parallel_for(mapping.index_range(), 512, [&](IndexRange range) { - for (const int i : range) { - dst[i] = src[mapping[i]]; - } - }); -} - static void copy_hashed_ids(const Span src, const int hash, MutableSpan dst) { for (const int i : src.index_range()) { @@ -440,17 +431,17 @@ static void copy_face_attributes_without_id(GeometrySet &geometry_set, MutableSpan dst = dst_attribute.span.typed(); switch (out_domain) { - case ATTR_DOMAIN_FACE: - threaded_slice_fill(offsets, selection, src, dst); + case ATTR_DOMAIN_POINT: + array_utils::gather(src, vert_mapping, dst); break; case ATTR_DOMAIN_EDGE: - threaded_mapped_copy(edge_mapping, src, dst); + array_utils::gather(src, edge_mapping, dst); break; - case ATTR_DOMAIN_POINT: - threaded_mapped_copy(vert_mapping, src, dst); + case ATTR_DOMAIN_FACE: + threaded_slice_fill(offsets, selection, src, dst); break; case ATTR_DOMAIN_CORNER: - threaded_mapped_copy(loop_mapping, src, dst); + array_utils::gather(src, loop_mapping, dst); break; default: break; @@ -653,7 +644,7 @@ static void copy_edge_attributes_without_id(GeometrySet &geometry_set, threaded_slice_fill(offsets, selection, src, dst); break; case ATTR_DOMAIN_POINT: - threaded_mapped_copy(point_mapping, src, dst); + array_utils::gather(src, point_mapping, dst); break; default: break; diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index d348d886ad6..151ba3e59cc 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BLI_array_utils.hh" #include "BLI_disjoint_set.hh" #include "BLI_task.hh" #include "BLI_vector_set.hh" @@ -175,24 +176,6 @@ static MPoly new_poly(const int loopstart, const int totloop) return poly; } -template void copy_with_indices(MutableSpan dst, Span src, Span indices) -{ - BLI_assert(dst.size() == indices.size()); - for (const int i : dst.index_range()) { - dst[i] = src[indices[i]]; - } -} - -template void copy_with_mask(MutableSpan dst, Span src, IndexMask mask) -{ - BLI_assert(dst.size() == mask.size()); - threading::parallel_for(mask.index_range(), 512, [&](const IndexRange range) { - for (const int i : range) { - dst[i] = src[mask[i]]; - } - }); -} - /** * \param get_mix_indices_fn: Returns a Span of indices of the source points to mix for every * result point. @@ -265,26 +248,24 @@ static void extrude_mesh_vertices(Mesh &mesh, } GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span( id, meta_data.domain, meta_data.data_type); - attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { - using T = decltype(dummy); - MutableSpan data = attribute.span.typed(); - switch (attribute.domain) { - case ATTR_DOMAIN_POINT: { - /* New vertices copy the attribute values from their source vertex. */ - copy_with_mask(data.slice(new_vert_range), data.as_span(), selection); - break; - } - case ATTR_DOMAIN_EDGE: { + switch (attribute.domain) { + case ATTR_DOMAIN_POINT: + /* New vertices copy the attribute values from their source vertex. */ + array_utils::gather(attribute.span, selection, attribute.span.slice(new_vert_range)); + break; + case ATTR_DOMAIN_EDGE: + attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { + using T = decltype(dummy); + MutableSpan data = attribute.span.typed(); /* New edge values are mixed from of all the edges connected to the source vertex. */ copy_with_mixing(data.slice(new_edge_range), data.as_span(), [&](const int i) { return vert_to_edge_map[selection[i]].as_span(); }); - break; - } - default: - BLI_assert_unreachable(); - } - }); + }); + break; + default: + BLI_assert_unreachable(); + } attribute.finish(); return true; @@ -524,13 +505,14 @@ static void extrude_mesh_edges(Mesh &mesh, switch (attribute.domain) { case ATTR_DOMAIN_POINT: { /* New vertices copy the attribute values from their source vertex. */ - copy_with_indices(data.slice(new_vert_range), data.as_span(), new_vert_indices); + array_utils::gather( + data.as_span(), new_vert_indices.as_span(), data.slice(new_vert_range)); break; } case ATTR_DOMAIN_EDGE: { /* Edges parallel to original edges copy the edge attributes from the original edges. */ MutableSpan duplicate_data = data.slice(duplicate_edge_range); - copy_with_mask(duplicate_data, data.as_span(), edge_selection); + array_utils::gather(data.as_span(), edge_selection, duplicate_data); /* Edges connected to original vertices mix values of selected connected edges. */ MutableSpan connect_data = data.slice(connect_edge_range); @@ -910,17 +892,18 @@ static void extrude_mesh_face_regions(Mesh &mesh, switch (attribute.domain) { case ATTR_DOMAIN_POINT: { /* New vertices copy the attributes from their original vertices. */ - copy_with_indices(data.slice(new_vert_range), data.as_span(), new_vert_indices); + array_utils::gather( + data.as_span(), new_vert_indices.as_span(), data.slice(new_vert_range)); break; } case ATTR_DOMAIN_EDGE: { /* Edges parallel to original edges copy the edge attributes from the original edges. */ MutableSpan boundary_data = data.slice(boundary_edge_range); - copy_with_indices(boundary_data, data.as_span(), boundary_edge_indices); + array_utils::gather(data.as_span(), boundary_edge_indices.as_span(), boundary_data); /* Edges inside of face regions also just duplicate their source data. */ MutableSpan new_inner_data = data.slice(new_inner_edge_range); - copy_with_indices(new_inner_data, data.as_span(), new_inner_edge_indices); + array_utils::gather(data.as_span(), new_inner_edge_indices.as_span(), new_inner_data); /* Edges connected to original vertices mix values of selected connected edges. */ MutableSpan connect_data = data.slice(connect_edge_range); @@ -932,8 +915,8 @@ static void extrude_mesh_face_regions(Mesh &mesh, case ATTR_DOMAIN_FACE: { /* New faces on the side of extrusions get the values from the corresponding selected * face. */ - copy_with_indices( - data.slice(side_poly_range), data.as_span(), edge_extruded_face_indices); + array_utils::gather( + data.as_span(), edge_extruded_face_indices.as_span(), data.slice(side_poly_range)); break; } case ATTR_DOMAIN_CORNER: { diff --git a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc index affeb43e33b..64546684186 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc @@ -2,6 +2,7 @@ #include "DNA_collection_types.h" +#include "BLI_array_utils.hh" #include "BLI_hash.h" #include "BLI_task.hh" @@ -172,18 +173,7 @@ static void add_instances_from_component( dst_attribute_opt = instance_attributes.get_for_write(attribute_id); } BLI_assert(dst_attribute_opt); - const GMutableSpan dst_attribute = dst_attribute_opt->slice(start_len, select_len); - threading::parallel_for(selection.index_range(), 1024, [&](IndexRange selection_range) { - attribute_math::convert_to_static_type(attribute_kind.data_type, [&](auto dummy) { - using T = decltype(dummy); - VArray src = src_attribute.typed(); - MutableSpan dst = dst_attribute.typed(); - for (const int range_i : selection_range) { - const int i = selection[range_i]; - dst[range_i] = src[i]; - } - }); - }); + array_utils::gather(src_attribute, selection, dst_attribute_opt->slice(start_len, select_len)); } } -- cgit v1.2.3 From c14b1137464708cccc9034e8abfd509f55c8ca85 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 19 Oct 2022 13:12:20 -0500 Subject: Fix: Geometry Nodes: Memory leak when deleting instances The instance attributes assignment operators were broken in multiple ways: there wasn't a move constructor (probably causing performance issues), and the destination attributes weren't freed before they were replaced. --- source/blender/blenkernel/BKE_attribute.hh | 2 ++ source/blender/blenkernel/intern/attribute_access.cc | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/BKE_attribute.hh b/source/blender/blenkernel/BKE_attribute.hh index 7b13b8a2b09..a4f9d73c31e 100644 --- a/source/blender/blenkernel/BKE_attribute.hh +++ b/source/blender/blenkernel/BKE_attribute.hh @@ -793,7 +793,9 @@ class CustomDataAttributes { ~CustomDataAttributes(); CustomDataAttributes(const CustomDataAttributes &other); CustomDataAttributes(CustomDataAttributes &&other); + CustomDataAttributes &operator=(const CustomDataAttributes &other); + CustomDataAttributes &operator=(CustomDataAttributes &&other); void reallocate(int size); diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index b86353bdb74..544427cfdd3 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -642,15 +642,26 @@ CustomDataAttributes::CustomDataAttributes(CustomDataAttributes &&other) size_ = other.size_; data = other.data; CustomData_reset(&other.data); + other.size_ = 0; } CustomDataAttributes &CustomDataAttributes::operator=(const CustomDataAttributes &other) { - if (this != &other) { - CustomData_copy(&other.data, &data, CD_MASK_ALL, CD_DUPLICATE, other.size_); - size_ = other.size_; + if (this == &other) { + return *this; } + this->~CustomDataAttributes(); + new (this) CustomDataAttributes(other); + return *this; +} +CustomDataAttributes &CustomDataAttributes::operator=(CustomDataAttributes &&other) +{ + if (this == &other) { + return *this; + } + this->~CustomDataAttributes(); + new (this) CustomDataAttributes(std::move(other)); return *this; } -- cgit v1.2.3 From c3d0ba3b333cb9cf09c94932edd98ae74d0b06a4 Mon Sep 17 00:00:00 2001 From: Yann Lanthony Date: Wed, 19 Oct 2022 19:49:15 +0200 Subject: Fix T101622: Sequencer channels not updating while panning view `V2D_VIEWSYNC_AREA_VERTICAL` flag was mistakenly set to the sequencer toolbar region instead of the channels region. Reviewed By: ISS Differential Revision: https://developer.blender.org/D16155 --- source/blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenloader/intern/versioning_300.cc | 23 ++++++++++++++++++++++ .../editors/space_sequencer/space_sequencer.c | 2 +- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 96df8f7a443..806fff2099e 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -25,7 +25,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 4 +#define BLENDER_FILE_SUBVERSION 5 /* 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/blenloader/intern/versioning_300.cc b/source/blender/blenloader/intern/versioning_300.cc index e2b98b2283f..a2bd7fd2fd1 100644 --- a/source/blender/blenloader/intern/versioning_300.cc +++ b/source/blender/blenloader/intern/versioning_300.cc @@ -3630,6 +3630,29 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) } } + if (!MAIN_VERSION_ATLEAST(bmain, 304, 5)) { + /* Fix for T101622 - update flags of sequence editor regions that were not initialized + * properly. */ + LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase : + &sl->regionbase; + if (sl->spacetype == SPACE_SEQ) { + LISTBASE_FOREACH (ARegion *, region, regionbase) { + if (region->regiontype == RGN_TYPE_TOOLS) { + region->v2d.flag &= ~V2D_VIEWSYNC_AREA_VERTICAL; + } + if (region->regiontype == RGN_TYPE_CHANNELS) { + region->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL; + } + } + } + } + } + } + } + /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 8b6d37caa41..1d20926d16c 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -129,7 +129,6 @@ static SpaceLink *sequencer_create(const ScrArea *UNUSED(area), const Scene *sce region->regiontype = RGN_TYPE_TOOLS; region->alignment = RGN_ALIGN_LEFT; region->flag = RGN_FLAG_HIDDEN; - region->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL; /* Channels. */ region = MEM_callocN(sizeof(ARegion), "channels for sequencer"); @@ -137,6 +136,7 @@ static SpaceLink *sequencer_create(const ScrArea *UNUSED(area), const Scene *sce BLI_addtail(&sseq->regionbase, region); region->regiontype = RGN_TYPE_CHANNELS; region->alignment = RGN_ALIGN_LEFT; + region->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL; /* Preview region. */ /* NOTE: if you change values here, also change them in sequencer_init_preview_region. */ -- cgit v1.2.3 From 193b456d2db87ac578a4dae25d654454ea0c03a0 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 19 Oct 2022 20:31:12 +0200 Subject: Fix macOS build error after recent changes to enable Intel GPUs This will only work once we upgrade to the macOS 13 SDK. Ref D16253 --- intern/cycles/device/metal/device_impl.mm | 2 ++ intern/cycles/device/metal/util.mm | 2 ++ 2 files changed, 4 insertions(+) diff --git a/intern/cycles/device/metal/device_impl.mm b/intern/cycles/device/metal/device_impl.mm index 82ad5d55ecd..4ec0ea065ab 100644 --- a/intern/cycles/device/metal/device_impl.mm +++ b/intern/cycles/device/metal/device_impl.mm @@ -339,11 +339,13 @@ bool MetalDevice::compile_and_load(MetalPipelineType pso_type) MTLCompileOptions *options = [[MTLCompileOptions alloc] init]; +#if defined(MAC_OS_VERSION_13_0) if (@available(macos 13.0, *)) { if (device_vendor == METAL_GPU_INTEL) { [options setOptimizationLevel:MTLLibraryOptimizationLevelSize]; } } +#endif options.fastMathEnabled = YES; if (@available(macOS 12.0, *)) { diff --git a/intern/cycles/device/metal/util.mm b/intern/cycles/device/metal/util.mm index eb77aeb6a54..63f84a9df33 100644 --- a/intern/cycles/device/metal/util.mm +++ b/intern/cycles/device/metal/util.mm @@ -110,9 +110,11 @@ vector> const &MetalInfo::get_usable_devices() usable |= (vendor == METAL_GPU_AMD); } +#if defined(MAC_OS_VERSION_13_0) if (@available(macos 13.0, *)) { usable |= (vendor == METAL_GPU_INTEL); } +#endif if (usable) { metal_printf("- %s\n", device_name.c_str()); -- cgit v1.2.3 From d046c8c9d756d5a22ed9aa5a8d0bf0b69d9deba6 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 19 Oct 2022 13:39:23 -0500 Subject: Fix T101926: Curves: Remove type-specific attributes when deleting Remove NURBS or Bezier specific attributes after removing points or curves. In theory we could avoid copying those attributes in the first place, but that doesn't seem worth the extra complexity here, since we don't necessarily know the result curve type counts before copying attributes. --- source/blender/blenkernel/intern/curves_geometry.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc index d65c31139fc..7c338480c71 100644 --- a/source/blender/blenkernel/intern/curves_geometry.cc +++ b/source/blender/blenkernel/intern/curves_geometry.cc @@ -1224,6 +1224,10 @@ static CurvesGeometry copy_with_removed_points(const CurvesGeometry &curves, attribute.dst.finish(); } + if (new_curves.curves_num() != curves.curves_num()) { + new_curves.remove_attributes_based_on_types(); + } + return new_curves; } @@ -1329,6 +1333,8 @@ static CurvesGeometry copy_with_removed_curves(const CurvesGeometry &curves, attribute.dst.finish(); } + new_curves.remove_attributes_based_on_types(); + return new_curves; } -- cgit v1.2.3 From bf8d4a9bc6fb285011f74f5fb36c77b299893ba9 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Wed, 19 Oct 2022 21:06:07 +0200 Subject: Fix T101857: Crash when trying to build proxies on read-only filesystem Skip building if proxy file can't be created. --- source/blender/imbuf/intern/indexer.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index 8965700c08a..e8e4b80ef45 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -498,7 +498,9 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg( rv->anim = anim; get_proxy_filepath(rv->anim, rv->proxy_size, filepath, true); - BLI_make_existing_file(filepath); + if (!BLI_make_existing_file(filepath)) { + return NULL; + } rv->of = avformat_alloc_context(); rv->of->oformat = av_guess_format("avi", NULL, NULL); @@ -905,6 +907,11 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, } } + if (context->proxy_ctx[0] == NULL && context->proxy_ctx[1] == NULL && + context->proxy_ctx[2] == NULL && context->proxy_ctx[3] == NULL) { + return NULL; /* Nothing to transcode. */ + } + for (i = 0; i < num_indexers; i++) { if (tcs_in_use & tc_types[i]) { char filepath[FILE_MAX]; -- cgit v1.2.3 From ba6f25dd1b6d746c361d78b9c6c898ff96fd50d4 Mon Sep 17 00:00:00 2001 From: Chris Blackbourn Date: Thu, 20 Oct 2022 10:10:39 +1300 Subject: Fix T101907: restore snapping in node editor Regression from 1edebb794b76 --- source/blender/editors/transform/transform_snap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 553202b5798..06aec3b45a6 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -523,6 +523,10 @@ void applyGridAbsolute(TransInfo *t) float grid_size_y = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_y[1] : t->snap_spatial_y[0]; float grid_size_z = grid_size_x; + if (grid_size_y == 0.0f) { + grid_size_y = grid_size_x; /* Just use `grid_size_x` when `grid_size_y` isn't set correctly. */ + } + /* Early exit on unusable grid size. */ if (grid_size_x == 0.0f || grid_size_y == 0.0f || grid_size_z == 0.0f) { return; -- cgit v1.2.3 From 1a11353d341aa46487ee8b4177cbb2d566bca932 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 19 Oct 2022 16:33:26 -0500 Subject: Cleanup: Remove unused grease pencil / RNA includes --- source/blender/editors/gpencil/annotate_paint.c | 3 --- source/blender/makesrna/intern/rna_gpencil_modifier.c | 14 ++------------ 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index 677bf1bb392..2fd58a9cee0 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -13,9 +13,6 @@ #include "MEM_guardedalloc.h" -#include "BLI_blenlib.h" -#include "BLI_math.h" -#include "BLI_math_geom.h" #include "BLI_utildefines.h" #include "BLT_translation.h" diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 4a36443ca42..320ef169ae5 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -9,11 +9,8 @@ #include #include "DNA_armature_types.h" -#include "DNA_brush_types.h" -#include "DNA_cachefile_types.h" #include "DNA_gpencil_modifier_types.h" #include "DNA_gpencil_types.h" -#include "DNA_mesh_types.h" #include "DNA_modifier_types.h" #include "DNA_object_force_types.h" #include "DNA_object_types.h" @@ -21,20 +18,13 @@ #include "MEM_guardedalloc.h" -#include "BLI_math.h" -#include "BLI_rand.h" +#include "BLI_math_base.h" +#include "BLI_math_rotation.h" #include "BLI_string_utils.h" #include "BLT_translation.h" #include "BKE_animsys.h" -#include "BKE_data_transfer.h" -#include "BKE_dynamicpaint.h" -#include "BKE_effect.h" -#include "BKE_fluid.h" /* For BKE_fluid_modifier_free & BKE_fluid_modifier_create_type_data */ -#include "BKE_mesh_mapping.h" -#include "BKE_mesh_remap.h" -#include "BKE_multires.h" #include "RNA_access.h" #include "RNA_define.h" -- cgit v1.2.3 From c67975c6bb70c6f877b005bbefcef71f2045b34b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 08:48:45 +1100 Subject: Cleanup: use 'wl_' prefix for data_source Without this the local and wayland native types could be mixed up. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 2d16fd4cff5..c0c55fb4cfa 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -289,7 +289,7 @@ struct GWL_DataOffer { }; struct GWL_DataSource { - struct wl_data_source *data_source = nullptr; + struct wl_data_source *wl_data_source = nullptr; char *buffer_out = nullptr; }; @@ -616,8 +616,8 @@ static void display_destroy(GWL_Display *display) std::lock_guard lock{seat->data_source_mutex}; if (seat->data_source) { free(seat->data_source->buffer_out); - if (seat->data_source->data_source) { - wl_data_source_destroy(seat->data_source->data_source); + if (seat->data_source->wl_data_source) { + wl_data_source_destroy(seat->data_source->wl_data_source); } delete seat->data_source; } @@ -3580,18 +3580,18 @@ void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) c data_source->buffer_out = static_cast(malloc(buffer_size)); std::memcpy(data_source->buffer_out, buffer, buffer_size); - data_source->data_source = wl_data_device_manager_create_data_source( + data_source->wl_data_source = wl_data_device_manager_create_data_source( display_->data_device_manager); - wl_data_source_add_listener(data_source->data_source, &data_source_listener, seat); + wl_data_source_add_listener(data_source->wl_data_source, &data_source_listener, seat); for (const std::string &type : mime_send) { - wl_data_source_offer(data_source->data_source, type.c_str()); + wl_data_source_offer(data_source->wl_data_source, type.c_str()); } if (seat->data_device) { wl_data_device_set_selection( - seat->data_device, data_source->data_source, seat->data_source_serial); + seat->data_device, data_source->wl_data_source, seat->data_source_serial); } } -- cgit v1.2.3 From 09e3ea49dbbec15a8fcc79cc609f6dc8c13bc91f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 08:51:24 +1100 Subject: GHOST/Wayland: clear data source pointer when canceled The external cancel callback destroyed the data source but didn't clear the pointer. While this didn't cause problems, avoid keeping references freed pointers. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index c0c55fb4cfa..5b6963dde7a 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1277,9 +1277,14 @@ static void data_source_handle_send(void *data, close(fd); } -static void data_source_handle_cancelled(void * /*data*/, struct wl_data_source *wl_data_source) +static void data_source_handle_cancelled(void *data, struct wl_data_source *wl_data_source) { CLOG_INFO(LOG, 2, "cancelled"); + GWL_Seat *seat = static_cast(data); + GWL_DataSource *data_source = seat->data_source; + GHOST_ASSERT(seat->data_source->wl_data_source == wl_data_source, "Data source mismatch!"); + data_source->wl_data_source = nullptr; + wl_data_source_destroy(wl_data_source); } -- cgit v1.2.3 From 21a1c332b00a63afaa82cce00ca5175b1b8dbd96 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 09:49:17 +1100 Subject: GHOST/Wayland: update code comment for Gnome-Shell workaround Note that the bug has been fixed upstream. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 5b6963dde7a..5c3f807d678 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -117,6 +117,8 @@ static bool use_gnome_confine_hack = false; * This define could be removed without changing any functionality, * it just means GNOME users will see verbose warning messages that alert them about * a known problem that needs to be fixed up-stream. + * + * This has been fixed for GNOME 43. Keep the workaround until support for gnome 42 is dropped. * See: https://gitlab.gnome.org/GNOME/mutter/-/issues/2457 */ #define USE_GNOME_KEYBOARD_SUPPRESS_WARNING -- cgit v1.2.3 From e3075f3cf7ce2fae086f3cd09867e4f0455e4115 Mon Sep 17 00:00:00 2001 From: Chris Blackbourn Date: Thu, 20 Oct 2022 12:35:17 +1300 Subject: Cleanup: simplify uv packing api Part of a wider set of changes to migrate UV packing from uv_parametrizer.cc to uvedit_islands.cc. This allows UV packing improvements including margin calculation, correctness fixes such as support for non-manifold geometry, and new packing algorithms including speed and quality improvements. See for example c2256bf7f714, T82637 This change migrates UV.unwrap and Live UV Unwrap. Differential Revision: https://developer.blender.org/D16296 --- source/blender/editors/include/ED_uvedit.h | 2 + source/blender/editors/uvedit/uvedit_islands.cc | 26 +++++++- source/blender/editors/uvedit/uvedit_unwrap_ops.c | 75 +++++++++++------------ 3 files changed, 62 insertions(+), 41 deletions(-) diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index c8ffbb9acb1..b97cd6a9099 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -345,12 +345,14 @@ typedef enum { ED_UVPACK_MARGIN_FRACTION, /* Specify a precise fraction of final UV output. */ } eUVPackIsland_MarginMethod; +/** See also #UnwrapOptions. */ struct UVPackIsland_Params { uint rotate : 1; uint only_selected_uvs : 1; uint only_selected_faces : 1; uint use_seams : 1; uint correct_aspect : 1; + bool ignore_pinned; /* Ignore islands which have any pinned UVs. */ eUVPackIsland_MarginMethod margin_method; /* Which formula to use when scaling island margin. */ float margin; /* Additional space to add around each island. */ }; diff --git a/source/blender/editors/uvedit/uvedit_islands.cc b/source/blender/editors/uvedit/uvedit_islands.cc index bdd05b06d94..92745667505 100644 --- a/source/blender/editors/uvedit/uvedit_islands.cc +++ b/source/blender/editors/uvedit/uvedit_islands.cc @@ -600,6 +600,22 @@ static BoxPack *pack_islands_params(const blender::Vector &island_ return box_array; } +static bool island_has_pins(FaceIsland *island) +{ + BMLoop *l; + BMIter iter; + const int cd_loop_uv_offset = island->cd_loop_uv_offset; + for (int i = 0; i < island->faces_len; i++) { + BM_ITER_ELEM (l, &iter, island->faces[i], BM_LOOPS_OF_FACE) { + MLoopUV *luv = static_cast(BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset)); + if (luv->flag & MLOOPUV_PINNED) { + return true; + } + } + } + return false; +} + /* -------------------------------------------------------------------- */ /** \name Public UV Island Packing * @@ -651,8 +667,14 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, aspect_y, cd_loop_uv_offset); - int index; - LISTBASE_FOREACH_INDEX (struct FaceIsland *, island, &island_list, index) { + /* Remove from linked list and append to blender::Vector. */ + LISTBASE_FOREACH_MUTABLE (struct FaceIsland *, island, &island_list) { + BLI_remlink(&island_list, island); + if (params->ignore_pinned && island_has_pins(island)) { + MEM_freeN(island->faces); + MEM_freeN(island); + continue; + } island_vector.append(island); } } diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 2c977552e72..ecaba3234a7 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -1050,31 +1050,6 @@ void UV_OT_minimize_stretch(wmOperatorType *ot) /** \name Pack UV Islands Operator * \{ */ -/** - * \warning Since this uses #ParamHandle it doesn't work with non-manifold meshes (see T82637). - * Use #ED_uvedit_pack_islands_multi for a more general solution. - * - * TODO: remove this function, in favor of #ED_uvedit_pack_islands_multi. - */ -static void uvedit_pack_islands_multi(const Scene *scene, - Object **objects, - const uint objects_len, - const UnwrapOptions *options, - bool rotate, - bool ignore_pinned) -{ - ParamHandle *handle = construct_param_handle_multi(scene, objects, objects_len, options); - GEO_uv_parametrizer_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned); - GEO_uv_parametrizer_flush(handle); - GEO_uv_parametrizer_delete(handle); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY); - WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data); - } -} - /* Packing targets. */ enum { PACK_UDIM_SRC_CLOSEST = 0, @@ -1119,16 +1094,22 @@ static int pack_islands_exec(bContext *C, wmOperator *op) const bool use_udim_params = ED_uvedit_udim_params_from_image_space( sima, use_active, &udim_params); - struct UVPackIsland_Params params = { + const struct UVPackIsland_Params pack_island_params = { .rotate = RNA_boolean_get(op->ptr, "rotate"), - .only_selected_uvs = true, - .only_selected_faces = true, - .correct_aspect = true, + .only_selected_uvs = options.only_selected_uvs, + .only_selected_faces = options.only_selected_faces, + .use_seams = !options.topology_from_uvs || options.topology_from_uvs_use_seams, + .correct_aspect = options.correct_aspect, + .ignore_pinned = false, .margin_method = RNA_enum_get(op->ptr, "margin_method"), .margin = RNA_float_get(op->ptr, "margin"), }; - ED_uvedit_pack_islands_multi( - scene, objects, objects_len, NULL, use_udim_params ? &udim_params : NULL, ¶ms); + ED_uvedit_pack_islands_multi(scene, + objects, + objects_len, + NULL, + use_udim_params ? &udim_params : NULL, + &pack_island_params); MEM_freeN(objects); return OPERATOR_FINISHED; @@ -1889,12 +1870,19 @@ void ED_uvedit_live_unwrap(const Scene *scene, Object **objects, int objects_len .fill_holes = (scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES) != 0, .correct_aspect = (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) == 0, }; - - bool rotate = true; - bool ignore_pinned = true; - uvedit_unwrap_multi(scene, objects, objects_len, &options, NULL); - uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned); + + const struct UVPackIsland_Params pack_island_params = { + .rotate = true, + .only_selected_uvs = options.only_selected_uvs, + .only_selected_faces = options.only_selected_faces, + .use_seams = !options.topology_from_uvs || options.topology_from_uvs_use_seams, + .correct_aspect = options.correct_aspect, + .ignore_pinned = true, + .margin_method = ED_UVPACK_MARGIN_SCALED, + .margin = scene->toolsettings->uvcalc_margin, + }; + ED_uvedit_pack_islands_multi(scene, objects, objects_len, NULL, NULL, &pack_island_params); } } @@ -1926,8 +1914,6 @@ static int unwrap_exec(bContext *C, wmOperator *op) .correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect"), }; - bool rotate = true; - bool ignore_pinned = true; if (CTX_wm_space_image(C)) { /* Inside the UV Editor, only unwrap selected UVs. */ options.only_selected_uvs = true; @@ -2032,7 +2018,18 @@ static int unwrap_exec(bContext *C, wmOperator *op) .count_failed = 0, }; uvedit_unwrap_multi(scene, objects, objects_len, &options, &result_info); - uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned); + + const struct UVPackIsland_Params pack_island_params = { + .rotate = true, + .only_selected_uvs = options.only_selected_uvs, + .only_selected_faces = options.only_selected_faces, + .use_seams = !options.topology_from_uvs || options.topology_from_uvs_use_seams, + .correct_aspect = options.correct_aspect, + .ignore_pinned = true, + .margin_method = RNA_enum_get(op->ptr, "margin_method"), + .margin = RNA_float_get(op->ptr, "margin"), + }; + ED_uvedit_pack_islands_multi(scene, objects, objects_len, NULL, NULL, &pack_island_params); MEM_freeN(objects); -- cgit v1.2.3 From 3411a96e74938afe9b7ffe64e61a225da5f2eb6a Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Wed, 19 Oct 2022 04:02:39 +0200 Subject: Fix T93382: Blender still generates subsurface render passes In T93382, the problem was that the Blender-side rendering code was still generating the subsurface passes because the old render pass flags were set, even though Cycles doesn't generate them anymore. After a closer look, it turns out that the entire hardcoded pass creation code can be removed. We already have an Engine API function to query the list of render passes from the engine, so we might as well just call that and create the returned passes. Turns out that Eevee already did this anyways. On the Cycles side, it allows to deduplicate a lot of `BlenderSync::sync_render_passes`. Before, passes were defined in engine.py and in sync.cpp. Now, all passes that engine.py returns are created automatically, so sync.cpp only needs to handle a few special cases. I'm not really concerned about affecting external renderer addons, since they already needed to handle the old "builtin passes" in their Engine API implementation anyways to make them show up in the compositor. So, unless they missed that for like 10 releases, they should not notice any difference. Differential Revision: https://developer.blender.org/D16295 --- intern/cycles/blender/addon/engine.py | 15 +- intern/cycles/blender/sync.cpp | 206 +++++++++----------------- source/blender/draw/intern/draw_manager.c | 18 --- source/blender/render/intern/engine.cc | 55 +++++-- source/blender/render/intern/render_result.cc | 87 ----------- 5 files changed, 128 insertions(+), 253 deletions(-) diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index 794338fe78e..e33891fa7a2 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -209,22 +209,25 @@ def list_render_passes(scene, srl): yield ("Debug Sample Count", "X", 'VALUE') # Cryptomatte passes. - crypto_depth = (srl.pass_cryptomatte_depth + 1) // 2 + # NOTE: Name channels are lowercase RGBA so that compression rules check in OpenEXR DWA code + # uses lossless compression. Reportedly this naming is the only one which works good from the + # interoperability point of view. Using XYZW naming is not portable. + crypto_depth = (min(16, srl.pass_cryptomatte_depth) + 1) // 2 if srl.use_pass_cryptomatte_object: for i in range(0, crypto_depth): - yield ("CryptoObject" + '{:02d}'.format(i), "RGBA", 'COLOR') + yield ("CryptoObject" + '{:02d}'.format(i), "rgba", 'COLOR') if srl.use_pass_cryptomatte_material: for i in range(0, crypto_depth): - yield ("CryptoMaterial" + '{:02d}'.format(i), "RGBA", 'COLOR') + yield ("CryptoMaterial" + '{:02d}'.format(i), "rgba", 'COLOR') if srl.use_pass_cryptomatte_asset: for i in range(0, crypto_depth): - yield ("CryptoAsset" + '{:02d}'.format(i), "RGBA", 'COLOR') + yield ("CryptoAsset" + '{:02d}'.format(i), "rgba", 'COLOR') # Denoising passes. if scene.cycles.use_denoising and crl.use_denoising: yield ("Noisy Image", "RGBA", 'COLOR') if crl.use_pass_shadow_catcher: - yield ("Noisy Shadow Catcher", "RGBA", 'COLOR') + yield ("Noisy Shadow Catcher", "RGB", 'COLOR') if crl.denoising_store_passes: yield ("Denoising Normal", "XYZ", 'VECTOR') yield ("Denoising Albedo", "RGB", 'COLOR') @@ -232,6 +235,8 @@ def list_render_passes(scene, srl): # Custom AOV passes. for aov in srl.aovs: + if not aov.is_valid: + continue if aov.type == 'VALUE': yield (aov.name, "X", 'VALUE') else: diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp index a69a94614d3..5251f0fee9c 100644 --- a/intern/cycles/blender/sync.cpp +++ b/intern/cycles/blender/sync.cpp @@ -575,68 +575,72 @@ void BlenderSync::sync_images() /* Passes */ -static PassType get_blender_pass_type(BL::RenderPass &b_pass) +static bool get_known_pass_type(BL::RenderPass &b_pass, PassType &type, PassMode &mode) { string name = b_pass.name(); -#define MAP_PASS(passname, passtype) \ +#define MAP_PASS(passname, passtype, noisy) \ if (name == passname) { \ - return passtype; \ + type = passtype; \ + mode = (noisy) ? PassMode::NOISY : PassMode::DENOISED; \ + return true; \ } \ ((void)0) - /* NOTE: Keep in sync with defined names from DNA_scene_types.h */ + /* NOTE: Keep in sync with defined names from engine.py */ - MAP_PASS("Combined", PASS_COMBINED); - MAP_PASS("Noisy Image", PASS_COMBINED); + MAP_PASS("Combined", PASS_COMBINED, false); + MAP_PASS("Noisy Image", PASS_COMBINED, true); - MAP_PASS("Depth", PASS_DEPTH); - MAP_PASS("Mist", PASS_MIST); - MAP_PASS("Position", PASS_POSITION); - MAP_PASS("Normal", PASS_NORMAL); - MAP_PASS("IndexOB", PASS_OBJECT_ID); - MAP_PASS("UV", PASS_UV); - MAP_PASS("Vector", PASS_MOTION); - MAP_PASS("IndexMA", PASS_MATERIAL_ID); + MAP_PASS("Depth", PASS_DEPTH, false); + MAP_PASS("Mist", PASS_MIST, false); + MAP_PASS("Position", PASS_POSITION, false); + MAP_PASS("Normal", PASS_NORMAL, false); + MAP_PASS("IndexOB", PASS_OBJECT_ID, false); + MAP_PASS("UV", PASS_UV, false); + MAP_PASS("Vector", PASS_MOTION, false); + MAP_PASS("IndexMA", PASS_MATERIAL_ID, false); - MAP_PASS("DiffDir", PASS_DIFFUSE_DIRECT); - MAP_PASS("GlossDir", PASS_GLOSSY_DIRECT); - MAP_PASS("TransDir", PASS_TRANSMISSION_DIRECT); - MAP_PASS("VolumeDir", PASS_VOLUME_DIRECT); + MAP_PASS("DiffDir", PASS_DIFFUSE_DIRECT, false); + MAP_PASS("GlossDir", PASS_GLOSSY_DIRECT, false); + MAP_PASS("TransDir", PASS_TRANSMISSION_DIRECT, false); + MAP_PASS("VolumeDir", PASS_VOLUME_DIRECT, false); - MAP_PASS("DiffInd", PASS_DIFFUSE_INDIRECT); - MAP_PASS("GlossInd", PASS_GLOSSY_INDIRECT); - MAP_PASS("TransInd", PASS_TRANSMISSION_INDIRECT); - MAP_PASS("VolumeInd", PASS_VOLUME_INDIRECT); + MAP_PASS("DiffInd", PASS_DIFFUSE_INDIRECT, false); + MAP_PASS("GlossInd", PASS_GLOSSY_INDIRECT, false); + MAP_PASS("TransInd", PASS_TRANSMISSION_INDIRECT, false); + MAP_PASS("VolumeInd", PASS_VOLUME_INDIRECT, false); - MAP_PASS("DiffCol", PASS_DIFFUSE_COLOR); - MAP_PASS("GlossCol", PASS_GLOSSY_COLOR); - MAP_PASS("TransCol", PASS_TRANSMISSION_COLOR); + MAP_PASS("DiffCol", PASS_DIFFUSE_COLOR, false); + MAP_PASS("GlossCol", PASS_GLOSSY_COLOR, false); + MAP_PASS("TransCol", PASS_TRANSMISSION_COLOR, false); - MAP_PASS("Emit", PASS_EMISSION); - MAP_PASS("Env", PASS_BACKGROUND); - MAP_PASS("AO", PASS_AO); - MAP_PASS("Shadow", PASS_SHADOW); + MAP_PASS("Emit", PASS_EMISSION, false); + MAP_PASS("Env", PASS_BACKGROUND, false); + MAP_PASS("AO", PASS_AO, false); + MAP_PASS("Shadow", PASS_SHADOW, false); - MAP_PASS("BakePrimitive", PASS_BAKE_PRIMITIVE); - MAP_PASS("BakeDifferential", PASS_BAKE_DIFFERENTIAL); + MAP_PASS("BakePrimitive", PASS_BAKE_PRIMITIVE, false); + MAP_PASS("BakeDifferential", PASS_BAKE_DIFFERENTIAL, false); - MAP_PASS("Denoising Normal", PASS_DENOISING_NORMAL); - MAP_PASS("Denoising Albedo", PASS_DENOISING_ALBEDO); - MAP_PASS("Denoising Depth", PASS_DENOISING_DEPTH); + MAP_PASS("Denoising Normal", PASS_DENOISING_NORMAL, true); + MAP_PASS("Denoising Albedo", PASS_DENOISING_ALBEDO, true); + MAP_PASS("Denoising Depth", PASS_DENOISING_DEPTH, true); - MAP_PASS("Shadow Catcher", PASS_SHADOW_CATCHER); - MAP_PASS("Noisy Shadow Catcher", PASS_SHADOW_CATCHER); + MAP_PASS("Shadow Catcher", PASS_SHADOW_CATCHER, false); + MAP_PASS("Noisy Shadow Catcher", PASS_SHADOW_CATCHER, true); - MAP_PASS("AdaptiveAuxBuffer", PASS_ADAPTIVE_AUX_BUFFER); - MAP_PASS("Debug Sample Count", PASS_SAMPLE_COUNT); + MAP_PASS("AdaptiveAuxBuffer", PASS_ADAPTIVE_AUX_BUFFER, false); + MAP_PASS("Debug Sample Count", PASS_SAMPLE_COUNT, false); if (string_startswith(name, cryptomatte_prefix)) { - return PASS_CRYPTOMATTE; + type = PASS_CRYPTOMATTE; + mode = PassMode::DENOISED; + return true; } #undef MAP_PASS - return PASS_NONE; + return false; } static Pass *pass_add(Scene *scene, @@ -655,8 +659,6 @@ static Pass *pass_add(Scene *scene, void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_view_layer) { - PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); - /* Delete all existing passes. */ set clear_passes(scene->passes.begin(), scene->passes.end()); scene->delete_nodes(clear_passes); @@ -664,103 +666,23 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v /* Always add combined pass. */ pass_add(scene, PASS_COMBINED, "Combined"); - /* Blender built-in data and light passes. */ - for (BL::RenderPass &b_pass : b_rlay.passes) { - const PassType pass_type = get_blender_pass_type(b_pass); - - if (pass_type == PASS_NONE) { - LOG(ERROR) << "Unknown pass " << b_pass.name(); - continue; - } - - if (pass_type == PASS_MOTION && - (b_view_layer.use_motion_blur() && b_scene.render().use_motion_blur())) { - continue; - } - - pass_add(scene, pass_type, b_pass.name().c_str()); - } - - PointerRNA crl = RNA_pointer_get(&b_view_layer.ptr, "cycles"); - - /* Debug passes. */ - if (get_boolean(crl, "pass_debug_sample_count")) { - b_engine.add_pass("Debug Sample Count", 1, "X", b_view_layer.name().c_str()); - pass_add(scene, PASS_SAMPLE_COUNT, "Debug Sample Count"); - } - - /* Cycles specific passes. */ - if (get_boolean(crl, "use_pass_volume_direct")) { - b_engine.add_pass("VolumeDir", 3, "RGB", b_view_layer.name().c_str()); - pass_add(scene, PASS_VOLUME_DIRECT, "VolumeDir"); - } - if (get_boolean(crl, "use_pass_volume_indirect")) { - b_engine.add_pass("VolumeInd", 3, "RGB", b_view_layer.name().c_str()); - pass_add(scene, PASS_VOLUME_INDIRECT, "VolumeInd"); - } - if (get_boolean(crl, "use_pass_shadow_catcher")) { - b_engine.add_pass("Shadow Catcher", 3, "RGB", b_view_layer.name().c_str()); - pass_add(scene, PASS_SHADOW_CATCHER, "Shadow Catcher"); - } - /* Cryptomatte stores two ID/weight pairs per RGBA layer. - * User facing parameter is the number of pairs. - * - * NOTE: Name channels lowercase RGBA so that compression rules check in OpenEXR DWA code uses - * lossless compression. Reportedly this naming is the only one which works good from the - * interoperability point of view. Using XYZW naming is not portable. */ + * User facing parameter is the number of pairs. */ int crypto_depth = divide_up(min(16, b_view_layer.pass_cryptomatte_depth()), 2); scene->film->set_cryptomatte_depth(crypto_depth); CryptomatteType cryptomatte_passes = CRYPT_NONE; if (b_view_layer.use_pass_cryptomatte_object()) { - for (int i = 0; i < crypto_depth; i++) { - string passname = cryptomatte_prefix + string_printf("Object%02d", i); - b_engine.add_pass(passname.c_str(), 4, "rgba", b_view_layer.name().c_str()); - pass_add(scene, PASS_CRYPTOMATTE, passname.c_str()); - } cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_OBJECT); } if (b_view_layer.use_pass_cryptomatte_material()) { - for (int i = 0; i < crypto_depth; i++) { - string passname = cryptomatte_prefix + string_printf("Material%02d", i); - b_engine.add_pass(passname.c_str(), 4, "rgba", b_view_layer.name().c_str()); - pass_add(scene, PASS_CRYPTOMATTE, passname.c_str()); - } cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_MATERIAL); } if (b_view_layer.use_pass_cryptomatte_asset()) { - for (int i = 0; i < crypto_depth; i++) { - string passname = cryptomatte_prefix + string_printf("Asset%02d", i); - b_engine.add_pass(passname.c_str(), 4, "rgba", b_view_layer.name().c_str()); - pass_add(scene, PASS_CRYPTOMATTE, passname.c_str()); - } cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_ASSET); } scene->film->set_cryptomatte_passes(cryptomatte_passes); - /* Denoising passes. */ - const bool use_denoising = get_boolean(cscene, "use_denoising") && - get_boolean(crl, "use_denoising"); - const bool store_denoising_passes = get_boolean(crl, "denoising_store_passes"); - if (use_denoising) { - b_engine.add_pass("Noisy Image", 4, "RGBA", b_view_layer.name().c_str()); - pass_add(scene, PASS_COMBINED, "Noisy Image", PassMode::NOISY); - if (get_boolean(crl, "use_pass_shadow_catcher")) { - b_engine.add_pass("Noisy Shadow Catcher", 3, "RGB", b_view_layer.name().c_str()); - pass_add(scene, PASS_SHADOW_CATCHER, "Noisy Shadow Catcher", PassMode::NOISY); - } - } - if (store_denoising_passes) { - b_engine.add_pass("Denoising Normal", 3, "XYZ", b_view_layer.name().c_str()); - pass_add(scene, PASS_DENOISING_NORMAL, "Denoising Normal", PassMode::NOISY); - - b_engine.add_pass("Denoising Albedo", 3, "RGB", b_view_layer.name().c_str()); - pass_add(scene, PASS_DENOISING_ALBEDO, "Denoising Albedo", PassMode::NOISY); - - b_engine.add_pass("Denoising Depth", 1, "Z", b_view_layer.name().c_str()); - pass_add(scene, PASS_DENOISING_DEPTH, "Denoising Depth", PassMode::NOISY); - } - + /* Path guiding debug passes. */ #ifdef WITH_CYCLES_DEBUG b_engine.add_pass("Guiding Color", 3, "RGB", b_view_layer.name().c_str()); pass_add(scene, PASS_GUIDING_COLOR, "Guiding Color", PassMode::NOISY); @@ -772,6 +694,8 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v pass_add(scene, PASS_GUIDING_AVG_ROUGHNESS, "Guiding Average Roughness", PassMode::NOISY); #endif + unordered_set expected_passes; + /* Custom AOV passes. */ BL::ViewLayer::aovs_iterator b_aov_iter; for (b_view_layer.aovs.begin(b_aov_iter); b_aov_iter != b_view_layer.aovs.end(); ++b_aov_iter) { @@ -781,16 +705,10 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v } string name = b_aov.name(); - bool is_color = b_aov.type() == BL::AOV::type_COLOR; + PassType type = (b_aov.type() == BL::AOV::type_COLOR) ? PASS_AOV_COLOR : PASS_AOV_VALUE; - if (is_color) { - b_engine.add_pass(name.c_str(), 4, "RGBA", b_view_layer.name().c_str()); - pass_add(scene, PASS_AOV_COLOR, name.c_str()); - } - else { - b_engine.add_pass(name.c_str(), 1, "X", b_view_layer.name().c_str()); - pass_add(scene, PASS_AOV_VALUE, name.c_str()); - } + pass_add(scene, type, name.c_str()); + expected_passes.insert(name); } /* Light Group passes. */ @@ -802,9 +720,29 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v string name = string_printf("Combined_%s", b_lightgroup.name().c_str()); - b_engine.add_pass(name.c_str(), 3, "RGB", b_view_layer.name().c_str()); Pass *pass = pass_add(scene, PASS_COMBINED, name.c_str(), PassMode::NOISY); pass->set_lightgroup(ustring(b_lightgroup.name())); + expected_passes.insert(name); + } + + /* Sync the passes that were defined in engine.py. */ + for (BL::RenderPass &b_pass : b_rlay.passes) { + PassType pass_type = PASS_NONE; + PassMode pass_mode = PassMode::DENOISED; + + if (!get_known_pass_type(b_pass, pass_type, pass_mode)) { + if (!expected_passes.count(b_pass.name())) { + LOG(ERROR) << "Unknown pass " << b_pass.name(); + } + continue; + } + + if (pass_type == PASS_MOTION && + (b_view_layer.use_motion_blur() && b_scene.render().use_motion_blur())) { + continue; + } + + pass_add(scene, pass_type, b_pass.name().c_str(), pass_mode); } scene->film->set_pass_alpha_threshold(b_view_layer.pass_alpha_threshold()); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index da77845feb4..b9a9780e651 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1959,20 +1959,6 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph DST.buffer_finish_called = false; } -/* Callback function for RE_engine_update_render_passes to ensure all - * render passes are registered. */ -static void draw_render_result_ensure_pass_cb(void *user_data, - struct Scene *UNUSED(scene), - struct ViewLayer *view_layer, - const char *name, - int channels, - const char *chanid, - eNodeSocketDatatype UNUSED(type)) -{ - RenderEngine *engine = user_data; - RE_engine_add_pass(engine, name, channels, chanid, view_layer->name); -} - void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) { Scene *scene = DEG_get_evaluated_scene(depsgraph); @@ -2023,10 +2009,6 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) /* set default viewport */ GPU_viewport(0, 0, size[0], size[1]); - /* Update the render passes. This needs to be done before acquiring the render result. */ - RE_engine_update_render_passes( - engine, scene, view_layer, draw_render_result_ensure_pass_cb, engine); - /* Init render result. */ RenderResult *render_result = RE_engine_begin_result(engine, 0, diff --git a/source/blender/render/intern/engine.cc b/source/blender/render/intern/engine.cc index 5eb4db6faa4..b8757d33580 100644 --- a/source/blender/render/intern/engine.cc +++ b/source/blender/render/intern/engine.cc @@ -969,6 +969,40 @@ static void engine_render_view_layer(Render *re, engine_depsgraph_exit(engine); } +/* Callback function for engine_render_create_result to add all render passes to the result. */ +static void engine_render_add_result_pass_cb(void *user_data, + struct Scene *UNUSED(scene), + struct ViewLayer *view_layer, + const char *name, + int channels, + const char *chanid, + eNodeSocketDatatype UNUSED(type)) +{ + RenderResult *rr = (RenderResult *)user_data; + RE_create_render_pass(rr, name, channels, chanid, view_layer->name, RR_ALL_VIEWS, false); +} + +static RenderResult *engine_render_create_result(Render *re) +{ + RenderResult *rr = render_result_new(re, &re->disprect, RR_ALL_LAYERS, RR_ALL_VIEWS); + if (rr == nullptr) { + return nullptr; + } + + FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer) { + RE_engine_update_render_passes( + re->engine, re->scene, view_layer, engine_render_add_result_pass_cb, rr); + } + FOREACH_VIEW_LAYER_TO_RENDER_END; + + /* Preview does not support deferred render result allocation. */ + if (re->r.scemode & R_BUTS_PREVIEW) { + render_result_passes_allocated_ensure(rr); + } + + return rr; +} + bool RE_engine_render(Render *re, bool do_all) { RenderEngineType *type = RE_engines_find(re->r.engine); @@ -1008,6 +1042,14 @@ bool RE_engine_render(Render *re, bool do_all) render_update_anim_renderdata(re, &re->scene->r, &re->scene->view_layers); } + /* Create engine. */ + RenderEngine *engine = re->engine; + + if (!engine) { + engine = RE_engine_create(type); + re->engine = engine; + } + /* create render result */ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if (re->result == nullptr || !(re->r.scemode & R_BUTS_PREVIEW)) { @@ -1015,7 +1057,7 @@ bool RE_engine_render(Render *re, bool do_all) render_result_free(re->result); } - re->result = render_result_new(re, &re->disprect, RR_ALL_LAYERS, RR_ALL_VIEWS); + re->result = engine_render_create_result(re); } BLI_rw_mutex_unlock(&re->resultmutex); @@ -1024,6 +1066,9 @@ bool RE_engine_render(Render *re, bool do_all) if (re->draw_lock) { re->draw_lock(re->dlh, false); } + /* Free engine. */ + RE_engine_free(engine); + re->engine = nullptr; /* Too small image is handled earlier, here it could only happen if * there was no sufficient memory to allocate all passes. */ @@ -1036,14 +1081,6 @@ bool RE_engine_render(Render *re, bool do_all) re->i.cfra = re->scene->r.cfra; BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name)); - /* render */ - RenderEngine *engine = re->engine; - - if (!engine) { - engine = RE_engine_create(type); - re->engine = engine; - } - engine->flag |= RE_ENGINE_RENDERING; /* TODO: actually link to a parent which shouldn't happen */ diff --git a/source/blender/render/intern/render_result.cc b/source/blender/render/intern/render_result.cc index bd5c6a0f5c4..f9524fdbf05 100644 --- a/source/blender/render/intern/render_result.cc +++ b/source/blender/render/intern/render_result.cc @@ -290,90 +290,8 @@ RenderResult *render_result_new(Render *re, } } -#define RENDER_LAYER_ADD_PASS_SAFE(rr, rl, channels, name, viewname, chan_id) \ - do { \ - if (render_layer_add_pass(rr, rl, channels, name, viewname, chan_id, false) == nullptr) { \ - render_result_free(rr); \ - return nullptr; \ - } \ - } while (false) - /* A render-layer should always have a "Combined" pass. */ render_layer_add_pass(rr, rl, 4, "Combined", view, "RGBA", false); - - if (view_layer->passflag & SCE_PASS_Z) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_Z, view, "Z"); - } - if (view_layer->passflag & SCE_PASS_VECTOR) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_VECTOR, view, "XYZW"); - } - if (view_layer->passflag & SCE_PASS_NORMAL) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_NORMAL, view, "XYZ"); - } - if (view_layer->passflag & SCE_PASS_POSITION) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_POSITION, view, "XYZ"); - } - if (view_layer->passflag & SCE_PASS_UV) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_UV, view, "UVA"); - } - if (view_layer->passflag & SCE_PASS_EMIT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_EMIT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_AO) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_AO, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_ENVIRONMENT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_ENVIRONMENT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_SHADOW) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SHADOW, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_INDEXOB) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXOB, view, "X"); - } - if (view_layer->passflag & SCE_PASS_INDEXMA) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXMA, view, "X"); - } - if (view_layer->passflag & SCE_PASS_MIST) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_MIST, view, "Z"); - } - if (view_layer->passflag & SCE_PASS_DIFFUSE_DIRECT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_DIRECT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_DIFFUSE_INDIRECT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_INDIRECT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_DIFFUSE_COLOR) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_COLOR, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_GLOSSY_DIRECT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_DIRECT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_GLOSSY_INDIRECT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_INDIRECT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_GLOSSY_COLOR) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_COLOR, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_TRANSM_DIRECT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_DIRECT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_TRANSM_INDIRECT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_INDIRECT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_TRANSM_COLOR) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_COLOR, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_SUBSURFACE_DIRECT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_DIRECT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_SUBSURFACE_INDIRECT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_INDIRECT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_SUBSURFACE_COLOR) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_COLOR, view, "RGB"); - } -#undef RENDER_LAYER_ADD_PASS_SAFE } } FOREACH_VIEW_LAYER_TO_RENDER_END; @@ -411,11 +329,6 @@ RenderResult *render_result_new(Render *re, rr->xof = re->disprect.xmin + BLI_rcti_cent_x(&re->disprect) - (re->winx / 2); rr->yof = re->disprect.ymin + BLI_rcti_cent_y(&re->disprect) - (re->winy / 2); - /* Preview does not support deferred render result allocation. */ - if (re->r.scemode & R_BUTS_PREVIEW) { - render_result_passes_allocated_ensure(rr); - } - return rr; } -- cgit v1.2.3 From 3915f5300ad2d2a3c12a8bb67bb97f60160953e7 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sun, 16 Oct 2022 00:57:09 +0200 Subject: Fix T99151: Cycles not updating on Object Type visibility change Differential Revision: https://developer.blender.org/D16259 --- source/blender/makesrna/intern/rna_internal.h | 4 +++- source/blender/makesrna/intern/rna_space.c | 10 +++++++++- source/blender/makesrna/intern/rna_space_api.c | 6 ++++-- source/blender/makesrna/intern/rna_xr.c | 2 +- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 8e652753ec0..ea829e5cd86 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -322,7 +322,9 @@ void rna_object_vcollayer_name_set(struct PointerRNA *ptr, PointerRNA rna_object_shapekey_index_get(struct ID *id, int value); int rna_object_shapekey_index_set(struct ID *id, PointerRNA value, int current); -void rna_def_object_type_visibility_flags_common(StructRNA *srna, int noteflag); +void rna_def_object_type_visibility_flags_common(StructRNA *srna, + int noteflag, + const char *update_func); int rna_object_type_visibility_icon_get_common(int object_type_exclude_viewport, const int *object_type_exclude_select); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 5c192b80dc1..b2663b89333 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -990,6 +990,13 @@ static PointerRNA rna_SpaceView3D_region_3d_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_RegionView3D, regiondata); } +static void rna_SpaceView3D_object_type_visibility_update(Main *UNUSED(bmain), + Scene *scene, + PointerRNA *UNUSED(ptr)) +{ + DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); +} + static void rna_SpaceView3D_region_quadviews_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { @@ -5086,7 +5093,8 @@ static void rna_def_space_view3d(BlenderRNA *brna) prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_mirror_xr_session_update"); rna_def_object_type_visibility_flags_common(srna, - NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING); + NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, + "rna_SpaceView3D_object_type_visibility_update"); /* Helper for drawing the icon. */ prop = RNA_def_property(srna, "icon_from_show_object_viewport", PROP_INT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_space_api.c b/source/blender/makesrna/intern/rna_space_api.c index b3896919275..9790a85e1c8 100644 --- a/source/blender/makesrna/intern/rna_space_api.c +++ b/source/blender/makesrna/intern/rna_space_api.c @@ -119,7 +119,9 @@ void RNA_api_space_text(StructRNA *srna) RNA_def_function_output(func, parm); } -void rna_def_object_type_visibility_flags_common(StructRNA *srna, int noteflag) +void rna_def_object_type_visibility_flags_common(StructRNA *srna, + int noteflag, + const char *update_func) { PropertyRNA *prop; @@ -173,7 +175,7 @@ void rna_def_object_type_visibility_flags_common(StructRNA *srna, int noteflag) RNA_def_property_boolean_negative_sdna( prop, NULL, view_mask_member[mask_index], info[type_index].type_mask); RNA_def_property_ui_text(prop, info[type_index].name, ""); - RNA_def_property_update(prop, noteflag, NULL); + RNA_def_property_update(prop, noteflag, update_func); } } } diff --git a/source/blender/makesrna/intern/rna_xr.c b/source/blender/makesrna/intern/rna_xr.c index dcfa1bbca51..c803e5dc9a8 100644 --- a/source/blender/makesrna/intern/rna_xr.c +++ b/source/blender/makesrna/intern/rna_xr.c @@ -2052,7 +2052,7 @@ static void rna_def_xr_session_settings(BlenderRNA *brna) "Allow the VR tracking origin to be defined independently of the headset location"); RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL); - rna_def_object_type_visibility_flags_common(srna, NC_WM | ND_XR_DATA_CHANGED); + rna_def_object_type_visibility_flags_common(srna, NC_WM | ND_XR_DATA_CHANGED, NULL); /* Helper for drawing the icon. */ prop = RNA_def_property(srna, "icon_from_show_object_viewport", PROP_INT, PROP_NONE); -- cgit v1.2.3 From e2a93e9c7c5fece5ea7d46da949694ad2eca872e Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Thu, 20 Oct 2022 04:38:50 +0200 Subject: Fix T94136: Cycles: No Hair Shadows with Transparent BSDF --- intern/cycles/kernel/bvh/shadow_all.h | 2 +- intern/cycles/kernel/bvh/util.h | 8 +++----- intern/cycles/kernel/device/cpu/bvh.h | 2 +- intern/cycles/kernel/device/metal/kernel.metal | 2 +- intern/cycles/kernel/device/optix/bvh.h | 2 +- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/intern/cycles/kernel/bvh/shadow_all.h b/intern/cycles/kernel/bvh/shadow_all.h index 2ffe1496c72..b31ba479e4f 100644 --- a/intern/cycles/kernel/bvh/shadow_all.h +++ b/intern/cycles/kernel/bvh/shadow_all.h @@ -229,7 +229,7 @@ ccl_device_inline /* Always use baked shadow transparency for curves. */ if (isect.type & PRIMITIVE_CURVE) { *r_throughput *= intersection_curve_shadow_transparency( - kg, isect.object, isect.prim, isect.u); + kg, isect.object, isect.prim, isect.type, isect.u); if (*r_throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) { return true; diff --git a/intern/cycles/kernel/bvh/util.h b/intern/cycles/kernel/bvh/util.h index a57703a8b8c..9ba787550c5 100644 --- a/intern/cycles/kernel/bvh/util.h +++ b/intern/cycles/kernel/bvh/util.h @@ -190,10 +190,8 @@ ccl_device_inline int intersection_find_attribute(KernelGlobals kg, /* Cut-off value to stop transparent shadow tracing when practically opaque. */ #define CURVE_SHADOW_TRANSPARENCY_CUTOFF 0.001f -ccl_device_inline float intersection_curve_shadow_transparency(KernelGlobals kg, - const int object, - const int prim, - const float u) +ccl_device_inline float intersection_curve_shadow_transparency( + KernelGlobals kg, const int object, const int prim, const int type, const float u) { /* Find attribute. */ const int offset = intersection_find_attribute(kg, object, ATTR_STD_SHADOW_TRANSPARENCY); @@ -204,7 +202,7 @@ ccl_device_inline float intersection_curve_shadow_transparency(KernelGlobals kg, /* Interpolate transparency between curve keys. */ const KernelCurve kcurve = kernel_data_fetch(curves, prim); - const int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(kcurve.type); + const int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(type); const int k1 = k0 + 1; const float f0 = kernel_data_fetch(attributes_float, offset + k0); diff --git a/intern/cycles/kernel/device/cpu/bvh.h b/intern/cycles/kernel/device/cpu/bvh.h index d9267e1cd6d..2d7d8c2d704 100644 --- a/intern/cycles/kernel/device/cpu/bvh.h +++ b/intern/cycles/kernel/device/cpu/bvh.h @@ -252,7 +252,7 @@ ccl_device void kernel_embree_filter_occluded_func(const RTCFilterFunctionNArgum /* Always use baked shadow transparency for curves. */ if (current_isect.type & PRIMITIVE_CURVE) { ctx->throughput *= intersection_curve_shadow_transparency( - kg, current_isect.object, current_isect.prim, current_isect.u); + kg, current_isect.object, current_isect.prim, current_isect.type, current_isect.u); if (ctx->throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) { ctx->opaque_hit = true; diff --git a/intern/cycles/kernel/device/metal/kernel.metal b/intern/cycles/kernel/device/metal/kernel.metal index 5646c7446db..8b69ee025cd 100644 --- a/intern/cycles/kernel/device/metal/kernel.metal +++ b/intern/cycles/kernel/device/metal/kernel.metal @@ -228,7 +228,7 @@ bool metalrt_shadow_all_hit(constant KernelParamsMetal &launch_params_metal, /* Always use baked shadow transparency for curves. */ if (type & PRIMITIVE_CURVE) { float throughput = payload.throughput; - throughput *= context.intersection_curve_shadow_transparency(nullptr, object, prim, u); + throughput *= context.intersection_curve_shadow_transparency(nullptr, object, prim, type, u); payload.throughput = throughput; payload.num_hits += 1; diff --git a/intern/cycles/kernel/device/optix/bvh.h b/intern/cycles/kernel/device/optix/bvh.h index fb9907709ce..6d81b44660c 100644 --- a/intern/cycles/kernel/device/optix/bvh.h +++ b/intern/cycles/kernel/device/optix/bvh.h @@ -202,7 +202,7 @@ extern "C" __global__ void __anyhit__kernel_optix_shadow_all_hit() /* Always use baked shadow transparency for curves. */ if (type & PRIMITIVE_CURVE) { float throughput = __uint_as_float(optixGetPayload_1()); - throughput *= intersection_curve_shadow_transparency(nullptr, object, prim, u); + throughput *= intersection_curve_shadow_transparency(nullptr, object, prim, type, u); optixSetPayload_1(__float_as_uint(throughput)); optixSetPayload_2(uint16_pack_to_uint(num_recorded_hits, num_hits + 1)); -- cgit v1.2.3 From c58d6b30add69fc3c6004d2ad2a590d7d44cc83b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 13:51:33 +1100 Subject: GHOST/Wayland: correct assert from recent commit Error in [0], only clear the stored clipboard data source pointer if it matches the data being cleared. [0]: 09e3ea49dbbec15a8fcc79cc609f6dc8c13bc91f --- intern/ghost/intern/GHOST_SystemWayland.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 5c3f807d678..4b3f3ec5ef2 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1284,8 +1284,9 @@ static void data_source_handle_cancelled(void *data, struct wl_data_source *wl_d CLOG_INFO(LOG, 2, "cancelled"); GWL_Seat *seat = static_cast(data); GWL_DataSource *data_source = seat->data_source; - GHOST_ASSERT(seat->data_source->wl_data_source == wl_data_source, "Data source mismatch!"); - data_source->wl_data_source = nullptr; + if (seat->data_source->wl_data_source == wl_data_source) { + data_source->wl_data_source = nullptr; + } wl_data_source_destroy(wl_data_source); } -- cgit v1.2.3 From f24dfdcd3cbd454ec62ef55f13ece4098b3fdda4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 13:53:34 +1100 Subject: Cleanup: format --- intern/cycles/device/metal/device_impl.mm | 4 ++-- intern/cycles/device/metal/util.mm | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/intern/cycles/device/metal/device_impl.mm b/intern/cycles/device/metal/device_impl.mm index 4ec0ea065ab..4b929b6bc0a 100644 --- a/intern/cycles/device/metal/device_impl.mm +++ b/intern/cycles/device/metal/device_impl.mm @@ -339,13 +339,13 @@ bool MetalDevice::compile_and_load(MetalPipelineType pso_type) MTLCompileOptions *options = [[MTLCompileOptions alloc] init]; -#if defined(MAC_OS_VERSION_13_0) +# if defined(MAC_OS_VERSION_13_0) if (@available(macos 13.0, *)) { if (device_vendor == METAL_GPU_INTEL) { [options setOptimizationLevel:MTLLibraryOptimizationLevelSize]; } } -#endif +# endif options.fastMathEnabled = YES; if (@available(macOS 12.0, *)) { diff --git a/intern/cycles/device/metal/util.mm b/intern/cycles/device/metal/util.mm index 63f84a9df33..f47638fac15 100644 --- a/intern/cycles/device/metal/util.mm +++ b/intern/cycles/device/metal/util.mm @@ -110,11 +110,11 @@ vector> const &MetalInfo::get_usable_devices() usable |= (vendor == METAL_GPU_AMD); } -#if defined(MAC_OS_VERSION_13_0) +# if defined(MAC_OS_VERSION_13_0) if (@available(macos 13.0, *)) { usable |= (vendor == METAL_GPU_INTEL); } -#endif +# endif if (usable) { metal_printf("- %s\n", device_name.c_str()); -- cgit v1.2.3 From d392e9afea569d4be065a31b208427e255cf1f8d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 13:55:34 +1100 Subject: Cleanup: correct prefix for internal wayland utility function --- intern/ghost/intern/GHOST_SystemWayland.cpp | 40 ++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 4b3f3ec5ef2..a307dabb690 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -391,16 +391,16 @@ struct GWL_SeatStateKeyboard { * * Needed as #GWL_Seat.xkb_state doesn't store which modifier keys are held. */ -struct WGL_KeyboardDepressedState { +struct GWL_KeyboardDepressedState { int16_t mods[GHOST_KEY_MODIFIER_NUM] = {0}; }; #ifdef WITH_GHOST_WAYLAND_LIBDECOR -struct WGL_LibDecor_System { +struct GWL_LibDecor_System { struct libdecor *context = nullptr; }; -static void wgl_libdecor_system_destroy(WGL_LibDecor_System *decor) +static void gwl_libdecor_system_destroy(GWL_LibDecor_System *decor) { if (decor->context) { libdecor_unref(decor->context); @@ -409,12 +409,12 @@ static void wgl_libdecor_system_destroy(WGL_LibDecor_System *decor) } #endif -struct WGL_XDG_Decor_System { +struct GWL_XDG_Decor_System { struct xdg_wm_base *shell = nullptr; struct zxdg_decoration_manager_v1 *manager = nullptr; }; -static void wgl_xdg_decor_system_destroy(WGL_XDG_Decor_System *decor) +static void gwl_xdg_decor_system_destroy(GWL_XDG_Decor_System *decor) { if (decor->manager) { zxdg_decoration_manager_v1_destroy(decor->manager); @@ -475,7 +475,7 @@ struct GWL_Seat { struct xkb_state *xkb_state_empty_with_numlock = nullptr; /** Keys held matching `xkb_state`. */ - struct WGL_KeyboardDepressedState key_depressed; + struct GWL_KeyboardDepressedState key_depressed; #ifdef USE_GNOME_KEYBOARD_SUPPRESS_WARNING struct { @@ -525,10 +525,10 @@ struct GWL_Display { struct wl_compositor *wl_compositor = nullptr; #ifdef WITH_GHOST_WAYLAND_LIBDECOR - WGL_LibDecor_System *libdecor = nullptr; + GWL_LibDecor_System *libdecor = nullptr; bool libdecor_required = false; #endif - WGL_XDG_Decor_System *xdg_decor = nullptr; + GWL_XDG_Decor_System *xdg_decor = nullptr; struct zxdg_output_manager_v1 *xdg_output_manager = nullptr; struct wl_shm *wl_shm = nullptr; @@ -702,14 +702,14 @@ static void display_destroy(GWL_Display *display) #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { if (display->libdecor) { - wgl_libdecor_system_destroy(display->libdecor); + gwl_libdecor_system_destroy(display->libdecor); } } else #endif { if (display->xdg_decor) { - wgl_xdg_decor_system_destroy(display->xdg_decor); + gwl_xdg_decor_system_destroy(display->xdg_decor); } } @@ -1082,7 +1082,7 @@ static void keyboard_depressed_state_key_event(GWL_Seat *seat, } static void keyboard_depressed_state_push_events_from_change( - GWL_Seat *seat, const WGL_KeyboardDepressedState &key_depressed_prev) + GWL_Seat *seat, const GWL_KeyboardDepressedState &key_depressed_prev) { GHOST_IWindow *win = ghost_wl_surface_user_data(seat->keyboard.wl_surface); GHOST_SystemWayland *system = seat->system; @@ -2576,7 +2576,7 @@ static void keyboard_handle_enter(void *data, /* If there are any keys held when activating the window, * modifiers will be compared against the seat state, * only enabling modifiers that were previously disabled. */ - WGL_KeyboardDepressedState key_depressed_prev = seat->key_depressed; + GWL_KeyboardDepressedState key_depressed_prev = seat->key_depressed; keyboard_depressed_state_reset(seat); uint32_t *key; @@ -3231,13 +3231,13 @@ static void global_handle_add(void *data, wl_registry_bind(wl_registry, name, &wl_compositor_interface, 3)); } else if (STREQ(interface, xdg_wm_base_interface.name)) { - WGL_XDG_Decor_System &decor = *display->xdg_decor; + GWL_XDG_Decor_System &decor = *display->xdg_decor; decor.shell = static_cast( wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1)); xdg_wm_base_add_listener(decor.shell, &shell_listener, nullptr); } else if (STREQ(interface, zxdg_decoration_manager_v1_interface.name)) { - WGL_XDG_Decor_System &decor = *display->xdg_decor; + GWL_XDG_Decor_System &decor = *display->xdg_decor; decor.manager = static_cast( wl_registry_bind(wl_registry, name, &zxdg_decoration_manager_v1_interface, 1)); } @@ -3361,7 +3361,7 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di } /* This may be removed later if decorations are required, needed as part of registration. */ - display_->xdg_decor = new WGL_XDG_Decor_System; + display_->xdg_decor = new GWL_XDG_Decor_System; /* Register interfaces. */ struct wl_registry *registry = wl_display_get_registry(display_->wl_display); @@ -3374,7 +3374,7 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (display_->libdecor_required) { - wgl_xdg_decor_system_destroy(display_->xdg_decor); + gwl_xdg_decor_system_destroy(display_->xdg_decor); display_->xdg_decor = nullptr; if (!has_libdecor) { @@ -3395,8 +3395,8 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { - display_->libdecor = new WGL_LibDecor_System; - WGL_LibDecor_System &decor = *display_->libdecor; + display_->libdecor = new GWL_LibDecor_System; + GWL_LibDecor_System &decor = *display_->libdecor; decor.context = libdecor_new(display_->wl_display, &libdecor_interface); if (!decor.context) { display_destroy(display_); @@ -3406,7 +3406,7 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di else #endif { - WGL_XDG_Decor_System &decor = *display_->xdg_decor; + GWL_XDG_Decor_System &decor = *display_->xdg_decor; if (!decor.shell) { display_destroy(display_); throw std::runtime_error("Wayland: unable to access xdg_shell!"); @@ -3505,7 +3505,7 @@ GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) co } #endif - /* Use local #WGL_KeyboardDepressedState to check which key is pressed. + /* Use local #GWL_KeyboardDepressedState to check which key is pressed. * Use XKB as the source of truth, if there is any discrepancy. */ for (int i = 0; i < MOD_INDEX_NUM; i++) { if (UNLIKELY(seat->xkb_keymap_mod_index[i] == XKB_MOD_INVALID)) { -- cgit v1.2.3 From 1e1b9eef1b1a424a1e9c0e53cf7a19db053b1f0c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 13:56:40 +1100 Subject: GHOST/Wayland: skip redundant strlen() sending the clipboard --- intern/ghost/intern/GHOST_SystemWayland.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index a307dabb690..b8b9fda8f74 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -293,6 +293,7 @@ struct GWL_DataOffer { struct GWL_DataSource { struct wl_data_source *wl_data_source = nullptr; char *buffer_out = nullptr; + size_t buffer_out_len = 0; }; /** @@ -1273,7 +1274,7 @@ static void data_source_handle_send(void *data, CLOG_INFO(LOG, 2, "send"); const char *const buffer = seat->data_source->buffer_out; - if (write(fd, buffer, strlen(buffer)) < 0) { + if (write(fd, buffer, seat->data_source->buffer_out_len) < 0) { GHOST_PRINT("error writing to clipboard: " << std::strerror(errno) << std::endl); } close(fd); @@ -3584,9 +3585,9 @@ void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) c /* Copy buffer. */ free(data_source->buffer_out); - const size_t buffer_size = strlen(buffer) + 1; - data_source->buffer_out = static_cast(malloc(buffer_size)); - std::memcpy(data_source->buffer_out, buffer, buffer_size); + data_source->buffer_out_len = strlen(buffer); + data_source->buffer_out = static_cast(malloc(data_source->buffer_out_len)); + std::memcpy(data_source->buffer_out, buffer, data_source->buffer_out_len); data_source->wl_data_source = wl_data_device_manager_create_data_source( display_->data_device_manager); -- cgit v1.2.3 From b0eff51fb73cfd9def696e3ede5ff23817f35784 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 14:02:32 +1100 Subject: GHOST/Wayland: primary clipboard support Match X11's primary clipboard support (typically used for MMB to paste the previous selection). --- intern/ghost/CMakeLists.txt | 4 + intern/ghost/intern/GHOST_SystemWayland.cpp | 341 +++++++++++++++++++++++++++- intern/ghost/intern/GHOST_SystemWayland.h | 3 + 3 files changed, 341 insertions(+), 7 deletions(-) diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 72621648608..c05f2a327b1 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -376,6 +376,10 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND) generate_protocol_bindings( "${WAYLAND_PROTOCOLS_DIR}/unstable/tablet/tablet-unstable-v2.xml" ) + # Primary-selection. + generate_protocol_bindings( + "${WAYLAND_PROTOCOLS_DIR}/unstable/primary-selection/primary-selection-unstable-v1.xml" + ) add_definitions(-DWITH_GHOST_WAYLAND) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index b8b9fda8f74..6db8b9d33f8 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -51,6 +51,7 @@ /* Generated by `wayland-scanner`. */ #include +#include #include #include #include @@ -426,6 +427,53 @@ static void gwl_xdg_decor_system_destroy(GWL_XDG_Decor_System *decor) delete decor; } +struct GWL_PrimarySelection_DataOffer { + struct zwp_primary_selection_offer_v1 *id = nullptr; + std::atomic in_use = false; + + std::unordered_set types; +}; + +struct GWL_PrimarySelection_DataSource { + struct zwp_primary_selection_source_v1 *wl_source = nullptr; + char *buffer_out = nullptr; + size_t buffer_out_len = 0; +}; + +/** Primary selection support. */ +struct GWL_PrimarySelection { + + GWL_PrimarySelection_DataSource *data_source = nullptr; + std::mutex data_source_mutex; + + GWL_PrimarySelection_DataOffer *data_offer = nullptr; + std::mutex data_offer_mutex; +}; + +static void gwl_primary_selection_discard_offer(GWL_PrimarySelection *primary) +{ + if (primary->data_offer == nullptr) { + return; + } + zwp_primary_selection_offer_v1_destroy(primary->data_offer->id); + delete primary->data_offer; + primary->data_offer = nullptr; +} + +static void gwl_primary_selection_discard_source(GWL_PrimarySelection *primary) +{ + GWL_PrimarySelection_DataSource *data_source = primary->data_source; + if (data_source == nullptr) { + return; + } + free(data_source->buffer_out); + if (data_source->wl_source) { + zwp_primary_selection_source_v1_destroy(data_source->wl_source); + } + delete primary->data_source; + primary->data_source = nullptr; +} + struct GWL_Seat { GHOST_SystemWayland *system = nullptr; @@ -515,6 +563,9 @@ struct GWL_Seat { struct GWL_DataSource *data_source = nullptr; std::mutex data_source_mutex; + struct zwp_primary_selection_device_v1 *primary_selection_device = nullptr; + struct GWL_PrimarySelection primary_selection; + /** Last device that was active. */ uint32_t data_source_serial = 0; }; @@ -540,6 +591,8 @@ struct GWL_Display { struct zwp_tablet_manager_v2 *tablet_manager = nullptr; struct zwp_relative_pointer_manager_v1 *relative_pointer_manager = nullptr; struct zwp_pointer_constraints_v1 *pointer_constraints = nullptr; + + struct zwp_primary_selection_device_manager_v1 *primary_selection_device_manager = nullptr; }; #undef LOG @@ -642,6 +695,22 @@ static void display_destroy(GWL_Display *display) } } + { + GWL_PrimarySelection *primary = &seat->primary_selection; + std::lock_guard lock{primary->data_offer_mutex}; + gwl_primary_selection_discard_offer(primary); + } + + { + GWL_PrimarySelection *primary = &seat->primary_selection; + std::lock_guard lock{primary->data_source_mutex}; + gwl_primary_selection_discard_source(primary); + } + + if (seat->primary_selection_device) { + zwp_primary_selection_device_v1_destroy(seat->primary_selection_device); + } + if (seat->data_device) { wl_data_device_release(seat->data_device); } @@ -696,6 +765,10 @@ static void display_destroy(GWL_Display *display) zwp_pointer_constraints_v1_destroy(display->pointer_constraints); } + if (display->primary_selection_device_manager) { + zwp_primary_selection_device_manager_v1_destroy(display->primary_selection_device_manager); + } + if (display->wl_compositor) { wl_compositor_destroy(display->wl_compositor); } @@ -1250,6 +1323,35 @@ static std::string read_pipe(GWL_DataOffer *data_offer, return data; } +static std::string read_pipe_primary(GWL_PrimarySelection_DataOffer *data_offer, + const std::string mime_receive, + std::mutex *mutex) +{ + int pipefd[2]; + if (UNLIKELY(pipe(pipefd) != 0)) { + return {}; + } + zwp_primary_selection_offer_v1_receive(data_offer->id, mime_receive.c_str(), pipefd[1]); + close(pipefd[1]); + + data_offer->in_use.store(false); + + if (mutex) { + mutex->unlock(); + } + /* WARNING: `data_offer_base` may be freed from now on. */ + + std::string data; + ssize_t len; + char buffer[4096]; + while ((len = read(pipefd[0], buffer, sizeof(buffer))) > 0) { + data.insert(data.end(), buffer, buffer + len); + } + close(pipefd[0]); + + return data; +} + /** * A target accepts an offered mime type. * @@ -2880,6 +2982,158 @@ static const struct wl_keyboard_listener keyboard_listener = { /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Listener (Primary Selection Offer), #zwp_primary_selection_offer_v1_listener + * \{ */ + +static CLG_LogRef LOG_WL_PRIMARY_SELECTION_OFFER = {"ghost.wl.handle.primary_selection_offer"}; +#define LOG (&LOG_WL_PRIMARY_SELECTION_OFFER) + +static void primary_selection_offer_offer(void *data, + struct zwp_primary_selection_offer_v1 *id, + const char *type) +{ + GWL_PrimarySelection_DataOffer *data_offer = static_cast(data); + if (data_offer->id != id) { + CLOG_INFO(LOG, 2, "offer: %p: offer for unknown selection %p of %s (skipped)", data, id, type); + return; + } + + data_offer->types.insert(std::string(type)); +} + +static const struct zwp_primary_selection_offer_v1_listener primary_selection_offer_listener = { + primary_selection_offer_offer, +}; + +#undef LOG + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Listener (Primary Selection Device), #zwp_primary_selection_device_v1_listener + * \{ */ + +static CLG_LogRef LOG_WL_PRIMARY_SELECTION_DEVICE = {"ghost.wl.handle.primary_selection_device"}; +#define LOG (&LOG_WL_PRIMARY_SELECTION_DEVICE) + +static void primary_selection_device_handle_data_offer( + void * /*data*/, + struct zwp_primary_selection_device_v1 * /*zwp_primary_selection_device_v1*/, + struct zwp_primary_selection_offer_v1 *id) +{ + CLOG_INFO(LOG, 2, "data_offer"); + + GWL_PrimarySelection_DataOffer *data_offer = new GWL_PrimarySelection_DataOffer; + data_offer->id = id; + zwp_primary_selection_offer_v1_add_listener(id, &primary_selection_offer_listener, data_offer); +} + +static void primary_selection_device_handle_selection( + void *data, + struct zwp_primary_selection_device_v1 * /*zwp_primary_selection_device_v1*/, + struct zwp_primary_selection_offer_v1 *id) +{ + GWL_PrimarySelection *primary = static_cast(data); + + std::lock_guard lock{primary->data_offer_mutex}; + + /* Delete old data offer. */ + if (primary->data_offer != nullptr) { + gwl_primary_selection_discard_offer(primary); + } + + if (id == nullptr) { + CLOG_INFO(LOG, 2, "selection: (skipped)"); + return; + } + CLOG_INFO(LOG, 2, "selection"); + /* Get new data offer. */ + GWL_PrimarySelection_DataOffer *data_offer = static_cast( + zwp_primary_selection_offer_v1_get_user_data(id)); + primary->data_offer = data_offer; + + auto read_selection_fn = [](GWL_PrimarySelection *primary) { + GHOST_SystemWayland *system = static_cast(GHOST_ISystem::getSystem()); + primary->data_offer_mutex.lock(); + + GWL_PrimarySelection_DataOffer *data_offer = primary->data_offer; + std::string mime_receive; + for (const std::string type : {mime_text_utf8, mime_text_plain}) { + if (data_offer->types.count(type)) { + mime_receive = type; + break; + } + } + const std::string data = read_pipe_primary( + data_offer, mime_receive, &primary->data_offer_mutex); + + { + std::lock_guard lock{system_clipboard_mutex}; + system->clipboard_primary_set(data); + } + }; + + std::thread read_thread(read_selection_fn, primary); + read_thread.detach(); +} + +static const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener = { + primary_selection_device_handle_data_offer, + primary_selection_device_handle_selection, +}; + +#undef LOG + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Listener (Primary Selection Source), #zwp_primary_selection_source_v1_listener + * \{ */ + +static CLG_LogRef LOG_WL_PRIMARY_SELECTION_SOURCE = {"ghost.wl.handle.primary_selection_source"}; +#define LOG (&LOG_WL_PRIMARY_SELECTION_SOURCE) + +static void primary_selection_source_send(void *data, + struct zwp_primary_selection_source_v1 * /*source*/, + const char * /*mime_type*/, + int32_t fd) +{ + CLOG_INFO(LOG, 2, "send"); + + GWL_PrimarySelection *primary = static_cast(data); + + std::lock_guard lock{primary->data_source_mutex}; + GWL_PrimarySelection_DataSource *data_source = primary->data_source; + + const char *const buffer = data_source->buffer_out; + if (write(fd, buffer, data_source->buffer_out_len) < 0) { + GHOST_PRINT("error writing to primary clipboard: " << std::strerror(errno) << std::endl); + } + close(fd); +} + +static void primary_selection_source_cancelled(void *data, + struct zwp_primary_selection_source_v1 *source) +{ + CLOG_INFO(LOG, 2, "cancelled"); + + GWL_PrimarySelection *primary = static_cast(data); + + if (source == primary->data_source->wl_source) { + gwl_primary_selection_discard_source(primary); + } +} + +static const struct zwp_primary_selection_source_v1_listener primary_selection_source_listener = { + primary_selection_source_send, + primary_selection_source_cancelled, +}; + +#undef LOG + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Listener (Seat), #wl_seat_listener * \{ */ @@ -2927,6 +3181,17 @@ static void seat_handle_capabilities(void *data, seat->wl_keyboard = wl_seat_get_keyboard(wl_seat); wl_keyboard_add_listener(seat->wl_keyboard, &keyboard_listener, data); } + + if (seat->system) { + zwp_primary_selection_device_manager_v1 *primary_selection_device_manager = + seat->system->wl_primary_selection_manager(); + seat->primary_selection_device = zwp_primary_selection_device_manager_v1_get_device( + primary_selection_device_manager, seat->wl_seat); + + zwp_primary_selection_device_v1_add_listener(seat->primary_selection_device, + &primary_selection_device_listener, + &seat->primary_selection); + } } static void seat_handle_name(void *data, struct wl_seat * /*wl_seat*/, const char *name) @@ -3297,6 +3562,12 @@ static void global_handle_add(void *data, display->pointer_constraints = static_cast( wl_registry_bind(wl_registry, name, &zwp_pointer_constraints_v1_interface, 1)); } + else if (!strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name)) { + display->primary_selection_device_manager = + static_cast(wl_registry_bind( + wl_registry, name, &zwp_primary_selection_device_manager_v1_interface, 1)); + } + else { found = false; @@ -3564,20 +3835,52 @@ GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const return GHOST_kSuccess; } -char *GHOST_SystemWayland::getClipboard(bool /*selection*/) const +char *GHOST_SystemWayland::getClipboard(bool selection) const { - char *clipboard = static_cast(malloc(clipboard_.size() + 1)); - memcpy(clipboard, clipboard_.data(), clipboard_.size() + 1); + const std::string &buf = selection ? clipboard_primary_ : clipboard_; + char *clipboard = static_cast(malloc(buf.size() + 1)); + memcpy(clipboard, buf.data(), buf.size() + 1); return clipboard; } -void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) const +static void system_clipboard_put_primary_selection(GWL_Display *display, const char *buffer) { - if (UNLIKELY(!display_->data_device_manager || display_->seats.empty())) { + if (!display->primary_selection_device_manager) { return; } + GWL_Seat *seat = display->seats[0]; + GWL_PrimarySelection *primary = &seat->primary_selection; - GWL_Seat *seat = display_->seats[0]; + std::lock_guard lock{primary->data_source_mutex}; + + gwl_primary_selection_discard_source(primary); + + GWL_PrimarySelection_DataSource *data_source = new GWL_PrimarySelection_DataSource; + primary->data_source = data_source; + + data_source->buffer_out_len = strlen(buffer); + data_source->buffer_out = static_cast(malloc(data_source->buffer_out_len)); + std::memcpy(data_source->buffer_out, buffer, data_source->buffer_out_len); + + data_source->wl_source = zwp_primary_selection_device_manager_v1_create_source( + display->primary_selection_device_manager); + + zwp_primary_selection_source_v1_add_listener( + data_source->wl_source, &primary_selection_source_listener, primary); + + for (const std::string &type : mime_send) { + zwp_primary_selection_source_v1_offer(data_source->wl_source, type.c_str()); + } + + if (seat->primary_selection_device) { + zwp_primary_selection_device_v1_set_selection( + seat->primary_selection_device, data_source->wl_source, seat->data_source_serial); + } +} + +static void system_clipboard_put(GWL_Display *display, const char *buffer) +{ + GWL_Seat *seat = display->seats[0]; std::lock_guard lock{seat->data_source_mutex}; @@ -3590,7 +3893,7 @@ void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) c std::memcpy(data_source->buffer_out, buffer, data_source->buffer_out_len); data_source->wl_data_source = wl_data_device_manager_create_data_source( - display_->data_device_manager); + display->data_device_manager); wl_data_source_add_listener(data_source->wl_data_source, &data_source_listener, seat); @@ -3604,6 +3907,20 @@ void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) c } } +void GHOST_SystemWayland::putClipboard(const char *buffer, bool selection) const +{ + if (UNLIKELY(!display_->data_device_manager || display_->seats.empty())) { + return; + } + + if (selection) { + system_clipboard_put_primary_selection(display_, buffer); + } + else { + system_clipboard_put(display_, buffer); + } +} + uint8_t GHOST_SystemWayland::getNumDisplays() const { return display_ ? uint8_t(display_->outputs.size()) : 0; @@ -4345,6 +4662,11 @@ wl_compositor *GHOST_SystemWayland::wl_compositor() return display_->wl_compositor; } +struct zwp_primary_selection_device_manager_v1 *GHOST_SystemWayland::wl_primary_selection_manager() +{ + return display_->primary_selection_device_manager; +} + #ifdef WITH_GHOST_WAYLAND_LIBDECOR libdecor *GHOST_SystemWayland::libdecor_context() @@ -4412,6 +4734,11 @@ void GHOST_SystemWayland::clipboard_set(const std::string &clipboard) clipboard_ = clipboard; } +void GHOST_SystemWayland::clipboard_primary_set(const std::string &clipboard) +{ + clipboard_primary_ = clipboard; +} + void GHOST_SystemWayland::window_surface_unref(const wl_surface *wl_surface) { #define SURFACE_CLEAR_PTR(surface_test) \ diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index ca78ccb89ab..ddcd63610ef 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -158,6 +158,7 @@ class GHOST_SystemWayland : public GHOST_System { struct wl_display *wl_display(); struct wl_compositor *wl_compositor(); + struct zwp_primary_selection_device_manager_v1 *wl_primary_selection_manager(); #ifdef WITH_GHOST_WAYLAND_LIBDECOR libdecor *libdecor_context(); @@ -173,6 +174,7 @@ class GHOST_SystemWayland : public GHOST_System { /* WAYLAND utility functions. */ void clipboard_set(const std::string &clipboard); + void clipboard_primary_set(const std::string &clipboard); /** Clear all references to this surface to prevent accessing NULL pointers. */ void window_surface_unref(const wl_surface *wl_surface); @@ -192,4 +194,5 @@ class GHOST_SystemWayland : public GHOST_System { private: struct GWL_Display *display_; std::string clipboard_; + std::string clipboard_primary_; }; -- cgit v1.2.3 From 90686ff6f47ef14e96d94b7ad32f63a7015ca1c8 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 20 Oct 2022 09:52:37 +0200 Subject: Fix WebM naming in the interface Use the official spelling of the WebM codec. Only affects the interface string and not the identifier used in the Python API. Should not even affect translations: the current msgstr's do no translate the original string. Reported by Anton Raves, thanks! --- source/blender/makesrna/intern/rna_scene.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 8fc504f192e..0eb168ecd8e 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -5945,7 +5945,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna) {AV_CODEC_ID_PNG, "PNG", 0, "PNG", ""}, {AV_CODEC_ID_QTRLE, "QTRLE", 0, "QT rle / QT Animation", ""}, {AV_CODEC_ID_THEORA, "THEORA", 0, "Theora", ""}, - {AV_CODEC_ID_VP9, "WEBM", 0, "WEBM / VP9", ""}, + {AV_CODEC_ID_VP9, "WEBM", 0, "WebM / VP9", ""}, {0, NULL, 0, NULL, NULL}, }; -- cgit v1.2.3 From ff157d7ebadc39cd027cbc75e67267d78cf1c80a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 20 Oct 2022 10:09:32 +0200 Subject: Fix incorrect shader state after shader interface creation Use store-current-and-restore-previous OpenGL program in the OpenGL Shader Interface. This is a better fix for the initial error, which additionally solves interface artifacts when opening non-default startyp files on macOS with AMD GPU. --- source/blender/gpu/opengl/gl_shader.cc | 5 ----- source/blender/gpu/opengl/gl_shader_interface.cc | 10 ++++++++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index f6f14932de7..dafcf4dbf33 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -1004,11 +1004,6 @@ bool GLShader::finalize(const shader::ShaderCreateInfo *info) else { interface = new GLShaderInterface(shader_program_); } - /** - * WORKAROUND: Creating the shader interface changes the active program. - * Make sure to update the context, otherwise we might have a missing bind. - */ - Context::get()->shader = this; return true; } diff --git a/source/blender/gpu/opengl/gl_shader_interface.cc b/source/blender/gpu/opengl/gl_shader_interface.cc index c9432fca561..ef97d74bf81 100644 --- a/source/blender/gpu/opengl/gl_shader_interface.cc +++ b/source/blender/gpu/opengl/gl_shader_interface.cc @@ -200,6 +200,9 @@ static Type gpu_type_from_gl_type(int gl_type) GLShaderInterface::GLShaderInterface(GLuint program) { + GLuint last_program; + glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *)&last_program); + /* Necessary to make #glUniform works. */ glUseProgram(program); @@ -385,6 +388,8 @@ GLShaderInterface::GLShaderInterface(GLuint program) // this->debug_print(); this->sort_inputs(); + + glUseProgram(last_program); } GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateInfo &info) @@ -442,6 +447,9 @@ GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateI uint32_t name_buffer_offset = 0; /* Necessary to make #glUniform works. TODO(fclem) Remove. */ + GLuint last_program; + glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *)&last_program); + glUseProgram(program); /* Attributes */ @@ -552,6 +560,8 @@ GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateI this->sort_inputs(); // this->debug_print(); + + glUseProgram(last_program); } GLShaderInterface::~GLShaderInterface() -- cgit v1.2.3 From bd9d68e4dc6fcc840afa514cba7975a6bd86386d Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 20 Oct 2022 11:22:51 +0200 Subject: Fix (studio-reported) issue with overrides on library relocating. Liboverrides that were using a missing linked reference ID would not get their 'MISSING' tag properly cleared afer relocating, in case their linked reference is no more missing. Reported by Andy (@eyecandy) from Blender studio. --- source/blender/blenkernel/intern/blendfile_link_append.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/blenkernel/intern/blendfile_link_append.c b/source/blender/blenkernel/intern/blendfile_link_append.c index 394469e19a4..a937c74578a 100644 --- a/source/blender/blenkernel/intern/blendfile_link_append.c +++ b/source/blender/blenkernel/intern/blendfile_link_append.c @@ -1614,6 +1614,9 @@ void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context, (id->tag & LIB_TAG_PRE_EXISTING) == 0) { continue; } + if ((id->override_library->reference->tag & LIB_TAG_MISSING) == 0) { + id->tag &= ~LIB_TAG_MISSING; + } if ((id->override_library->reference->tag & LIB_TAG_PRE_EXISTING) == 0) { BKE_lib_override_library_update(bmain, id); } -- cgit v1.2.3 From 40afb8ae6a036d904a10680530a89955248d0e06 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 20 Oct 2022 11:29:47 +0200 Subject: Lib reload/relocate: Improve performances. Reduce amounts of viewlayer updates during remapping while relocating libraries. Gives some improvements on relocating process, depending on complexity of existing scene and reloaded libraries, whether there is liboverrides to resync, etc., can give up to 10% speedup. --- source/blender/blenkernel/intern/blendfile_link_append.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/blenkernel/intern/blendfile_link_append.c b/source/blender/blenkernel/intern/blendfile_link_append.c index a937c74578a..4dd225c09ec 100644 --- a/source/blender/blenkernel/intern/blendfile_link_append.c +++ b/source/blender/blenkernel/intern/blendfile_link_append.c @@ -1494,6 +1494,7 @@ void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context, * code is wrong, we need to redo it here after adding them back to main. */ BKE_main_id_refcount_recompute(bmain, false); + BKE_layer_collection_resync_forbid(); /* Note that in reload case, we also want to replace indirect usages. */ const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE | (do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE); @@ -1523,6 +1524,8 @@ void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context, id_us_plus_no_lib(&old_key->id); } } + BKE_layer_collection_resync_allow(); + BKE_main_collection_sync_remap(bmain); BKE_main_unlock(bmain); -- cgit v1.2.3 From 8a43bfd8fd8d08438c5cc58befdf3e661aa17297 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 20:44:03 +1100 Subject: GHOST/Wayland: refactor copy/paste buffer storage - Improve reporting when reading a file descriptor into a buffer fails, also check for failure to allocate memory. - Store buffers with size in a simple struct. - Use shared utility functions for simple buffer operations. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 217 ++++++++++++++++++++-------- intern/ghost/intern/GHOST_SystemWayland.h | 7 +- 2 files changed, 157 insertions(+), 67 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 6db8b9d33f8..42bfc6aa1e7 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -237,6 +237,43 @@ static const GWL_ModifierInfo g_modifier_info_table[MOD_INDEX_NUM] = { /** \name Private Types & Defines * \{ */ +struct GWL_SimpleBuffer { + /** Constant data, but may be freed. */ + const char *data = nullptr; + size_t data_size = 0; +}; + +static void gwl_simple_buffer_free_data(GWL_SimpleBuffer *buffer) +{ + free(const_cast(buffer->data)); + buffer->data = nullptr; + buffer->data_size = 0; +} + +static void gwl_simple_buffer_set(GWL_SimpleBuffer *buffer, const char *data, size_t data_size) +{ + free(const_cast(buffer->data)); + buffer->data = data; + buffer->data_size = data_size; +} + +static void gwl_simple_buffer_set_from_string(GWL_SimpleBuffer *buffer, const char *str) +{ + free(const_cast(buffer->data)); + buffer->data_size = strlen(str); + char *data = static_cast(malloc(buffer->data_size)); + std::memcpy(data, str, buffer->data_size); + buffer->data = data; +} + +static char *gwl_simple_buffer_as_string(const GWL_SimpleBuffer *buffer) +{ + char *buffer_str = static_cast(malloc(buffer->data_size + 1)); + memcpy(buffer_str, buffer->data, buffer->data_size); + buffer_str[buffer->data_size] = '\0'; + return buffer_str; +} + /** * From XKB internals, use for converting a scan-code from WAYLAND to a #xkb_keycode_t. * Ideally this wouldn't need a local define. @@ -293,8 +330,7 @@ struct GWL_DataOffer { struct GWL_DataSource { struct wl_data_source *wl_data_source = nullptr; - char *buffer_out = nullptr; - size_t buffer_out_len = 0; + GWL_SimpleBuffer buffer_out; }; /** @@ -436,8 +472,7 @@ struct GWL_PrimarySelection_DataOffer { struct GWL_PrimarySelection_DataSource { struct zwp_primary_selection_source_v1 *wl_source = nullptr; - char *buffer_out = nullptr; - size_t buffer_out_len = 0; + GWL_SimpleBuffer buffer_out; }; /** Primary selection support. */ @@ -466,7 +501,7 @@ static void gwl_primary_selection_discard_source(GWL_PrimarySelection *primary) if (data_source == nullptr) { return; } - free(data_source->buffer_out); + gwl_simple_buffer_free_data(&data_source->buffer_out); if (data_source->wl_source) { zwp_primary_selection_source_v1_destroy(data_source->wl_source); } @@ -593,6 +628,9 @@ struct GWL_Display { struct zwp_pointer_constraints_v1 *pointer_constraints = nullptr; struct zwp_primary_selection_device_manager_v1 *primary_selection_device_manager = nullptr; + + GWL_SimpleBuffer clipboard; + GWL_SimpleBuffer clipboard_primary; }; #undef LOG @@ -671,7 +709,7 @@ static void display_destroy(GWL_Display *display) { std::lock_guard lock{seat->data_source_mutex}; if (seat->data_source) { - free(seat->data_source->buffer_out); + gwl_simple_buffer_free_data(&seat->data_source->buffer_out); if (seat->data_source->wl_data_source) { wl_data_source_destroy(seat->data_source->wl_data_source); } @@ -795,6 +833,9 @@ static void display_destroy(GWL_Display *display) wl_display_disconnect(display->wl_display); } + gwl_simple_buffer_free_data(&display->clipboard); + gwl_simple_buffer_free_data(&display->clipboard_primary); + delete display; } @@ -1294,9 +1335,74 @@ static void dnd_events(const GWL_Seat *const seat, const GHOST_TEventType event) } } -static std::string read_pipe(GWL_DataOffer *data_offer, +/** + * Read from `fd` into a buffer which is returned. + * \return the buffer or null on failure. + */ +static const char *read_file_as_buffer(const int fd, size_t *r_len) +{ + struct ByteChunk { + ByteChunk *next; + char data[4096 - sizeof(ByteChunk *)]; + }; + ByteChunk *chunk_first = nullptr, **chunk_link_p = &chunk_first; + bool ok = true; + size_t len = 0; + while (true) { + ByteChunk *chunk = static_cast(malloc(sizeof(*chunk))); + if (UNLIKELY(chunk == nullptr)) { + CLOG_WARN(LOG, "unable to allocate chunk for file buffer"); + ok = false; + break; + } + chunk->next = nullptr; + const ssize_t len_chunk = read(fd, chunk->data, sizeof(chunk->data)); + if (len_chunk <= 0) { + if (UNLIKELY(len_chunk < 0)) { + CLOG_WARN(LOG, "error reading from pipe: %s", std::strerror(errno)); + ok = false; + } + free(chunk); + break; + } + if (chunk_first == nullptr) { + chunk_first = chunk; + } + *chunk_link_p = chunk; + chunk_link_p = &chunk->next; + len += len_chunk; + } + + char *buf = nullptr; + if (ok) { + buf = static_cast(malloc(len)); + if (UNLIKELY(buf == nullptr)) { + CLOG_WARN(LOG, "unable to allocate file buffer: %zu bytes", len); + ok = false; + } + } + + *r_len = ok ? len : 0; + char *buf_stride = buf; + while (chunk_first) { + if (ok) { + const size_t len_chunk = std::min(len, sizeof(chunk_first->data)); + memcpy(buf_stride, chunk_first->data, len_chunk); + buf_stride += len_chunk; + len -= len_chunk; + } + ByteChunk *chunk = chunk_first->next; + free(chunk_first); + chunk_first = chunk; + } + + return buf; +} + +static const char *read_pipe(GWL_DataOffer *data_offer, const std::string mime_receive, - std::mutex *mutex) + std::mutex *mutex, + size_t *r_len) { int pipefd[2]; if (UNLIKELY(pipe(pipefd) != 0)) { @@ -1312,20 +1418,15 @@ static std::string read_pipe(GWL_DataOffer *data_offer, } /* WARNING: `data_offer` may be freed from now on. */ - std::string data; - ssize_t len; - char buffer[4096]; - while ((len = read(pipefd[0], buffer, sizeof(buffer))) > 0) { - data.insert(data.end(), buffer, buffer + len); - } + const char *buf = read_file_as_buffer(pipefd[0], r_len); close(pipefd[0]); - - return data; + return buf; } -static std::string read_pipe_primary(GWL_PrimarySelection_DataOffer *data_offer, +static const char *read_pipe_primary(GWL_PrimarySelection_DataOffer *data_offer, const std::string mime_receive, - std::mutex *mutex) + std::mutex *mutex, + size_t *r_len) { int pipefd[2]; if (UNLIKELY(pipe(pipefd) != 0)) { @@ -1339,17 +1440,10 @@ static std::string read_pipe_primary(GWL_PrimarySelection_DataOffer *data_offer, if (mutex) { mutex->unlock(); } - /* WARNING: `data_offer_base` may be freed from now on. */ - - std::string data; - ssize_t len; - char buffer[4096]; - while ((len = read(pipefd[0], buffer, sizeof(buffer))) > 0) { - data.insert(data.end(), buffer, buffer + len); - } + /* WARNING: `data_offer` may be freed from now on. */ + const char *buf = read_file_as_buffer(pipefd[0], r_len); close(pipefd[0]); - - return data; + return buf; } /** @@ -1375,9 +1469,9 @@ static void data_source_handle_send(void *data, CLOG_INFO(LOG, 2, "send"); - const char *const buffer = seat->data_source->buffer_out; - if (write(fd, buffer, seat->data_source->buffer_out_len) < 0) { - GHOST_PRINT("error writing to clipboard: " << std::strerror(errno) << std::endl); + const char *const buffer = seat->data_source->buffer_out.data; + if (UNLIKELY(write(fd, buffer, seat->data_source->buffer_out.data_size) < 0)) { + CLOG_WARN(LOG, "error writing to clipboard: %s", std::strerror(errno)); } close(fd); } @@ -1598,7 +1692,9 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat const std::string mime_receive) { const wl_fixed_t xy[2] = {UNPACK2(data_offer->dnd.xy)}; - const std::string data = read_pipe(data_offer, mime_receive, nullptr); + size_t data_buf_len = 0; + const char *data_buf = read_pipe(data_offer, mime_receive, nullptr, &data_buf_len); + std::string data = data_buf ? std::string(data_buf, data_buf_len) : ""; CLOG_INFO( LOG, 2, "drop_read_uris mime_receive=%s, data=%s", mime_receive.c_str(), data.c_str()); @@ -1713,12 +1809,15 @@ static void data_device_handle_selection(void *data, break; } } - const std::string data = read_pipe( - data_offer, mime_receive, &seat->data_offer_copy_paste_mutex); + + size_t data_len = 0; + const char *data = read_pipe( + data_offer, mime_receive, &seat->data_offer_copy_paste_mutex, &data_len); { std::lock_guard lock{system_clipboard_mutex}; - system->clipboard_set(data); + GWL_SimpleBuffer *buf = system->clipboard_data(false); + gwl_simple_buffer_set(buf, data, data_len); } }; @@ -3065,12 +3164,14 @@ static void primary_selection_device_handle_selection( break; } } - const std::string data = read_pipe_primary( - data_offer, mime_receive, &primary->data_offer_mutex); + size_t data_len = 0; + const char *data = read_pipe_primary( + data_offer, mime_receive, &primary->data_offer_mutex, &data_len); { std::lock_guard lock{system_clipboard_mutex}; - system->clipboard_primary_set(data); + GWL_SimpleBuffer *buf = system->clipboard_data(true); + gwl_simple_buffer_set(buf, data, data_len); } }; @@ -3106,9 +3207,9 @@ static void primary_selection_source_send(void *data, std::lock_guard lock{primary->data_source_mutex}; GWL_PrimarySelection_DataSource *data_source = primary->data_source; - const char *const buffer = data_source->buffer_out; - if (write(fd, buffer, data_source->buffer_out_len) < 0) { - GHOST_PRINT("error writing to primary clipboard: " << std::strerror(errno) << std::endl); + const char *const buffer = data_source->buffer_out.data; + if (UNLIKELY(write(fd, buffer, data_source->buffer_out.data_size) < 0)) { + CLOG_WARN(LOG, "error writing to primary clipboard: %s", std::strerror(errno)); } close(fd); } @@ -3837,10 +3938,11 @@ GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const char *GHOST_SystemWayland::getClipboard(bool selection) const { - const std::string &buf = selection ? clipboard_primary_ : clipboard_; - char *clipboard = static_cast(malloc(buf.size() + 1)); - memcpy(clipboard, buf.data(), buf.size() + 1); - return clipboard; + const GWL_SimpleBuffer *buf = clipboard_data(selection); + if (buf->data == nullptr) { + return nullptr; + } + return gwl_simple_buffer_as_string(buf); } static void system_clipboard_put_primary_selection(GWL_Display *display, const char *buffer) @@ -3858,9 +3960,8 @@ static void system_clipboard_put_primary_selection(GWL_Display *display, const c GWL_PrimarySelection_DataSource *data_source = new GWL_PrimarySelection_DataSource; primary->data_source = data_source; - data_source->buffer_out_len = strlen(buffer); - data_source->buffer_out = static_cast(malloc(data_source->buffer_out_len)); - std::memcpy(data_source->buffer_out, buffer, data_source->buffer_out_len); + /* Copy buffer. */ + gwl_simple_buffer_set_from_string(&data_source->buffer_out, buffer); data_source->wl_source = zwp_primary_selection_device_manager_v1_create_source( display->primary_selection_device_manager); @@ -3887,10 +3988,7 @@ static void system_clipboard_put(GWL_Display *display, const char *buffer) GWL_DataSource *data_source = seat->data_source; /* Copy buffer. */ - free(data_source->buffer_out); - data_source->buffer_out_len = strlen(buffer); - data_source->buffer_out = static_cast(malloc(data_source->buffer_out_len)); - std::memcpy(data_source->buffer_out, buffer, data_source->buffer_out_len); + gwl_simple_buffer_set_from_string(&data_source->buffer_out, buffer); data_source->wl_data_source = wl_data_device_manager_create_data_source( display->data_device_manager); @@ -4729,16 +4827,6 @@ GHOST_WindowWayland *ghost_wl_surface_user_data(struct wl_surface *wl_surface) * Functionality only used for the WAYLAND implementation. * \{ */ -void GHOST_SystemWayland::clipboard_set(const std::string &clipboard) -{ - clipboard_ = clipboard; -} - -void GHOST_SystemWayland::clipboard_primary_set(const std::string &clipboard) -{ - clipboard_primary_ = clipboard; -} - void GHOST_SystemWayland::window_surface_unref(const wl_surface *wl_surface) { #define SURFACE_CLEAR_PTR(surface_test) \ @@ -4939,6 +5027,11 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod return GHOST_kSuccess; } +struct GWL_SimpleBuffer *GHOST_SystemWayland::clipboard_data(bool selection) const +{ + return selection ? &display_->clipboard_primary : &display_->clipboard; +} + #ifdef WITH_GHOST_WAYLAND_LIBDECOR bool GHOST_SystemWayland::use_libdecor_runtime() { diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index ddcd63610ef..4e77c5b9c0b 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -173,9 +173,6 @@ class GHOST_SystemWayland : public GHOST_System { /* WAYLAND utility functions. */ - void clipboard_set(const std::string &clipboard); - void clipboard_primary_set(const std::string &clipboard); - /** Clear all references to this surface to prevent accessing NULL pointers. */ void window_surface_unref(const wl_surface *wl_surface); @@ -187,12 +184,12 @@ class GHOST_SystemWayland : public GHOST_System { wl_surface *wl_surface, int scale); + struct GWL_SimpleBuffer *clipboard_data(bool selection) const; + #ifdef WITH_GHOST_WAYLAND_LIBDECOR static bool use_libdecor_runtime(); #endif private: struct GWL_Display *display_; - std::string clipboard_; - std::string clipboard_primary_; }; -- cgit v1.2.3 From c81bc09876f84753f3c69e024196b70a88c6cebe Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Thu, 20 Oct 2022 12:51:20 +0200 Subject: GPU: Avoid undocumented/fragile dependency on shader enumerator order Previously this was using `GPU_SHADER_TEXT` as default value indicating an "unset" state. This wasn't documented in the definition (and so D16284 added a new enumerator that broke this). Plus code was assuming this enumerator would always have the value 0 without specifying this in the definition either. In this case it's easy to not rely on the enum value at all, and just use `std::optional` to add a "unset" state. Differential Revision: https://developer.blender.org/D16303 --- source/blender/gpu/intern/gpu_immediate.cc | 11 +++++++---- source/blender/gpu/intern/gpu_immediate_private.hh | 8 +++++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/source/blender/gpu/intern/gpu_immediate.cc b/source/blender/gpu/intern/gpu_immediate.cc index 3b4accf9cc5..81c0a65bb7c 100644 --- a/source/blender/gpu/intern/gpu_immediate.cc +++ b/source/blender/gpu/intern/gpu_immediate.cc @@ -45,7 +45,7 @@ void immBindShader(GPUShader *shader) BLI_assert(imm->shader == nullptr); imm->shader = shader; - imm->builtin_shader_bound = GPU_SHADER_TEXT; /* Default value. */ + imm->builtin_shader_bound = std::nullopt; if (!imm->vertex_format.packed) { VertexFormat_pack(&imm->vertex_format); @@ -125,9 +125,12 @@ static void wide_line_workaround_start(GPUPrimType prim_type) /* No need to change the shader. */ return; } + if (!imm->builtin_shader_bound) { + return; + } eGPUBuiltinShader polyline_sh; - switch (imm->builtin_shader_bound) { + switch (*imm->builtin_shader_bound) { case GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR: polyline_sh = GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR; break; @@ -180,8 +183,8 @@ static void wide_line_workaround_end() } immUnbindProgram(); - immBindBuiltinProgram(imm->prev_builtin_shader); - imm->prev_builtin_shader = GPU_SHADER_TEXT; + immBindBuiltinProgram(*imm->prev_builtin_shader); + imm->prev_builtin_shader = std::nullopt; } } diff --git a/source/blender/gpu/intern/gpu_immediate_private.hh b/source/blender/gpu/intern/gpu_immediate_private.hh index 74ebbdc7ae3..c4e11e7082b 100644 --- a/source/blender/gpu/intern/gpu_immediate_private.hh +++ b/source/blender/gpu/intern/gpu_immediate_private.hh @@ -9,6 +9,8 @@ #pragma once +#include + #include "GPU_batch.h" #include "GPU_primitive.h" #include "GPU_shader.h" @@ -42,9 +44,9 @@ class Immediate { /** Wide Line workaround. */ /** Previously bound shader to restore after drawing. */ - eGPUBuiltinShader prev_builtin_shader = GPU_SHADER_TEXT; - /** Builtin shader index. Used to test if the workaround can be done. */ - eGPUBuiltinShader builtin_shader_bound = GPU_SHADER_TEXT; + std::optional prev_builtin_shader; + /** Builtin shader index. Used to test if the line width workaround can be done. */ + std::optional builtin_shader_bound; /** Uniform color: Kept here to update the wide-line shader just before #immBegin. */ float uniform_color[4]; -- cgit v1.2.3 From a30128a3c1a2eb7767ec87b99a09f2893e1c5de7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 22:25:19 +1100 Subject: Fix missing free in 8a43bfd8fd8d08438c5cc58befdf3e661aa17297 --- intern/ghost/intern/GHOST_SystemWayland.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 42bfc6aa1e7..264476f00bc 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1695,6 +1695,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat size_t data_buf_len = 0; const char *data_buf = read_pipe(data_offer, mime_receive, nullptr, &data_buf_len); std::string data = data_buf ? std::string(data_buf, data_buf_len) : ""; + free(const_cast(data_buf)); CLOG_INFO( LOG, 2, "drop_read_uris mime_receive=%s, data=%s", mime_receive.c_str(), data.c_str()); -- cgit v1.2.3 From 303dd263e2590f981ee1917554cd688dd951ee2c Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Thu, 20 Oct 2022 13:33:08 +0200 Subject: Build: update OSL to version 1.12.6.2 Required changes to make OSL pick up the new oslnoise library. Ref D16269, T101403 --- build_files/build_environment/cmake/versions.cmake | 6 +++--- build_files/cmake/Modules/FindOSL.cmake | 15 +++++++++++++-- build_files/cmake/platform/platform_apple.cmake | 17 +++-------------- build_files/cmake/platform/platform_win32.cmake | 8 ++++++++ 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake index bfc6d27f74d..469988dab0c 100644 --- a/build_files/build_environment/cmake/versions.cmake +++ b/build_files/build_environment/cmake/versions.cmake @@ -189,9 +189,9 @@ set(TIFF_HASH_TYPE MD5) set(TIFF_FILE tiff-${TIFF_VERSION}.tar.gz) set(TIFF_CPE "cpe:2.3:a:libtiff:libtiff:${TIFF_VERSION}:*:*:*:*:*:*:*") -set(OSL_VERSION 1.11.17.0) -set(OSL_URI https://github.com/imageworks/OpenShadingLanguage/archive/Release-${OSL_VERSION}.tar.gz) -set(OSL_HASH 63265472ce14548839ace2e21e401544) +set(OSL_VERSION 1.12.6.2) +set(OSL_URI https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/archive/refs/tags/v${OSL_VERSION}.tar.gz) +set(OSL_HASH 6fef11548adfdd3e5b25c49d2dae96ee) set(OSL_HASH_TYPE MD5) set(OSL_FILE OpenShadingLanguage-${OSL_VERSION}.tar.gz) diff --git a/build_files/cmake/Modules/FindOSL.cmake b/build_files/cmake/Modules/FindOSL.cmake index ab5de53d3c9..a8d8344ae66 100644 --- a/build_files/cmake/Modules/FindOSL.cmake +++ b/build_files/cmake/Modules/FindOSL.cmake @@ -20,6 +20,7 @@ IF(NOT OSL_ROOT_DIR AND NOT $ENV{OSL_ROOT_DIR} STREQUAL "") ENDIF() SET(_osl_FIND_COMPONENTS + oslnoise oslcomp oslexec oslquery @@ -39,7 +40,6 @@ FIND_PATH(OSL_INCLUDE_DIR include ) -SET(_osl_LIBRARIES) FOREACH(COMPONENT ${_osl_FIND_COMPONENTS}) STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT) @@ -51,9 +51,20 @@ FOREACH(COMPONENT ${_osl_FIND_COMPONENTS}) PATH_SUFFIXES lib64 lib ) - LIST(APPEND _osl_LIBRARIES "${OSL_${UPPERCOMPONENT}_LIBRARY}") ENDFOREACH() +# Note linking order matters, and oslnoise existence depends on version. +SET(_osl_LIBRARIES ${OSL_OSLCOMP_LIBRARY}) +IF(APPLE) + list(APPEND _osl_LIBRARIES -force_load ${OSL_OSLEXEC_LIBRARY}) +ELSE() + list(APPEND _osl_LIBRARIES ${OSL_OSLEXEC_LIBRARY}) +ENDIF() +list(APPEND _osl_LIBRARIES ${OSL_OSLQUERY_LIBRARY}) +IF(OSL_OSLNOISE_LIBRARY) + list(APPEND _osl_LIBRARIES ${OSL_OSLNOISE_LIBRARY}) +ENDIF() + FIND_PROGRAM(OSL_COMPILER oslc HINTS ${_osl_SEARCH_DIRS} PATH_SUFFIXES bin) diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake index 04f5a312030..dbcaf9d02d3 100644 --- a/build_files/cmake/platform/platform_apple.cmake +++ b/build_files/cmake/platform/platform_apple.cmake @@ -331,20 +331,9 @@ if(WITH_LLVM) endif() if(WITH_CYCLES AND WITH_CYCLES_OSL) - set(CYCLES_OSL ${LIBDIR}/osl) - - find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib) - find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib) - find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib) - # WARNING! depends on correct order of OSL libs linking - list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} -force_load ${OSL_LIB_EXEC} ${OSL_LIB_QUERY}) - find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include) - find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin) - find_path(OSL_SHADER_DIR NAMES stdosl.h PATHS ${CYCLES_OSL}/share/OSL/shaders) - - if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER AND OSL_SHADER_DIR) - set(OSL_FOUND TRUE) - else() + find_package(OSL) + + if(NOT OSL_FOUND) message(WARNING "OSL not found, disabling WITH_CYCLES_OSL") set(WITH_CYCLES_OSL OFF) endif() diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index cfb8bf34b81..4478a2f8051 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -773,9 +773,11 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL) find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib) + find_library(OSL_LIB_NOISE NAMES oslnoise PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_EXEC_DEBUG NAMES oslexec_d PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_COMP_DEBUG NAMES oslcomp_d PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_QUERY_DEBUG NAMES oslquery_d PATHS ${CYCLES_OSL}/lib) + find_library(OSL_LIB_NOISE_DEBUG NAMES oslnoise_d PATHS ${CYCLES_OSL}/lib) list(APPEND OSL_LIBRARIES optimized ${OSL_LIB_COMP} optimized ${OSL_LIB_EXEC} @@ -785,6 +787,12 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL) debug ${OSL_LIB_QUERY_DEBUG} ${PUGIXML_LIBRARIES} ) + if(OSL_LIB_NOISE) + list(APPEND OSL_LIBRARIES optimized ${OSL_LIB_NOISE}) + endif() + if(OSL_LIB_NOISE_DEBUG) + list(APPEND OSL_LIBRARIES debug ${OSL_LIB_NOISE_DEBUG}) + endif() find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include) find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin) -- cgit v1.2.3 From debacbfe5c8fb38a01504463b70f590386a3f62c Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Thu, 20 Oct 2022 13:37:18 +0200 Subject: Build: update OpenPGL hash for re-tagged version without symbols conflicts Ref D16269, T101403 --- build_files/build_environment/cmake/versions.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake index 469988dab0c..6f358fd6f86 100644 --- a/build_files/build_environment/cmake/versions.cmake +++ b/build_files/build_environment/cmake/versions.cmake @@ -564,7 +564,7 @@ set(BROTLI_CPE "cpe:2.3:a:google:brotli:${BROTLI_VERSION}:*:*:*:*:*:*:*") set(OPENPGL_VERSION v0.4.0-beta) set(OPENPGL_SHORT_VERSION 0.4.0) set(OPENPGL_URI https://github.com/OpenPathGuidingLibrary/openpgl/archive/refs/tags/${OPENPGL_VERSION}.tar.gz) -set(OPENPGL_HASH 58d5b65c533ce6cac3f7e1d51cf169a5411adf356abcd85f04049bbcaecc2e77) +set(OPENPGL_HASH 1f090f88ab2bad028e8b3619aa926f4f97cf7b2c175b904704d2fec8593dd3cd) set(OPENPGL_HASH_TYPE SHA256) set(OPENPGL_FILE openpgl-${OPENPGL_VERSION}.tar.gz) -- cgit v1.2.3 From 21deba56aaeccf94d83024a9de4eef49ea05984f Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Thu, 20 Oct 2022 13:25:54 +0200 Subject: Build: update various libraries for 3.4, fixing bugs and security issues THis is bumping dependencies to fix known CVEs, with the exception of OpenImageIO which also includes bugfixes for performance and correctness with some image types. zlib 1.2.12 -> 1.2.13 freetype 2.11.1 -> 2.12.1 openimageio 2.3.13.0 -> 2.3.20.0 python 3.10.2 -> 3.10.8 openjpeg 2.4.0 -> 2.5.0 ffmpeg 5.0 -> 5.1.2 sndfile 1.0.28 -> 1.1.0 xml2 2.9.10 -> 2.10.3 expat 2.4.4 -> 2.4.9 openssl 1.1.1g/i -> 1.1.1q sqlite 3.31.1 -> 3.37.2 Notable changes: * AOM: the hack we had in place to make it not detect pthreads on windows no longer worked with a more recent cmake version. Disabled pthreads with a diff on Windows. * Python: embedded copy of zlib 2.1.12 swapped out for our 2.1.13 copy with some folder manipulation on Windows. * Freetype: was harbouring a copy of zlib 2.1.12 as well, so that had to end. * FFmpeg: patch used to fix D11796 is no longer needed. Add new patch to deal with simple_idct.asm generating an object file with no sections in it, backport from upstream commit. * TinyXML: still being downloaded but no longer used by OpenColorIO, removed. * GMP applied upstream patch to fix CVE-2021-43618, as there is no release yet. * SQLite and Libsndfile patches no longer needed. Includes contributes by Ray Molenkamp, Campbell Barton and Brecht Van Lommel. Ref T101403 Differential Revision: https://developer.blender.org/D16269 --- build_files/build_environment/cmake/aom.cmake | 6 +- build_files/build_environment/cmake/download.cmake | 3 +- build_files/build_environment/cmake/ffmpeg.cmake | 6 - build_files/build_environment/cmake/freetype.cmake | 4 + build_files/build_environment/cmake/gmp.cmake | 1 + build_files/build_environment/cmake/llvm.cmake | 1 + build_files/build_environment/cmake/osl.cmake | 2 + build_files/build_environment/cmake/python.cmake | 17 ++- build_files/build_environment/cmake/sndfile.cmake | 7 -- build_files/build_environment/cmake/sqlite.cmake | 1 - build_files/build_environment/cmake/ssl.cmake | 1 + build_files/build_environment/cmake/tiff.cmake | 1 + build_files/build_environment/cmake/versions.cmake | 95 +++++++-------- build_files/build_environment/cmake/wayland.cmake | 8 +- build_files/build_environment/dependencies.dot | 120 ++++++++++-------- build_files/build_environment/patches/aom.diff | 18 +++ build_files/build_environment/patches/ffmpeg.diff | 40 ++---- build_files/build_environment/patches/gmp.diff | 15 +++ build_files/build_environment/patches/osl.diff | 135 +++++++++++++-------- .../build_environment/patches/python_windows.diff | 24 ---- build_files/build_environment/patches/sndfile.diff | 42 ------- build_files/build_environment/patches/sqlite.diff | 14 --- build_files/build_environment/patches/ssl.diff | 10 ++ build_files/cmake/platform/platform_win32.cmake | 8 +- 24 files changed, 290 insertions(+), 289 deletions(-) create mode 100644 build_files/build_environment/patches/aom.diff create mode 100644 build_files/build_environment/patches/gmp.diff delete mode 100644 build_files/build_environment/patches/python_windows.diff delete mode 100644 build_files/build_environment/patches/sndfile.diff delete mode 100644 build_files/build_environment/patches/sqlite.diff create mode 100644 build_files/build_environment/patches/ssl.diff diff --git a/build_files/build_environment/cmake/aom.cmake b/build_files/build_environment/cmake/aom.cmake index 9f64439771f..11c81c3f6e4 100644 --- a/build_files/build_environment/cmake/aom.cmake +++ b/build_files/build_environment/cmake/aom.cmake @@ -8,11 +8,6 @@ if(WIN32) # building with mingw, it'll have an unhappy time with that and # we need to clear them out. set(AOM_CMAKE_FLAGS ) - # CMake will correctly identify phreads being available, however - # we do not want to use them, as that gains a dependency on - # libpthreadswin.dll which we do not want. when pthreads is not - # available oam will use a pthreads emulation layer using win32 threads - set(AOM_EXTRA_ARGS_WIN32 -DCMAKE_HAVE_PTHREAD_H=OFF) else() set(AOM_GENERATOR "Unix Makefiles") set(AOM_CMAKE_FLAGS ${DEFAULT_CMAKE_FLAGS}) @@ -36,6 +31,7 @@ ExternalProject_Add(external_aom DOWNLOAD_DIR ${DOWNLOAD_DIR} URL_HASH ${AOM_HASH_TYPE}=${AOM_HASH} PREFIX ${BUILD_DIR}/aom + PATCH_COMMAND ${PATCH_CMD} --verbose -p 1 -N -d ${BUILD_DIR}/aom/src/external_aom < ${PATCH_DIR}/aom.diff CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/aom/src/external_aom-build/ && ${CMAKE_COMMAND} -G "${AOM_GENERATOR}" -DCMAKE_INSTALL_PREFIX=${LIBDIR}/aom ${AOM_CMAKE_FLAGS} ${AOM_EXTRA_ARGS} ${BUILD_DIR}/aom/src/external_aom/ diff --git a/build_files/build_environment/cmake/download.cmake b/build_files/build_environment/cmake/download.cmake index 35bc028a1e3..8d75f0ff0ed 100644 --- a/build_files/build_environment/cmake/download.cmake +++ b/build_files/build_environment/cmake/download.cmake @@ -62,7 +62,7 @@ function(download_source dep) # since the actual build of the dep will notify the # platform maintainer if there is a problem with the # source package and refuse to build. - if(NOT PACKAGE_USE_UPSTREAM_SOURCES) + if(NOT PACKAGE_USE_UPSTREAM_SOURCES OR FORCE_CHECK_HASH) file(${TARGET_HASH_TYPE} ${TARGET_FILE} LOCAL_HASH) if(NOT ${TARGET_HASH} STREQUAL ${LOCAL_HASH}) message(FATAL_ERROR "${TARGET_FILE} ${TARGET_HASH_TYPE} mismatch\nExpected\t: ${TARGET_HASH}\nActual\t: ${LOCAL_HASH}") @@ -114,7 +114,6 @@ download_source(WEBP) download_source(SPNAV) download_source(JEMALLOC) download_source(XML2) -download_source(TINYXML) download_source(YAMLCPP) download_source(EXPAT) download_source(PUGIXML) diff --git a/build_files/build_environment/cmake/ffmpeg.cmake b/build_files/build_environment/cmake/ffmpeg.cmake index 7730607c514..e2b60e161f2 100644 --- a/build_files/build_environment/cmake/ffmpeg.cmake +++ b/build_files/build_environment/cmake/ffmpeg.cmake @@ -16,12 +16,6 @@ if(WIN32) --enable-libopenjpeg --disable-mediafoundation ) - if("${CMAKE_SIZEOF_VOID_P}" EQUAL "4") - set(FFMPEG_EXTRA_FLAGS - ${FFMPEG_EXTRA_FLAGS} - --x86asmexe=yasm - ) - endif() else() set(FFMPEG_EXTRA_FLAGS ${FFMPEG_EXTRA_FLAGS} diff --git a/build_files/build_environment/cmake/freetype.cmake b/build_files/build_environment/cmake/freetype.cmake index b6f53ede2db..842e5c42e25 100644 --- a/build_files/build_environment/cmake/freetype.cmake +++ b/build_files/build_environment/cmake/freetype.cmake @@ -7,8 +7,11 @@ set(FREETYPE_EXTRA_ARGS -DFT_DISABLE_HARFBUZZ=ON -DFT_DISABLE_PNG=ON -DFT_REQUIRE_BROTLI=ON + -DFT_REQUIRE_ZLIB=ON -DPC_BROTLIDEC_INCLUDEDIR=${LIBDIR}/brotli/include -DPC_BROTLIDEC_LIBDIR=${LIBDIR}/brotli/lib + -DZLIB_LIBRARY=${LIBDIR}/zlib/lib/${ZLIB_LIBRARY} + -DZLIB_INCLUDE_DIR=${LIBDIR}/zlib/include ) ExternalProject_Add(external_freetype @@ -23,6 +26,7 @@ ExternalProject_Add(external_freetype add_dependencies( external_freetype external_brotli + external_zlib ) if(BUILD_MODE STREQUAL Release AND WIN32) diff --git a/build_files/build_environment/cmake/gmp.cmake b/build_files/build_environment/cmake/gmp.cmake index e624778869e..ddfdba6662d 100644 --- a/build_files/build_environment/cmake/gmp.cmake +++ b/build_files/build_environment/cmake/gmp.cmake @@ -27,6 +27,7 @@ ExternalProject_Add(external_gmp DOWNLOAD_DIR ${DOWNLOAD_DIR} URL_HASH ${GMP_HASH_TYPE}=${GMP_HASH} PREFIX ${BUILD_DIR}/gmp + PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/gmp/src/external_gmp < ${PATCH_DIR}/gmp.diff CONFIGURE_COMMAND ${CONFIGURE_ENV_NO_PERL} && cd ${BUILD_DIR}/gmp/src/external_gmp/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/gmp ${GMP_OPTIONS} ${GMP_EXTRA_ARGS} BUILD_COMMAND ${CONFIGURE_ENV_NO_PERL} && cd ${BUILD_DIR}/gmp/src/external_gmp/ && make -j${MAKE_THREADS} INSTALL_COMMAND ${CONFIGURE_ENV_NO_PERL} && cd ${BUILD_DIR}/gmp/src/external_gmp/ && make install diff --git a/build_files/build_environment/cmake/llvm.cmake b/build_files/build_environment/cmake/llvm.cmake index e4ddc7db846..11f6bf7c218 100644 --- a/build_files/build_environment/cmake/llvm.cmake +++ b/build_files/build_environment/cmake/llvm.cmake @@ -9,6 +9,7 @@ endif() if(APPLE) set(LLVM_XML2_ARGS -DLIBXML2_LIBRARY=${LIBDIR}/xml2/lib/libxml2.a + -DLIBXML2_INCLUDE_DIR=${LIBDIR}/xml2/include/libxml2 ) set(LLVM_BUILD_CLANG_TOOLS_EXTRA ^^clang-tools-extra) set(BUILD_CLANG_TOOLS ON) diff --git a/build_files/build_environment/cmake/osl.cmake b/build_files/build_environment/cmake/osl.cmake index 9719de94d47..8bac2c5c1ab 100644 --- a/build_files/build_environment/cmake/osl.cmake +++ b/build_files/build_environment/cmake/osl.cmake @@ -32,6 +32,8 @@ set(OSL_EXTRA_ARGS -DUSE_Qt5=OFF -DINSTALL_DOCS=OFF -Dpugixml_ROOT=${LIBDIR}/pugixml + -DTIFF_ROOT=${LIBDIR}/tiff + -DJPEG_ROOT=${LIBDIR}/jpeg -DUSE_PYTHON=OFF -DCMAKE_CXX_STANDARD=14 -DImath_ROOT=${LIBDIR}/imath diff --git a/build_files/build_environment/cmake/python.cmake b/build_files/build_environment/cmake/python.cmake index 8fed10e9d72..72ae27ddfdb 100644 --- a/build_files/build_environment/cmake/python.cmake +++ b/build_files/build_environment/cmake/python.cmake @@ -15,9 +15,11 @@ if(WIN32) endmacro() set(PYTHON_EXTERNALS_FOLDER ${BUILD_DIR}/python/src/external_python/externals) + set(ZLIB_SOURCE_FOLDER ${BUILD_DIR}/zlib/src/external_zlib) set(DOWNLOADS_EXTERNALS_FOLDER ${DOWNLOAD_DIR}/externals) cmake_to_dos_path(${PYTHON_EXTERNALS_FOLDER} PYTHON_EXTERNALS_FOLDER_DOS) + cmake_to_dos_path(${ZLIB_SOURCE_FOLDER} ZLIB_SOURCE_FOLDER_DOS) cmake_to_dos_path(${DOWNLOADS_EXTERNALS_FOLDER} DOWNLOADS_EXTERNALS_FOLDER_DOS) ExternalProject_Add(external_python @@ -25,12 +27,21 @@ if(WIN32) DOWNLOAD_DIR ${DOWNLOAD_DIR} URL_HASH ${PYTHON_HASH_TYPE}=${PYTHON_HASH} PREFIX ${BUILD_DIR}/python - CONFIGURE_COMMAND "" + # Python will download its own deps and there's very little we can do about + # that beyond placing some code in their externals dir before it tries. + # the foldernames *HAVE* to match the ones inside pythons get_externals.cmd. + # python 3.10.8 still ships zlib 1.2.12, replace it with our 1.2.13 + # copy until they update. + CONFIGURE_COMMAND mkdir ${PYTHON_EXTERNALS_FOLDER_DOS} && + mklink /J ${PYTHON_EXTERNALS_FOLDER_DOS}\\zlib-1.2.12 ${ZLIB_SOURCE_FOLDER_DOS} && + ${CMAKE_COMMAND} -E copy ${ZLIB_SOURCE_FOLDER}/../external_zlib-build/zconf.h ${PYTHON_EXTERNALS_FOLDER}/zlib-1.2.12/zconf.h BUILD_COMMAND cd ${BUILD_DIR}/python/src/external_python/pcbuild/ && set IncludeTkinter=false && call build.bat -e -p x64 -c ${BUILD_MODE} - PATCH_COMMAND ${PATCH_CMD} --verbose -p1 -d ${BUILD_DIR}/python/src/external_python < ${PATCH_DIR}/python_windows.diff INSTALL_COMMAND ${PYTHON_BINARY_INTERNAL} ${PYTHON_SRC}/PC/layout/main.py -b ${PYTHON_SRC}/PCbuild/amd64 -s ${PYTHON_SRC} -t ${PYTHON_SRC}/tmp/ --include-stable --include-pip --include-dev --include-launchers --include-venv --include-symbols ${PYTHON_EXTRA_INSTLAL_FLAGS} --copy ${LIBDIR}/python ) - + add_dependencies( + external_python + external_zlib + ) else() if(APPLE) # Disable functions that can be in 10.13 sdk but aren't available on 10.9 target. diff --git a/build_files/build_environment/cmake/sndfile.cmake b/build_files/build_environment/cmake/sndfile.cmake index 192c25f5ed1..a2ac2a33779 100644 --- a/build_files/build_environment/cmake/sndfile.cmake +++ b/build_files/build_environment/cmake/sndfile.cmake @@ -11,18 +11,11 @@ else() set(SNDFILE_OPTIONS --enable-static --disable-shared ) endif() -if(UNIX) - set(SNDFILE_PATCH_CMD ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/sndfile/src/external_sndfile < ${PATCH_DIR}/sndfile.diff) -else() - set(SNDFILE_PATCH_CMD) -endif() - ExternalProject_Add(external_sndfile URL file://${PACKAGE_DIR}/${SNDFILE_FILE} DOWNLOAD_DIR ${DOWNLOAD_DIR} URL_HASH ${SNDFILE_HASH_TYPE}=${SNDFILE_HASH} PREFIX ${BUILD_DIR}/sndfile - PATCH_COMMAND ${SNDFILE_PATCH_CMD} CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sndfile/src/external_sndfile/ && ${SNDFILE_ENV} ${CONFIGURE_COMMAND} ${SNDFILE_OPTIONS} --prefix=${mingw_LIBDIR}/sndfile BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sndfile/src/external_sndfile/ && make -j${MAKE_THREADS} INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sndfile/src/external_sndfile/ && make install diff --git a/build_files/build_environment/cmake/sqlite.cmake b/build_files/build_environment/cmake/sqlite.cmake index c82d832574a..c151a495ff1 100644 --- a/build_files/build_environment/cmake/sqlite.cmake +++ b/build_files/build_environment/cmake/sqlite.cmake @@ -48,7 +48,6 @@ ExternalProject_Add(external_sqlite DOWNLOAD_DIR ${DOWNLOAD_DIR} URL_HASH ${SQLITE_HASH_TYPE}=${SQLITE_HASH} PREFIX ${BUILD_DIR}/sqlite - PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/sqlite/src/external_sqlite < ${PATCH_DIR}/sqlite.diff CONFIGURE_COMMAND ${SQLITE_CONFIGURE_ENV} && cd ${BUILD_DIR}/sqlite/src/external_sqlite/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/sqlite ${SQLITE_CONFIGURATION_ARGS} BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sqlite/src/external_sqlite/ && make -j${MAKE_THREADS} INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sqlite/src/external_sqlite/ && make install diff --git a/build_files/build_environment/cmake/ssl.cmake b/build_files/build_environment/cmake/ssl.cmake index 21c4d2418c3..628187dc0ac 100644 --- a/build_files/build_environment/cmake/ssl.cmake +++ b/build_files/build_environment/cmake/ssl.cmake @@ -5,6 +5,7 @@ set(SSL_PATCH_CMD echo .) if(APPLE) set(SSL_OS_COMPILER "blender-darwin-${CMAKE_OSX_ARCHITECTURES}") + set(SSL_PATCH_CMD ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/ssl/src/external_ssl < ${PATCH_DIR}/ssl.diff) else() if(BLENDER_PLATFORM_ARM) set(SSL_OS_COMPILER "blender-linux-aarch64") diff --git a/build_files/build_environment/cmake/tiff.cmake b/build_files/build_environment/cmake/tiff.cmake index 1f8e9442ae5..1ac2e4c6058 100644 --- a/build_files/build_environment/cmake/tiff.cmake +++ b/build_files/build_environment/cmake/tiff.cmake @@ -25,6 +25,7 @@ ExternalProject_Add(external_tiff add_dependencies( external_tiff external_zlib + external_jpeg ) if(WIN32) if(BUILD_MODE STREQUAL Release) diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake index 6f358fd6f86..5fa138ff01b 100644 --- a/build_files/build_environment/cmake/versions.cmake +++ b/build_files/build_environment/cmake/versions.cmake @@ -8,9 +8,9 @@ # Not all of our dependencies are currently in the nvd database so not all # dependencies have one assigned. -set(ZLIB_VERSION 1.2.12) +set(ZLIB_VERSION 1.2.13) set(ZLIB_URI https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz) -set(ZLIB_HASH 5fc414a9726be31427b440b434d05f78) +set(ZLIB_HASH 9b8aa094c4e5765dabf4da391f00d15c) set(ZLIB_HASH_TYPE MD5) set(ZLIB_FILE zlib-${ZLIB_VERSION}.tar.gz) set(ZLIB_CPE "cpe:2.3:a:zlib:zlib:${ZLIB_VERSION}:*:*:*:*:*:*:*") @@ -88,9 +88,9 @@ else() set(OPENEXR_VERSION_POSTFIX) endif() -set(FREETYPE_VERSION 2.11.1) +set(FREETYPE_VERSION 2.12.1) set(FREETYPE_URI http://prdownloads.sourceforge.net/freetype/freetype-${FREETYPE_VERSION}.tar.gz) -set(FREETYPE_HASH bd4e3b007474319909a6b79d50908e85) +set(FREETYPE_HASH 8bc5c9c9df7ac12c504f8918552a7cf2) set(FREETYPE_HASH_TYPE MD5) set(FREETYPE_FILE freetype-${FREETYPE_VERSION}.tar.gz) SET(FREETYPE_CPE "cpe:2.3:a:freetype:freetype:${FREETYPE_VERSION}:*:*:*:*:*:*:*") @@ -159,9 +159,9 @@ set(OPENMP_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${ set(OPENMP_HASH_TYPE MD5) set(OPENMP_FILE openmp-${OPENMP_VERSION}.src.tar.xz) -set(OPENIMAGEIO_VERSION v2.3.13.0) +set(OPENIMAGEIO_VERSION v2.3.20.0) set(OPENIMAGEIO_URI https://github.com/OpenImageIO/oiio/archive/refs/tags/${OPENIMAGEIO_VERSION}.tar.gz) -set(OPENIMAGEIO_HASH de45fb38501c4581062b522b53b6141c) +set(OPENIMAGEIO_HASH defb1fe7c8e64bac60eb3cacaf5c3736) set(OPENIMAGEIO_HASH_TYPE MD5) set(OPENIMAGEIO_FILE OpenImageIO-${OPENIMAGEIO_VERSION}.tar.gz) @@ -195,11 +195,11 @@ set(OSL_HASH 6fef11548adfdd3e5b25c49d2dae96ee) set(OSL_HASH_TYPE MD5) set(OSL_FILE OpenShadingLanguage-${OSL_VERSION}.tar.gz) -set(PYTHON_VERSION 3.10.2) +set(PYTHON_VERSION 3.10.8) set(PYTHON_SHORT_VERSION 3.10) set(PYTHON_SHORT_VERSION_NO_DOTS 310) set(PYTHON_URI https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz) -set(PYTHON_HASH 14e8c22458ed7779a1957b26cde01db9) +set(PYTHON_HASH e92356b012ed4d0e09675131d39b1bde) set(PYTHON_HASH_TYPE MD5) set(PYTHON_FILE Python-${PYTHON_VERSION}.tar.xz) set(PYTHON_CPE "cpe:2.3:a:python:python:${PYTHON_VERSION}:-:*:*:*:*:*:*") @@ -298,17 +298,17 @@ set(XVIDCORE_HASH abbdcbd39555691dd1c9b4d08f0a031376a3b211652c0d8b3b8aa9be1303ce set(XVIDCORE_HASH_TYPE SHA256) set(XVIDCORE_FILE xvidcore-${XVIDCORE_VERSION}.tar.gz) -set(OPENJPEG_VERSION 2.4.0) -set(OPENJPEG_SHORT_VERSION 2.4) +set(OPENJPEG_VERSION 2.5.0) +set(OPENJPEG_SHORT_VERSION 2.5) set(OPENJPEG_URI https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSION}.tar.gz) -set(OPENJPEG_HASH 8702ba68b442657f11aaeb2b338443ca8d5fb95b0d845757968a7be31ef7f16d) +set(OPENJPEG_HASH 0333806d6adecc6f7a91243b2b839ff4d2053823634d4f6ed7a59bc87409122a) set(OPENJPEG_HASH_TYPE SHA256) set(OPENJPEG_FILE openjpeg-v${OPENJPEG_VERSION}.tar.gz) set(OPENJPEG_CPE "cpe:2.3:a:uclouvain:openjpeg:${OPENJPEG_VERSION}:*:*:*:*:*:*:*") -set(FFMPEG_VERSION 5.0) +set(FFMPEG_VERSION 5.1.2) set(FFMPEG_URI http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2) -set(FFMPEG_HASH c0130b8db2c763430fd1c6905288d61bc44ee0548ad5fcd2dfd650b88432bed9) +set(FFMPEG_HASH 39a0bcc8d98549f16c570624678246a6ac736c066cebdb409f9502e915b22f2b) set(FFMPEG_HASH_TYPE SHA256) set(FFMPEG_FILE ffmpeg-${FFMPEG_VERSION}.tar.bz2) set(FFMPEG_CPE "cpe:2.3:a:ffmpeg:ffmpeg:${FFMPEG_VERSION}:*:*:*:*:*:*:*") @@ -325,9 +325,9 @@ set(ICONV_HASH 7d2a800b952942bb2880efb00cfd524c) set(ICONV_HASH_TYPE MD5) set(ICONV_FILE libiconv-${ICONV_VERSION}.tar.gz) -set(SNDFILE_VERSION 1.0.28) -set(SNDFILE_URI http://www.mega-nerd.com/libsndfile/files/libsndfile-${SNDFILE_VERSION}.tar.gz) -set(SNDFILE_HASH 646b5f98ce89ac60cdb060fcd398247c) +set(SNDFILE_VERSION 1.1.0) +set(SNDFILE_URI https://github.com/libsndfile/libsndfile/releases/download/1.1.0/libsndfile-${SNDFILE_VERSION}.tar.xz) +set(SNDFILE_HASH e63dead2b4f0aaf323687619d007ee6a) set(SNDFILE_HASH_TYPE MD5) set(SNDFILE_FILE libsndfile-${SNDFILE_VERSION}.tar.gz) set(SNDFILE_CPE "cpe:2.3:a:libsndfile_project:libsndfile:${SNDFILE_VERSION}:*:*:*:*:*:*:*") @@ -351,21 +351,13 @@ set(JEMALLOC_HASH 3d41fbf006e6ebffd489bdb304d009ae) set(JEMALLOC_HASH_TYPE MD5) set(JEMALLOC_FILE jemalloc-${JEMALLOC_VERSION}.tar.bz2) -set(XML2_VERSION 2.9.10) -set(XML2_URI http://xmlsoft.org/sources/libxml2-${XML2_VERSION}.tar.gz) -set(XML2_HASH 10942a1dc23137a8aa07f0639cbfece5) +set(XML2_VERSION 2.10.3) +set(XML2_URI https://download.gnome.org/sources/libxml2/2.10/libxml2-${XML2_VERSION}.tar.xz) +set(XML2_HASH f9edac7fac232b3657a003fd9a5bbe42) set(XML2_HASH_TYPE MD5) -set(XML2_FILE libxml2-${XML2_VERSION}.tar.gz) +set(XML2_FILE libxml2-${XML2_VERSION}.tar.xz) set(XML2_CPE "cpe:2.3:a:xmlsoft:libxml2:${XML2_VERSION}:*:*:*:*:*:*:*") -set(TINYXML_VERSION 2_6_2) -set(TINYXML_VERSION_DOTS 2.6.2) -set(TINYXML_URI https://nchc.dl.sourceforge.net/project/tinyxml/tinyxml/${TINYXML_VERSION_DOTS}/tinyxml_${TINYXML_VERSION}.tar.gz) -set(TINYXML_HASH c1b864c96804a10526540c664ade67f0) -set(TINYXML_HASH_TYPE MD5) -set(TINYXML_FILE tinyxml_${TINYXML_VERSION}.tar.gz) -set(TINYXML_CPE "cpe:2.3:a:tinyxml_project:tinyxml:${TINYXML_VERSION_DOTS}:*:*:*:*:*:*:*") - set(YAMLCPP_VERSION 0.6.3) set(YAMLCPP_URI https://codeload.github.com/jbeder/yaml-cpp/tar.gz/yaml-cpp-${YAMLCPP_VERSION}) set(YAMLCPP_HASH b45bf1089a382e81f6b661062c10d0c2) @@ -379,10 +371,10 @@ set(PYSTRING_HASH f2c68786b359f5e4e62bed53bc4fb86d) set(PYSTRING_HASH_TYPE MD5) set(PYSTRING_FILE pystring-${PYSTRING_VERSION}.tar.gz) -set(EXPAT_VERSION 2_4_4) -set(EXPAT_VERSION_DOTS 2.4.4) +set(EXPAT_VERSION 2_4_9) +set(EXPAT_VERSION_DOTS 2.4.9) set(EXPAT_URI https://github.com/libexpat/libexpat/archive/R_${EXPAT_VERSION}.tar.gz) -set(EXPAT_HASH 2d3e81dee94b452369dc6394ff0f8f98) +set(EXPAT_HASH b59a2aa796be1ee177bbab3b7231dfa5) set(EXPAT_HASH_TYPE MD5) set(EXPAT_FILE libexpat-${EXPAT_VERSION}.tar.gz) set(EXPAT_CPE "cpe:2.3:a:libexpat_project:libexpat:${EXPAT_VERSION_DOTS}:*:*:*:*:*:*:*") @@ -410,6 +402,10 @@ set(FLEX_FILE flex-${FLEX_VERSION}.tar.gz) # NOTE: bzip.org domain does no longer belong to BZip 2 project, so we download # sources from Debian packaging. +# +# NOTE 2: This will *HAVE* to match the version python ships on windows which +# is hardcoded in pythons PCbuild/get_externals.bat. For compliance reasons there +# can be no exceptions to this. set(BZIP2_VERSION 1.0.8) set(BZIP2_URI http://http.debian.net/debian/pool/main/b/bzip2/bzip2_${BZIP2_VERSION}.orig.tar.gz) set(BZIP2_HASH ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269) @@ -417,6 +413,9 @@ set(BZIP2_HASH_TYPE SHA256) set(BZIP2_FILE bzip2_${BZIP2_VERSION}.orig.tar.gz) set(BZIP2_CPE "cpe:2.3:a:bzip:bzip2:${BZIP2_VERSION}:*:*:*:*:*:*:*") +# NOTE: This will *HAVE* to match the version python ships on windows which +# is hardcoded in pythons PCbuild/get_externals.bat. For compliance reasons there +# can be no exceptions to this. set(FFI_VERSION 3.3) set(FFI_URI https://sourceware.org/pub/libffi/libffi-${FFI_VERSION}.tar.gz) set(FFI_HASH 72fba7922703ddfa7a028d513ac15a85c8d54c8d67f55fa5a4802885dc652056) @@ -430,27 +429,25 @@ set(LZMA_HASH 5117f930900b341493827d63aa910ff5e011e0b994197c3b71c08a20228a42df) set(LZMA_HASH_TYPE SHA256) set(LZMA_FILE xz-${LZMA_VERSION}.tar.bz2) -if(BLENDER_PLATFORM_ARM) - # Need at least 1.1.1i for aarch64 support (https://github.com/openssl/openssl/pull/13218) - set(SSL_VERSION 1.1.1i) - set(SSL_URI https://www.openssl.org/source/openssl-${SSL_VERSION}.tar.gz) - set(SSL_HASH e8be6a35fe41d10603c3cc635e93289ed00bf34b79671a3a4de64fcee00d5242) - set(SSL_HASH_TYPE SHA256) - set(SSL_FILE openssl-${SSL_VERSION}.tar.gz) -else() - set(SSL_VERSION 1.1.1g) - set(SSL_URI https://www.openssl.org/source/openssl-${SSL_VERSION}.tar.gz) - set(SSL_HASH ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46) - set(SSL_HASH_TYPE SHA256) - set(SSL_FILE openssl-${SSL_VERSION}.tar.gz) -endif() +# NOTE: This will *HAVE* to match the version python ships on windows which +# is hardcoded in pythons PCbuild/get_externals.bat. For compliance reasons there +# can be no exceptions to this. +set(SSL_VERSION 1.1.1q) +set(SSL_URI https://www.openssl.org/source/openssl-${SSL_VERSION}.tar.gz) +set(SSL_HASH d7939ce614029cdff0b6c20f0e2e5703158a489a72b2507b8bd51bf8c8fd10ca) +set(SSL_HASH_TYPE SHA256) +set(SSL_FILE openssl-${SSL_VERSION}.tar.gz) set(SSL_CPE "cpe:2.3:a:openssl:openssl:${SSL_VERSION}:*:*:*:*:*:*:*") -set(SQLITE_VERSION 3.31.1) -set(SQLITE_URI https://www.sqlite.org/2018/sqlite-src-3240000.zip) -set(SQLITE_HASH fb558c49ee21a837713c4f1e7e413309aabdd9c7) +# Note: This will *HAVE* to match the version python ships on windows which +# is hardcoded in pythons PCbuild/get_externals.bat for compliance reasons there +# can be no exceptions to this. +set(SQLITE_VERSION 3.37.2) +set(SQLLITE_LONG_VERSION 3370200) +set(SQLITE_URI https://www.sqlite.org/2022/sqlite-autoconf-${SQLLITE_LONG_VERSION}.tar.gz) +set(SQLITE_HASH e56faacadfb4154f8fbd0f2a3f827d13706b70a1) set(SQLITE_HASH_TYPE SHA1) -set(SQLITE_FILE sqlite-src-3240000.zip) +set(SQLITE_FILE sqlite-autoconf-${SQLLITE_LONG_VERSION}.tar.gz) set(SQLITE_CPE "cpe:2.3:a:sqlite:sqlite:${SQLITE_VERSION}:*:*:*:*:*:*:*") set(EMBREE_VERSION 3.13.4) diff --git a/build_files/build_environment/cmake/wayland.cmake b/build_files/build_environment/cmake/wayland.cmake index 799f2513da9..c73db1d10ff 100644 --- a/build_files/build_environment/cmake/wayland.cmake +++ b/build_files/build_environment/cmake/wayland.cmake @@ -7,10 +7,14 @@ ExternalProject_Add(external_wayland PREFIX ${BUILD_DIR}/wayland PATCH_COMMAND ${PATCH_CMD} -d ${BUILD_DIR}/wayland/src/external_wayland < ${PATCH_DIR}/wayland.diff # Use `-E` so the `PKG_CONFIG_PATH` can be defined to link against our own LIBEXPAT & LIBXML2. - # Note that passing link args "ffi/lib" should not be needed, but + # + # NOTE: passing link args "ffi/lib" should not be needed, but # `pkgconfig` would incorrectly look in "ffi/lib/../lib64" otherwise. + # + # NOTE: `-lm` is needed for `libxml2` which is a static library that uses `libm.so`, + # without this, math symbols such as `floor` aren't found. CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env PKG_CONFIG_PATH=${LIBDIR}/expat/lib/pkgconfig:${LIBDIR}/xml2/lib/pkgconfig:${LIBDIR}/ffi/lib/pkgconfig:$PKG_CONFIG_PATH - meson --prefix ${LIBDIR}/wayland -Ddocumentation=false -Dtests=false -Dc_link_args=-L${LIBDIR}/ffi/lib . ../external_wayland + meson --prefix ${LIBDIR}/wayland -Ddocumentation=false -Dtests=false -D "c_link_args=-L${LIBDIR}/ffi/lib -lm" . ../external_wayland BUILD_COMMAND ninja INSTALL_COMMAND ninja install ) diff --git a/build_files/build_environment/dependencies.dot b/build_files/build_environment/dependencies.dot index 7e8637fbced..bb42856c3ac 100644 --- a/build_files/build_environment/dependencies.dot +++ b/build_files/build_environment/dependencies.dot @@ -1,96 +1,114 @@ strict graph { -graph[autosize = false, size = "25.7,8.3!", resolution = 300, overlap = false, splines = false, outputorder=edgesfirst ]; - node [style=filled fillcolor=white]; - external_alembic -- external_boost; - external_alembic -- external_zlib; +graph[autosize = false, size = "25.7,8.3!", resolution = 300]; external_alembic -- external_openexr; + external_alembic -- external_imath; external_blosc -- external_zlib; external_blosc -- external_pthreads; - external_boost -- Make_Python_Environment; - external_clang -- ll; + external_boost -- external_python; + external_boost -- external_numpy; + external_dpcpp -- external_python; + external_dpcpp -- external_python_site_packages; + external_dpcpp -- external_vcintrinsics; + external_dpcpp -- external_openclheaders; + external_dpcpp -- external_icdloader; + external_dpcpp -- external_mp11; + external_dpcpp -- external_level_zero; + external_dpcpp -- external_spirvheaders; + external_embree -- external_tbb; external_ffmpeg -- external_zlib; - external_ffmpeg -- external_faad; external_ffmpeg -- external_openjpeg; external_ffmpeg -- external_xvidcore; external_ffmpeg -- external_x264; + external_ffmpeg -- external_opus; external_ffmpeg -- external_vpx; external_ffmpeg -- external_theora; external_ffmpeg -- external_vorbis; external_ffmpeg -- external_ogg; external_ffmpeg -- external_lame; + external_ffmpeg -- external_aom; external_ffmpeg -- external_zlib_mingw; - external_numpy -- Make_Python_Environment; + external_ffmpeg -- external_nasm; + external_freetype -- external_brotli; + external_freetype -- external_zlib; + external_gmpxx -- external_gmp; + external_igc_llvm -- external_igc_opencl_clang; + external_igc_spirv_translator -- external_igc_opencl_clang; + external_igc -- external_igc_vcintrinsics; + external_igc -- external_igc_llvm; + external_igc -- external_igc_opencl_clang; + external_igc -- external_igc_vcintrinsics; + external_igc -- external_igc_spirv_headers; + external_igc -- external_igc_spirv_tools; + external_igc -- external_igc_spirv_translator; + external_igc -- external_flex; + external_ispc -- ll; + external_ispc -- external_python; + external_ispc -- external_flexbison; + external_ispc -- external_flex; + ll -- external_xml2; + ll -- external_python; + external_mesa -- ll; + external_numpy -- external_python; + external_numpy -- external_python_site_packages; + external_ocloc -- external_igc; + external_ocloc -- external_gmmlib; external_opencollada -- external_xml2; - external_opencolorio -- external_boost; - external_opencolorio -- external_tinyxml; external_opencolorio -- external_yamlcpp; + external_opencolorio -- external_expat; + external_opencolorio -- external_imath; + external_opencolorio -- external_pystring; external_openexr -- external_zlib; + external_openimagedenoise -- external_tbb; + external_openimagedenoise -- external_ispc; + external_openimagedenoise -- external_python; external_openimageio -- external_png; external_openimageio -- external_zlib; external_openimageio -- external_openexr; - external_openimageio -- external_openexr; + external_openimageio -- external_imath; external_openimageio -- external_jpeg; external_openimageio -- external_boost; external_openimageio -- external_tiff; - external_openimageio -- external_opencolorio; + external_openimageio -- external_pugixml; + external_openimageio -- external_fmt; + external_openimageio -- external_robinmap; external_openimageio -- external_openjpeg; external_openimageio -- external_webp; - external_openimageio -- external_opencolorio_extra; - external_openmp -- external_clang; + external_openmp -- ll; + external_openpgl -- external_tbb; external_opensubdiv -- external_tbb; openvdb -- external_tbb; openvdb -- external_boost; - openvdb -- external_openexr; - openvdb -- external_openexr; openvdb -- external_zlib; openvdb -- external_blosc; external_osl -- external_boost; external_osl -- ll; - external_osl -- external_clang; - external_osl -- external_openexr; external_osl -- external_openexr; external_osl -- external_zlib; - external_osl -- external_flexbison; external_osl -- external_openimageio; external_osl -- external_pugixml; + external_osl -- external_flexbison; + external_osl -- external_flex; external_png -- external_zlib; - external_python_site_packages -- Make_Python_Environment; + external_python -- external_bzip2; + external_python -- external_ffi; + external_python -- external_lzma; + external_python -- external_ssl; + external_python -- external_sqlite; + external_python -- external_zlib; + external_python_site_packages -- external_python; external_sndfile -- external_ogg; external_sndfile -- external_vorbis; external_sndfile -- external_flac; external_theora -- external_vorbis; external_theora -- external_ogg; external_tiff -- external_zlib; + external_usd -- external_tbb; + external_usd -- external_boost; + external_usd -- external_opensubdiv; external_vorbis -- external_ogg; - blender-- external_ffmpeg; - blender-- external_alembic; - blender-- external_openjpeg; - blender-- external_opencolorio; - blender-- external_openexr; - blender-- external_opensubdiv; - blender-- openvdb; - blender-- external_osl; - blender-- external_boost; - blender-- external_jpeg; - blender-- external_png; - blender-- external_python; - blender-- external_sndfile; - blender-- external_iconv; - blender-- external_fftw3; - external_python-- external_python_site_packages; - external_python_site_packages-- requests; - external_python_site_packages-- idna; - external_python_site_packages-- chardet; - external_python_site_packages-- urllib3; - external_python_site_packages-- certifi; - external_python-- external_numpy; - external_usd-- external_boost; - external_usd-- external_tbb; - blender-- external_opencollada; - blender-- external_sdl; - blender-- external_freetype; - blender-- external_pthreads; - blender-- external_zlib; - blender-- external_openal; - blender-- external_usd; + external_wayland -- external_expat; + external_wayland -- external_xml2; + external_wayland -- external_ffi; + external_wayland_protocols -- external_wayland; + external_x264 -- external_nasm; } diff --git a/build_files/build_environment/patches/aom.diff b/build_files/build_environment/patches/aom.diff new file mode 100644 index 00000000000..1611cff5dca --- /dev/null +++ b/build_files/build_environment/patches/aom.diff @@ -0,0 +1,18 @@ +diff -Naur libaom-3.4.0/build/cmake/aom_configure.cmake external_aom/build/cmake/aom_configure.cmake +--- libaom-3.4.0/build/cmake/aom_configure.cmake 2022-06-17 11:46:18 -0600 ++++ external_aom/build/cmake/aom_configure.cmake 2022-10-16 15:35:54 -0600 +@@ -15,8 +15,12 @@ + + include(FindGit) + include(FindPerl) +-include(FindThreads) +- ++# Blender: This will drag in a dep on libwinpthreads which we prefer ++# not to have, aom will fallback on a native win32 thread wrapper ++# if pthreads are not found. ++if(NOT WIN32) ++ include(FindThreads) ++endif() + include("${AOM_ROOT}/build/cmake/aom_config_defaults.cmake") + include("${AOM_ROOT}/build/cmake/aom_experiment_deps.cmake") + include("${AOM_ROOT}/build/cmake/aom_optimization.cmake") diff --git a/build_files/build_environment/patches/ffmpeg.diff b/build_files/build_environment/patches/ffmpeg.diff index c255f7c37a3..ac104a20ffe 100644 --- a/build_files/build_environment/patches/ffmpeg.diff +++ b/build_files/build_environment/patches/ffmpeg.diff @@ -68,34 +68,18 @@ + return ret; } ---- a/libavcodec/rl.c -+++ b/libavcodec/rl.c -@@ -71,17 +71,19 @@ - av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size) - { - int i, q; -- VLC_TYPE table[1500][2] = {{0}}; -+ VLC_TYPE (*table)[2] = av_calloc(sizeof(VLC_TYPE), 1500 * 2); - VLC vlc = { .table = table, .table_allocated = static_size }; -- av_assert0(static_size <= FF_ARRAY_ELEMS(table)); -+ av_assert0(static_size < 1500); - init_vlc(&vlc, 9, rl->n + 1, &rl->table_vlc[0][1], 4, 2, &rl->table_vlc[0][0], 4, 2, INIT_VLC_USE_NEW_STATIC); +diff --git a/libavcodec/x86/simple_idct.asm b/libavcodec/x86/simple_idct.asm +index dcf0da6df121..982b2f0bbba1 100644 +--- a/libavcodec/x86/simple_idct.asm ++++ b/libavcodec/x86/simple_idct.asm +@@ -25,9 +25,9 @@ - for (q = 0; q < 32; q++) { - int qmul = q * 2; - int qadd = (q - 1) | 1; + %include "libavutil/x86/x86util.asm" -- if (!rl->rl_vlc[q]) -+ if (!rl->rl_vlc[q]){ -+ av_free(table); - return; -+ } +-%if ARCH_X86_32 + SECTION_RODATA - if (q == 0) { - qmul = 1; -@@ -113,4 +115,5 @@ - rl->rl_vlc[q][i].run = run; - } - } -+ av_free(table); - } ++%if ARCH_X86_32 + cextern pb_80 + + wm1010: dw 0, 0xffff, 0, 0xffff diff --git a/build_files/build_environment/patches/gmp.diff b/build_files/build_environment/patches/gmp.diff new file mode 100644 index 00000000000..bf22f93bc4f --- /dev/null +++ b/build_files/build_environment/patches/gmp.diff @@ -0,0 +1,15 @@ +--- a/mpz/inp_raw.c Tue Dec 22 23:49:51 2020 +0100 ++++ b/mpz/inp_raw.c Thu Oct 21 19:06:49 2021 +0200 +@@ -88,8 +88,11 @@ + + abs_csize = ABS (csize); + ++ if (UNLIKELY (abs_csize > ~(mp_bitcnt_t) 0 / 8)) ++ return 0; /* Bit size overflows */ ++ + /* round up to a multiple of limbs */ +- abs_xsize = BITS_TO_LIMBS (abs_csize*8); ++ abs_xsize = BITS_TO_LIMBS ((mp_bitcnt_t) abs_csize * 8); + + if (abs_xsize != 0) + { diff --git a/build_files/build_environment/patches/osl.diff b/build_files/build_environment/patches/osl.diff index 28e1d6e101d..3f4a485b037 100644 --- a/build_files/build_environment/patches/osl.diff +++ b/build_files/build_environment/patches/osl.diff @@ -1,67 +1,53 @@ -diff -Naur OpenShadingLanguage-Release-1.9.9/src/include/OSL/llvm_util.h external_osl/src/include/OSL/llvm_util.h ---- OpenShadingLanguage-Release-1.9.9/src/include/OSL/llvm_util.h 2018-05-01 16:39:02 -0600 -+++ external_osl/src/include/OSL/llvm_util.h 2018-08-25 14:05:00 -0600 -@@ -33,6 +33,8 @@ - - #include - -+#define OSL_HAS_BLENDER_CLEANUP_FIX -+ - #ifdef LLVM_NAMESPACE - namespace llvm = LLVM_NAMESPACE; - #endif -@@ -487,6 +489,7 @@ - std::string func_name (llvm::Function *f); - - static size_t total_jit_memory_held (); -+ static void Cleanup (); - - private: - class MemoryManager; -diff -Naur OpenShadingLanguage-Release-1.9.9/src/liboslexec/llvm_util.cpp external_osl/src/liboslexec/llvm_util.cpp ---- OpenShadingLanguage-Release-1.9.9/src/liboslexec/llvm_util.cpp 2018-05-01 16:39:02 -0600 -+++ external_osl/src/liboslexec/llvm_util.cpp 2018-08-25 14:04:27 -0600 -@@ -140,7 +140,10 @@ - }; - - -- -+void LLVM_Util::Cleanup () -+{ -+ if(jitmm_hold) jitmm_hold->clear(); -+} - - size_t - LLVM_Util::total_jit_memory_held () -diff -Naur org/CMakeLists.txt external_osl/CMakeLists.txt ---- org/CMakeLists.txt 2020-12-01 12:37:15 -0700 -+++ external_osl/CMakeLists.txt 2021-01-20 13:26:50 -0700 -@@ -84,6 +84,11 @@ +diff -Naur OpenShadingLanguage-1.12.6.2/CMakeLists.txt external_osl/CMakeLists.txt +--- OpenShadingLanguage-1.12.6.2/CMakeLists.txt 2022-09-30 17:43:53 -0600 ++++ external_osl/CMakeLists.txt 2022-10-15 14:49:26 -0600 +@@ -101,6 +101,11 @@ CACHE STRING "Directory where OptiX PTX files will be installed") set (CMAKE_DEBUG_POSTFIX "" CACHE STRING "Library naming postfix for Debug builds (e.g., '_debug')") - + +set (USE_OIIO_STATIC ON CACHE BOOL "If OIIO is built static") +if (USE_OIIO_STATIC) + add_definitions ("-DOIIO_STATIC_BUILD=1") + add_definitions ("-DOIIO_STATIC_DEFINE=1") +endif () - + set (OSL_NO_DEFAULT_TEXTURESYSTEM OFF CACHE BOOL "Do not use create a raw OIIO::TextureSystem") if (OSL_NO_DEFAULT_TEXTURESYSTEM) -diff -Naur external_osl_orig/src/cmake/externalpackages.cmake external_osl/src/cmake/externalpackages.cmake ---- external_osl_orig/src/cmake/externalpackages.cmake 2021-06-01 13:44:18 -0600 -+++ external_osl/src/cmake/externalpackages.cmake 2021-06-28 07:44:32 -0600 -@@ -80,6 +80,7 @@ - - +diff -Naur OpenShadingLanguage-1.12.6.2/src/cmake/externalpackages.cmake external_osl/src/cmake/externalpackages.cmake +--- OpenShadingLanguage-1.12.6.2/src/cmake/externalpackages.cmake 2022-09-30 17:43:53 -0600 ++++ external_osl/src/cmake/externalpackages.cmake 2022-10-15 14:49:26 -0600 +@@ -77,6 +77,7 @@ + + checked_find_package (ZLIB REQUIRED) # Needed by several packages +checked_find_package (PNG REQUIRED) # Needed since OIIO needs it - + # IlmBase & OpenEXR checked_find_package (OpenEXR REQUIRED -diff -Naur external_osl_orig/src/liboslcomp/oslcomp.cpp external_osl/src/liboslcomp/oslcomp.cpp ---- external_osl_orig/src/liboslcomp/oslcomp.cpp 2021-06-01 13:44:18 -0600 -+++ external_osl/src/liboslcomp/oslcomp.cpp 2021-06-28 09:11:06 -0600 +diff -Naur OpenShadingLanguage-1.12.6.2/src/include/OSL/llvm_util.h external_osl/src/include/OSL/llvm_util.h +--- OpenShadingLanguage-1.12.6.2/src/include/OSL/llvm_util.h 2022-09-30 17:43:53 -0600 ++++ external_osl/src/include/OSL/llvm_util.h 2022-10-15 15:37:24 -0600 +@@ -9,6 +9,8 @@ + #include + #include + ++#define OSL_HAS_BLENDER_CLEANUP_FIX ++ + #ifdef LLVM_NAMESPACE + namespace llvm = LLVM_NAMESPACE; + #endif +@@ -455,7 +457,7 @@ + llvm::BasicBlock* masked_return_block() const; + + bool is_masking_required() const { return m_is_masking_required; } +- ++ static void Cleanup (); + struct ScopedMasking { + ScopedMasking() {} + +diff -Naur OpenShadingLanguage-1.12.6.2/src/liboslcomp/oslcomp.cpp external_osl/src/liboslcomp/oslcomp.cpp +--- OpenShadingLanguage-1.12.6.2/src/liboslcomp/oslcomp.cpp 2022-09-30 17:43:53 -0600 ++++ external_osl/src/liboslcomp/oslcomp.cpp 2022-10-15 14:49:26 -0600 @@ -21,6 +21,13 @@ #if !defined(__STDC_CONSTANT_MACROS) # define __STDC_CONSTANT_MACROS 1 @@ -76,3 +62,50 @@ diff -Naur external_osl_orig/src/liboslcomp/oslcomp.cpp external_osl/src/liboslc #include #include #include +diff -Naur OpenShadingLanguage-1.12.6.2/src/liboslexec/llvm_util.cpp external_osl/src/liboslexec/llvm_util.cpp +--- OpenShadingLanguage-1.12.6.2/src/liboslexec/llvm_util.cpp 2022-09-30 17:43:53 -0600 ++++ external_osl/src/liboslexec/llvm_util.cpp 2022-10-15 15:53:11 -0600 +@@ -116,8 +116,6 @@ + return { A.data(), size_t(A.size()) }; + } + +- +- + namespace pvt { + + typedef llvm::SectionMemoryManager LLVMMemoryManager; +@@ -182,6 +180,13 @@ + ++jit_mem_hold_users; + } + ++void ++LLVM_Util::Cleanup() ++{ ++ if (jitmm_hold) ++ jitmm_hold->clear(); ++} ++ + + LLVM_Util::ScopedJitMemoryUser::~ScopedJitMemoryUser() + { +diff --git a/src/include/OSL/mask.h b/src/include/OSL/mask.h +index 24197af..b9275f6 100644 +--- a/src/include/OSL/mask.h ++++ b/src/include/OSL/mask.h +@@ -4,7 +4,6 @@ + + #pragma once + +-#include + #include + + #include +@@ -23,6 +22,8 @@ using std::countr_zero; + + #elif OSL_INTEL_CLASSIC_COMPILER_VERSION + ++#include ++ + OSL_FORCEINLINE int popcount(uint32_t x) noexcept { return _mm_popcnt_u32(x);} + OSL_FORCEINLINE int popcount(uint64_t x) noexcept { return _mm_popcnt_u64(x); } + OSL_FORCEINLINE int countr_zero(uint32_t x) noexcept { return _bit_scan_forward(x); } diff --git a/build_files/build_environment/patches/python_windows.diff b/build_files/build_environment/patches/python_windows.diff deleted file mode 100644 index f9c89a90fde..00000000000 --- a/build_files/build_environment/patches/python_windows.diff +++ /dev/null @@ -1,24 +0,0 @@ -diff -Naur orig/PCbuild/get_externals.bat Python-3.10.2/PCbuild/get_externals.bat ---- orig/PCbuild/get_externals.bat 2022-01-13 11:52:14 -0700 -+++ Python-3.10.2/PCbuild/get_externals.bat 2022-08-17 11:24:42 -0600 -@@ -51,7 +51,7 @@ - echo.Fetching external libraries... - - set libraries= --set libraries=%libraries% bzip2-1.0.6 -+set libraries=%libraries% bzip2-1.0.8 - if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.3.0 - if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1m - set libraries=%libraries% sqlite-3.35.5.0 - diff -Naur orig/PCbuild/python.props external_python/PCbuild/python.props ---- orig/PCbuild/python.props 2022-01-13 11:52:14 -0700 -+++ external_python/PCbuild/python.props 2022-08-17 11:38:38 -0600 -@@ -58,7 +58,7 @@ - $([System.IO.Path]::GetFullPath(`$(PySourcePath)externals`)) - $(ExternalsDir)\ - $(ExternalsDir)sqlite-3.35.5.0\ -- $(ExternalsDir)bzip2-1.0.6\ -+ $(ExternalsDir)bzip2-1.0.8\ - $(ExternalsDir)xz-5.2.2\ - $(ExternalsDir)libffi-3.3.0\ - $(ExternalsDir)libffi-3.3.0\$(ArchName)\ diff --git a/build_files/build_environment/patches/sndfile.diff b/build_files/build_environment/patches/sndfile.diff deleted file mode 100644 index ab43baa78df..00000000000 --- a/build_files/build_environment/patches/sndfile.diff +++ /dev/null @@ -1,42 +0,0 @@ ---- src/Makefile.in 2017-09-26 01:28:47.000000000 +0300 -+++ src/Makefile.in 2017-09-26 01:19:06.000000000 +0300 -@@ -513,7 +513,7 @@ - libcommon_la_SOURCES = common.c file_io.c command.c pcm.c ulaw.c alaw.c \ - float32.c double64.c ima_adpcm.c ms_adpcm.c gsm610.c dwvw.c vox_adpcm.c \ - interleave.c strings.c dither.c cart.c broadcast.c audio_detect.c \ -- ima_oki_adpcm.c ima_oki_adpcm.h alac.c chunk.c ogg.c chanmap.c \ -+ ima_oki_adpcm.c ima_oki_adpcm.h alac.c chunk.c ogg.c chanmap.c \ - windows.c id3.c $(WIN_VERSION_FILE) - - -@@ -719,10 +719,10 @@ - $(AM_V_CCLD)$(LINK) $(GSM610_libgsm_la_OBJECTS) $(GSM610_libgsm_la_LIBADD) $(LIBS) - - libcommon.la: $(libcommon_la_OBJECTS) $(libcommon_la_DEPENDENCIES) $(EXTRA_libcommon_la_DEPENDENCIES) -- $(AM_V_CCLD)$(LINK) $(libcommon_la_OBJECTS) $(libcommon_la_LIBADD) $(LIBS) -+ $(AM_V_CCLD)$(LINK) $(libcommon_la_OBJECTS) $(libcommon_la_LIBADD) $(LIBS) $(EXTERNAL_XIPH_LIBS) - - libsndfile.la: $(libsndfile_la_OBJECTS) $(libsndfile_la_DEPENDENCIES) $(EXTRA_libsndfile_la_DEPENDENCIES) -- $(AM_V_CCLD)$(libsndfile_la_LINK) -rpath $(libdir) $(libsndfile_la_OBJECTS) $(libsndfile_la_LIBADD) $(LIBS) -+ $(AM_V_CCLD)$(libsndfile_la_LINK) -rpath $(libdir) $(libsndfile_la_OBJECTS) $(libsndfile_la_LIBADD) $(LIBS) $(EXTERNAL_XIPH_LIBS) - - clean-checkPROGRAMS: - @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ -@@ -924,7 +924,7 @@ - @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) -c -o libsndfile_la-dwd.lo `test -f 'dwd.c' || echo '$(srcdir)/'`dwd.c - - libsndfile_la-flac.lo: flac.c --@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) -MT libsndfile_la-flac.lo -MD -MP -MF $(DEPDIR)/libsndfile_la-flac.Tpo -c -o libsndfile_la-flac.lo `test -f 'flac.c' || echo '$(srcdir)/'`flac.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) $(EXTERNAL_XIPH_CFLAGS) -MT libsndfile_la-flac.lo -MD -MP -MF $(DEPDIR)/libsndfile_la-flac.Tpo -c -o libsndfile_la-flac.lo `test -f 'flac.c' || echo '$(srcdir)/'`flac.c - @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsndfile_la-flac.Tpo $(DEPDIR)/libsndfile_la-flac.Plo - @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='flac.c' object='libsndfile_la-flac.lo' libtool=yes @AMDEPBACKSLASH@ - @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@@ -1092,7 +1092,7 @@ - @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) -c -o libsndfile_la-rf64.lo `test -f 'rf64.c' || echo '$(srcdir)/'`rf64.c - - libsndfile_la-ogg_vorbis.lo: ogg_vorbis.c --@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) -MT libsndfile_la-ogg_vorbis.lo -MD -MP -MF $(DEPDIR)/libsndfile_la-ogg_vorbis.Tpo -c -o libsndfile_la-ogg_vorbis.lo `test -f 'ogg_vorbis.c' || echo '$(srcdir)/'`ogg_vorbis.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) $(EXTERNAL_XIPH_CFLAGS) -MT libsndfile_la-ogg_vorbis.lo -MD -MP -MF $(DEPDIR)/libsndfile_la-ogg_vorbis.Tpo -c -o libsndfile_la-ogg_vorbis.lo `test -f 'ogg_vorbis.c' || echo '$(srcdir)/'`ogg_vorbis.c - @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsndfile_la-ogg_vorbis.Tpo $(DEPDIR)/libsndfile_la-ogg_vorbis.Plo - @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ogg_vorbis.c' object='libsndfile_la-ogg_vorbis.lo' libtool=yes @AMDEPBACKSLASH@ - @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ diff --git a/build_files/build_environment/patches/sqlite.diff b/build_files/build_environment/patches/sqlite.diff deleted file mode 100644 index 80f1384f9cf..00000000000 --- a/build_files/build_environment/patches/sqlite.diff +++ /dev/null @@ -1,14 +0,0 @@ -Only in external_sqlite_orig: config.log -diff -ru external_sqlite_orig/config.sub external_sqlite/config.sub ---- external_sqlite_orig/config.sub 2020-07-10 14:06:42.000000000 +0200 -+++ external_sqlite/config.sub 2020-07-10 14:10:24.000000000 +0200 -@@ -314,6 +314,7 @@ - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ -+ | aarch64-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ -Only in external_sqlite: mksourceid -Only in external_sqlite: sqlite3session.h diff --git a/build_files/build_environment/patches/ssl.diff b/build_files/build_environment/patches/ssl.diff new file mode 100644 index 00000000000..7bb4413952c --- /dev/null +++ b/build_files/build_environment/patches/ssl.diff @@ -0,0 +1,10 @@ +--- ./test/v3ext.c 2022-07-05 11:08:33.000000000 +0200 ++++ ./test/v3ext.c 2022-10-18 13:58:05.000000000 +0200 +@@ -8,6 +8,7 @@ + */ + + #include ++#include + #include + #include + #include diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index 4478a2f8051..5fb921fc97d 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -679,11 +679,11 @@ endif() if(WITH_IMAGE_OPENJPEG) set(OPENJPEG ${LIBDIR}/openjpeg) - set(OPENJPEG_INCLUDE_DIRS ${OPENJPEG}/include/openjpeg-2.4) + set(OPENJPEG_INCLUDE_DIRS ${OPENJPEG}/include/openjpeg-2.5) if(NOT EXISTS "${OPENJPEG_INCLUDE_DIRS}") - # when not found, could be an older lib folder with openjpeg 2.3 - # to ease the transition period, fall back if 2.4 is not found. - set(OPENJPEG_INCLUDE_DIRS ${OPENJPEG}/include/openjpeg-2.3) + # when not found, could be an older lib folder with openjpeg 2.4 + # to ease the transition period, fall back if 2.5 is not found. + set(OPENJPEG_INCLUDE_DIRS ${OPENJPEG}/include/openjpeg-2.4) endif() set(OPENJPEG_LIBRARIES ${OPENJPEG}/lib/openjp2.lib) endif() -- cgit v1.2.3 From 0d7065504effe3fe7f1483e79e39162249fa5099 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 20 Oct 2022 13:26:47 +0200 Subject: Build: mark remaining CVEs reported by cve_check as mitigated or ignored After the last library update cve_check still reported some false positives. One GMP issues was mitigated with a patch in the library update. The others are ignored, with a description explaining why they do not affect Blender. Ref D16269, T101403 --- .../build_environment/cmake/cve_check.cmake | 4 +++- .../build_environment/cmake/cve_check.csv.in | 23 +++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/build_files/build_environment/cmake/cve_check.cmake b/build_files/build_environment/cmake/cve_check.cmake index dfb190bcffa..ac42444aef1 100644 --- a/build_files/build_environment/cmake/cve_check.cmake +++ b/build_files/build_environment/cmake/cve_check.cmake @@ -27,10 +27,12 @@ get_cmake_property(_variableNames VARIABLES) foreach (_variableName ${_variableNames}) if(_variableName MATCHES "CPE$") string(REPLACE ":" ";" CPE_LIST ${${_variableName}}) + string(REPLACE "_CPE" "_ID" CPE_DEPNAME ${_variableName}) list(GET CPE_LIST 3 CPE_VENDOR) list(GET CPE_LIST 4 CPE_NAME) list(GET CPE_LIST 5 CPE_VERSION) - set(SBOMCONTENTS "${SBOMCONTENTS}${CPE_VENDOR},${CPE_NAME},${CPE_VERSION}\n") + set(${CPE_DEPNAME} "${CPE_VENDOR},${CPE_NAME},${CPE_VERSION}") + set(SBOMCONTENTS "${SBOMCONTENTS}${CPE_VENDOR},${CPE_NAME},${CPE_VERSION},,,\n") endif() endforeach() configure_file(${CMAKE_SOURCE_DIR}/cmake/cve_check.csv.in ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv @ONLY) diff --git a/build_files/build_environment/cmake/cve_check.csv.in b/build_files/build_environment/cmake/cve_check.csv.in index 6e7e8db5609..734a24f8c77 100644 --- a/build_files/build_environment/cmake/cve_check.csv.in +++ b/build_files/build_environment/cmake/cve_check.csv.in @@ -1,2 +1,23 @@ -vendor,product,version +vendor,product,version,cve_number,remarks,comment +@OPENJPEG_ID@,CVE-2016-9675,Ignored,issue in convert command line tool not used by blender +@PYTHON_ID@,CVE-2009-2940,Ignored,issue in pygresql not used by blender +@PYTHON_ID@,CVE-2020-29396,Ignored,issue in odoo not used by blender +@PYTHON_ID@,CVE-2021-32052,Ignored,issue in django not used by blender +@PYTHON_ID@,CVE-2009-3720,Ignored,already fixed in libexpat version used +@SSL_ID@,CVE-2009-1390,Ignored,issue in mutt not used by blender +@SSL_ID@,CVE-2009-3765,Ignored,issue in mutt not used by blender +@SSL_ID@,CVE-2009-3766,Ignored,issue in mutt not used by blender +@SSL_ID@,CVE-2009-3767,Ignored,issue in ldap not used by blender +@SSL_ID@,CVE-2019-0190,Ignored,issue in apache not used by blender +@TIFF_ID@,CVE-2022-2056,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-2057,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-2058,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-2519,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-2520,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-2521,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-2953,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-34526,Ignored,issue in tiff command line tool not used by blender +@XML2_ID@,CVE-2016-3709,Ignored,not affecting blender and not considered a security issue upstream +@GMP_ID@,CVE-2021-43618,Mitigated,patched using upstream commit 561a9c25298e +@SQLITE_ID@,CVE-2022-35737,Ignored,only affects SQLITE_ENABLE_STAT4 compile option not used by blender or python @SBOMCONTENTS@ -- cgit v1.2.3 From fd7a3e262224e2936eee1216a8aa57e6e381aba6 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 19 Oct 2022 15:33:42 +0200 Subject: Cleanup: compiler warnings --- intern/ghost/intern/GHOST_SystemWayland.cpp | 90 ++++++++++++++--------------- intern/ghost/intern/GHOST_SystemWayland.h | 6 +- 2 files changed, 47 insertions(+), 49 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 264476f00bc..fb69973eac6 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -193,42 +193,42 @@ struct GWL_ModifierInfo { }; static const GWL_ModifierInfo g_modifier_info_table[MOD_INDEX_NUM] = { - [MOD_INDEX_SHIFT] = - { - .display_name = "Shift", - .xkb_id = XKB_MOD_NAME_SHIFT, - .key_l = GHOST_kKeyLeftShift, - .key_r = GHOST_kKeyRightShift, - .mod_l = GHOST_kModifierKeyLeftShift, - .mod_r = GHOST_kModifierKeyRightShift, - }, - [MOD_INDEX_ALT] = - { - .display_name = "Alt", - .xkb_id = XKB_MOD_NAME_ALT, - .key_l = GHOST_kKeyLeftAlt, - .key_r = GHOST_kKeyRightAlt, - .mod_l = GHOST_kModifierKeyLeftAlt, - .mod_r = GHOST_kModifierKeyRightAlt, - }, - [MOD_INDEX_CTRL] = - { - .display_name = "Control", - .xkb_id = XKB_MOD_NAME_CTRL, - .key_l = GHOST_kKeyLeftControl, - .key_r = GHOST_kKeyRightControl, - .mod_l = GHOST_kModifierKeyLeftControl, - .mod_r = GHOST_kModifierKeyRightControl, - }, - [MOD_INDEX_OS] = - { - .display_name = "OS", - .xkb_id = XKB_MOD_NAME_LOGO, - .key_l = GHOST_kKeyLeftOS, - .key_r = GHOST_kKeyRightOS, - .mod_l = GHOST_kModifierKeyLeftOS, - .mod_r = GHOST_kModifierKeyRightOS, - }, + /* MOD_INDEX_SHIFT */ + { + /* display_name */ "Shift", + /* xkb_id */ XKB_MOD_NAME_SHIFT, + /* key_l */ GHOST_kKeyLeftShift, + /* key_r */ GHOST_kKeyRightShift, + /* mod_l */ GHOST_kModifierKeyLeftShift, + /* mod_r */ GHOST_kModifierKeyRightShift, + }, + /* MOD_INDEX_ALT */ + { + /* display_name */ "Alt", + /* xkb_id */ XKB_MOD_NAME_ALT, + /* key_l */ GHOST_kKeyLeftAlt, + /* key_r */ GHOST_kKeyRightAlt, + /* mod_l */ GHOST_kModifierKeyLeftAlt, + /* mod_r */ GHOST_kModifierKeyRightAlt, + }, + /* MOD_INDEX_CTRL */ + { + /* display_name */ "Control", + /* xkb_id */ XKB_MOD_NAME_CTRL, + /* key_l */ GHOST_kKeyLeftControl, + /* key_r */ GHOST_kKeyRightControl, + /* mod_l */ GHOST_kModifierKeyLeftControl, + /* mod_r */ GHOST_kModifierKeyRightControl, + }, + /* MOD_INDEX_OS */ + { + /* display_name */ "OS", + /* xkb_id */ XKB_MOD_NAME_LOGO, + /* key_l */ GHOST_kKeyLeftOS, + /* key_r */ GHOST_kKeyRightOS, + /* mod_l */ GHOST_kModifierKeyLeftOS, + /* mod_r */ GHOST_kModifierKeyRightOS, + }, }; /** \} */ @@ -2989,11 +2989,10 @@ static void keyboard_handle_key(void *data, /* Start timer for repeating key, if applicable. */ if ((seat->key_repeat.rate > 0) && (etype == GHOST_kEventKeyDown) && xkb_keymap_key_repeats(xkb_state_get_keymap(seat->xkb_state), key_code)) { - key_repeat_payload = new GWL_KeyRepeatPlayload({ - .seat = seat, - .key_code = key_code, - .key_data = {.gkey = gkey}, - }); + key_repeat_payload = new GWL_KeyRepeatPlayload(); + key_repeat_payload->seat = seat; + key_repeat_payload->key_code = key_code; + key_repeat_payload->key_data.gkey = gkey; } } @@ -4683,11 +4682,10 @@ static GWL_SeatStateGrab seat_grab_state_from_mode(const GHOST_TGrabCursorMode m const bool use_software_confine) { /* Initialize all members. */ - const struct GWL_SeatStateGrab grab_state = { - /* Warping happens to require software cursor which also hides. */ - .use_lock = ELEM(mode, GHOST_kGrabWrap, GHOST_kGrabHide) || use_software_confine, - .use_confine = (mode == GHOST_kGrabNormal) && (use_software_confine == false), - }; + GWL_SeatStateGrab grab_state; + /* Warping happens to require software cursor which also hides. */ + grab_state.use_lock = ELEM(mode, GHOST_kGrabWrap, GHOST_kGrabHide) || use_software_confine; + grab_state.use_confine = (mode == GHOST_kGrabNormal) && (use_software_confine == false); return grab_state; } diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index 4e77c5b9c0b..23ffabf739e 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -88,7 +88,7 @@ class GHOST_SystemWayland : public GHOST_System { ~GHOST_SystemWayland() override; - GHOST_TSuccess init(); + GHOST_TSuccess init() override; bool processEvents(bool waitForEvent) override; @@ -149,8 +149,8 @@ class GHOST_SystemWayland : public GHOST_System { GHOST_TSuccess setCursorVisibility(bool visible); - bool supportsCursorWarp(); - bool supportsWindowPosition(); + bool supportsCursorWarp() override; + bool supportsWindowPosition() override; bool getCursorGrabUseSoftwareDisplay(const GHOST_TGrabCursorMode mode); -- cgit v1.2.3 From 7f2cd2d969cb227fcde406f68492492d97d1322e Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Thu, 20 Oct 2022 15:02:41 +0200 Subject: Realtime Compositor: Implement Tone Map node This patch implements the tone map node for the realtime compositor based on the two papers: Reinhard, Erik, et al. "Photographic tone reproduction for digital images." Proceedings of the 29th annual conference on Computer graphics and interactive techniques. 2002. Reinhard, Erik, and Kate Devlin. "Dynamic range reduction inspired by photoreceptor physiology." IEEE transactions on visualization and computer graphics 11.1 (2005): 13-24. The original implementation should be revisited later due to apparent incompatibilities with the reference papers, which makes the operation less useful. Differential Revision: https://developer.blender.org/D16306 Reviewed By: Clement Foucault --- .../algorithms/COM_algorithm_parallel_reduction.hh | 23 ++ .../intern/algorithm_parallel_reduction.cc | 66 ++++++ source/blender/gpu/CMakeLists.txt | 4 + .../compositor_tone_map_photoreceptor.glsl | 22 ++ .../compositor/compositor_tone_map_simple.glsl | 26 +++ .../infos/compositor_parallel_reduction_info.hh | 57 ++++- .../compositor_tone_map_photoreceptor_info.hh | 16 ++ .../infos/compositor_tone_map_simple_info.hh | 13 ++ source/blender/makesdna/DNA_node_types.h | 6 + .../composite/nodes/node_composite_tonemap.cc | 248 ++++++++++++++++++++- 10 files changed, 475 insertions(+), 6 deletions(-) create mode 100644 source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl create mode 100644 source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl create mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh create mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh diff --git a/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh b/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh index 9d0851eff84..b094782c18e 100644 --- a/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh +++ b/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh @@ -27,6 +27,13 @@ float sum_blue(Context &context, GPUTexture *texture); * coefficients to compute the luminance. */ float sum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients); +/* Computes the sum of the logarithm of the luminance of all pixels in the given texture, using the + * given luminance coefficients to compute the luminance. */ +float sum_log_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients); + +/* Computes the sum of the colors of all pixels in the given texture. */ +float4 sum_color(Context &context, GPUTexture *texture); + /* -------------------------------------------------------------------- * Sum Of Squared Difference Reductions. */ @@ -55,4 +62,20 @@ float sum_luminance_squared_difference(Context &context, float3 luminance_coefficients, float subtrahend); +/* -------------------------------------------------------------------- + * Maximum Reductions. + */ + +/* Computes the maximum luminance of all pixels in the given texture, using the given luminance + * coefficients to compute the luminance. */ +float maximum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients); + +/* -------------------------------------------------------------------- + * Minimum Reductions. + */ + +/* Computes the minimum luminance of all pixels in the given texture, using the given luminance + * coefficients to compute the luminance. */ +float minimum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients); + } // namespace blender::realtime_compositor diff --git a/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc b/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc index 3266ccd14eb..139c58bc190 100644 --- a/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc +++ b/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc @@ -134,6 +134,34 @@ float sum_luminance(Context &context, GPUTexture *texture, float3 luminance_coef return sum; } +float sum_log_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients) +{ + GPUShader *shader = context.shader_manager().get("compositor_sum_log_luminance"); + GPU_shader_bind(shader); + + GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients); + + float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F); + const float sum = *reduced_value; + MEM_freeN(reduced_value); + GPU_shader_unbind(); + + return sum; +} + +float4 sum_color(Context &context, GPUTexture *texture) +{ + GPUShader *shader = context.shader_manager().get("compositor_sum_color"); + GPU_shader_bind(shader); + + float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_RGBA32F); + const float4 sum = float4(reduced_value); + MEM_freeN(reduced_value); + GPU_shader_unbind(); + + return sum; +} + /* -------------------------------------------------------------------- * Sum Of Squared Difference Reductions. */ @@ -202,4 +230,42 @@ float sum_luminance_squared_difference(Context &context, return sum; } +/* -------------------------------------------------------------------- + * Maximum Reductions. + */ + +float maximum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients) +{ + GPUShader *shader = context.shader_manager().get("compositor_maximum_luminance"); + GPU_shader_bind(shader); + + GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients); + + float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F); + const float maximum = *reduced_value; + MEM_freeN(reduced_value); + GPU_shader_unbind(); + + return maximum; +} + +/* -------------------------------------------------------------------- + * Minimum Reductions. + */ + +float minimum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients) +{ + GPUShader *shader = context.shader_manager().get("compositor_minimum_luminance"); + GPU_shader_bind(shader); + + GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients); + + float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F); + const float minimum = *reduced_value; + MEM_freeN(reduced_value); + GPU_shader_unbind(); + + return minimum; +} + } // namespace blender::realtime_compositor diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 5a1e0cde1d8..56031b2722b 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -357,6 +357,8 @@ set(GLSL_SRC shaders/compositor/compositor_split_viewer.glsl shaders/compositor/compositor_symmetric_blur.glsl shaders/compositor/compositor_symmetric_separable_blur.glsl + shaders/compositor/compositor_tone_map_photoreceptor.glsl + shaders/compositor/compositor_tone_map_simple.glsl shaders/compositor/library/gpu_shader_compositor_alpha_over.glsl shaders/compositor/library/gpu_shader_compositor_blur_common.glsl @@ -639,6 +641,8 @@ set(SRC_SHADER_CREATE_INFOS shaders/compositor/infos/compositor_split_viewer_info.hh shaders/compositor/infos/compositor_symmetric_blur_info.hh shaders/compositor/infos/compositor_symmetric_separable_blur_info.hh + shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh + shaders/compositor/infos/compositor_tone_map_simple_info.hh ) set(SRC_SHADER_CREATE_INFOS_MTL diff --git a/source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl b/source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl new file mode 100644 index 00000000000..167006585ca --- /dev/null +++ b/source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl @@ -0,0 +1,22 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +/* Tone mapping based on equation (1) and the trilinear interpolation between equations (6) and (7) + * from Reinhard, Erik, and Kate Devlin. "Dynamic range reduction inspired by photoreceptor + * physiology." IEEE transactions on visualization and computer graphics 11.1 (2005): 13-24. */ +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + vec4 input_color = texture_load(input_tx, texel); + float input_luminance = dot(input_color.rgb, luminance_coefficients); + + /* Trilinear interpolation between equations (6) and (7) from Reinhard's 2005 paper. */ + vec4 local_adaptation_level = mix(vec4(input_luminance), input_color, chromatic_adaptation); + vec4 adaptation_level = mix(global_adaptation_level, local_adaptation_level, light_adaptation); + + /* Equation (1) from Reinhard's 2005 paper, assuming Vmax is 1. */ + vec4 semi_saturation = pow(intensity * adaptation_level, vec4(contrast)); + vec4 tone_mapped_color = input_color / (input_color + semi_saturation); + + imageStore(output_img, texel, vec4(tone_mapped_color.rgb, input_color.a)); +} diff --git a/source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl b/source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl new file mode 100644 index 00000000000..ce42d021dd1 --- /dev/null +++ b/source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl @@ -0,0 +1,26 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl) + +/* Tone mapping based on equation (3) from Reinhard, Erik, et al. "Photographic tone reproduction + * for digital images." Proceedings of the 29th annual conference on Computer graphics and + * interactive techniques. 2002. */ +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + vec4 input_color = texture_load(input_tx, texel); + + /* Equation (2) from Reinhard's 2002 paper. */ + vec4 scaled_color = input_color * luminance_scale; + + /* Equation (3) from Reinhard's 2002 paper, but with the 1 replaced with the blend factor for + * more flexibility. See ToneMapOperation::compute_luminance_scale_blend_factor. */ + vec4 denominator = luminance_scale_blend_factor + scaled_color; + vec4 tone_mapped_color = safe_divide(scaled_color, denominator); + + if (inverse_gamma != 0.0) { + tone_mapped_color = pow(max(tone_mapped_color, vec4(0.0)), vec4(inverse_gamma)); + } + + imageStore(output_img, texel, vec4(tone_mapped_color.rgb, input_color.a)); +} diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh index 2e661f280af..4a71bdc80e2 100644 --- a/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh +++ b/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh @@ -12,14 +12,17 @@ GPU_SHADER_CREATE_INFO(compositor_parallel_reduction_shared) * Sum Reductions. */ -GPU_SHADER_CREATE_INFO(compositor_sum_float_shared) +GPU_SHADER_CREATE_INFO(compositor_sum_shared) .additional_info("compositor_parallel_reduction_shared") - .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .define("TYPE", "float") .define("IDENTITY", "vec4(0.0)") - .define("LOAD(value)", "value.x") .define("REDUCE(lhs, rhs)", "lhs + rhs"); +GPU_SHADER_CREATE_INFO(compositor_sum_float_shared) + .additional_info("compositor_sum_shared") + .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .define("TYPE", "float") + .define("LOAD(value)", "value.x"); + GPU_SHADER_CREATE_INFO(compositor_sum_red) .additional_info("compositor_sum_float_shared") .define("INITIALIZE(value)", "value.r") @@ -41,6 +44,20 @@ GPU_SHADER_CREATE_INFO(compositor_sum_luminance) .define("INITIALIZE(value)", "dot(value.rgb, luminance_coefficients)") .do_static_compilation(true); +GPU_SHADER_CREATE_INFO(compositor_sum_log_luminance) + .additional_info("compositor_sum_float_shared") + .push_constant(Type::VEC3, "luminance_coefficients") + .define("INITIALIZE(value)", "log(max(dot(value.rgb, luminance_coefficients), 1e-5))") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_sum_color) + .additional_info("compositor_sum_shared") + .image(0, GPU_RGBA32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .define("TYPE", "vec4") + .define("INITIALIZE(value)", "value") + .define("LOAD(value)", "value") + .do_static_compilation(true); + /* -------------------------------------------------------------------- * Sum Of Squared Difference Reductions. */ @@ -74,3 +91,35 @@ GPU_SHADER_CREATE_INFO(compositor_sum_luminance_squared_difference) .push_constant(Type::VEC3, "luminance_coefficients") .define("INITIALIZE(value)", "pow(dot(value.rgb, luminance_coefficients) - subtrahend, 2.0)") .do_static_compilation(true); + +/* -------------------------------------------------------------------- + * Maximum Reductions. + */ + +GPU_SHADER_CREATE_INFO(compositor_maximum_luminance) + .additional_info("compositor_parallel_reduction_shared") + .typedef_source("common_math_lib.glsl") + .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .push_constant(Type::VEC3, "luminance_coefficients") + .define("TYPE", "float") + .define("IDENTITY", "vec4(FLT_MIN)") + .define("INITIALIZE(value)", "dot(value.rgb, luminance_coefficients)") + .define("LOAD(value)", "value.x") + .define("REDUCE(lhs, rhs)", "max(lhs, rhs)") + .do_static_compilation(true); + +/* -------------------------------------------------------------------- + * Minimum Reductions. + */ + +GPU_SHADER_CREATE_INFO(compositor_minimum_luminance) + .additional_info("compositor_parallel_reduction_shared") + .typedef_source("common_math_lib.glsl") + .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .push_constant(Type::VEC3, "luminance_coefficients") + .define("TYPE", "float") + .define("IDENTITY", "vec4(FLT_MAX)") + .define("INITIALIZE(value)", "dot(value.rgb, luminance_coefficients)") + .define("LOAD(value)", "value.x") + .define("REDUCE(lhs, rhs)", "min(lhs, rhs)") + .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh new file mode 100644 index 00000000000..a460c9d58a6 --- /dev/null +++ b/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_tone_map_photoreceptor) + .local_group_size(16, 16) + .push_constant(Type::VEC4, "global_adaptation_level") + .push_constant(Type::FLOAT, "contrast") + .push_constant(Type::FLOAT, "intensity") + .push_constant(Type::FLOAT, "chromatic_adaptation") + .push_constant(Type::FLOAT, "light_adaptation") + .push_constant(Type::VEC3, "luminance_coefficients") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_tone_map_photoreceptor.glsl") + .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh new file mode 100644 index 00000000000..2b220af9460 --- /dev/null +++ b/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_tone_map_simple) + .local_group_size(16, 16) + .push_constant(Type::FLOAT, "luminance_scale") + .push_constant(Type::FLOAT, "luminance_scale_blend_factor") + .push_constant(Type::FLOAT, "inverse_gamma") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_tone_map_simple.glsl") + .do_static_compilation(true); diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 315bcbd971c..c7962db8198 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -2083,6 +2083,12 @@ typedef enum CMPNodeLevelsChannel { CMP_NODE_LEVLES_LUMINANCE_BT709 = 5, } CMPNodeLevelsChannel; +/* Tone Map Node. Stored in NodeTonemap.type. */ +typedef enum CMPNodeToneMapType { + CMP_NODE_TONE_MAP_SIMPLE = 0, + CMP_NODE_TONE_MAP_PHOTORECEPTOR = 1, +} CMPNodeToneMapType; + /* Plane track deform node. */ enum { diff --git a/source/blender/nodes/composite/nodes/node_composite_tonemap.cc b/source/blender/nodes/composite/nodes/node_composite_tonemap.cc index 2e06ad99df1..d26a01bb3c9 100644 --- a/source/blender/nodes/composite/nodes/node_composite_tonemap.cc +++ b/source/blender/nodes/composite/nodes/node_composite_tonemap.cc @@ -5,20 +5,35 @@ * \ingroup cmpnodes */ +#include + +#include "BLI_assert.h" +#include "BLI_math_base.hh" +#include "BLI_math_vec_types.hh" +#include "BLI_math_vector.hh" + #include "RNA_access.h" #include "UI_interface.h" #include "UI_resources.h" +#include "IMB_colormanagement.h" + +#include "COM_algorithm_parallel_reduction.hh" #include "COM_node_operation.hh" +#include "COM_utilities.hh" #include "node_composite_util.hh" namespace blender::nodes::node_composite_tonemap_cc { +NODE_STORAGE_FUNCS(NodeTonemap) + static void cmp_node_tonemap_declare(NodeDeclarationBuilder &b) { - b.add_input(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input(N_("Image")) + .default_value({1.0f, 1.0f, 1.0f, 1.0f}) + .compositor_domain_priority(0); b.add_output(N_("Image")); } @@ -68,7 +83,236 @@ class ToneMapOperation : public NodeOperation { void execute() override { - get_input("Image").pass_through(get_result("Image")); + Result &input_image = get_input("Image"); + Result &output_image = get_result("Image"); + if (input_image.is_single_value()) { + input_image.pass_through(output_image); + return; + } + + switch (get_type()) { + case CMP_NODE_TONE_MAP_SIMPLE: + execute_simple(); + return; + case CMP_NODE_TONE_MAP_PHOTORECEPTOR: + execute_photoreceptor(); + return; + default: + BLI_assert_unreachable(); + return; + } + } + + /* Tone mapping based on equation (3) from Reinhard, Erik, et al. "Photographic tone reproduction + * for digital images." Proceedings of the 29th annual conference on Computer graphics and + * interactive techniques. 2002. */ + void execute_simple() + { + const float luminance_scale = compute_luminance_scale(); + const float luminance_scale_blend_factor = compute_luminance_scale_blend_factor(); + const float gamma = node_storage(bnode()).gamma; + const float inverse_gamma = gamma != 0.0f ? 1.0f / gamma : 0.0f; + + GPUShader *shader = shader_manager().get("compositor_tone_map_simple"); + GPU_shader_bind(shader); + + GPU_shader_uniform_1f(shader, "luminance_scale", luminance_scale); + GPU_shader_uniform_1f(shader, "luminance_scale_blend_factor", luminance_scale_blend_factor); + GPU_shader_uniform_1f(shader, "inverse_gamma", inverse_gamma); + + const Result &input_image = get_input("Image"); + input_image.bind_as_texture(shader, "input_tx"); + + const Domain domain = compute_domain(); + Result &output_image = get_result("Image"); + output_image.allocate_texture(domain); + output_image.bind_as_image(shader, "output_img"); + + compute_dispatch_threads_at_least(shader, domain.size); + + GPU_shader_unbind(); + output_image.unbind_as_image(); + input_image.unbind_as_texture(); + } + + /* Computes the scaling factor in equation (2) from Reinhard's 2002 paper. */ + float compute_luminance_scale() + { + const float geometric_mean = compute_geometric_mean_of_luminance(); + return geometric_mean != 0.0 ? node_storage(bnode()).key / geometric_mean : 0.0f; + } + + /* Computes equation (1) from Reinhard's 2002 paper. However, note that the equation in the paper + * is most likely wrong, and the intention is actually to compute the geometric mean through a + * logscale arithmetic mean, that is, the division should happen inside the exponential function, + * not outside of it. That's because the sum of the log luminance will be a very large negative + * number, whose exponential will almost always be zero, which is unexpected and useless. */ + float compute_geometric_mean_of_luminance() + { + return std::exp(compute_average_log_luminance()); + } + + /* Equation (3) from Reinhard's 2002 paper blends between high luminance scaling for high + * luminance values and low luminance scaling for low luminance values. This is done by adding 1 + * to the denominator, since for low luminance values, the denominator will be close to 1 and for + * high luminance values, the 1 in the denominator will be relatively insignificant. But the + * response of such function is not always ideal, so in this implementation, the 1 was exposed as + * a parameter to the user for more flexibility. */ + float compute_luminance_scale_blend_factor() + { + return node_storage(bnode()).offset; + } + + /* Tone mapping based on equation (1) and the trilinear interpolation between equations (6) and + * (7) from Reinhard, Erik, and Kate Devlin. "Dynamic range reduction inspired by photoreceptor + * physiology." IEEE transactions on visualization and computer graphics 11.1 (2005): 13-24. */ + void execute_photoreceptor() + { + const float4 global_adaptation_level = compute_global_adaptation_level(); + const float contrast = compute_contrast(); + const float intensity = compute_intensity(); + const float chromatic_adaptation = get_chromatic_adaptation(); + const float light_adaptation = get_light_adaptation(); + + GPUShader *shader = shader_manager().get("compositor_tone_map_photoreceptor"); + GPU_shader_bind(shader); + + GPU_shader_uniform_4fv(shader, "global_adaptation_level", global_adaptation_level); + GPU_shader_uniform_1f(shader, "contrast", contrast); + GPU_shader_uniform_1f(shader, "intensity", intensity); + GPU_shader_uniform_1f(shader, "chromatic_adaptation", chromatic_adaptation); + GPU_shader_uniform_1f(shader, "light_adaptation", light_adaptation); + + float luminance_coefficients[3]; + IMB_colormanagement_get_luminance_coefficients(luminance_coefficients); + GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients); + + const Result &input_image = get_input("Image"); + input_image.bind_as_texture(shader, "input_tx"); + + const Domain domain = compute_domain(); + Result &output_image = get_result("Image"); + output_image.allocate_texture(domain); + output_image.bind_as_image(shader, "output_img"); + + compute_dispatch_threads_at_least(shader, domain.size); + + GPU_shader_unbind(); + output_image.unbind_as_image(); + input_image.unbind_as_texture(); + } + + /* Computes the global adaptation level from the trilinear interpolation equations constructed + * from equations (6) and (7) in Reinhard's 2005 paper. */ + float4 compute_global_adaptation_level() + { + const float4 average_color = compute_average_color(); + const float average_luminance = compute_average_luminance(); + const float chromatic_adaptation = get_chromatic_adaptation(); + return math::interpolate(float4(average_luminance), average_color, chromatic_adaptation); + } + + float4 compute_average_color() + { + /* The average color will reduce to zero if chromatic adaptation is zero, so just return zero + * in this case to avoid needlessly computing the average. See the trilinear interpolation + * equations constructed from equations (6) and (7) in Reinhard's 2005 paper. */ + if (get_chromatic_adaptation() == 0.0f) { + return float4(0.0f); + } + + const Result &input = get_input("Image"); + return sum_color(context(), input.texture()) / (input.domain().size.x * input.domain().size.y); + } + + float compute_average_luminance() + { + /* The average luminance will reduce to zero if chromatic adaptation is one, so just return + * zero in this case to avoid needlessly computing the average. See the trilinear interpolation + * equations constructed from equations (6) and (7) in Reinhard's 2005 paper. */ + if (get_chromatic_adaptation() == 1.0f) { + return 0.0f; + } + + float luminance_coefficients[3]; + IMB_colormanagement_get_luminance_coefficients(luminance_coefficients); + const Result &input = get_input("Image"); + float sum = sum_luminance(context(), input.texture(), luminance_coefficients); + return sum / (input.domain().size.x * input.domain().size.y); + } + + /* Computes equation (5) from Reinhard's 2005 paper. */ + float compute_intensity() + { + return std::exp(-node_storage(bnode()).f); + } + + /* If the contrast is not zero, return it, otherwise, a zero contrast denote automatic derivation + * of the contrast value based on equations (2) and (4) from Reinhard's 2005 paper. */ + float compute_contrast() + { + if (node_storage(bnode()).m != 0.0f) { + return node_storage(bnode()).m; + } + + const float log_maximum_luminance = compute_log_maximum_luminance(); + const float log_minimum_luminance = compute_log_minimum_luminance(); + + /* This is merely to guard against zero division later. */ + if (log_maximum_luminance == log_minimum_luminance) { + return 1.0f; + } + + const float average_log_luminance = compute_average_log_luminance(); + const float dynamic_range = log_maximum_luminance - log_minimum_luminance; + const float luminance_key = (log_maximum_luminance - average_log_luminance) / (dynamic_range); + + return 0.3f + 0.7f * std::pow(luminance_key, 1.4f); + } + + float compute_average_log_luminance() + { + const Result &input_image = get_input("Image"); + + float luminance_coefficients[3]; + IMB_colormanagement_get_luminance_coefficients(luminance_coefficients); + const float sum_of_log_luminance = sum_log_luminance( + context(), input_image.texture(), luminance_coefficients); + + return sum_of_log_luminance / (input_image.domain().size.x * input_image.domain().size.y); + } + + float compute_log_maximum_luminance() + { + float luminance_coefficients[3]; + IMB_colormanagement_get_luminance_coefficients(luminance_coefficients); + const float maximum = maximum_luminance( + context(), get_input("Image").texture(), luminance_coefficients); + return std::log(math::max(maximum, 1e-5f)); + } + + float compute_log_minimum_luminance() + { + float luminance_coefficients[3]; + IMB_colormanagement_get_luminance_coefficients(luminance_coefficients); + const float minimum = minimum_luminance( + context(), get_input("Image").texture(), luminance_coefficients); + return std::log(math::max(minimum, 1e-5f)); + } + + float get_chromatic_adaptation() + { + return node_storage(bnode()).c; + } + + float get_light_adaptation() + { + return node_storage(bnode()).a; + } + + CMPNodeToneMapType get_type() + { + return static_cast(node_storage(bnode()).type); } }; -- cgit v1.2.3 From 7aaebf31df034397f3b28ab12daac9d3177c0950 Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Thu, 20 Oct 2022 15:49:36 +0200 Subject: Cycles: replace (tm) with unicode equivalent in UI It was already done for (TM) which is present in some GPU names on Windows. Names on Linux ended up using (tm) instead: https://gitlab.freedesktop.org/mesa/mesa/-/commit/91fec2657a0dcf9bc2e6d080d84a114ecde44382 --- intern/cycles/blender/addon/properties.py | 1 + 1 file changed, 1 insertion(+) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index b7ce76d8f44..425d123e9e6 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1651,6 +1651,7 @@ class CyclesPreferences(bpy.types.AddonPreferences): box.prop( device, "use", text=device.name .replace('(TM)', unicodedata.lookup('TRADE MARK SIGN')) + .replace('(tm)', unicodedata.lookup('TRADE MARK SIGN')) .replace('(R)', unicodedata.lookup('REGISTERED SIGN')) .replace('(C)', unicodedata.lookup('COPYRIGHT SIGN')) ) -- cgit v1.2.3 From 66a166d2366b6f2070965b0872d48301aeba1354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Thu, 20 Oct 2022 16:07:08 +0200 Subject: GL: Make restart index consistent on older implementation This prevents weird quirks where the implementation might skip the ushort max index even in non-indexed draws. --- source/blender/gpu/opengl/gl_batch.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/gpu/opengl/gl_batch.cc b/source/blender/gpu/opengl/gl_batch.cc index ff8867fe3e6..28105e326ee 100644 --- a/source/blender/gpu/opengl/gl_batch.cc +++ b/source/blender/gpu/opengl/gl_batch.cc @@ -272,8 +272,8 @@ void GLBatch::bind(int i_first) #if GPU_TRACK_INDEX_RANGE /* Can be removed if GL 4.3 is required. */ - if (!GLContext::fixed_restart_index_support && (elem != nullptr)) { - glPrimitiveRestartIndex(this->elem_()->restart_index()); + if (!GLContext::fixed_restart_index_support) { + glPrimitiveRestartIndex((elem != nullptr) ? this->elem_()->restart_index() : 0xFFFFFFFFu); } #endif -- cgit v1.2.3 From f017fdecefc41ffe796ccfe9a1cb05772a7ad315 Mon Sep 17 00:00:00 2001 From: Monique Dewanchand Date: Thu, 20 Oct 2022 16:14:03 +0200 Subject: ViewLayer: Reduce object duplication syncing During object duplication the syncing is temporarily disabled. With {D15885} this isn't useful as when disabled the view_layer is still accessed to locate bases. This can be improved by first locating the source bases, then duplicate and sync and locate the new bases. This patch removes the resync forbid and improve the times that resyncing actually must happen. Reviewed By: mont29 Maniphest Tasks: T73411 Differential Revision: https://developer.blender.org/D15886 --- source/blender/editors/object/object_add.cc | 197 ++++++++++++++++------------ 1 file changed, 112 insertions(+), 85 deletions(-) diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc index 3ce39b695e0..f6eee7c0c9e 100644 --- a/source/blender/editors/object/object_add.cc +++ b/source/blender/editors/object/object_add.cc @@ -3556,11 +3556,62 @@ void OBJECT_OT_convert(wmOperatorType *ot) /** \name Duplicate Object Operator * \{ */ +static void object_add_sync_base_collection( + Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_src, Object *object_new) +{ + if ((base_src != nullptr) && (base_src->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT)) { + BKE_collection_object_add_from(bmain, scene, base_src->object, object_new); + } + else { + LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer); + BKE_collection_object_add(bmain, layer_collection->collection, object_new); + } +} + +static void object_add_sync_local_view(Base *base_src, Base *base_new) +{ + base_new->local_view_bits = base_src->local_view_bits; +} + +static void object_add_sync_rigid_body(Main *bmain, Object *object_src, Object *object_new) +{ + /* 1) duplis should end up in same collection as the original + * 2) Rigid Body sim participants MUST always be part of a collection... + */ + /* XXX: is 2) really a good measure here? */ + if (object_src->rigidbody_object || object_src->rigidbody_constraint) { + LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { + if (BKE_collection_has_object(collection, object_src)) { + BKE_collection_object_add(bmain, collection, object_new); + } + } + } +} + /** * - Assumes `id.new` is correct. * - Leaves selection of base/object unaltered. * - Sets #ID.newid pointers. */ +static void object_add_duplicate_internal(Main *bmain, + Object *ob, + const eDupli_ID_Flags dupflag, + const eLibIDDuplicateFlags duplicate_options, + Object **r_ob_new) +{ + if (ob->mode & OB_MODE_POSE) { + return; + } + + Object *obn = static_cast( + ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag, duplicate_options))); + if (r_ob_new) { + *r_ob_new = obn; + } + DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + return; +} + static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer *view_layer, @@ -3569,49 +3620,25 @@ static Base *object_add_duplicate_internal(Main *bmain, const eLibIDDuplicateFlags duplicate_options, Object **r_ob_new) { - Base *base, *basen = nullptr; - Object *obn; - - if (ob->mode & OB_MODE_POSE) { - /* nothing? */ + Object *object_new = nullptr; + object_add_duplicate_internal(bmain, ob, dupflag, duplicate_options, &object_new); + if (r_ob_new) { + *r_ob_new = object_new; + } + if (object_new == nullptr) { + return nullptr; } - else { - obn = static_cast( - ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag, duplicate_options))); - if (r_ob_new) { - *r_ob_new = obn; - } - DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - - BKE_view_layer_synced_ensure(scene, view_layer); - base = BKE_view_layer_base_find(view_layer, ob); - if ((base != nullptr) && (base->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT)) { - BKE_collection_object_add_from(bmain, scene, ob, obn); - } - else { - LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer); - BKE_collection_object_add(bmain, layer_collection->collection, obn); - } - - BKE_view_layer_synced_ensure(scene, view_layer); - basen = BKE_view_layer_base_find(view_layer, obn); - if (base != nullptr && basen != nullptr) { - basen->local_view_bits = base->local_view_bits; - } - /* 1) duplis should end up in same collection as the original - * 2) Rigid Body sim participants MUST always be part of a collection... - */ - /* XXX: is 2) really a good measure here? */ - if (ob->rigidbody_object || ob->rigidbody_constraint) { - LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { - if (BKE_collection_has_object(collection, ob)) { - BKE_collection_object_add(bmain, collection, obn); - } - } - } + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base_src = BKE_view_layer_base_find(view_layer, ob); + object_add_sync_base_collection(bmain, scene, view_layer, base_src, object_new); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base_new = BKE_view_layer_base_find(view_layer, object_new); + if (base_src && base_new) { + object_add_sync_local_view(base_src, base_new); } - return basen; + object_add_sync_rigid_body(bmain, ob, object_new); + return base_new; } Base *ED_object_add_duplicate( @@ -3665,70 +3692,70 @@ static int duplicate_exec(bContext *C, wmOperator *op) * we also want to remap pointers between those... */ BKE_main_id_newptr_and_tag_clear(bmain); - /* Do not do collection re-syncs for each object; will do it once afterwards. - * However this means we can't get to new duplicated Base's immediately, will - * have to process them after the sync. */ - BKE_layer_collection_resync_forbid(); - /* Duplicate the selected objects, remember data needed to process - * after the sync (the base of the original object, and the copy of the - * original object). */ - blender::Vector> source_bases_new_objects; - Object *ob_new_active = nullptr; + * after the sync. */ + struct DuplicateObjectLink { + Base *base_src = nullptr; + Object *object_new = nullptr; + + DuplicateObjectLink(Base *base_src) : base_src(base_src) + { + } + }; + blender::Vector object_base_links; CTX_DATA_BEGIN (C, Base *, base, selected_bases) { - Object *ob_new = nullptr; + object_base_links.append(DuplicateObjectLink(base)); + } + CTX_DATA_END; + + bool new_objects_created = false; + for (DuplicateObjectLink &link : object_base_links) { object_add_duplicate_internal(bmain, - scene, - view_layer, - base->object, + link.base_src->object, dupflag, LIB_ID_DUPLICATE_IS_SUBPROCESS | LIB_ID_DUPLICATE_IS_ROOT_ID, - &ob_new); - if (ob_new == nullptr) { - continue; - } - source_bases_new_objects.append({base, ob_new}); - - /* note that this is safe to do with this context iterator, - * the list is made in advance */ - ED_object_base_select(base, BA_DESELECT); - - /* new object will become active */ - BKE_view_layer_synced_ensure(scene, view_layer); - if (BKE_view_layer_active_base_get(view_layer) == base) { - ob_new_active = ob_new; + &link.object_new); + if (link.object_new) { + new_objects_created = true; } } - CTX_DATA_END; - BKE_layer_collection_resync_allow(); - if (source_bases_new_objects.is_empty()) { + if (!new_objects_created) { return OPERATOR_CANCELLED; } - /* Sync the collection now, after everything is duplicated. */ - BKE_main_collection_sync(bmain); + /* Sync that could tag the view_layer out of sync. */ + for (DuplicateObjectLink &link : object_base_links) { + /* note that this is safe to do with this context iterator, + * the list is made in advance */ + ED_object_base_select(link.base_src, BA_DESELECT); + if (link.object_new) { + object_add_sync_base_collection(bmain, scene, view_layer, link.base_src, link.object_new); + object_add_sync_rigid_body(bmain, link.base_src->object, link.object_new); + } + } - /* After sync we can get to the new Base data, process it here. */ - for (const auto &item : source_bases_new_objects) { - Object *ob_new = item.second; - Base *base_source = item.first; - BKE_view_layer_synced_ensure(scene, view_layer); - Base *base_new = BKE_view_layer_base_find(view_layer, ob_new); - if (base_new == nullptr) { + /* Sync the view layer. Everything else should not tag the view_layer out of sync. */ + BKE_view_layer_synced_ensure(scene, view_layer); + const Base *active_base = BKE_view_layer_active_base_get(view_layer); + for (DuplicateObjectLink &link : object_base_links) { + if (!link.object_new) { continue; } + + Base *base_new = BKE_view_layer_base_find(view_layer, link.object_new); + BLI_assert(base_new); ED_object_base_select(base_new, BA_SELECT); - if (ob_new == ob_new_active) { + if (active_base == link.base_src) { ED_object_base_activate(C, base_new); } - if (base_new->object->data) { - DEG_id_tag_update(static_cast(base_new->object->data), 0); + + if (link.object_new->data) { + DEG_id_tag_update(static_cast(link.object_new->data), 0); } - /* #object_add_duplicate_internal will not have done this, since - * before the collection sync it would not have found the new base yet. */ - base_new->local_view_bits = base_source->local_view_bits; + + object_add_sync_local_view(link.base_src, base_new); } /* Note that this will also clear newid pointers and tags. */ -- cgit v1.2.3 From 9d710374bda41359132f929286f5eea7340441b5 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 20 Oct 2022 16:15:02 +0200 Subject: Fix T101645: division by zero in fillet node --- source/blender/geometry/intern/fillet_curves.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/blender/geometry/intern/fillet_curves.cc b/source/blender/geometry/intern/fillet_curves.cc index 1bbbee6edef..2479458f88d 100644 --- a/source/blender/geometry/intern/fillet_curves.cc +++ b/source/blender/geometry/intern/fillet_curves.cc @@ -148,12 +148,14 @@ static float limit_radius(const float3 &position_prev, const float displacement_prev = radius_prev * std::tan(angle_prev / 2.0f); const float segment_length_prev = math::distance(position, position_prev); const float total_displacement_prev = displacement_prev + displacement; - const float factor_prev = std::clamp(segment_length_prev / total_displacement_prev, 0.0f, 1.0f); + const float factor_prev = std::clamp( + safe_divide(segment_length_prev, total_displacement_prev), 0.0f, 1.0f); const float displacement_next = radius_next * std::tan(angle_next / 2.0f); const float segment_length_next = math::distance(position, position_next); const float total_displacement_next = displacement_next + displacement; - const float factor_next = std::clamp(segment_length_next / total_displacement_next, 0.0f, 1.0f); + const float factor_next = std::clamp( + safe_divide(segment_length_next, total_displacement_next), 0.0f, 1.0f); return radius * std::min(factor_prev, factor_next); } -- cgit v1.2.3 From 58e25f11ae9eb805dd857fae56be1d1a43710091 Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Thu, 20 Oct 2022 16:31:35 +0200 Subject: Realtime Compositor: Implement normalize node This patch implements the normalize node for the realtime compositor. Differential Revision: https://developer.blender.org/D16279 Reviewed By: Clement Foucault --- .../algorithms/COM_algorithm_parallel_reduction.hh | 22 ++++++++++ .../intern/algorithm_parallel_reduction.cc | 38 +++++++++++++++++ source/blender/gpu/CMakeLists.txt | 2 + .../shaders/compositor/compositor_normalize.glsl | 10 +++++ .../compositor/infos/compositor_normalize_info.hh | 12 ++++++ .../infos/compositor_parallel_reduction_info.hh | 24 +++++++++++ .../composite/nodes/node_composite_normalize.cc | 47 +++++++++++++++++++++- 7 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 source/blender/gpu/shaders/compositor/compositor_normalize.glsl create mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh diff --git a/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh b/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh index b094782c18e..f6d479f9bbe 100644 --- a/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh +++ b/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh @@ -70,6 +70,17 @@ float sum_luminance_squared_difference(Context &context, * coefficients to compute the luminance. */ float maximum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients); +/* Computes the maximum float of all pixels in the given float texture, limited to the given range. + * Values outside of the given range are ignored. If non of the pixel values are in the range, the + * lower bound of the range is returned. For instance, if the given range is [-10, 10] and the + * image contains the values {2, 5, 11}, the maximum will be 5, since 11 is outside of the range. + * This is particularly useful for Z Depth normalization, since Z Depth can contain near infinite + * values, so enforcing an upper bound is beneficial. */ +float maximum_float_in_range(Context &context, + GPUTexture *texture, + float lower_bound, + float upper_bound); + /* -------------------------------------------------------------------- * Minimum Reductions. */ @@ -78,4 +89,15 @@ float maximum_luminance(Context &context, GPUTexture *texture, float3 luminance_ * coefficients to compute the luminance. */ float minimum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients); +/* Computes the minimum float of all pixels in the given float texture, limited to the given range. + * Values outside of the given range are ignored. If non of the pixel values are in the range, the + * upper bound of the range is returned. For instance, if the given range is [-10, 10] and the + * image contains the values {-11, 2, 5}, the minimum will be 2, since -11 is outside of the range. + * This is particularly useful for Z Depth normalization, since Z Depth can contain near infinite + * values, so enforcing a lower bound is beneficial. */ +float minimum_float_in_range(Context &context, + GPUTexture *texture, + float lower_bound, + float upper_bound); + } // namespace blender::realtime_compositor diff --git a/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc b/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc index 139c58bc190..9672431992d 100644 --- a/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc +++ b/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc @@ -249,6 +249,25 @@ float maximum_luminance(Context &context, GPUTexture *texture, float3 luminance_ return maximum; } +float maximum_float_in_range(Context &context, + GPUTexture *texture, + float lower_bound, + float upper_bound) +{ + GPUShader *shader = context.shader_manager().get("compositor_maximum_float_in_range"); + GPU_shader_bind(shader); + + GPU_shader_uniform_1f(shader, "lower_bound", lower_bound); + GPU_shader_uniform_1f(shader, "upper_bound", upper_bound); + + float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F); + const float maximum = *reduced_value; + MEM_freeN(reduced_value); + GPU_shader_unbind(); + + return maximum; +} + /* -------------------------------------------------------------------- * Minimum Reductions. */ @@ -268,4 +287,23 @@ float minimum_luminance(Context &context, GPUTexture *texture, float3 luminance_ return minimum; } +float minimum_float_in_range(Context &context, + GPUTexture *texture, + float lower_bound, + float upper_bound) +{ + GPUShader *shader = context.shader_manager().get("compositor_minimum_float_in_range"); + GPU_shader_bind(shader); + + GPU_shader_uniform_1f(shader, "lower_bound", lower_bound); + GPU_shader_uniform_1f(shader, "upper_bound", upper_bound); + + float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F); + const float minimum = *reduced_value; + MEM_freeN(reduced_value); + GPU_shader_unbind(); + + return minimum; +} + } // namespace blender::realtime_compositor diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 56031b2722b..1ede48a3265 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -349,6 +349,7 @@ set(GLSL_SRC shaders/compositor/compositor_morphological_distance_feather.glsl shaders/compositor/compositor_morphological_distance_threshold.glsl shaders/compositor/compositor_morphological_step.glsl + shaders/compositor/compositor_normalize.glsl shaders/compositor/compositor_parallel_reduction.glsl shaders/compositor/compositor_projector_lens_distortion.glsl shaders/compositor/compositor_realize_on_domain.glsl @@ -633,6 +634,7 @@ set(SRC_SHADER_CREATE_INFOS shaders/compositor/infos/compositor_morphological_distance_info.hh shaders/compositor/infos/compositor_morphological_distance_threshold_info.hh shaders/compositor/infos/compositor_morphological_step_info.hh + shaders/compositor/infos/compositor_normalize_info.hh shaders/compositor/infos/compositor_parallel_reduction_info.hh shaders/compositor/infos/compositor_projector_lens_distortion_info.hh shaders/compositor/infos/compositor_realize_on_domain_info.hh diff --git a/source/blender/gpu/shaders/compositor/compositor_normalize.glsl b/source/blender/gpu/shaders/compositor/compositor_normalize.glsl new file mode 100644 index 00000000000..53dfeb01730 --- /dev/null +++ b/source/blender/gpu/shaders/compositor/compositor_normalize.glsl @@ -0,0 +1,10 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + float value = texture_load(input_tx, texel).x; + float normalized_value = (value - minimum) * scale; + float clamped_value = clamp(normalized_value, 0.0, 1.0); + imageStore(output_img, texel, vec4(clamped_value)); +} diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh new file mode 100644 index 00000000000..02fdc424014 --- /dev/null +++ b/source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_normalize) + .local_group_size(16, 16) + .push_constant(Type::FLOAT, "minimum") + .push_constant(Type::FLOAT, "scale") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_normalize.glsl") + .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh index 4a71bdc80e2..e2252b14758 100644 --- a/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh +++ b/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh @@ -108,6 +108,18 @@ GPU_SHADER_CREATE_INFO(compositor_maximum_luminance) .define("REDUCE(lhs, rhs)", "max(lhs, rhs)") .do_static_compilation(true); +GPU_SHADER_CREATE_INFO(compositor_maximum_float_in_range) + .additional_info("compositor_parallel_reduction_shared") + .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .push_constant(Type::FLOAT, "lower_bound") + .push_constant(Type::FLOAT, "upper_bound") + .define("TYPE", "float") + .define("IDENTITY", "vec4(lower_bound)") + .define("INITIALIZE(v)", "((v.x <= upper_bound) && (v.x >= lower_bound)) ? v.x : lower_bound") + .define("LOAD(value)", "value.x") + .define("REDUCE(lhs, rhs)", "((rhs > lhs) && (rhs <= upper_bound)) ? rhs : lhs") + .do_static_compilation(true); + /* -------------------------------------------------------------------- * Minimum Reductions. */ @@ -123,3 +135,15 @@ GPU_SHADER_CREATE_INFO(compositor_minimum_luminance) .define("LOAD(value)", "value.x") .define("REDUCE(lhs, rhs)", "min(lhs, rhs)") .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_minimum_float_in_range) + .additional_info("compositor_parallel_reduction_shared") + .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .push_constant(Type::FLOAT, "lower_bound") + .push_constant(Type::FLOAT, "upper_bound") + .define("TYPE", "float") + .define("IDENTITY", "vec4(upper_bound)") + .define("INITIALIZE(v)", "((v.x <= upper_bound) && (v.x >= lower_bound)) ? v.x : upper_bound") + .define("LOAD(value)", "value.x") + .define("REDUCE(lhs, rhs)", "((rhs < lhs) && (rhs >= lower_bound)) ? rhs : lhs") + .do_static_compilation(true); diff --git a/source/blender/nodes/composite/nodes/node_composite_normalize.cc b/source/blender/nodes/composite/nodes/node_composite_normalize.cc index 21765825468..34fd63e5805 100644 --- a/source/blender/nodes/composite/nodes/node_composite_normalize.cc +++ b/source/blender/nodes/composite/nodes/node_composite_normalize.cc @@ -5,7 +5,9 @@ * \ingroup cmpnodes */ +#include "COM_algorithm_parallel_reduction.hh" #include "COM_node_operation.hh" +#include "COM_utilities.hh" #include "node_composite_util.hh" @@ -15,19 +17,60 @@ namespace blender::nodes::node_composite_normalize_cc { static void cmp_node_normalize_declare(NodeDeclarationBuilder &b) { - b.add_input(N_("Value")).default_value(1.0f).min(0.0f).max(1.0f); + b.add_input(N_("Value")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .compositor_domain_priority(0); b.add_output(N_("Value")); } using namespace blender::realtime_compositor; class NormalizeOperation : public NodeOperation { + private: + /* The normalize operation is specifically designed to normalize Z Depth information. But since Z + * Depth can contain near infinite values, normalization is limited to [-range_, range], meaning + * that values outside of that range will be ignored when computing the maximum and minimum for + * normalization and will eventually be 0 or 1 if they are less than or larger than the range + * respectively. */ + constexpr static float range_ = 10000.0f; + public: using NodeOperation::NodeOperation; void execute() override { - get_input("Value").pass_through(get_result("Value")); + Result &input_image = get_input("Value"); + Result &output_image = get_result("Value"); + if (input_image.is_single_value()) { + input_image.pass_through(output_image); + return; + } + + const float maximum = maximum_float_in_range( + context(), input_image.texture(), -range_, range_); + const float minimum = minimum_float_in_range( + context(), input_image.texture(), -range_, range_); + const float scale = (maximum != minimum) ? (1.0f / (maximum - minimum)) : 0.0f; + + GPUShader *shader = shader_manager().get("compositor_normalize"); + GPU_shader_bind(shader); + + GPU_shader_uniform_1f(shader, "minimum", minimum); + GPU_shader_uniform_1f(shader, "scale", scale); + + input_image.bind_as_texture(shader, "input_tx"); + + const Domain domain = compute_domain(); + output_image.allocate_texture(domain); + output_image.bind_as_image(shader, "output_img"); + + compute_dispatch_threads_at_least(shader, domain.size); + + GPU_shader_unbind(); + output_image.unbind_as_image(); + input_image.unbind_as_texture(); } }; -- cgit v1.2.3 From 84825e4ed2e098954f0c46adee4d65c8c0ba0e99 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Thu, 20 Oct 2022 16:37:07 +0200 Subject: UI: Icon number indicator for data-blocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the possibility of having a little number on top of icons. At the moment this is used for: * Outliner * Node Editor bread-crumb * Node Group node header For the outliner there is almost no functional change. It is mostly a refactor to handle the indicators as part of the icon shader instead of the outliner draw code. (note that this was already recently changed in a5d3b648e3e2). The difference is that now we use rounded border rectangle instead of circles, and we can go up to 999 elements. So for the outliner this shows the number of collapsed elements of a certain type (e.g., mesh objects inside a collapsed collection). For the node editors is being used to show the use count for the data-block. This is important for the node editor, so users know whether the node-group they are editing (or are about to edit) is used elsewhere. This is particularly important when the Node Options are hidden, which is the default for node groups appended from the asset libraries. --- Note: This can be easily enabled for ID templates which can then be part of T84669. It just need to call UI_but_icon_indicator_number_set in the function template_add_button_search_menu. --- Special thanks Clément Foucault for the help figuring out the shader, Julian Eisel for the help navigating the UI code, and Pablo Vazquez for the collaboration in this design solution. For images showing the result check the Differential Revision. Differential Revision: https://developer.blender.org/D16284 --- source/blender/blenlib/BLI_string.h | 22 ++++ source/blender/blenlib/intern/string.c | 30 +++++ source/blender/blenlib/tests/BLI_string_test.cc | 97 +++++++++++++++ source/blender/editors/include/UI_interface.h | 4 +- source/blender/editors/include/UI_interface.hh | 1 + .../blender/editors/include/UI_interface_icons.h | 12 +- source/blender/editors/interface/interface.cc | 5 + .../editors/interface/interface_context_path.cc | 14 ++- source/blender/editors/interface/interface_icons.c | 117 +++++++++++++++--- .../blender/editors/interface/interface_intern.h | 4 + .../blender/editors/interface/interface_layout.c | 4 +- .../blender/editors/interface/interface_panel.cc | 6 +- .../blender/editors/interface/interface_widgets.c | 15 ++- source/blender/editors/screen/area.c | 3 +- source/blender/editors/space_file/file_draw.c | 65 ++++++++-- source/blender/editors/space_info/textview.c | 3 +- source/blender/editors/space_node/node_draw.cc | 3 + .../editors/space_node/node_relationships.cc | 3 +- .../editors/space_outliner/outliner_draw.cc | 134 +++------------------ source/blender/gpu/CMakeLists.txt | 3 + source/blender/gpu/GPU_shader.h | 4 + source/blender/gpu/intern/gpu_shader_builtin.c | 5 + .../blender/gpu/shaders/gpu_shader_icon_frag.glsl | 42 +++++++ .../blender/gpu/shaders/gpu_shader_icon_vert.glsl | 37 ++++++ .../gpu/shaders/infos/gpu_interface_info.hh | 3 + .../gpu/shaders/infos/gpu_shader_icon_info.hh | 22 ++++ source/blender/windowmanager/intern/wm_dragdrop.cc | 3 +- 27 files changed, 499 insertions(+), 162 deletions(-) create mode 100644 source/blender/gpu/shaders/gpu_shader_icon_frag.glsl create mode 100644 source/blender/gpu/shaders/gpu_shader_icon_vert.glsl create mode 100644 source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index 15926e8f2d2..17abcf52ecc 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -308,6 +308,28 @@ void BLI_str_format_byte_unit(char dst[15], long long int bytes, bool base_10) A * Length of 7 is the maximum of the resulting string, for example, `-15.5K\0`. */ void BLI_str_format_decimal_unit(char dst[7], int number_to_format) ATTR_NONNULL(); +/** + * Format a count to up to 3 places (plus minus sign, plus '\0' terminator) string using long + * number names abbreviations. Used to produce a compact representation of large numbers as + * integers. + * + * It shows a lower bound instead of rounding the number. + * + * 1 -> 1 + * 15 -> 15 + * 155 -> 155 + * 1555 -> 1K + * 15555 -> 15K + * 155555 -> .1M + * 1555555 -> 1M + * 15555555 -> 15M + * 155555555 -> .1B + * 1000000000 -> 1B + * ... + * + * Length of 5 is the maximum of the resulting string, for example, `-15K\0`. + */ +void BLI_str_format_integer_unit(char dst[5], int number_to_format) ATTR_NONNULL(); /** * Compare two strings without regard to case. * diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 89d31c5e93f..755d2dbd55d 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -1176,4 +1176,34 @@ void BLI_str_format_decimal_unit(char dst[7], int number_to_format) BLI_snprintf(dst, dst_len, "%.*f%s", decimals, number_to_format_converted, units[order]); } +void BLI_str_format_integer_unit(char dst[5], const int number_to_format) +{ + float number_to_format_converted = number_to_format; + int order = 0; + const float base = 1000; + const char *units[] = {"", "K", "M", "B"}; + const int units_num = ARRAY_SIZE(units); + + while ((fabsf(number_to_format_converted) >= base) && ((order + 1) < units_num)) { + number_to_format_converted /= base; + order++; + } + + const bool add_dot = (abs(number_to_format) > 99999) && fabsf(number_to_format_converted) > 99; + + if (add_dot) { + number_to_format_converted /= 100; + order++; + } + + const size_t dst_len = 5; + BLI_snprintf(dst, + dst_len, + "%s%s%d%s", + number_to_format < 0 ? "-" : "", + add_dot ? "." : "", + (int)floorf(fabsf(number_to_format_converted)), + units[order]); +} + /** \} */ diff --git a/source/blender/blenlib/tests/BLI_string_test.cc b/source/blender/blenlib/tests/BLI_string_test.cc index 9bdf6075c70..d726fbccf20 100644 --- a/source/blender/blenlib/tests/BLI_string_test.cc +++ b/source/blender/blenlib/tests/BLI_string_test.cc @@ -515,6 +515,103 @@ TEST(string, StrFormatDecimalUnits) EXPECT_STREQ("-2.1B", size_str); } +/* BLI_str_format_integer_unit */ +TEST(string, StrFormatIntegerUnits) +{ + char size_str[7]; + int size; + + BLI_str_format_integer_unit(size_str, size = 0); + EXPECT_STREQ("0", size_str); + BLI_str_format_integer_unit(size_str, size = 1); + EXPECT_STREQ("1", size_str); + BLI_str_format_integer_unit(size_str, size = 10); + EXPECT_STREQ("10", size_str); + BLI_str_format_integer_unit(size_str, size = 15); + EXPECT_STREQ("15", size_str); + BLI_str_format_integer_unit(size_str, size = 100); + EXPECT_STREQ("100", size_str); + BLI_str_format_integer_unit(size_str, size = 155); + EXPECT_STREQ("155", size_str); + BLI_str_format_integer_unit(size_str, size = 1000); + EXPECT_STREQ("1K", size_str); + BLI_str_format_integer_unit(size_str, size = 1555); + EXPECT_STREQ("1K", size_str); + BLI_str_format_integer_unit(size_str, size = 10000); + EXPECT_STREQ("10K", size_str); + BLI_str_format_integer_unit(size_str, size = 15555); + EXPECT_STREQ("15K", size_str); + BLI_str_format_integer_unit(size_str, size = 100000); + EXPECT_STREQ(".1M", size_str); + BLI_str_format_integer_unit(size_str, size = 155555); + EXPECT_STREQ(".1M", size_str); + BLI_str_format_integer_unit(size_str, size = 1000000); + EXPECT_STREQ("1M", size_str); + BLI_str_format_integer_unit(size_str, size = 1555555); + EXPECT_STREQ("1M", size_str); + BLI_str_format_integer_unit(size_str, size = 2555555); + EXPECT_STREQ("2M", size_str); + BLI_str_format_integer_unit(size_str, size = 10000000); + EXPECT_STREQ("10M", size_str); + BLI_str_format_integer_unit(size_str, size = 15555555); + EXPECT_STREQ("15M", size_str); + BLI_str_format_integer_unit(size_str, size = 100000000); + EXPECT_STREQ(".1B", size_str); + BLI_str_format_integer_unit(size_str, size = 155555555); + EXPECT_STREQ(".1B", size_str); + BLI_str_format_integer_unit(size_str, size = 255555555); + EXPECT_STREQ(".2B", size_str); + BLI_str_format_integer_unit(size_str, size = 1000000000); + EXPECT_STREQ("1B", size_str); + + /* Largest possible value. */ + BLI_str_format_integer_unit(size_str, size = INT32_MAX); + EXPECT_STREQ("2B", size_str); + + BLI_str_format_integer_unit(size_str, size = -0); + EXPECT_STREQ("0", size_str); + BLI_str_format_integer_unit(size_str, size = -1); + EXPECT_STREQ("-1", size_str); + BLI_str_format_integer_unit(size_str, size = -10); + EXPECT_STREQ("-10", size_str); + BLI_str_format_integer_unit(size_str, size = -15); + EXPECT_STREQ("-15", size_str); + BLI_str_format_integer_unit(size_str, size = -100); + EXPECT_STREQ("-100", size_str); + BLI_str_format_integer_unit(size_str, size = -155); + EXPECT_STREQ("-155", size_str); + BLI_str_format_integer_unit(size_str, size = -1000); + EXPECT_STREQ("-1K", size_str); + BLI_str_format_integer_unit(size_str, size = -1555); + EXPECT_STREQ("-1K", size_str); + BLI_str_format_integer_unit(size_str, size = -10000); + EXPECT_STREQ("-10K", size_str); + BLI_str_format_integer_unit(size_str, size = -15555); + EXPECT_STREQ("-15K", size_str); + BLI_str_format_integer_unit(size_str, size = -100000); + EXPECT_STREQ("-.1M", size_str); + BLI_str_format_integer_unit(size_str, size = -155555); + EXPECT_STREQ("-.1M", size_str); + BLI_str_format_integer_unit(size_str, size = -1000000); + EXPECT_STREQ("-1M", size_str); + BLI_str_format_integer_unit(size_str, size = -1555555); + EXPECT_STREQ("-1M", size_str); + BLI_str_format_integer_unit(size_str, size = -10000000); + EXPECT_STREQ("-10M", size_str); + BLI_str_format_integer_unit(size_str, size = -15555555); + EXPECT_STREQ("-15M", size_str); + BLI_str_format_integer_unit(size_str, size = -100000000); + EXPECT_STREQ("-.1B", size_str); + BLI_str_format_integer_unit(size_str, size = -155555555); + EXPECT_STREQ("-.1B", size_str); + BLI_str_format_integer_unit(size_str, size = -1000000000); + EXPECT_STREQ("-1B", size_str); + + /* Smallest possible value. */ + BLI_str_format_integer_unit(size_str, size = -INT32_MAX); + EXPECT_STREQ("-2B", size_str); +} + struct WordInfo { WordInfo() = default; WordInfo(int start, int end) : start(start), end(end) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 2a1941f0d9e..7e9422ff867 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -1683,6 +1683,7 @@ int UI_search_items_find_index(uiSearchItems *items, const char *name); * Adds a hint to the button which draws right aligned, grayed out and never clipped. */ void UI_but_hint_drawstr_set(uiBut *but, const char *string); +void UI_but_icon_indicator_number_set(uiBut *but, const int indicator_number); void UI_but_node_link_set(uiBut *but, struct bNodeSocket *socket, const float draw_color[4]); @@ -2788,7 +2789,8 @@ typedef struct uiPropertySplitWrapper { uiPropertySplitWrapper uiItemPropertySplitWrapperCreate(uiLayout *parent_layout); void uiItemL(uiLayout *layout, const char *name, int icon); /* label */ -void uiItemL_ex(uiLayout *layout, const char *name, int icon, bool highlight, bool redalert); +struct uiBut *uiItemL_ex( + uiLayout *layout, const char *name, int icon, bool highlight, bool redalert); /** * Helper to add a label and creates a property split layout if needed. */ diff --git a/source/blender/editors/include/UI_interface.hh b/source/blender/editors/include/UI_interface.hh index 6c756984203..fc03b0218c0 100644 --- a/source/blender/editors/include/UI_interface.hh +++ b/source/blender/editors/include/UI_interface.hh @@ -35,6 +35,7 @@ struct ContextPathItem { std::string name; /* #BIFIconID */ int icon; + int icon_indicator_number; }; void context_path_add_generic(Vector &path, diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index a1a98a4b08c..9669e242dac 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -27,6 +27,12 @@ typedef struct IconFile { int index; } IconFile; +typedef struct IconTextOverlay { + char text[5]; +} IconTextOverlay; + +#define UI_NO_ICON_OVERLAY_TEXT NULL + #define ICON_DEFAULT_HEIGHT 16 #define ICON_DEFAULT_WIDTH 16 @@ -105,7 +111,8 @@ void UI_icon_draw_ex(float x, float alpha, float desaturate, const uchar mono_color[4], - bool mono_border); + bool mono_border, + const struct IconTextOverlay *text_overlay); void UI_icons_free(void); void UI_icons_free_drawinfo(void *drawinfo); @@ -124,6 +131,9 @@ int UI_icon_from_library(const struct ID *id); int UI_icon_from_object_mode(int mode); int UI_icon_color_from_collection(const struct Collection *collection); +void UI_icon_text_overlay_init_from_count(struct IconTextOverlay *text_overlay, + const int icon_indicator_number); + #ifdef __cplusplus } #endif diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc index 422fc34aa50..1f88d25af2b 100644 --- a/source/blender/editors/interface/interface.cc +++ b/source/blender/editors/interface/interface.cc @@ -6452,6 +6452,11 @@ void UI_but_hint_drawstr_set(uiBut *but, const char *string) ui_but_add_shortcut(but, string, false); } +void UI_but_icon_indicator_number_set(uiBut *but, const int indicator_number) +{ + UI_icon_text_overlay_init_from_count(&but->icon_overlay_text, indicator_number); +} + void UI_but_node_link_set(uiBut *but, bNodeSocket *socket, const float draw_color[4]) { but->flag |= UI_BUT_NODE_LINK; diff --git a/source/blender/editors/interface/interface_context_path.cc b/source/blender/editors/interface/interface_context_path.cc index e8f552e26a3..91b2f9613de 100644 --- a/source/blender/editors/interface/interface_context_path.cc +++ b/source/blender/editors/interface/interface_context_path.cc @@ -17,6 +17,8 @@ #include "UI_interface.hh" #include "UI_resources.h" +#include "RNA_prototypes.h" + #include "WM_api.h" namespace blender::ui { @@ -41,7 +43,13 @@ void context_path_add_generic(Vector &path, static_cast(RNA_struct_ui_icon(rna_ptr.type)) : icon_override; - path.append({name, int(icon)}); + if (&rna_type == &RNA_NodeTree) { + ID *id = (ID *)ptr; + path.append({name, int(icon), id->us}); + } + else { + path.append({name, int(icon), 1}); + } } /* -------------------------------------------------------------------- */ @@ -60,7 +68,9 @@ void template_breadcrumbs(uiLayout &layout, Span context_path) if (i > 0) { uiItemL(sub_row, "", ICON_RIGHTARROW_THIN); } - uiItemL(sub_row, context_path[i].name.c_str(), context_path[i].icon); + uiBut *but = uiItemL_ex( + sub_row, context_path[i].name.c_str(), context_path[i].icon, false, false); + UI_but_icon_indicator_number_set(but, context_path[i].icon_indicator_number); } } diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index deb3d84ae66..9a4f98ebcd6 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -415,8 +415,15 @@ static void vicon_collection_color_draw( const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w; - UI_icon_draw_ex( - x, y, ICON_OUTLINER_COLLECTION, aspect, 1.0f, 0.0f, collection_color->color, true); + UI_icon_draw_ex(x, + y, + ICON_OUTLINER_COLLECTION, + aspect, + 1.0f, + 0.0f, + collection_color->color, + true, + UI_NO_ICON_OVERLAY_TEXT); } # define DEF_ICON_COLLECTION_COLOR_DRAW(index, color) \ @@ -444,7 +451,8 @@ static void vicon_strip_color_draw( const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w; - UI_icon_draw_ex(x, y, ICON_SNAP_FACE, aspect, 1.0f, 0.0f, strip_color->color, true); + UI_icon_draw_ex( + x, y, ICON_SNAP_FACE, aspect, 1.0f, 0.0f, strip_color->color, true, UI_NO_ICON_OVERLAY_TEXT); } # define DEF_ICON_STRIP_COLOR_DRAW(index, color) \ @@ -472,8 +480,15 @@ static void vicon_strip_color_draw_library_data_indirect( { const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w; - UI_icon_draw_ex( - x, y, ICON_LIBRARY_DATA_DIRECT, aspect, ICON_INDIRECT_DATA_ALPHA * alpha, 0.0f, NULL, false); + UI_icon_draw_ex(x, + y, + ICON_LIBRARY_DATA_DIRECT, + aspect, + ICON_INDIRECT_DATA_ALPHA * alpha, + 0.0f, + NULL, + false, + UI_NO_ICON_OVERLAY_TEXT); } static void vicon_strip_color_draw_library_data_override_noneditable( @@ -488,7 +503,8 @@ static void vicon_strip_color_draw_library_data_override_noneditable( ICON_INDIRECT_DATA_ALPHA * alpha * 0.75f, 0.0f, NULL, - false); + false, + UI_NO_ICON_OVERLAY_TEXT); } /* Dynamically render icon instead of rendering a plain color to a texture/buffer @@ -1716,9 +1732,47 @@ static void icon_draw_texture(float x, int ih, float alpha, const float rgb[3], - bool with_border) -{ - if (g_icon_draw_cache.enabled) { + bool with_border, + const IconTextOverlay *text_overlay) +{ + const float zoom_factor = w / UI_DPI_ICON_SIZE; + float text_width = 0.0f; + + /* No need to show if too zoomed out, otherwise it just adds noise. */ + const bool show_indicator = (text_overlay && text_overlay->text[0] != '\0') && + (zoom_factor > 0.7f); + + if (show_indicator) { + /* Handle the little numbers on top of the icon. */ + uchar text_color[4]; + UI_GetThemeColor3ubv(TH_TEXT, text_color); + text_color[3] = 255; + + uiFontStyle fstyle_small = *UI_FSTYLE_WIDGET; + fstyle_small.points *= zoom_factor; + fstyle_small.points *= 0.8f; + + rcti text_rect = { + .xmax = x + UI_UNIT_X * zoom_factor, + .xmin = x, + .ymax = y, + .ymin = y, + }; + + UI_fontstyle_draw(&fstyle_small, + &text_rect, + text_overlay->text, + sizeof(text_overlay->text), + text_color, + &(struct uiFontStyleDraw_Params){ + .align = UI_STYLE_TEXT_RIGHT, + }); + text_width = (float)UI_fontstyle_string_width(&fstyle_small, text_overlay->text) / UI_UNIT_X / + zoom_factor; + } + + /* Draw the actual icon. */ + if (!show_indicator && g_icon_draw_cache.enabled) { icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb, with_border); return; } @@ -1735,7 +1789,7 @@ static void icon_draw_texture(float x, GPUTexture *texture = with_border ? icongltex.tex[1] : icongltex.tex[0]; - GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR); + GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_ICON); GPU_shader_bind(shader); const int img_binding = GPU_shader_get_texture_binding(shader, "image"); @@ -1752,6 +1806,7 @@ static void icon_draw_texture(float x, GPU_shader_uniform_vector(shader, rect_tex_loc, 4, 1, (float[4]){x1, y1, x2, y2}); GPU_shader_uniform_vector(shader, rect_geom_loc, 4, 1, (float[4]){x, y, x + w, y + h}); + GPU_shader_uniform_1f(shader, "text_width", text_width); GPU_texture_bind_ex(texture, GPU_SAMPLER_ICON, img_binding, false); @@ -1786,7 +1841,8 @@ static void icon_draw_size(float x, int draw_size, const float desaturate, const uchar mono_rgba[4], - const bool mono_border) + const bool mono_border, + const IconTextOverlay *text_overlay) { bTheme *btheme = UI_GetTheme(); const float fdraw_size = (float)draw_size; @@ -1874,7 +1930,8 @@ static void icon_draw_size(float x, di->data.texture.h, alpha, NULL, - false); + false, + text_overlay); } else if (di->type == ICON_TYPE_MONO_TEXTURE) { /* Monochrome icon that uses text or theme color. */ @@ -1908,7 +1965,8 @@ static void icon_draw_size(float x, di->data.texture.h + 2 * border_texel, color[3], color, - with_border); + with_border, + text_overlay); } else if (di->type == ICON_TYPE_BUFFER) { @@ -2425,17 +2483,27 @@ int UI_icon_color_from_collection(const Collection *collection) void UI_icon_draw(float x, float y, int icon_id) { - UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, 1.0f, 0.0f, NULL, false); + UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, 1.0f, 0.0f, NULL, false, UI_NO_ICON_OVERLAY_TEXT); } void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha) { - UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, alpha, 0.0f, NULL, false); + UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, alpha, 0.0f, NULL, false, UI_NO_ICON_OVERLAY_TEXT); } void UI_icon_draw_preview(float x, float y, int icon_id, float aspect, float alpha, int size) { - icon_draw_size(x, y, icon_id, aspect, alpha, ICON_SIZE_PREVIEW, size, false, NULL, false); + icon_draw_size(x, + y, + icon_id, + aspect, + alpha, + ICON_SIZE_PREVIEW, + size, + false, + NULL, + false, + UI_NO_ICON_OVERLAY_TEXT); } void UI_icon_draw_ex(float x, @@ -2445,7 +2513,8 @@ void UI_icon_draw_ex(float x, float alpha, float desaturate, const uchar mono_color[4], - const bool mono_border) + const bool mono_border, + const IconTextOverlay *text_overlay) { const int draw_size = get_draw_size(ICON_SIZE_ICON); icon_draw_size(x, @@ -2457,7 +2526,19 @@ void UI_icon_draw_ex(float x, draw_size, desaturate, mono_color, - mono_border); + mono_border, + text_overlay); +} + +void UI_icon_text_overlay_init_from_count(IconTextOverlay *text_overlay, + const int icon_indicator_number) +{ + /* The icon indicator is used as an aggregator, no need to show if it is 1. */ + if (icon_indicator_number < 2) { + text_overlay->text[0] = '\0'; + return; + } + BLI_str_format_integer_unit(text_overlay->text, icon_indicator_number); } /* ********** Alert Icons ********** */ diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 6ef7d346418..6ef81ad897e 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -23,6 +23,7 @@ struct ARegion; struct AnimationEvalContext; struct CurveMapping; struct CurveProfile; +struct IconTextOverlay; struct ID; struct ImBuf; struct Main; @@ -275,6 +276,9 @@ struct uiBut { uiButPushedStateFunc pushed_state_func; const void *pushed_state_arg; + /** Little indicator (e.g., counter) displayed on top of some icons. */ + struct IconTextOverlay icon_overlay_text; + /* pointer back */ uiBlock *block; }; diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index c906a5b36f1..496f72c089a 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -3235,7 +3235,7 @@ static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon) return but; } -void uiItemL_ex( +uiBut *uiItemL_ex( uiLayout *layout, const char *name, int icon, const bool highlight, const bool redalert) { uiBut *but = uiItemL_(layout, name, icon); @@ -3248,6 +3248,8 @@ void uiItemL_ex( if (redalert) { UI_but_flag_enable(but, UI_BUT_REDALERT); } + + return but; } void uiItemL(uiLayout *layout, const char *name, int icon) diff --git a/source/blender/editors/interface/interface_panel.cc b/source/blender/editors/interface/interface_panel.cc index 7a69e2f9b2f..24d8281aad8 100644 --- a/source/blender/editors/interface/interface_panel.cc +++ b/source/blender/editors/interface/interface_panel.cc @@ -1112,7 +1112,8 @@ static void panel_draw_aligned_widgets(const uiStyle *style, 0.7f, 0.0f, title_color, - false); + false, + UI_NO_ICON_OVERLAY_TEXT); GPU_blend(GPU_BLEND_NONE); } @@ -1140,7 +1141,8 @@ static void panel_draw_aligned_widgets(const uiStyle *style, 1.0f, 0.0f, title_color, - false); + false, + UI_NO_ICON_OVERLAY_TEXT); GPU_blend(GPU_BLEND_NONE); } diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 6ba80e2e0d9..1bad9b34a72 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1420,21 +1420,25 @@ static void widget_draw_icon( /* to indicate draggable */ if (ui_but_drag_is_draggable(but) && (but->flag & UI_ACTIVE)) { - UI_icon_draw_ex(xs, ys, icon, aspect, 1.25f, 0.0f, color, has_theme); + UI_icon_draw_ex( + xs, ys, icon, aspect, 1.25f, 0.0f, color, has_theme, &but->icon_overlay_text); } else if (but->flag & (UI_ACTIVE | UI_SELECT | UI_SELECT_DRAW)) { - UI_icon_draw_ex(xs, ys, icon, aspect, alpha, 0.0f, color, has_theme); + UI_icon_draw_ex( + xs, ys, icon, aspect, alpha, 0.0f, color, has_theme, &but->icon_overlay_text); } else if (!((but->icon != ICON_NONE) && UI_but_is_tool(but))) { if (has_theme) { alpha *= 0.8f; } - UI_icon_draw_ex(xs, ys, icon, aspect, alpha, 0.0f, color, has_theme); + UI_icon_draw_ex( + xs, ys, icon, aspect, alpha, 0.0f, color, has_theme, &but->icon_overlay_text); } else { const bTheme *btheme = UI_GetTheme(); const float desaturate = 1.0 - btheme->tui.icon_saturation; - UI_icon_draw_ex(xs, ys, icon, aspect, alpha, desaturate, color, has_theme); + UI_icon_draw_ex( + xs, ys, icon, aspect, alpha, desaturate, color, has_theme, &but->icon_overlay_text); } } @@ -5426,7 +5430,8 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, GPU_blend(GPU_BLEND_ALPHA); /* XXX scale weak get from fstyle? */ - UI_icon_draw_ex(xs, ys, iconid, aspect, 1.0f, 0.0f, wt->wcol.text, false); + UI_icon_draw_ex( + xs, ys, iconid, aspect, 1.0f, 0.0f, wt->wcol.text, false, UI_NO_ICON_OVERLAY_TEXT); GPU_blend(GPU_BLEND_NONE); } diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 39e3c7a2f0a..8db968cbb8a 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -187,7 +187,8 @@ static void area_draw_azone_fullscreen( min_ff(alpha, 0.75f), 0.0f, NULL, - false); + false, + UI_NO_ICON_OVERLAY_TEXT); } /** diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index e4085bbe9cc..240901318b5 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -410,8 +410,15 @@ static void file_draw_preview(const SpaceFile *sfile, } icon_x = xco + (ex / 2.0f) - (icon_size / 2.0f); icon_y = yco + (ey / 2.0f) - (icon_size * ((file->typeflag & FILE_TYPE_DIR) ? 0.78f : 0.75f)); - UI_icon_draw_ex( - icon_x, icon_y, icon, icon_aspect / U.dpi_fac, icon_opacity, 0.0f, icon_color, false); + UI_icon_draw_ex(icon_x, + icon_y, + icon, + icon_aspect / U.dpi_fac, + icon_opacity, + 0.0f, + icon_color, + false, + UI_NO_ICON_OVERLAY_TEXT); } if (is_link || is_offline) { @@ -424,8 +431,24 @@ static void file_draw_preview(const SpaceFile *sfile, /* At very bottom-left if preview style. */ const uchar dark[4] = {0, 0, 0, 255}; const uchar light[4] = {255, 255, 255, 255}; - UI_icon_draw_ex(icon_x + 1, icon_y - 1, arrow, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false); - UI_icon_draw_ex(icon_x, icon_y, arrow, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false); + UI_icon_draw_ex(icon_x + 1, + icon_y - 1, + arrow, + 1.0f / U.dpi_fac, + 0.2f, + 0.0f, + dark, + false, + UI_NO_ICON_OVERLAY_TEXT); + UI_icon_draw_ex(icon_x, + icon_y, + arrow, + 1.0f / U.dpi_fac, + 0.6f, + 0.0f, + light, + false, + UI_NO_ICON_OVERLAY_TEXT); } else { /* Link to folder or non-previewed file. */ @@ -433,8 +456,15 @@ static void file_draw_preview(const SpaceFile *sfile, UI_GetThemeColor4ubv(TH_BACK, icon_color); icon_x = xco + ((file->typeflag & FILE_TYPE_DIR) ? 0.14f : 0.23f) * scaledx; icon_y = yco + ((file->typeflag & FILE_TYPE_DIR) ? 0.24f : 0.14f) * scaledy; - UI_icon_draw_ex( - icon_x, icon_y, arrow, icon_aspect / U.dpi_fac * 1.8, 0.3f, 0.0f, icon_color, false); + UI_icon_draw_ex(icon_x, + icon_y, + arrow, + icon_aspect / U.dpi_fac * 1.8, + 0.3f, + 0.0f, + icon_color, + false, + UI_NO_ICON_OVERLAY_TEXT); } } else if (icon && !is_icon && !(file->typeflag & FILE_TYPE_FTFONT)) { @@ -444,8 +474,17 @@ static void file_draw_preview(const SpaceFile *sfile, const uchar light[4] = {255, 255, 255, 255}; icon_x = xco + (2.0f * UI_DPI_FAC); icon_y = yco + (2.0f * UI_DPI_FAC); - UI_icon_draw_ex(icon_x + 1, icon_y - 1, icon, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false); - UI_icon_draw_ex(icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false); + UI_icon_draw_ex(icon_x + 1, + icon_y - 1, + icon, + 1.0f / U.dpi_fac, + 0.2f, + 0.0f, + dark, + false, + UI_NO_ICON_OVERLAY_TEXT); + UI_icon_draw_ex( + icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false, UI_NO_ICON_OVERLAY_TEXT); } const bool is_current_main_data = filelist_file_get_id(file) != NULL; @@ -456,7 +495,15 @@ static void file_draw_preview(const SpaceFile *sfile, const uchar light[4] = {255, 255, 255, 255}; icon_x = xco + ex - UI_UNIT_X; icon_y = yco + ey - UI_UNIT_Y; - UI_icon_draw_ex(icon_x, icon_y, ICON_CURRENT_FILE, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false); + UI_icon_draw_ex(icon_x, + icon_y, + ICON_CURRENT_FILE, + 1.0f / U.dpi_fac, + 0.6f, + 0.0f, + light, + false, + UI_NO_ICON_OVERLAY_TEXT); } /* Contrasting outline around some preview types. */ diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c index aee72860a0a..12ee6f45991 100644 --- a/source/blender/editors/space_info/textview.c +++ b/source/blender/editors/space_info/textview.c @@ -235,7 +235,8 @@ static bool textview_draw_string(TextViewDrawState *tds, 1.0f, 0.0f, icon_fg, - false); + false, + UI_NO_ICON_OVERLAY_TEXT); GPU_blend(GPU_BLEND_NONE); } diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index ee9ebd541a0..98b2cacd162 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -2145,6 +2145,9 @@ static void node_draw_basis(const bContext &C, 0, ""); UI_but_func_set(but, node_toggle_button_cb, &node, (void *)"NODE_OT_group_edit"); + if (node.id) { + UI_but_icon_indicator_number_set(but, node.id->us); + } UI_block_emboss_set(&block, UI_EMBOSS); } if (node.type == NODE_CUSTOM && node.typeinfo->ui_icon != ICON_NONE) { diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index b12afcb1faa..637c795d4d7 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -815,7 +815,8 @@ static void draw_draglink_tooltip(const bContext * /*C*/, ARegion * /*region*/, nldrag->cursor[0]; const float y = nldrag->cursor[1] - 2.0f * UI_DPI_FAC; - UI_icon_draw_ex(x, y, ICON_ADD, U.inv_dpi_fac, 1.0f, 0.0f, text_col, false); + UI_icon_draw_ex( + x, y, ICON_ADD, U.inv_dpi_fac, 1.0f, 0.0f, text_col, false, UI_NO_ICON_OVERLAY_TEXT); } static void draw_draglink_tooltip_activate(const ARegion ®ion, bNodeLinkDrag &nldrag) diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc index e366c58349f..f76c0980c4f 100644 --- a/source/blender/editors/space_outliner/outliner_draw.cc +++ b/source/blender/editors/space_outliner/outliner_draw.cc @@ -2877,7 +2877,8 @@ static bool tselem_draw_icon(uiBlock *block, TreeStoreElem *tselem, TreeElement *te, float alpha, - const bool is_clickable) + const bool is_clickable, + const int num_elements) { TreeElementIcon data = tree_element_get_icon(tselem, te); if (data.icon == 0) { @@ -2885,6 +2886,8 @@ static bool tselem_draw_icon(uiBlock *block, } const bool is_collection = outliner_is_collection_tree_element(te); + IconTextOverlay text_overlay; + UI_icon_text_overlay_init_from_count(&text_overlay, num_elements); /* Collection colors and icons covered by restrict buttons. */ if (!is_clickable || x >= xmax || is_collection) { @@ -2904,7 +2907,8 @@ static bool tselem_draw_icon(uiBlock *block, alpha, 0.0f, btheme->collection_color[collection->color_tag].color, - true); + true, + &text_overlay); return true; } } @@ -2915,10 +2919,10 @@ static bool tselem_draw_icon(uiBlock *block, /* Restrict column clip. it has been coded by simply overdrawing, doesn't work for buttons. */ uchar color[4]; if (UI_icon_get_theme_color(data.icon, color)) { - UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, color, true); + UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, color, true, &text_overlay); } else { - UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, nullptr, false); + UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, nullptr, false, &text_overlay); } } else { @@ -2941,104 +2945,6 @@ static bool tselem_draw_icon(uiBlock *block, return true; } -static bool outliner_is_main_row(const ARegion *region, const int ys) -{ - int ystart; - - ystart = int(region->v2d.tot.ymax); - ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET; - - return ((ys - ystart) / UI_UNIT_Y) % 2; -} - -/** - * Get the expected row background color to use for the data-block counter - * - * This reproduces some of the logic of outliner_draw_highlights. - * At the moment it doesn't implement the search match color since - * we don't draw the data-block counter in those cases. - */ -static void outliner_get_row_color(const ARegion *region, - const TreeElement *te, - int ys, - float r_color[4]) -{ - const TreeStoreElem *tselem = TREESTORE(te); - - if ((tselem->flag & TSE_ACTIVE) && (tselem->flag & TSE_SELECTED)) { - UI_GetThemeColor3fv(TH_ACTIVE, r_color); - } - else if (tselem->flag & TSE_SELECTED) { - UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, r_color); - } - else if (outliner_is_main_row(region, ys)) { - UI_GetThemeColor3fv(TH_BACK, r_color); - } - else { - float color_alternating[4]; - UI_GetThemeColor4fv(TH_ROW_ALTERNATE, color_alternating); - UI_GetThemeColorBlend3f(TH_BACK, TH_ROW_ALTERNATE, color_alternating[3], r_color); - } - - if (tselem->flag & TSE_HIGHLIGHTED) { - const float color_highlight[4] = {1.0f, 1.0f, 1.0f, 0.13f}; - interp_v3_v3v3(r_color, r_color, color_highlight, color_highlight[3]); - } - r_color[3] = 1.0f; -} - -/** - * For icon-only children of a collapsed tree, - * Draw small number over the icon to show how many items of this type are displayed. - */ -static void outliner_draw_iconrow_number(const ARegion *region, - const uiFontStyle *fstyle, - int offsx, - int ys, - const TreeElement *te_visible, - const int num_elements) -{ - float color[4]; - outliner_get_row_color(region, te_visible, ys, color); - - float ufac = 0.25f * UI_UNIT_X; - float offset_x = float(offsx) + UI_UNIT_X * 0.35f; - rctf rect{}; - BLI_rctf_init(&rect, - offset_x + ufac, - offset_x + UI_UNIT_X - ufac, - float(ys) - UI_UNIT_Y * 0.2f + ufac, - float(ys) - UI_UNIT_Y * 0.2f + UI_UNIT_Y - ufac); - - UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_4fv_ex( - &rect, color, NULL, 1.0f, color, U.pixelsize, float(UI_UNIT_Y) / 2.0f - ufac); - - /* Now the numbers. */ - uchar text_col[4]; - - UI_GetThemeColor3ubv(TH_TEXT, text_col); - text_col[3] = 255; - - uiFontStyle fstyle_small = *fstyle; - fstyle_small.points *= 0.8f; - - /* We treat +99 as 4 digits to make sure the (eyeballed) alignment looks nice. */ - int num_digits = 4; - char number_text[4] = "+99"; - if (num_elements < 100) { - BLI_snprintf(number_text, sizeof(number_text), "%d", num_elements); - num_digits = num_elements < 10 ? 1 : 2; - } - UI_fontstyle_draw_simple(&fstyle_small, - (offset_x + ufac + UI_UNIT_X * (2 - num_digits) * 0.12f), - float(ys) - UI_UNIT_Y * 0.095f + ufac, - number_text, - text_col); - UI_fontstyle_set(fstyle); - GPU_blend(GPU_BLEND_ALPHA); /* Round-box and text drawing disables. */ -} - static void outliner_icon_background_colors(float icon_color[4], float icon_border[4]) { float text[4]; @@ -3069,11 +2975,8 @@ static void outliner_draw_active_indicator(const float minx, GPU_blend(GPU_BLEND_ALPHA); /* Round-box disables. */ } -static void outliner_draw_iconrow_doit(const ARegion *region, - uiBlock *block, - TreeElement *te_visible, +static void outliner_draw_iconrow_doit(uiBlock *block, TreeElement *te, - const uiFontStyle *fstyle, int xmax, int *offsx, int ys, @@ -3102,13 +3005,13 @@ static void outliner_draw_iconrow_doit(const ARegion *region, if (tselem->flag & TSE_HIGHLIGHTED_ICON) { alpha_fac += 0.5; } - tselem_draw_icon(block, xmax, float(*offsx), float(ys), tselem, te, alpha_fac, false); + tselem_draw_icon( + block, xmax, float(*offsx), float(ys), tselem, te, alpha_fac, false, num_elements); te->xs = *offsx; te->ys = ys; te->xend = short(*offsx) + UI_UNIT_X; if (num_elements > 1) { - outliner_draw_iconrow_number(region, fstyle, *offsx, ys, te_visible, num_elements); te->flag |= TE_ICONROW_MERGED; } else { @@ -3145,7 +3048,6 @@ static void outliner_draw_iconrow(bContext *C, const uiFontStyle *fstyle, const TreeViewContext *tvc, SpaceOutliner *space_outliner, - TreeElement *te_visible, ListBase *lb, int level, int xmax, @@ -3154,7 +3056,6 @@ static void outliner_draw_iconrow(bContext *C, float alpha_fac, MergedIconRow *merged) { - const ARegion *region = CTX_wm_region(C); eOLDrawState active = OL_DRAWSEL_NONE; LISTBASE_FOREACH (TreeElement *, te, lb) { @@ -3194,8 +3095,7 @@ static void outliner_draw_iconrow(bContext *C, TSE_POSE_CHANNEL, TSE_POSEGRP, TSE_DEFGROUP)) { - outliner_draw_iconrow_doit( - region, block, te_visible, te, fstyle, xmax, offsx, ys, alpha_fac, active, 1); + outliner_draw_iconrow_doit(block, te, xmax, offsx, ys, alpha_fac, active, 1); } else { const int index = tree_element_id_type_to_index(te); @@ -3214,7 +3114,6 @@ static void outliner_draw_iconrow(bContext *C, fstyle, tvc, space_outliner, - te, &te->subtree, level + 1, xmax, @@ -3236,11 +3135,8 @@ static void outliner_draw_iconrow(bContext *C, for (int j = 0; j < num_subtypes; j++) { const int index = index_base + j; if (merged->num_elements[index] != 0) { - outliner_draw_iconrow_doit(region, - block, - te_visible, + outliner_draw_iconrow_doit(block, merged->tree_element[index], - fstyle, xmax, offsx, ys, @@ -3429,7 +3325,8 @@ static void outliner_draw_tree_element(bContext *C, tselem, te, (tselem->flag & TSE_HIGHLIGHTED_ICON) ? alpha_fac + 0.5f : alpha_fac, - true)) { + true, + 1)) { offsx += UI_UNIT_X + 4 * ufac; } else { @@ -3478,7 +3375,6 @@ static void outliner_draw_tree_element(bContext *C, fstyle, tvc, space_outliner, - te, &te->subtree, 0, xmax, diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 1ede48a3265..58b1cd0a50b 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -282,6 +282,8 @@ set(GLSL_SRC shaders/gpu_shader_2D_image_vert.glsl shaders/gpu_shader_2D_image_rect_vert.glsl shaders/gpu_shader_2D_image_multi_rect_vert.glsl + shaders/gpu_shader_icon_frag.glsl + shaders/gpu_shader_icon_vert.glsl shaders/gpu_shader_image_frag.glsl shaders/gpu_shader_image_desaturate_frag.glsl shaders/gpu_shader_image_overlays_merge_frag.glsl @@ -609,6 +611,7 @@ set(SRC_SHADER_CREATE_INFOS shaders/infos/gpu_shader_3D_smooth_color_info.hh shaders/infos/gpu_shader_3D_uniform_color_info.hh shaders/infos/gpu_shader_gpencil_stroke_info.hh + shaders/infos/gpu_shader_icon_info.hh shaders/infos/gpu_shader_instance_varying_color_varying_size_info.hh shaders/infos/gpu_shader_keyframe_shape_info.hh shaders/infos/gpu_shader_line_dashed_uniform_color_info.hh diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index 3f35db42eb9..1148207fc57 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -208,6 +208,10 @@ typedef enum eGPUBuiltinShader { GPU_SHADER_TEXT, GPU_SHADER_KEYFRAME_SHAPE, GPU_SHADER_SIMPLE_LIGHTING, + /** + * Draw an icon, leaving a semi-transparent rectangle on top of the icon. + */ + GPU_SHADER_ICON, /** * Take a 2D position and color for each vertex with linear interpolation in window space. * diff --git a/source/blender/gpu/intern/gpu_shader_builtin.c b/source/blender/gpu/intern/gpu_shader_builtin.c index 8a6586e06f6..470643ba863 100644 --- a/source/blender/gpu/intern/gpu_shader_builtin.c +++ b/source/blender/gpu/intern/gpu_shader_builtin.c @@ -153,6 +153,11 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = { .create_info = "gpu_shader_2D_diag_stripes", }, + [GPU_SHADER_ICON] = + { + .name = "GPU_SHADER_ICON", + .create_info = "gpu_shader_icon", + }, [GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE] = { .name = "GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE", diff --git a/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl b/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl new file mode 100644 index 00000000000..ff56d772317 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl @@ -0,0 +1,42 @@ +/** + * Draw the icons, leaving a semi-transparent rectangle on top of the icon. + * + * The top-left corner of the rectangle is rounded and drawned with anti-alias. + * The anti-alias is done by transitioning from the outer to the inner radius of + * the rounded corner, and the rectangle sides. + */ + +void main() +{ + /* Top-left rounded corner parameters. */ + const float circle_radius_outer = 0.1; + const float circle_radius_inner = 0.075; + + /** + * Add a bit transparency to see a bit of the icon, without + * getting on the way of readability. */ + const float mask_transparency = 0.25; + + vec2 circle_center = vec2(circle_radius_outer - text_width, 0.5); + fragColor = texture(image, texCoord_interp) * color; + + /* radius in icon space (1 is the icon width). */ + float radius = length(mask_coord_interp - circle_center); + float mask = smoothstep(circle_radius_inner, circle_radius_outer, radius); + + bool lower_half = mask_coord_interp.y < circle_center.y; + bool right_half = mask_coord_interp.x > circle_center.x; + + if (right_half && mask_coord_interp.t < circle_center.y + circle_radius_outer) { + mask = smoothstep(circle_center.y + circle_radius_inner, + circle_center.y + circle_radius_outer, + mask_coord_interp.t); + } + if (lower_half && mask_coord_interp.s > circle_center.x - circle_radius_outer) { + mask = smoothstep(circle_center.x - circle_radius_inner, + circle_center.x - circle_radius_outer, + mask_coord_interp.s); + } + + fragColor = mix(vec4(0.0), fragColor, max(mask_transparency, mask)); +} diff --git a/source/blender/gpu/shaders/gpu_shader_icon_vert.glsl b/source/blender/gpu/shaders/gpu_shader_icon_vert.glsl new file mode 100644 index 00000000000..25f64bfe0b6 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_icon_vert.glsl @@ -0,0 +1,37 @@ +/** + * Simple shader that just draw one icon at the specified location + * does not need any vertex input (producing less call to immBegin/End) + */ + +void main() +{ + vec2 uv; + vec2 co; + + if (gl_VertexID == 0) { + co = rect_geom.xw; + uv = rect_icon.xw; + mask_coord_interp = vec2(0, 1); + } + else if (gl_VertexID == 1) { + co = rect_geom.xy; + uv = rect_icon.xy; + mask_coord_interp = vec2(0, 0); + } + else if (gl_VertexID == 2) { + co = rect_geom.zw; + uv = rect_icon.zw; + mask_coord_interp = vec2(1, 1); + } + else { + co = rect_geom.zy; + uv = rect_icon.zy; + mask_coord_interp = vec2(1, 0); + } + + /* Put origin in lower right corner. */ + mask_coord_interp.x -= 1; + + gl_Position = ModelViewProjectionMatrix * vec4(co, 0.0f, 1.0f); + texCoord_interp = uv; +} diff --git a/source/blender/gpu/shaders/infos/gpu_interface_info.hh b/source/blender/gpu/shaders/infos/gpu_interface_info.hh index d77c65e48a7..060def16f81 100644 --- a/source/blender/gpu/shaders/infos/gpu_interface_info.hh +++ b/source/blender/gpu/shaders/infos/gpu_interface_info.hh @@ -18,3 +18,6 @@ GPU_SHADER_INTERFACE_INFO(smooth_radii_outline_iface, "").smooth(Type::VEC4, "ra GPU_SHADER_INTERFACE_INFO(flat_color_smooth_tex_coord_interp_iface, "") .flat(Type::VEC4, "finalColor") .smooth(Type::VEC2, "texCoord_interp"); +GPU_SHADER_INTERFACE_INFO(smooth_icon_interp_iface, "") + .smooth(Type::VEC2, "texCoord_interp") + .smooth(Type::VEC2, "mask_coord_interp"); diff --git a/source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh new file mode 100644 index 00000000000..3d4077bdb09 --- /dev/null +++ b/source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#include "gpu_interface_info.hh" +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(gpu_shader_icon) + .vertex_out(smooth_icon_interp_iface) + .fragment_out(0, Type::VEC4, "fragColor") + .push_constant(Type::MAT4, "ModelViewProjectionMatrix") + .push_constant(Type::VEC4, "color") + .push_constant(Type::VEC4, "rect_icon") + .push_constant(Type::VEC4, "rect_geom") + .push_constant(Type::FLOAT, "text_width") + .sampler(0, ImageType::FLOAT_2D, "image") + .vertex_source("gpu_shader_icon_vert.glsl") + .fragment_source("gpu_shader_icon_frag.glsl") + .do_static_compilation(true); diff --git a/source/blender/windowmanager/intern/wm_dragdrop.cc b/source/blender/windowmanager/intern/wm_dragdrop.cc index 0896daec561..fb63abed9e9 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.cc +++ b/source/blender/windowmanager/intern/wm_dragdrop.cc @@ -853,7 +853,8 @@ static void wm_drag_draw_icon(bContext * /*C*/, wmWindow * /*win*/, wmDrag *drag y = xy[1] - 2 * UI_DPI_FAC; const uchar text_col[] = {255, 255, 255, 255}; - UI_icon_draw_ex(x, y, drag->icon, U.inv_dpi_fac, 0.8, 0.0f, text_col, false); + UI_icon_draw_ex( + x, y, drag->icon, U.inv_dpi_fac, 0.8, 0.0f, text_col, false, UI_NO_ICON_OVERLAY_TEXT); } } -- cgit v1.2.3 From 8415bc9c80aad878f7b85a48ffd2ae55150f9dc4 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 20 Oct 2022 16:54:19 +0200 Subject: Fix T101554: disable viewer node when corresponding modifier is disabled --- source/blender/editors/util/ed_viewer_path.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/editors/util/ed_viewer_path.cc b/source/blender/editors/util/ed_viewer_path.cc index 5c03367cba8..4da1559b726 100644 --- a/source/blender/editors/util/ed_viewer_path.cc +++ b/source/blender/editors/util/ed_viewer_path.cc @@ -249,6 +249,9 @@ bool is_active_geometry_nodes_viewer(const bContext &C, if (md->type != eModifierType_Nodes) { return false; } + if ((md->mode & eModifierMode_Realtime) == 0) { + return false; + } modifier = reinterpret_cast(md); break; } -- cgit v1.2.3 From 3bac6f17f1c197d69387e45d0ca8a5f77e8274ac Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 20 Oct 2022 17:04:49 +0200 Subject: install_deps: Update Python, OIIO, openPGL and FFMPEG versions. Update libraries for Blender 3.4, according to T101403: * python: 3.10.8 * OIIO: 2.3.20.0 * OpenPGL: 0.4.0-beta * FFMpeg: 5.1.2 --- build_files/build_environment/install_deps.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh index f913ac5e73c..ef72ad5b40b 100755 --- a/build_files/build_environment/install_deps.sh +++ b/build_files/build_environment/install_deps.sh @@ -394,7 +394,7 @@ CLANG_FORMAT_VERSION="10.0" CLANG_FORMAT_VERSION_MIN="6.0" CLANG_FORMAT_VERSION_MEX="14.0" -PYTHON_VERSION="3.10.2" +PYTHON_VERSION="3.10.8" PYTHON_VERSION_SHORT="3.10" PYTHON_VERSION_MIN="3.10" PYTHON_VERSION_MEX="3.12" @@ -505,7 +505,7 @@ OPENEXR_FORCE_REBUILD=false OPENEXR_SKIP=false _with_built_openexr=false -OIIO_VERSION="2.3.13.0" +OIIO_VERSION="2.3.20.0" OIIO_VERSION_SHORT="2.3" OIIO_VERSION_MIN="2.1.12" OIIO_VERSION_MEX="2.4.0" @@ -602,10 +602,10 @@ LEVEL_ZERO_FORCE_BUILD=false LEVEL_ZERO_FORCE_REBUILD=false LEVEL_ZERO_SKIP=false -OPENPGL_VERSION="0.3.1" -OPENPGL_VERSION_SHORT="0.3" +OPENPGL_VERSION="0.4.0" +OPENPGL_VERSION_SHORT="0.4" OPENPGL_VERSION_MIN="0.3.1" -OPENPGL_VERSION_MEX="0.3.2" +OPENPGL_VERSION_MEX="0.5" OPENPGL_FORCE_BUILD=false OPENPGL_FORCE_REBUILD=false OPENPGL_SKIP=false @@ -618,8 +618,8 @@ XR_OPENXR_FORCE_BUILD=false XR_OPENXR_FORCE_REBUILD=false XR_OPENXR_SKIP=false -FFMPEG_VERSION="5.0" -FFMPEG_VERSION_SHORT="5.0" +FFMPEG_VERSION="5.1.2" +FFMPEG_VERSION_SHORT="5.1" FFMPEG_VERSION_MIN="4.0" FFMPEG_VERSION_MEX="6.0" FFMPEG_FORCE_BUILD=false -- cgit v1.2.3 From 4b30ee773ce7f5e423830195e49ca06763ba230a Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 20 Oct 2022 17:34:22 +0200 Subject: Fix T101316: workbench texture mode not working with geometry nodes The `ED_object_get_active_image` is used from the renderer which deals with evaluated objects. This means the material api for evaluated objects has to be used. --- source/blender/editors/uvedit/uvedit_ops.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 5e2d9097abd..b65f4889347 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -37,6 +37,7 @@ #include "BKE_node.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "ED_image.h" #include "ED_mesh.h" @@ -113,7 +114,8 @@ bool ED_object_get_active_image(Object *ob, bNode **r_node, bNodeTree **r_ntree) { - Material *ma = BKE_object_material_get(ob, mat_nr); + Material *ma = DEG_is_evaluated_object(ob) ? BKE_object_material_get_eval(ob, mat_nr) : + BKE_object_material_get(ob, mat_nr); bNodeTree *ntree = (ma && ma->use_nodes) ? ma->nodetree : NULL; bNode *node = (ntree) ? nodeGetActiveTexture(ntree) : NULL; -- cgit v1.2.3 From 24fd8f729a58b18159912a84525b910b0d4e7ef5 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Thu, 20 Oct 2022 17:54:29 +0200 Subject: Fix memory leak when proxy building fails Leak introduced in recent fix - bf8d4a9bc6fb28. --- source/blender/imbuf/intern/indexer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index e8e4b80ef45..eaa72441fb6 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -909,6 +909,9 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, if (context->proxy_ctx[0] == NULL && context->proxy_ctx[1] == NULL && context->proxy_ctx[2] == NULL && context->proxy_ctx[3] == NULL) { + avformat_close_input(&context->iFormatCtx); + avcodec_free_context(&context->iCodecCtx); + MEM_freeN(context); return NULL; /* Nothing to transcode. */ } -- cgit v1.2.3 From 5e0e5b13410350166553256272311774acd5aaa4 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 20 Oct 2022 18:01:44 +0200 Subject: Fix T101215: Distribute Points in Volume node does not refresh on frame change --- .../blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc index 091337c28cf..3a021bfe2d7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc @@ -208,6 +208,7 @@ static void geo_node_distribute_points_in_volume_exec(GeoNodeExecParams params) } const VolumeComponent *component = geometry_set.get_component_for_read(); const Volume *volume = component->get_for_read(); + BKE_volume_load(volume, DEG_get_bmain(params.depsgraph())); Vector positions; -- cgit v1.2.3 From 8c361d6f66cf4d87f5fd220ff056ea563a7d8e07 Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Thu, 20 Oct 2022 11:46:42 -0600 Subject: deps_builder: fix missing png harvest on windows --- build_files/build_environment/cmake/png.cmake | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build_files/build_environment/cmake/png.cmake b/build_files/build_environment/cmake/png.cmake index 890be673cb8..371f2608e2a 100644 --- a/build_files/build_environment/cmake/png.cmake +++ b/build_files/build_environment/cmake/png.cmake @@ -24,6 +24,14 @@ add_dependencies( external_zlib ) +if(WIN32 AND BUILD_MODE STREQUAL Release) + ExternalProject_Add_Step(external_png after_install + COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/png/include/ ${HARVEST_TARGET}/png/include/ + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/png/lib/libpng16_static${LIBEXT} ${HARVEST_TARGET}/png/lib/libpng${LIBEXT} + DEPENDEES install + ) +endif() + if(WIN32 AND BUILD_MODE STREQUAL Debug) ExternalProject_Add_Step(external_png after_install COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/png/lib/libpng16_staticd${LIBEXT} ${LIBDIR}/png/lib/libpng16${LIBEXT} -- cgit v1.2.3 From bd1ff201b1dfb7bd382ed19079bcebddfc5e30d4 Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Thu, 20 Oct 2022 21:06:44 +0200 Subject: Buildfix for 078e034 missing include --- .../nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc index 3a021bfe2d7..95173bd23a5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc @@ -15,6 +15,8 @@ #include "UI_interface.h" #include "UI_resources.h" +#include "DEG_depsgraph_query.h" + #include "node_geometry_util.hh" namespace blender::nodes { -- cgit v1.2.3 From 97f4e076c7fcd362c9803dcf1afb303c110c997e Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 20 Oct 2022 17:23:37 -0500 Subject: Fix: USD & Alembic importers might not initialize material indices f1c0249f34c4171ec incorrectly assumed that the importer functions that assigned material indices set all of the values, but that isn't true for all files. --- source/blender/io/alembic/intern/abc_reader_mesh.cc | 6 +++--- source/blender/io/usd/intern/usd_reader_mesh.cc | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index f08514dc45c..2531bd62609 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -763,7 +763,7 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh, std::map mat_map; bke::MutableAttributeAccessor attributes = new_mesh->attributes_for_write(); bke::SpanAttributeWriter material_indices = - attributes.lookup_or_add_for_write_only_span("material_index", ATTR_DOMAIN_FACE); + attributes.lookup_or_add_for_write_span("material_index", ATTR_DOMAIN_FACE); assign_facesets_to_material_indices(sample_sel, material_indices.span, mat_map); material_indices.finish(); } @@ -823,8 +823,8 @@ void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const ISampleSel { std::map mat_map; bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); - bke::SpanAttributeWriter material_indices = - attributes.lookup_or_add_for_write_only_span("material_index", ATTR_DOMAIN_FACE); + bke::SpanAttributeWriter material_indices = attributes.lookup_or_add_for_write_span( + "material_index", ATTR_DOMAIN_FACE); assign_facesets_to_material_indices(sample_sel, material_indices.span, mat_map); material_indices.finish(); utils::assign_materials(bmain, m_object, mat_map); diff --git a/source/blender/io/usd/intern/usd_reader_mesh.cc b/source/blender/io/usd/intern/usd_reader_mesh.cc index 77c79852141..01db6baeb5c 100644 --- a/source/blender/io/usd/intern/usd_reader_mesh.cc +++ b/source/blender/io/usd/intern/usd_reader_mesh.cc @@ -804,8 +804,8 @@ void USDMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const double mot std::map mat_map; bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); - bke::SpanAttributeWriter material_indices = - attributes.lookup_or_add_for_write_only_span("material_index", ATTR_DOMAIN_FACE); + bke::SpanAttributeWriter material_indices = attributes.lookup_or_add_for_write_span( + "material_index", ATTR_DOMAIN_FACE); this->assign_facesets_to_material_indices(motionSampleTime, material_indices.span, &mat_map); material_indices.finish(); /* Build material name map if it's not built yet. */ @@ -914,7 +914,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh, std::map mat_map; bke::MutableAttributeAccessor attributes = active_mesh->attributes_for_write(); bke::SpanAttributeWriter material_indices = - attributes.lookup_or_add_for_write_only_span("material_index", ATTR_DOMAIN_FACE); + attributes.lookup_or_add_for_write_span("material_index", ATTR_DOMAIN_FACE); assign_facesets_to_material_indices(motionSampleTime, material_indices.span, &mat_map); material_indices.finish(); } -- cgit v1.2.3 From ff8c0f062a6ac521b13ebbda3103cda4f9a4dc46 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 21 Oct 2022 10:00:09 +1100 Subject: GHOST/Wayland: code comments, minor improvements - Clarify how data_offer is used for both the clipboard & drag-and-drop. - Acquire the clipboards mutex lock before freeing. - Log a warning when creating a pipe fails. - Add doxy-sections. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 203 ++++++++++++++++++---------- 1 file changed, 132 insertions(+), 71 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index fb69973eac6..68ad028631c 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -234,7 +234,7 @@ static const GWL_ModifierInfo g_modifier_info_table[MOD_INDEX_NUM] = { /** \} */ /* -------------------------------------------------------------------- */ -/** \name Private Types & Defines +/** \name Internal #GWL_SimpleBuffer Type * \{ */ struct GWL_SimpleBuffer { @@ -250,7 +250,9 @@ static void gwl_simple_buffer_free_data(GWL_SimpleBuffer *buffer) buffer->data_size = 0; } -static void gwl_simple_buffer_set(GWL_SimpleBuffer *buffer, const char *data, size_t data_size) +static void gwl_simple_buffer_set_and_take_ownership(GWL_SimpleBuffer *buffer, + const char *data, + size_t data_size) { free(const_cast(buffer->data)); buffer->data = data; @@ -274,6 +276,12 @@ static char *gwl_simple_buffer_as_string(const GWL_SimpleBuffer *buffer) return buffer_str; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal #GWL_Cursor Type + * \{ */ + /** * From XKB internals, use for converting a scan-code from WAYLAND to a #xkb_keycode_t. * Ideally this wouldn't need a local define. @@ -289,16 +297,26 @@ struct GWL_Cursor { * the hardware cursor is used. */ bool is_hardware = true; + /** When true, a custom image is used to display the cursor (stored in `wl_image`). */ bool is_custom = false; struct wl_surface *wl_surface = nullptr; struct wl_buffer *wl_buffer = nullptr; struct wl_cursor_image wl_image = {0}; struct wl_cursor_theme *wl_theme = nullptr; void *custom_data = nullptr; + /** The size of `custom_data` in bytes. */ size_t custom_data_size = 0; - int size = 0; + /** + * The name of the theme (loaded by DBUS, depends on #WITH_GHOST_WAYLAND_DBUS). + * When disabled, leave as an empty string and the default theme will be used. + */ std::string theme_name; - + /** + * The size of the cursor (when looking up a cursor theme). + * This must be scaled by the maximum output scale when passing to wl_cursor_theme_load. + * See #update_cursor_scale. + * */ + int theme_size = 0; int custom_scale = 1; }; @@ -309,6 +327,7 @@ struct GWL_Cursor { */ struct GWL_TabletTool { struct GWL_Seat *seat = nullptr; + /** Tablets have a separate cursor to the 'pointer', this surface is used for cursor drawing. */ struct wl_surface *wl_surface_cursor = nullptr; /** Used to delay clearing tablet focused wl_surface until the frame is handled. */ bool proximity = false; @@ -316,23 +335,51 @@ struct GWL_TabletTool { GHOST_TabletData data = GHOST_TABLET_DATA_NONE; }; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal #GWL_DataOffer Type + * \{ */ + +/** + * Data storage used for clipboard paste & drag-and-drop. + */ struct GWL_DataOffer { - std::unordered_set types; - uint32_t source_actions = 0; - uint32_t dnd_action = 0; struct wl_data_offer *id = nullptr; + std::unordered_set types; std::atomic in_use = false; + struct { + /** + * Bit-mask with available drop options. + * #WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY, #WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE.. etc. + * The application that initializes the drag may set these depending on modifiers held + * \note when dragging begins. Currently ghost doesn't make use of these. + */ + enum wl_data_device_manager_dnd_action source_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; + enum wl_data_device_manager_dnd_action action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; /** Compatible with #GWL_Seat.xy coordinates. */ wl_fixed_t xy[2] = {0, 0}; } dnd; }; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal #GWL_DataSource Type + * \{ */ + struct GWL_DataSource { - struct wl_data_source *wl_data_source = nullptr; + struct wl_data_source *wl_source = nullptr; GWL_SimpleBuffer buffer_out; }; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal #GWL_Seat Type (#wl_seat wrapper & associated types) + * \{ */ + /** * Data used to implement client-side key-repeat. * @@ -605,6 +652,12 @@ struct GWL_Seat { uint32_t data_source_serial = 0; }; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal #GWL_Display Type (#wl_display & #wl_compositor wrapper) + * \{ */ + struct GWL_Display { GHOST_SystemWayland *system = nullptr; @@ -633,8 +686,6 @@ struct GWL_Display { GWL_SimpleBuffer clipboard_primary; }; -#undef LOG - /** \} */ /* -------------------------------------------------------------------- */ @@ -710,8 +761,8 @@ static void display_destroy(GWL_Display *display) std::lock_guard lock{seat->data_source_mutex}; if (seat->data_source) { gwl_simple_buffer_free_data(&seat->data_source->buffer_out); - if (seat->data_source->wl_data_source) { - wl_data_source_destroy(seat->data_source->wl_data_source); + if (seat->data_source->wl_source) { + wl_data_source_destroy(seat->data_source->wl_source); } delete seat->data_source; } @@ -833,8 +884,11 @@ static void display_destroy(GWL_Display *display) wl_display_disconnect(display->wl_display); } - gwl_simple_buffer_free_data(&display->clipboard); - gwl_simple_buffer_free_data(&display->clipboard_primary); + { + std::lock_guard lock{system_clipboard_mutex}; + gwl_simple_buffer_free_data(&display->clipboard); + gwl_simple_buffer_free_data(&display->clipboard_primary); + } delete display; } @@ -1399,16 +1453,17 @@ static const char *read_file_as_buffer(const int fd, size_t *r_len) return buf; } -static const char *read_pipe(GWL_DataOffer *data_offer, - const std::string mime_receive, - std::mutex *mutex, - size_t *r_len) +static const char *read_buffer_from_data_offer(GWL_DataOffer *data_offer, + const char *mime_receive, + std::mutex *mutex, + size_t *r_len) { int pipefd[2]; if (UNLIKELY(pipe(pipefd) != 0)) { - return {}; + CLOG_WARN(LOG, "error creating pipe: %s", std::strerror(errno)); + return nullptr; } - wl_data_offer_receive(data_offer->id, mime_receive.c_str(), pipefd[1]); + wl_data_offer_receive(data_offer->id, mime_receive, pipefd[1]); close(pipefd[1]); data_offer->in_use.store(false); @@ -1423,16 +1478,18 @@ static const char *read_pipe(GWL_DataOffer *data_offer, return buf; } -static const char *read_pipe_primary(GWL_PrimarySelection_DataOffer *data_offer, - const std::string mime_receive, - std::mutex *mutex, - size_t *r_len) +static const char *read_buffer_from_primary_selection_offer( + GWL_PrimarySelection_DataOffer *data_offer, + const char *mime_receive, + std::mutex *mutex, + size_t *r_len) { int pipefd[2]; if (UNLIKELY(pipe(pipefd) != 0)) { - return {}; + CLOG_WARN(LOG, "error creating pipe: %s", std::strerror(errno)); + return nullptr; } - zwp_primary_selection_offer_v1_receive(data_offer->id, mime_receive.c_str(), pipefd[1]); + zwp_primary_selection_offer_v1_receive(data_offer->id, mime_receive, pipefd[1]); close(pipefd[1]); data_offer->in_use.store(false); @@ -1481,8 +1538,8 @@ static void data_source_handle_cancelled(void *data, struct wl_data_source *wl_d CLOG_INFO(LOG, 2, "cancelled"); GWL_Seat *seat = static_cast(data); GWL_DataSource *data_source = seat->data_source; - if (seat->data_source->wl_data_source == wl_data_source) { - data_source->wl_data_source = nullptr; + if (seat->data_source->wl_source == wl_data_source) { + data_source->wl_source = nullptr; } wl_data_source_destroy(wl_data_source); @@ -1553,7 +1610,8 @@ static void data_offer_handle_offer(void *data, const char *mime_type) { CLOG_INFO(LOG, 2, "offer (mime_type=%s)", mime_type); - static_cast(data)->types.insert(mime_type); + GWL_DataOffer *data_offer = static_cast(data); + data_offer->types.insert(mime_type); } static void data_offer_handle_source_actions(void *data, @@ -1561,7 +1619,8 @@ static void data_offer_handle_source_actions(void *data, const uint32_t source_actions) { CLOG_INFO(LOG, 2, "source_actions (%u)", source_actions); - static_cast(data)->source_actions = source_actions; + GWL_DataOffer *data_offer = static_cast(data); + data_offer->dnd.source_actions = (enum wl_data_device_manager_dnd_action)source_actions; } static void data_offer_handle_action(void *data, @@ -1569,7 +1628,8 @@ static void data_offer_handle_action(void *data, const uint32_t dnd_action) { CLOG_INFO(LOG, 2, "actions (%u)", dnd_action); - static_cast(data)->dnd_action = dnd_action; + GWL_DataOffer *data_offer = static_cast(data); + data_offer->dnd.action = (enum wl_data_device_manager_dnd_action)dnd_action; } static const struct wl_data_offer_listener data_offer_listener = { @@ -1693,7 +1753,8 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat const wl_fixed_t xy[2] = {UNPACK2(data_offer->dnd.xy)}; size_t data_buf_len = 0; - const char *data_buf = read_pipe(data_offer, mime_receive, nullptr, &data_buf_len); + const char *data_buf = read_buffer_from_data_offer( + data_offer, mime_receive.c_str(), nullptr, &data_buf_len); std::string data = data_buf ? std::string(data_buf, data_buf_len) : ""; free(const_cast(data_buf)); @@ -1812,13 +1873,13 @@ static void data_device_handle_selection(void *data, } size_t data_len = 0; - const char *data = read_pipe( - data_offer, mime_receive, &seat->data_offer_copy_paste_mutex, &data_len); + const char *data = read_buffer_from_data_offer( + data_offer, mime_receive.c_str(), &seat->data_offer_copy_paste_mutex, &data_len); { std::lock_guard lock{system_clipboard_mutex}; GWL_SimpleBuffer *buf = system->clipboard_data(false); - gwl_simple_buffer_set(buf, data, data_len); + gwl_simple_buffer_set_and_take_ownership(buf, data, data_len); } }; @@ -1892,7 +1953,8 @@ static bool update_cursor_scale(GWL_Cursor &cursor, wl_surface_set_buffer_scale(wl_cursor_surface, scale); } wl_cursor_theme_destroy(cursor.wl_theme); - cursor.wl_theme = wl_cursor_theme_load(cursor.theme_name.c_str(), scale * cursor.size, shm); + cursor.wl_theme = wl_cursor_theme_load( + cursor.theme_name.c_str(), scale * cursor.theme_size, shm); return true; } return false; @@ -3165,13 +3227,13 @@ static void primary_selection_device_handle_selection( } } size_t data_len = 0; - const char *data = read_pipe_primary( - data_offer, mime_receive, &primary->data_offer_mutex, &data_len); + const char *data = read_buffer_from_primary_selection_offer( + data_offer, mime_receive.c_str(), &primary->data_offer_mutex, &data_len); { std::lock_guard lock{system_clipboard_mutex}; GWL_SimpleBuffer *buf = system->clipboard_data(true); - gwl_simple_buffer_set(buf, data, data_len); + gwl_simple_buffer_set_and_take_ownership(buf, data, data_len); } }; @@ -3262,9 +3324,9 @@ static void seat_handle_capabilities(void *data, seat->cursor.wl_surface = wl_compositor_create_surface(seat->system->wl_compositor()); seat->cursor.visible = true; seat->cursor.wl_buffer = nullptr; - if (!get_cursor_settings(seat->cursor.theme_name, seat->cursor.size)) { + if (!get_cursor_settings(seat->cursor.theme_name, seat->cursor.theme_size)) { seat->cursor.theme_name = std::string(); - seat->cursor.size = default_cursor_size; + seat->cursor.theme_size = default_cursor_size; } wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, data); @@ -3990,18 +4052,17 @@ static void system_clipboard_put(GWL_Display *display, const char *buffer) /* Copy buffer. */ gwl_simple_buffer_set_from_string(&data_source->buffer_out, buffer); - data_source->wl_data_source = wl_data_device_manager_create_data_source( - display->data_device_manager); + data_source->wl_source = wl_data_device_manager_create_data_source(display->data_device_manager); - wl_data_source_add_listener(data_source->wl_data_source, &data_source_listener, seat); + wl_data_source_add_listener(data_source->wl_source, &data_source_listener, seat); for (const std::string &type : mime_send) { - wl_data_source_offer(data_source->wl_data_source, type.c_str()); + wl_data_source_offer(data_source->wl_source, type.c_str()); } if (seat->data_device) { wl_data_device_set_selection( - seat->data_device, data_source->wl_data_source, seat->data_source_serial); + seat->data_device, data_source->wl_source, seat->data_source_serial); } } @@ -4284,22 +4345,22 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title, */ static void cursor_buffer_show(const GWL_Seat *seat) { - const GWL_Cursor *c = &seat->cursor; + const GWL_Cursor *cursor = &seat->cursor; if (seat->wl_pointer) { - const int scale = c->is_custom ? c->custom_scale : seat->pointer.theme_scale; - const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / scale; - const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / scale; + const int scale = cursor->is_custom ? cursor->custom_scale : seat->pointer.theme_scale; + const int32_t hotspot_x = int32_t(cursor->wl_image.hotspot_x) / scale; + const int32_t hotspot_y = int32_t(cursor->wl_image.hotspot_y) / scale; if (seat->wl_pointer) { wl_pointer_set_cursor( - seat->wl_pointer, seat->pointer.serial, c->wl_surface, hotspot_x, hotspot_y); + seat->wl_pointer, seat->pointer.serial, cursor->wl_surface, hotspot_x, hotspot_y); } } if (!seat->tablet_tools.empty()) { - const int scale = c->is_custom ? c->custom_scale : seat->tablet.theme_scale; - const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / scale; - const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / scale; + const int scale = cursor->is_custom ? cursor->custom_scale : seat->tablet.theme_scale; + const int32_t hotspot_x = int32_t(cursor->wl_image.hotspot_x) / scale; + const int32_t hotspot_y = int32_t(cursor->wl_image.hotspot_y) / scale; for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->tablet_tools) { GWL_TabletTool *tablet_tool = static_cast( zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2)); @@ -4362,21 +4423,21 @@ static void cursor_buffer_set_surface_impl(const GWL_Seat *seat, static void cursor_buffer_set(const GWL_Seat *seat, wl_buffer *buffer) { - const GWL_Cursor *c = &seat->cursor; + const GWL_Cursor *cursor = &seat->cursor; const wl_cursor_image *wl_image = &seat->cursor.wl_image; - const bool visible = (c->visible && c->is_hardware); + const bool visible = (cursor->visible && cursor->is_hardware); /* This is a requirement of WAYLAND, when this isn't the case, * it causes Blender's window to close intermittently. */ if (seat->wl_pointer) { const int scale = cursor_buffer_compatible_scale_from_image( - wl_image, c->is_custom ? c->custom_scale : seat->pointer.theme_scale); + wl_image, cursor->is_custom ? cursor->custom_scale : seat->pointer.theme_scale); const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale; const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale; - cursor_buffer_set_surface_impl(seat, buffer, c->wl_surface, scale); + cursor_buffer_set_surface_impl(seat, buffer, cursor->wl_surface, scale); wl_pointer_set_cursor(seat->wl_pointer, seat->pointer.serial, - visible ? c->wl_surface : nullptr, + visible ? cursor->wl_surface : nullptr, hotspot_x, hotspot_y); } @@ -4384,7 +4445,7 @@ static void cursor_buffer_set(const GWL_Seat *seat, wl_buffer *buffer) /* Set the cursor for all tablet tools as well. */ if (!seat->tablet_tools.empty()) { const int scale = cursor_buffer_compatible_scale_from_image( - wl_image, c->is_custom ? c->custom_scale : seat->tablet.theme_scale); + wl_image, cursor->is_custom ? cursor->custom_scale : seat->tablet.theme_scale); const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale; const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale; for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->tablet_tools) { @@ -4471,31 +4532,31 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor s (*cursor_find).second; GWL_Seat *seat = display_->seats[0]; - GWL_Cursor *c = &seat->cursor; + GWL_Cursor *cursor = &seat->cursor; - if (!c->wl_theme) { + if (!cursor->wl_theme) { /* The cursor wl_surface hasn't entered an output yet. Initialize theme with scale 1. */ - c->wl_theme = wl_cursor_theme_load( - c->theme_name.c_str(), c->size, display_->seats[0]->system->wl_shm()); + cursor->wl_theme = wl_cursor_theme_load( + cursor->theme_name.c_str(), cursor->theme_size, wl_shm()); } - wl_cursor *cursor = wl_cursor_theme_get_cursor(c->wl_theme, cursor_name); + wl_cursor *wl_cursor = wl_cursor_theme_get_cursor(cursor->wl_theme, cursor_name); - if (!cursor) { + if (!wl_cursor) { GHOST_PRINT("cursor '" << cursor_name << "' does not exist" << std::endl); return GHOST_kFailure; } - struct wl_cursor_image *image = cursor->images[0]; + struct wl_cursor_image *image = wl_cursor->images[0]; struct wl_buffer *buffer = wl_cursor_image_get_buffer(image); if (!buffer) { return GHOST_kFailure; } - c->visible = true; - c->is_custom = false; - c->wl_buffer = buffer; - c->wl_image = *image; + cursor->visible = true; + cursor->is_custom = false; + cursor->wl_buffer = buffer; + cursor->wl_image = *image; cursor_buffer_set(seat, buffer); -- cgit v1.2.3 From 65151779811bb68f9afa0fb5d3dfacbd9fd3d6cb Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Thu, 20 Oct 2022 18:29:59 -0600 Subject: deps_builder: OpenCollada fixes for windows - build and use our version of libxml - the cli tools had a linker error due to it trying to link a shared version of libxml, disabled both and zlib 1.2.3 with a patch since we do not want/need them for blender. - postfix the libraries with _d for debug automatically so we don't have to fix that during the harvest. due to this only being windows changes no rebuild needed for the other platforms. --- build_files/build_environment/CMakeLists.txt | 3 +- .../build_environment/cmake/opencollada.cmake | 33 ++++++----- build_files/build_environment/cmake/xml2.cmake | 64 ++++++++++++++++------ .../build_environment/patches/opencollada.diff | 25 +++++++++ 4 files changed, 89 insertions(+), 36 deletions(-) diff --git a/build_files/build_environment/CMakeLists.txt b/build_files/build_environment/CMakeLists.txt index 4f40f44ad18..023d113b551 100644 --- a/build_files/build_environment/CMakeLists.txt +++ b/build_files/build_environment/CMakeLists.txt @@ -97,6 +97,8 @@ include(cmake/embree.cmake) include(cmake/openpgl.cmake) include(cmake/fmt.cmake) include(cmake/robinmap.cmake) +include(cmake/xml2.cmake) + if(NOT APPLE) include(cmake/xr_openxr.cmake) if(NOT WIN32 OR BUILD_MODE STREQUAL Release) @@ -149,7 +151,6 @@ if(NOT WIN32 OR ENABLE_MINGW64) endif() if(UNIX) include(cmake/flac.cmake) - include(cmake/xml2.cmake) if(NOT APPLE) include(cmake/spnav.cmake) include(cmake/jemalloc.cmake) diff --git a/build_files/build_environment/cmake/opencollada.cmake b/build_files/build_environment/cmake/opencollada.cmake index b2ae1a1a351..9473aafbe88 100644 --- a/build_files/build_environment/cmake/opencollada.cmake +++ b/build_files/build_environment/cmake/opencollada.cmake @@ -4,6 +4,16 @@ if(UNIX) set(OPENCOLLADA_EXTRA_ARGS -DLIBXML2_INCLUDE_DIR=${LIBDIR}/xml2/include/libxml2 -DLIBXML2_LIBRARIES=${LIBDIR}/xml2/lib/libxml2.a) +else() + set(OPENCOLLADA_EXTRA_ARGS + -DCMAKE_DEBUG_POSTFIX=_d + -DLIBXML2_INCLUDE_DIR=${LIBDIR}/xml2/include/libxml2 + ) + if(BUILD_MODE STREQUAL Release) + list(APPEND OPENCOLLADA_EXTRA_ARGS -DLIBXML2_LIBRARIES=${LIBDIR}/xml2/lib/libxml2s.lib) + else() + list(APPEND OPENCOLLADA_EXTRA_ARGS -DLIBXML2_LIBRARIES=${LIBDIR}/xml2/lib/libxml2sd.lib) + endif() endif() ExternalProject_Add(external_opencollada @@ -16,12 +26,11 @@ ExternalProject_Add(external_opencollada INSTALL_DIR ${LIBDIR}/opencollada ) -if(UNIX) - add_dependencies( - external_opencollada - external_xml2 - ) -endif() + +add_dependencies( + external_opencollada + external_xml2 +) if(WIN32) if(BUILD_MODE STREQUAL Release) @@ -32,17 +41,7 @@ if(WIN32) endif() if(BUILD_MODE STREQUAL Debug) ExternalProject_Add_Step(external_opencollada after_install - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/buffer.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/buffer_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/ftoa.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/ftoa_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/GeneratedSaxParser.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/GeneratedSaxParser_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/MathMLSolver.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/MathMLSolver_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADABaseUtils.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADABaseUtils_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADAFramework.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADAFramework_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADASaxFrameworkLoader.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADASaxFrameworkLoader_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADAStreamWriter.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADAStreamWriter_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/pcre.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/pcre_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/UTF.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/UTF_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/xml.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/xml_d.lib + COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/opencollada/lib ${HARVEST_TARGET}/opencollada/lib DEPENDEES install ) endif() diff --git a/build_files/build_environment/cmake/xml2.cmake b/build_files/build_environment/cmake/xml2.cmake index cd24fd836b0..3d31ec131bb 100644 --- a/build_files/build_environment/cmake/xml2.cmake +++ b/build_files/build_environment/cmake/xml2.cmake @@ -1,20 +1,48 @@ # SPDX-License-Identifier: GPL-2.0-or-later -ExternalProject_Add(external_xml2 - URL file://${PACKAGE_DIR}/${XML2_FILE} - DOWNLOAD_DIR ${DOWNLOAD_DIR} - URL_HASH ${XML2_HASH_TYPE}=${XML2_HASH} - PREFIX ${BUILD_DIR}/xml2 - CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && ${CONFIGURE_COMMAND} - --prefix=${LIBDIR}/xml2 - --disable-shared - --enable-static - --with-pic - --with-python=no - --with-lzma=no - --with-zlib=no - --with-iconv=no - BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && make -j${MAKE_THREADS} - INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && make install - INSTALL_DIR ${LIBDIR}/xml2 -) +if(WIN32) + set(XML2_EXTRA_ARGS + -DLIBXML2_WITH_ZLIB=OFF + -DLIBXML2_WITH_LZMA=OFF + -DLIBXML2_WITH_PYTHON=OFF + -DLIBXML2_WITH_ICONV=OFF + -DLIBXML2_WITH_TESTS=OFF + -DLIBXML2_WITH_PROGRAMS=OFF + -DBUILD_SHARED_LIBS=OFF + ) + ExternalProject_Add(external_xml2 + URL file://${PACKAGE_DIR}/${XML2_FILE} + DOWNLOAD_DIR ${DOWNLOAD_DIR} + URL_HASH ${XML2_HASH_TYPE}=${XML2_HASH} + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/xml2 ${DEFAULT_CMAKE_FLAGS} ${XML2_EXTRA_ARGS} + PREFIX ${BUILD_DIR}/xml2 + INSTALL_DIR ${LIBDIR}/xml2 + ) +else() + ExternalProject_Add(external_xml2 + URL file://${PACKAGE_DIR}/${XML2_FILE} + DOWNLOAD_DIR ${DOWNLOAD_DIR} + URL_HASH ${XML2_HASH_TYPE}=${XML2_HASH} + PREFIX ${BUILD_DIR}/xml2 + CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && ${CONFIGURE_COMMAND} + --prefix=${LIBDIR}/xml2 + --disable-shared + --enable-static + --with-pic + --with-python=no + --with-lzma=no + --with-zlib=no + --with-iconv=no + BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && make -j${MAKE_THREADS} + INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && make install + INSTALL_DIR ${LIBDIR}/xml2 + ) +endif() + +if(WIN32 AND BUILD_MODE STREQUAL Release) + ExternalProject_Add_Step(external_xml2 after_install + COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/xml2/include ${HARVEST_TARGET}/xml2/include + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/xml2/lib/libxml2s.lib ${HARVEST_TARGET}/xml2/lib/libxml2s.lib + DEPENDEES install + ) +endif() diff --git a/build_files/build_environment/patches/opencollada.diff b/build_files/build_environment/patches/opencollada.diff index e8efc1a6909..02eab251a13 100644 --- a/build_files/build_environment/patches/opencollada.diff +++ b/build_files/build_environment/patches/opencollada.diff @@ -130,3 +130,28 @@ index 715d903..24423ce 100644 { string id = node.attribute("id").value(); size_t line = node.line(); +diff -Naur a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -274,7 +274,7 @@ + add_subdirectory(${EXTERNAL_LIBRARIES}/UTF) + add_subdirectory(common/libBuffer) + add_subdirectory(${EXTERNAL_LIBRARIES}/MathMLSolver) +-add_subdirectory(${EXTERNAL_LIBRARIES}/zlib) ++#add_subdirectory(${EXTERNAL_LIBRARIES}/zlib) + + # building OpenCOLLADA libs + add_subdirectory(COLLADABaseUtils) +@@ -284,10 +284,10 @@ + add_subdirectory(COLLADAStreamWriter) + + # building COLLADAValidator app +-add_subdirectory(COLLADAValidator) ++#add_subdirectory(COLLADAValidator) + + # DAE validator app +-add_subdirectory(DAEValidator) ++#add_subdirectory(DAEValidator) + + # Library export + install(EXPORT LibraryExport DESTINATION ${OPENCOLLADA_INST_CMAKECONFIG} FILE OpenCOLLADATargets.cmake) -- cgit v1.2.3 From dc09cc13ea49a0de72aafcb8a48d6189d13aa6d9 Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Thu, 20 Oct 2022 18:31:15 -0600 Subject: deps_builder: add missing OSLNoise library on windows OSLNoise is a new library, was missing in the debug configuration on windows. --- build_files/build_environment/cmake/osl.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/build_files/build_environment/cmake/osl.cmake b/build_files/build_environment/cmake/osl.cmake index 8bac2c5c1ab..a5d000e4f44 100644 --- a/build_files/build_environment/cmake/osl.cmake +++ b/build_files/build_environment/cmake/osl.cmake @@ -83,6 +83,7 @@ if(WIN32) COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslcomp.lib ${HARVEST_TARGET}/osl/lib/oslcomp_d.lib COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslexec.lib ${HARVEST_TARGET}/osl/lib/oslexec_d.lib COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslquery.lib ${HARVEST_TARGET}/osl/lib/oslquery_d.lib + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslnoise.lib ${HARVEST_TARGET}/osl/lib/oslnoise_d.lib DEPENDEES install ) endif() -- cgit v1.2.3 From a0bbd65d57f38344fb71565c3c34396363a4be23 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 21 Oct 2022 16:11:07 +1100 Subject: Fix T66713: Walk mode doesn't take scene unit scale into account When changing a scene's unit scale from 1 to something else, 0.1 for e.g. walk navigation no longer worked properly. Whenever gravity is enabled, and the user starts to fall or jump, the view-port glitched out into low earth orbit. Reviewed By: campbellbarton Ref D16277 --- source/blender/editors/space_view3d/view3d_navigate_walk.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_navigate_walk.c b/source/blender/editors/space_view3d/view3d_navigate_walk.c index aea322d73d9..fcb4f549353 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_walk.c +++ b/source/blender/editors/space_view3d/view3d_navigate_walk.c @@ -1231,11 +1231,11 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) /* keep moving if we were moving */ copy_v2_v2(dvec, walk->teleport.direction); - z_cur = walk->rv3d->viewinv[3][2]; - z_new = walk->teleport.origin[2] - getFreeFallDistance(walk->gravity, t) * walk->grid; + z_cur = walk->rv3d->viewinv[3][2] / walk->grid; + z_new = (walk->teleport.origin[2] / walk->grid) - getFreeFallDistance(walk->gravity, t); /* jump */ - z_new += t * walk->speed_jump * walk->grid; + z_new += t * walk->speed_jump; /* duration is the jump duration */ if (t > walk->teleport.duration) { -- cgit v1.2.3 From 5814e35af115413d27dc6c777230452171ad19bd Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 21 Oct 2022 08:50:08 +0200 Subject: install_deps: Update OSL for Blender 2.4 release. As requested by T101403, OSL version is now 1.12.6.2. --- build_files/build_environment/install_deps.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh index ef72ad5b40b..5a191f7669b 100755 --- a/build_files/build_environment/install_deps.sh +++ b/build_files/build_environment/install_deps.sh @@ -523,8 +523,8 @@ LLVM_FORCE_REBUILD=false LLVM_SKIP=false # OSL needs to be compiled for now! -OSL_VERSION="1.11.17.0" -OSL_VERSION_SHORT="1.11" +OSL_VERSION="1.12.6.2" +OSL_VERSION_SHORT="1.12" OSL_VERSION_MIN="1.11" OSL_VERSION_MEX="2.0" OSL_FORCE_BUILD=false @@ -1139,7 +1139,7 @@ LLVM_SOURCE=( "$_LLVM_SOURCE_ROOT/llvm-$LLVM_VERSION.src.tar.xz" ) LLVM_CLANG_SOURCE=( "$_LLVM_SOURCE_ROOT/clang-$LLVM_VERSION.src.tar.xz" "$_LLVM_SOURCE_ROOT/cfe-$LLVM_VERSION.src.tar.xz" ) OSL_USE_REPO=false -OSL_SOURCE=( "https://github.com/imageworks/OpenShadingLanguage/archive/Release-$OSL_VERSION.tar.gz" ) +OSL_SOURCE=( "https://github.com/imageworks/OpenShadingLanguage/archive/v$OSL_VERSION.tar.gz" ) #~ OSL_SOURCE_REPO=( "https://github.com/imageworks/OpenShadingLanguage.git" ) #~ OSL_SOURCE_REPO_BRANCH="master" #~ OSL_SOURCE_REPO_UID="85179714e1bc69cd25ecb6bb711c1a156685d395" -- cgit v1.2.3 From 4bfb99e4d8f890a14cb2d1f584de11f0ac8bd1a7 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 21 Oct 2022 12:19:54 +0200 Subject: Cycles: Bump versions of DPC++, IGC, and dependencies Patch by Xavier Hallade. Committing next to the actual libraries update in the svn. --- build_files/build_environment/cmake/versions.cmake | 44 +++++++++++----------- build_files/cmake/Modules/FindSYCL.cmake | 25 +++++++----- intern/cycles/device/CMakeLists.txt | 13 +++---- intern/cycles/kernel/CMakeLists.txt | 4 +- 4 files changed, 45 insertions(+), 41 deletions(-) diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake index 5fa138ff01b..06a923e5c22 100644 --- a/build_files/build_environment/cmake/versions.cmake +++ b/build_files/build_environment/cmake/versions.cmake @@ -565,15 +565,15 @@ set(OPENPGL_HASH 1f090f88ab2bad028e8b3619aa926f4f97cf7b2c175b904704d2fec8593dd3c set(OPENPGL_HASH_TYPE SHA256) set(OPENPGL_FILE openpgl-${OPENPGL_VERSION}.tar.gz) -set(LEVEL_ZERO_VERSION v1.7.15) +set(LEVEL_ZERO_VERSION v1.8.5) set(LEVEL_ZERO_URI https://github.com/oneapi-src/level-zero/archive/refs/tags/${LEVEL_ZERO_VERSION}.tar.gz) -set(LEVEL_ZERO_HASH c39bb05a8e5898aa6c444e1704105b93d3f1888b9c333f8e7e73825ffbfb2617) +set(LEVEL_ZERO_HASH b6e9663bbcc53c148d32376998298bec6f7c434ef2218c61fa708963e3a09394) set(LEVEL_ZERO_HASH_TYPE SHA256) set(LEVEL_ZERO_FILE level-zero-${LEVEL_ZERO_VERSION}.tar.gz) -set(DPCPP_VERSION 20220812) +set(DPCPP_VERSION 20221019) set(DPCPP_URI https://github.com/intel/llvm/archive/refs/tags/sycl-nightly/${DPCPP_VERSION}.tar.gz) -set(DPCPP_HASH 0e3c95346c295f5cf80f3a42d80b1c49481955898530242636ddc002627248d6) +set(DPCPP_HASH 2f533946e91ce3829431758ea17b0b834b960c1a796e9e4563c86e03eb9603a2) set(DPCPP_HASH_TYPE SHA256) set(DPCPP_FILE DPCPP-${DPCPP_VERSION}.tar.gz) @@ -586,9 +586,9 @@ set(DPCPP_FILE DPCPP-${DPCPP_VERSION}.tar.gz) # will take care of building them, unpack is being done in dpcpp_deps.cmake # Source llvm/lib/SYCLLowerIR/CMakeLists.txt -set(VCINTRINSICS_VERSION 984bb27baacce6ee5c716c2e64845f2a1928025b) +set(VCINTRINSICS_VERSION abce9184b7a3a7fe1b02289b9285610d9dc45465) set(VCINTRINSICS_URI https://github.com/intel/vc-intrinsics/archive/${VCINTRINSICS_VERSION}.tar.gz) -set(VCINTRINSICS_HASH abea415a15a0dd11fdc94dee8fb462910f2548311b787e02f42509789e1b0d7b) +set(VCINTRINSICS_HASH 3e9fd471246b87633b26f7e15e17ab7733d357458c53d5c5881c03929d6c551f) set(VCINTRINSICS_HASH_TYPE SHA256) set(VCINTRINSICS_FILE vc-intrinsics-${VCINTRINSICS_VERSION}.tar.gz) @@ -600,9 +600,9 @@ set(OPENCLHEADERS_HASH_TYPE SHA256) set(OPENCLHEADERS_FILE opencl_headers-${OPENCLHEADERS_VERSION}.tar.gz) # Source opencl/CMakeLists.txt -set(ICDLOADER_VERSION aec3952654832211636fc4af613710f80e203b0a) +set(ICDLOADER_VERSION 792682ad3d877ab38573b997808bab3b43902b70) set(ICDLOADER_URI https://github.com/KhronosGroup/OpenCL-ICD-Loader/archive/${ICDLOADER_VERSION}.tar.gz) -set(ICDLOADER_HASH e1880551d67bd8dc31d13de63b94bbfd6b1f315b6145dad1ffcd159b89bda93c) +set(ICDLOADER_HASH b33a0320d94bf300efa1da97931ded506d27813bd1148da6858fe79d412d1ea2) set(ICDLOADER_HASH_TYPE SHA256) set(ICDLOADER_FILE icdloader-${ICDLOADER_VERSION}.tar.gz) @@ -617,9 +617,9 @@ set(MP11_FILE mp11-${MP11_VERSION}.tar.gz) # Source llvm-spirv/CMakeLists.txt (repo) # Source llvm-spirv/spirv-headers-tag.conf (hash) -set(SPIRV_HEADERS_VERSION 36c0c1596225e728bd49abb7ef56a3953e7ed468) +set(SPIRV_HEADERS_VERSION 5a121866927a16ab9d49bed4788b532c7fcea766) set(SPIRV_HEADERS_URI https://github.com/KhronosGroup/SPIRV-Headers/archive/${SPIRV_HEADERS_VERSION}.tar.gz) -set(SPIRV_HEADERS_HASH 7a5c89633f8740456fe8adee052033e134476d267411d1336c0cb1e587a9229a) +set(SPIRV_HEADERS_HASH ec8ecb471a62672697846c436501638ab25447ae9d4a6761e0bfe8a9a839502a) set(SPIRV_HEADERS_HASH_TYPE SHA256) set(SPIRV_HEADERS_FILE SPIR-V-Headers-${SPIRV_HEADERS_VERSION}.tar.gz) @@ -634,9 +634,9 @@ set(SPIRV_HEADERS_FILE SPIR-V-Headers-${SPIRV_HEADERS_VERSION}.tar.gz) # compiler, the versions used are taken from the following location # https://github.com/intel/intel-graphics-compiler/releases -set(IGC_VERSION 1.0.11222) +set(IGC_VERSION 1.0.12149.1) set(IGC_URI https://github.com/intel/intel-graphics-compiler/archive/refs/tags/igc-${IGC_VERSION}.tar.gz) -set(IGC_HASH d92f0608dcbb52690855685f9447282e5c09c0ba98ae35fabf114fcf8b1e9fcf) +set(IGC_HASH 44f67f24e3bc5130f9f062533abf8154782a9d0a992bc19b498639a8521ae836) set(IGC_HASH_TYPE SHA256) set(IGC_FILE igc-${IGC_VERSION}.tar.gz) @@ -656,15 +656,15 @@ set(IGC_LLVM_FILE ${IGC_LLVM_VERSION}.tar.gz) # # WARNING WARNING WARNING -set(IGC_OPENCL_CLANG_VERSION bbdd1587f577397a105c900be114b56755d1f7dc) +set(IGC_OPENCL_CLANG_VERSION 363a5262d8c7cff3fb28f3bdb5d85c8d7e91c1bb) set(IGC_OPENCL_CLANG_URI https://github.com/intel/opencl-clang/archive/${IGC_OPENCL_CLANG_VERSION}.tar.gz) -set(IGC_OPENCL_CLANG_HASH d08315f1b0d8a6fef33de2b3e6aa7356534c324910634962c72523d970773efc) +set(IGC_OPENCL_CLANG_HASH aa8cf72bb239722ce8ce44f79413c6887ecc8ca18477dd520aa5c4809756da9a) set(IGC_OPENCL_CLANG_HASH_TYPE SHA256) set(IGC_OPENCL_CLANG_FILE opencl-clang-${IGC_OPENCL_CLANG_VERSION}.tar.gz) -set(IGC_VCINTRINSICS_VERSION v0.4.0) +set(IGC_VCINTRINSICS_VERSION v0.5.0) set(IGC_VCINTRINSICS_URI https://github.com/intel/vc-intrinsics/archive/refs/tags/${IGC_VCINTRINSICS_VERSION}.tar.gz) -set(IGC_VCINTRINSICS_HASH c8b92682ad5031cf9d5b82a40e7d5c0e763cd9278660adbcaa69aab988e4b589) +set(IGC_VCINTRINSICS_HASH 70bb47c5e32173cf61514941e83ae7c7eb4485e6d2fca60cfa1f50d4f42c41f2) set(IGC_VCINTRINSICS_HASH_TYPE SHA256) set(IGC_VCINTRINSICS_FILE vc-intrinsics-${IGC_VCINTRINSICS_VERSION}.tar.gz) @@ -680,9 +680,9 @@ set(IGC_SPIRV_TOOLS_HASH 6e19900e948944243024aedd0a201baf3854b377b9cc7a386553bc1 set(IGC_SPIRV_TOOLS_HASH_TYPE SHA256) set(IGC_SPIRV_TOOLS_FILE SPIR-V-Tools-${IGC_SPIRV_TOOLS_VERSION}.tar.gz) -set(IGC_SPIRV_TRANSLATOR_VERSION 99420daab98998a7e36858befac9c5ed109d4920) +set(IGC_SPIRV_TRANSLATOR_VERSION a31ffaeef77e23d500b3ea3d35e0c42ff5648ad9) set(IGC_SPIRV_TRANSLATOR_URI https://github.com/KhronosGroup/SPIRV-LLVM-Translator/archive/${IGC_SPIRV_TRANSLATOR_VERSION}.tar.gz) -set(IGC_SPIRV_TRANSLATOR_HASH 77dfb4ddb6bfb993535562c02ddea23f0a0d1c5a0258c1afe7e27c894ff783a8) +set(IGC_SPIRV_TRANSLATOR_HASH 9e26c96a45341b8f8af521bacea20e752623346340addd02af95d669f6e89252) set(IGC_SPIRV_TRANSLATOR_HASH_TYPE SHA256) set(IGC_SPIRV_TRANSLATOR_FILE SPIR-V-Translator-${IGC_SPIRV_TRANSLATOR_VERSION}.tar.gz) @@ -690,15 +690,15 @@ set(IGC_SPIRV_TRANSLATOR_FILE SPIR-V-Translator-${IGC_SPIRV_TRANSLATOR_VERSION}. ### Intel Graphics Compiler DEPS END ### ######################################## -set(GMMLIB_VERSION intel-gmmlib-22.1.2) +set(GMMLIB_VERSION intel-gmmlib-22.1.8) set(GMMLIB_URI https://github.com/intel/gmmlib/archive/refs/tags/${GMMLIB_VERSION}.tar.gz) -set(GMMLIB_HASH 3b9a6d5e7e3f5748b3d0a2fb0e980ae943907fece0980bd9c0508e71c838e334) +set(GMMLIB_HASH bf23e9a3742b4fb98c7666c9e9b29f3219e4b2fb4d831aaf4eed71f5e2d17368) set(GMMLIB_HASH_TYPE SHA256) set(GMMLIB_FILE ${GMMLIB_VERSION}.tar.gz) -set(OCLOC_VERSION 22.20.23198) +set(OCLOC_VERSION 22.38.24278) set(OCLOC_URI https://github.com/intel/compute-runtime/archive/refs/tags/${OCLOC_VERSION}.tar.gz) -set(OCLOC_HASH ab22b8bf2560a57fdd3def0e35a62ca75991406f959c0263abb00cd6cd9ae998) +set(OCLOC_HASH db0c542fccd651e6404b15a74d46027f1ce0eda8dc9e25a40cbb6c0faef257ee) set(OCLOC_HASH_TYPE SHA256) set(OCLOC_FILE ocloc-${OCLOC_VERSION}.tar.gz) diff --git a/build_files/cmake/Modules/FindSYCL.cmake b/build_files/cmake/Modules/FindSYCL.cmake index 139ebad46b1..7abf074fb7f 100644 --- a/build_files/cmake/Modules/FindSYCL.cmake +++ b/build_files/cmake/Modules/FindSYCL.cmake @@ -30,6 +30,7 @@ SET(_sycl_search_dirs # dpcpp binary. FIND_PROGRAM(SYCL_COMPILER NAMES + icpx dpcpp clang++ HINTS @@ -45,6 +46,7 @@ FIND_PROGRAM(SYCL_COMPILER if(NOT SYCL_COMPILER) FIND_PROGRAM(SYCL_COMPILER NAMES + icpx dpcpp HINTS ${_sycl_search_dirs} @@ -55,6 +57,8 @@ endif() FIND_LIBRARY(SYCL_LIBRARY NAMES + sycl7 + sycl6 sycl HINTS ${_sycl_search_dirs} @@ -63,20 +67,25 @@ FIND_LIBRARY(SYCL_LIBRARY ) if(WIN32) - string(REPLACE ".lib" "d.lib" SYCL_LIBRARY_DEBUG ${SYCL_LIBRARY}) - set(SYCL_LIBRARY_DEBUG ${SYCL_LIBRARY_DEBUG} CACHE FILEPATH "Path to SYCL debug library") -else() - set(SYCL_LIBRARY_DEBUG ${SYCL_LIBRARY} CACHE FILEPATH "Path to SYCL debug library") + FIND_LIBRARY(SYCL_LIBRARY_DEBUG + NAMES + sycl7d + sycl6d + sycld + HINTS + ${_sycl_search_dirs} + PATH_SUFFIXES + lib64 lib + ) endif() FIND_PATH(SYCL_INCLUDE_DIR NAMES - CL/sycl.hpp + sycl/sycl.hpp HINTS ${_sycl_search_dirs} PATH_SUFFIXES include - include/sycl ) INCLUDE(FindPackageHandleStandardArgs) @@ -84,13 +93,11 @@ INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(SYCL DEFAULT_MSG SYCL_LIBRARY SYCL_INCLUDE_DIR) IF(SYCL_FOUND) - get_filename_component(_SYCL_INCLUDE_PARENT_DIR ${SYCL_INCLUDE_DIR} DIRECTORY) - SET(SYCL_INCLUDE_DIR ${SYCL_INCLUDE_DIR} ${_SYCL_INCLUDE_PARENT_DIR}) + SET(SYCL_INCLUDE_DIR ${SYCL_INCLUDE_DIR} ${SYCL_INCLUDE_DIR}/sycl) ELSE() SET(SYCL_SYCL_FOUND FALSE) ENDIF() MARK_AS_ADVANCED( _SYCL_INCLUDE_PARENT_DIR - SYCL_LIBRARY_DEBUG ) diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt index 5516e97f34f..9c0de57f203 100644 --- a/intern/cycles/device/CMakeLists.txt +++ b/intern/cycles/device/CMakeLists.txt @@ -192,13 +192,12 @@ if (WITH_CYCLES_DEVICE_ONEAPI) else() set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/libcycles_kernel_oneapi.so) endif() - list(APPEND LIB - ${cycles_kernel_oneapi_lib} - "$<$:${SYCL_LIBRARY_DEBUG}>" - "$<$:${SYCL_LIBRARY}>" - "$<$:${SYCL_LIBRARY}>" - "$<$:${SYCL_LIBRARY}>" - ) + list(APPEND LIB ${cycles_kernel_oneapi_lib}) + if(WIN32) + list(APPEND LIB debug ${SYCL_LIBRARY_DEBUG} optimized ${SYCL_LIBRARY}) + else() + list(APPEND LIB ${SYCL_LIBRARY}) + endif() add_definitions(-DWITH_ONEAPI) list(APPEND SRC ${SRC_ONEAPI} diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 6140e90042b..1e69d14b1b7 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -844,12 +844,10 @@ if(WITH_CYCLES_DEVICE_ONEAPI) set(sycl_compiler_flags_RelWithDebInfo ${sycl_compiler_flags}) set(sycl_compiler_flags_MinSizeRel ${sycl_compiler_flags}) list(APPEND sycl_compiler_flags_RelWithDebInfo -g) - get_filename_component(sycl_library_debug_name ${SYCL_LIBRARY_DEBUG} NAME_WE) list(APPEND sycl_compiler_flags_Debug -g -D_DEBUG - -nostdlib -Xclang --dependent-lib=msvcrtd - -Xclang --dependent-lib=${sycl_library_debug_name}) + -nostdlib -Xclang --dependent-lib=msvcrtd) add_custom_command( OUTPUT ${cycles_kernel_oneapi_lib} ${cycles_kernel_oneapi_linker_lib} -- cgit v1.2.3 From 26f181c6b7b28cd1d6f035a82e7a17d4424807eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Fri, 21 Oct 2022 13:11:31 +0200 Subject: EEVEE: Fix ill defined blend in cubemap array workaround This fixes some firefly issues on corners of the cubemaps where the blending factors would go above 1 or below 0. --- source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl b/source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl index 90272400915..5af317b7398 100644 --- a/source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl @@ -96,7 +96,7 @@ vec4 cubemap_seamless(sampler2DArray tex, vec4 cubevec, float lod) /* Mix all colors to get the corner color. */ vec4 col3 = (col + col1 + col2) / 3.0; - vec2 mix_fac = uv_border * 0.5; + vec2 mix_fac = saturate(uv_border * 0.5); return mix(mix(col, col2, mix_fac.x), mix(col1, col3, mix_fac.x), mix_fac.y); } else if (any(border)) { @@ -108,7 +108,7 @@ vec4 cubemap_seamless(sampler2DArray tex, vec4 cubevec, float lod) uv = cubemap_face_coord(cubevec.xyz, face); coord = vec3(uv, cubevec.w * 6.0 + face); - float mix_fac = max(uv_border.x, uv_border.y) * 0.5; + float mix_fac = saturate(max(uv_border.x, uv_border.y) * 0.5); return mix(col, textureLod(tex, coord, lod), mix_fac); } else { -- cgit v1.2.3 From 899d4ddbd08cdb8130894c9de8533d5bb98214be Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Fri, 21 Oct 2022 14:05:19 +0200 Subject: Fix: Bokeh blur node flips its bokeh input The bokeh blur node flipped its bokeh input due to the conceptual difference between the search window space and the weights texture space. This patches fixes that by inverting the weights texture to match the search window. The variable size option actually flips the bokeh input for the CPU compositor. It is unclear if this is expected, so we deviate from that behavior for now. --- .../gpu/shaders/compositor/compositor_blur.glsl | 21 ++++++++++++++++----- .../compositor/compositor_blur_variable_size.glsl | 21 ++++++++++++++++----- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/source/blender/gpu/shaders/compositor/compositor_blur.glsl b/source/blender/gpu/shaders/compositor/compositor_blur.glsl index 4f981c84f59..c7ac620f99b 100644 --- a/source/blender/gpu/shaders/compositor/compositor_blur.glsl +++ b/source/blender/gpu/shaders/compositor/compositor_blur.glsl @@ -18,13 +18,24 @@ vec4 load_input(ivec2 texel) } /* Given the texel in the range [-radius, radius] in both axis, load the appropriate weight from - * the weights texture, where the texel (0, 0) is considered the center of weights texture. */ + * the weights texture, where the given texel (0, 0) corresponds the center of weights texture. + * Note that we load the weights texture inverted along both directions to maintain the shape of + * the weights if it was not symmetrical. To understand why inversion makes sense, consider a 1D + * weights texture whose right half is all ones and whose left half is all zeros. Further, consider + * that we are blurring a single white pixel on a black background. When computing the value of a + * pixel that is to the right of the white pixel, the white pixel will be in the left region of the + * search window, and consequently, without inversion, a zero will be sampled from the left side of + * the weights texture and result will be zero. However, what we expect is that pixels to the right + * of the white pixel will be white, that is, they should sample a weight of 1 from the right side + * of the weights texture, hence the need for inversion. */ vec4 load_weight(ivec2 texel) { - /* Add the radius to transform the texel into the range [0, radius * 2], then divide by the upper - * bound plus one to transform the texel into the normalized range [0, 1] needed to sample the - * weights sampler. Finally, also add 0.5 to sample at the center of the pixels. */ - return texture(weights_tx, (texel + vec2(radius + 0.5)) / (radius * 2 + 1)); + /* Add the radius to transform the texel into the range [0, radius * 2], with an additional 0.5 + * to sample at the center of the pixels, then divide by the upper bound plus one to transform + * the texel into the normalized range [0, 1] needed to sample the weights sampler. Finally, + * invert the textures coordinates by subtracting from 1 to maintain the shape of the weights as + * mentioned in the function description. */ + return texture(weights_tx, 1.0 - ((texel + vec2(radius + 0.5)) / (radius * 2 + 1))); } void main() diff --git a/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl b/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl index e7e5aac12a5..9383bbf9825 100644 --- a/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl +++ b/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl @@ -2,7 +2,16 @@ #pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) /* Given the texel in the range [-radius, radius] in both axis, load the appropriate weight from - * the weights texture, where the texel (0, 0) is considered the center of weights texture. */ + * the weights texture, where the given texel (0, 0) corresponds the center of weights texture. + * Note that we load the weights texture inverted along both directions to maintain the shape of + * the weights if it was not symmetrical. To understand why inversion makes sense, consider a 1D + * weights texture whose right half is all ones and whose left half is all zeros. Further, consider + * that we are blurring a single white pixel on a black background. When computing the value of a + * pixel that is to the right of the white pixel, the white pixel will be in the left region of the + * search window, and consequently, without inversion, a zero will be sampled from the left side of + * the weights texture and result will be zero. However, what we expect is that pixels to the right + * of the white pixel will be white, that is, they should sample a weight of 1 from the right side + * of the weights texture, hence the need for inversion. */ vec4 load_weight(ivec2 texel, float radius) { /* The center zero texel is always assigned a unit weight regardless of the corresponding weight @@ -12,10 +21,12 @@ vec4 load_weight(ivec2 texel, float radius) return vec4(1.0); } - /* Add the radius to transform the texel into the range [0, radius * 2], then divide by the upper - * bound plus one to transform the texel into the normalized range [0, 1] needed to sample the - * weights sampler. Finally, also add 0.5 to sample at the center of the pixels. */ - return texture(weights_tx, (texel + vec2(radius + 0.5)) / (radius * 2 + 1)); + /* Add the radius to transform the texel into the range [0, radius * 2], with an additional 0.5 + * to sample at the center of the pixels, then divide by the upper bound plus one to transform + * the texel into the normalized range [0, 1] needed to sample the weights sampler. Finally, + * invert the textures coordinates by subtracting from 1 to maintain the shape of the weights as + * mentioned in the function description. */ + return texture(weights_tx, 1.0 - ((texel + vec2(radius + 0.5)) / (radius * 2 + 1))); } void main() -- cgit v1.2.3 From f0ebf696cbbb521f956c5b612037f4d11e87cb0d Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 21 Oct 2022 09:52:53 -0300 Subject: Fix T101964: Edge and face snapping no locking to axis In rBed6c8d82b804 it was wrongly assumed that the constraint functions always apply the transformations. But that is not the case for when axes are aligned. The `mul_m3_v3(t->con.pmtx, out)` fallback is still required. --- source/blender/editors/transform/transform_constraints.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index fa56456d8e7..7abf0e5c00c 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -404,9 +404,11 @@ static void applyAxisConstraintVec(const TransInfo *t, } } + /* Fallback for when axes are aligned. */ + mul_m3_v3(t->con.pmtx, out); + if (is_snap_to_point) { - /* With snap points, a projection is alright, no adjustments needed. */ - mul_m3_v3(t->con.pmtx, out); + /* Pass. With snap points, a projection is alright, no adjustments needed. */ } else { const int dims = getConstraintSpaceDimension(t); @@ -422,14 +424,9 @@ static void applyAxisConstraintVec(const TransInfo *t, /* Disabled, as it has not proven to be really useful. (See T82386). */ // constraint_snap_plane_to_face(t, plane, out); } - else { + else if (!isPlaneProjectionViewAligned(t, plane)) { /* View alignment correction. */ - if (!isPlaneProjectionViewAligned(t, plane)) { - planeProjection(t, plane, in, out); - } - else { - mul_m3_v3(t->con.pmtx, out); - } + planeProjection(t, plane, in, out); } } } -- cgit v1.2.3 From 3225bc2e7fb6100c74788acbaba9849a77c93ef2 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 21 Oct 2022 14:36:25 +0200 Subject: GPU: Fix Metal GLSL compilation errors due to recent changes. vec.st is legacy OpenGL and should not be used. --- source/blender/gpu/shaders/gpu_shader_icon_frag.glsl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl b/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl index ff56d772317..4452349f23c 100644 --- a/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl @@ -27,15 +27,15 @@ void main() bool lower_half = mask_coord_interp.y < circle_center.y; bool right_half = mask_coord_interp.x > circle_center.x; - if (right_half && mask_coord_interp.t < circle_center.y + circle_radius_outer) { + if (right_half && mask_coord_interp.y < circle_center.y + circle_radius_outer) { mask = smoothstep(circle_center.y + circle_radius_inner, circle_center.y + circle_radius_outer, - mask_coord_interp.t); + mask_coord_interp.y); } - if (lower_half && mask_coord_interp.s > circle_center.x - circle_radius_outer) { + if (lower_half && mask_coord_interp.x > circle_center.x - circle_radius_outer) { mask = smoothstep(circle_center.x - circle_radius_inner, circle_center.x - circle_radius_outer, - mask_coord_interp.s); + mask_coord_interp.x); } fragColor = mix(vec4(0.0), fragColor, max(mask_transparency, mask)); -- cgit v1.2.3 From e8c4411035234696742b9cd97525fe094fd3f4ac Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 21 Oct 2022 14:38:30 +0200 Subject: GPU: Add gpu.platform.backend_type_get function. Function returns the active GPU backend type. --- source/blender/python/gpu/gpu_py_platform.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/source/blender/python/gpu/gpu_py_platform.c b/source/blender/python/gpu/gpu_py_platform.c index b877e3ceb98..51366d199b0 100644 --- a/source/blender/python/gpu/gpu_py_platform.c +++ b/source/blender/python/gpu/gpu_py_platform.c @@ -11,6 +11,7 @@ #include "BLI_utildefines.h" +#include "GPU_context.h" #include "GPU_platform.h" #include "gpu_py_platform.h" /* Own include. */ @@ -83,6 +84,28 @@ static PyObject *pygpu_platform_device_type_get(PyObject *UNUSED(self)) return PyUnicode_FromString("UNKNOWN"); } +PyDoc_STRVAR(pygpu_platform_backend_type_get_doc, + ".. function:: backend_type_get()\n" + "\n" + " Get actuve GPU backend.\n" + "\n" + " :return: Backend type ('OPENGL', 'METAL', 'NONE', 'UNKNOWN').\n" + " :rtype: str\n"); +static PyObject *pygpu_platform_backend_type_get(PyObject *UNUSED(self)) +{ + switch (GPU_backend_get_type()) { + case GPU_BACKEND_METAL: + return PyUnicode_FromString("METAL"); + case GPU_BACKEND_NONE: + return PyUnicode_FromString("NONE"); + case GPU_BACKEND_OPENGL: + return PyUnicode_FromString("OPENGL"); + case GPU_BACKEND_ANY: + break; + } + return PyUnicode_FromString("UNKNOWN"); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -106,6 +129,10 @@ static struct PyMethodDef pygpu_platform__tp_methods[] = { (PyCFunction)pygpu_platform_device_type_get, METH_NOARGS, pygpu_platform_device_type_get_doc}, + {"backend_type_get", + (PyCFunction)pygpu_platform_backend_type_get, + METH_NOARGS, + pygpu_platform_backend_type_get_doc}, {NULL, NULL, 0, NULL}, }; -- cgit v1.2.3 From d39f2eed980dc97de2180d29a7f8c45f4233e70c Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 21 Oct 2022 14:57:54 +0200 Subject: GPU: Don't exit after first GPUBackend. --- source/blender/gpu/intern/gpu_shader_builder.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/gpu/intern/gpu_shader_builder.cc b/source/blender/gpu/intern/gpu_shader_builder.cc index 9a67ddde5e6..abb45ca074a 100644 --- a/source/blender/gpu/intern/gpu_shader_builder.cc +++ b/source/blender/gpu/intern/gpu_shader_builder.cc @@ -115,8 +115,8 @@ int main(int argc, const char *argv[]) exit_code = 1; } builder.exit(); - exit(exit_code); } + exit(exit_code); return exit_code; } -- cgit v1.2.3 From 3ccec478414eda8eafebaead302eadbd9453d558 Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Fri, 21 Oct 2022 07:04:21 -0600 Subject: cmake/windows: Prepare for 3.4 library changes for opencollada The opencollada dependency will be using an external xml2 library for 3.4. This change allows to build against both old and new style lib folders. As it is a C library it did not need a special debug version. --- build_files/cmake/platform/platform_win32.cmake | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index 5fb921fc97d..32c467b4b46 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -358,7 +358,6 @@ if(WITH_OPENCOLLADA) optimized ${OPENCOLLADA}/lib/opencollada/OpenCOLLADAStreamWriter.lib optimized ${OPENCOLLADA}/lib/opencollada/MathMLSolver.lib optimized ${OPENCOLLADA}/lib/opencollada/GeneratedSaxParser.lib - optimized ${OPENCOLLADA}/lib/opencollada/xml.lib optimized ${OPENCOLLADA}/lib/opencollada/buffer.lib optimized ${OPENCOLLADA}/lib/opencollada/ftoa.lib @@ -368,10 +367,14 @@ if(WITH_OPENCOLLADA) debug ${OPENCOLLADA}/lib/opencollada/OpenCOLLADAStreamWriter_d.lib debug ${OPENCOLLADA}/lib/opencollada/MathMLSolver_d.lib debug ${OPENCOLLADA}/lib/opencollada/GeneratedSaxParser_d.lib - debug ${OPENCOLLADA}/lib/opencollada/xml_d.lib debug ${OPENCOLLADA}/lib/opencollada/buffer_d.lib debug ${OPENCOLLADA}/lib/opencollada/ftoa_d.lib ) + if(EXISTS ${LIBDIR}/xml2/lib/libxml2s.lib) # 3.4 libraries + list(APPEND OPENCOLLADA_LIBRARIES ${LIBDIR}/xml2/lib/libxml2s.lib) + else() + list(APPEND OPENCOLLADA_LIBRARIES ${OPENCOLLADA}/lib/opencollada/xml.lib) + endif() list(APPEND OPENCOLLADA_LIBRARIES ${OPENCOLLADA}/lib/opencollada/UTF.lib) -- cgit v1.2.3 From ec60c8abe76e4473f45d783010be92114c0ed608 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 21 Oct 2022 15:03:21 +0200 Subject: SystemInfo: Add active GPU backend. For debugging it is useful to known the active GPU backend. Although it could be determined from looking at the extensions, this is easier to understand when not activly working in this area. --- release/scripts/modules/sys_info.py | 1 + 1 file changed, 1 insertion(+) diff --git a/release/scripts/modules/sys_info.py b/release/scripts/modules/sys_info.py index 7f6d0b1e9bf..5bd38acb19c 100644 --- a/release/scripts/modules/sys_info.py +++ b/release/scripts/modules/sys_info.py @@ -184,6 +184,7 @@ def write_sysinfo(filepath): output.write("vendor:\t\t%r\n" % gpu.platform.vendor_get()) output.write("version:\t%r\n" % gpu.platform.version_get()) output.write("device type:\t%r\n" % gpu.platform.device_type_get()) + output.write("backend type:\t%r\n" % gpu.platform.backend_type_get()) output.write("extensions:\n") glext = sorted(gpu.capabilities.extensions_get()) -- cgit v1.2.3 From 4776a74bf7f1ed60efee22290c5fea732d7e2e5a Mon Sep 17 00:00:00 2001 From: Edward Date: Fri, 21 Oct 2022 15:35:20 +0200 Subject: Fix T101974: Potential memoryleak GHOST_WindowWayland.newDrawingContext Reviewed By: jbakker Maniphest Tasks: T101974 Differential Revision: https://developer.blender.org/D16309 --- intern/ghost/intern/GHOST_WindowWayland.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp index b29c5efd8d4..986e18d7a87 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.cpp +++ b/intern/ghost/intern/GHOST_WindowWayland.cpp @@ -946,7 +946,12 @@ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType EGL_OPENGL_API); } - return (context->initializeDrawingContext() == GHOST_kSuccess) ? context : nullptr; + if (context->initializeDrawingContext()) { + return context; + } + + delete context; + return nullptr; } /** \} */ -- cgit v1.2.3 From 305b92e05f748a0fd9cb62b9829791d717ba2d57 Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Fri, 21 Oct 2022 14:10:25 +0200 Subject: Cycles: oneAPI: remove use of SYCL host device Host device is deprecated in SYCL 2020 spec, cpu device or standard C++ should be used instead. --- CMakeLists.txt | 2 - intern/cycles/device/oneapi/device.cpp | 4 +- intern/cycles/device/oneapi/device_impl.cpp | 30 +++------------ intern/cycles/kernel/CMakeLists.txt | 4 -- .../kernel/device/gpu/parallel_active_index.h | 33 +++------------- intern/cycles/kernel/device/oneapi/compat.h | 45 +++++----------------- intern/cycles/kernel/device/oneapi/globals.h | 9 ----- intern/cycles/kernel/device/oneapi/kernel.cpp | 7 ---- 8 files changed, 21 insertions(+), 113 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9134c7c1ed6..a3ea162d040 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -489,14 +489,12 @@ endif() if(NOT APPLE) option(WITH_CYCLES_DEVICE_ONEAPI "Enable Cycles oneAPI compute support" OFF) option(WITH_CYCLES_ONEAPI_BINARIES "Enable Ahead-Of-Time compilation for Cycles oneAPI device" OFF) - option(WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED "Enable use of SYCL host (CPU) device execution by oneAPI implementation. This option is for debugging purposes and impacts GPU execution." OFF) # https://www.intel.com/content/www/us/en/develop/documentation/oneapi-dpcpp-cpp-compiler-dev-guide-and-reference/top/compilation/ahead-of-time-compilation.html # acm-g10 is the architecture for the first Arc Alchemist GPUs but we'll keep using dg2 until IGC dependency is updated to support acm-g10. set(CYCLES_ONEAPI_SPIR64_GEN_DEVICES "dg2" CACHE STRING "oneAPI Intel GPU architectures to build binaries for") set(CYCLES_ONEAPI_SYCL_TARGETS spir64 spir64_gen CACHE STRING "oneAPI targets to build AOT binaries for") - mark_as_advanced(WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED) mark_as_advanced(CYCLES_ONEAPI_SPIR64_GEN_DEVICES) mark_as_advanced(CYCLES_ONEAPI_SYCL_TARGETS) endif() diff --git a/intern/cycles/device/oneapi/device.cpp b/intern/cycles/device/oneapi/device.cpp index f303ab41627..66d6f749e30 100644 --- a/intern/cycles/device/oneapi/device.cpp +++ b/intern/cycles/device/oneapi/device.cpp @@ -39,7 +39,7 @@ bool device_oneapi_init() _putenv_s("SYCL_CACHE_THRESHOLD", "0"); } if (getenv("SYCL_DEVICE_FILTER") == nullptr) { - _putenv_s("SYCL_DEVICE_FILTER", "host,level_zero"); + _putenv_s("SYCL_DEVICE_FILTER", "level_zero"); } if (getenv("SYCL_ENABLE_PCI") == nullptr) { _putenv_s("SYCL_ENABLE_PCI", "1"); @@ -50,7 +50,7 @@ bool device_oneapi_init() # elif __linux__ setenv("SYCL_CACHE_PERSISTENT", "1", false); setenv("SYCL_CACHE_THRESHOLD", "0", false); - setenv("SYCL_DEVICE_FILTER", "host,level_zero", false); + setenv("SYCL_DEVICE_FILTER", "level_zero", false); setenv("SYCL_ENABLE_PCI", "1", false); setenv("SYCL_PI_LEVEL_ZERO_USE_COPY_ENGINE_FOR_IN_ORDER_QUEUE", "0", false); # endif diff --git a/intern/cycles/device/oneapi/device_impl.cpp b/intern/cycles/device/oneapi/device_impl.cpp index f14eada071d..4e7849e6b9a 100644 --- a/intern/cycles/device/oneapi/device_impl.cpp +++ b/intern/cycles/device/oneapi/device_impl.cpp @@ -430,8 +430,7 @@ void OneapiDevice::check_usm(SyclQueue *queue_, const void *usm_ptr, bool allow_ sycl::usm::alloc usm_type = get_pointer_type(usm_ptr, queue->get_context()); (void)usm_type; assert(usm_type == sycl::usm::alloc::device || - ((device_type == sycl::info::device_type::host || - device_type == sycl::info::device_type::cpu || allow_host) && + ((device_type == sycl::info::device_type::cpu || allow_host) && usm_type == sycl::usm::alloc::host || usm_type == sycl::usm::alloc::unknown)); # else @@ -672,14 +671,6 @@ std::vector OneapiDevice::available_devices() if (getenv("CYCLES_ONEAPI_ALL_DEVICES") != nullptr) allow_all_devices = true; - /* Host device is useful only for debugging at the moment - * so we hide this device with default build settings. */ -# ifdef WITH_ONEAPI_SYCL_HOST_ENABLED - bool allow_host = true; -# else - bool allow_host = false; -# endif - const std::vector &oneapi_platforms = sycl::platform::get_platforms(); std::vector available_devices; @@ -691,17 +682,11 @@ std::vector OneapiDevice::available_devices() } const std::vector &oneapi_devices = - (allow_all_devices || allow_host) ? platform.get_devices(sycl::info::device_type::all) : - platform.get_devices(sycl::info::device_type::gpu); + (allow_all_devices) ? platform.get_devices(sycl::info::device_type::all) : + platform.get_devices(sycl::info::device_type::gpu); for (const sycl::device &device : oneapi_devices) { - if (allow_all_devices) { - /* still filter out host device if build doesn't support it. */ - if (allow_host || !device.is_host()) { - available_devices.push_back(device); - } - } - else { + if (!allow_all_devices) { bool filter_out = false; /* For now we support all Intel(R) Arc(TM) devices and likely any future GPU, @@ -733,9 +718,6 @@ std::vector OneapiDevice::available_devices() } } } - else if (!allow_host && device.is_host()) { - filter_out = true; - } else if (!allow_all_devices) { filter_out = true; } @@ -798,9 +780,7 @@ char *OneapiDevice::device_capabilities() GET_NUM_ATTR(native_vector_width_double) GET_NUM_ATTR(native_vector_width_half) - size_t max_clock_frequency = - (size_t)(device.is_host() ? (size_t)0 : - device.get_info()); + size_t max_clock_frequency = device.get_info(); WRITE_ATTR("max_clock_frequency", max_clock_frequency) GET_NUM_ATTR(address_bits) diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 1e69d14b1b7..b6a53117a3b 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -752,10 +752,6 @@ if(WITH_CYCLES_DEVICE_ONEAPI) ${SYCL_CPP_FLAGS} ) - if (WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED) - list(APPEND sycl_compiler_flags -DWITH_ONEAPI_SYCL_HOST_ENABLED) - endif() - # Set defaults for spir64 and spir64_gen options if (NOT DEFINED CYCLES_ONEAPI_SYCL_OPTIONS_spir64) set(CYCLES_ONEAPI_SYCL_OPTIONS_spir64 "-options '-ze-opt-large-register-file -ze-opt-regular-grf-kernel integrator_intersect'") diff --git a/intern/cycles/kernel/device/gpu/parallel_active_index.h b/intern/cycles/kernel/device/gpu/parallel_active_index.h index c1df49c4f49..38cdcb572eb 100644 --- a/intern/cycles/kernel/device/gpu/parallel_active_index.h +++ b/intern/cycles/kernel/device/gpu/parallel_active_index.h @@ -23,22 +23,6 @@ CCL_NAMESPACE_BEGIN * and keep device specific code in compat.h */ #ifdef __KERNEL_ONEAPI__ -# ifdef WITH_ONEAPI_SYCL_HOST_ENABLED -template -void cpu_serial_active_index_array_impl(const uint num_states, - ccl_global int *ccl_restrict indices, - ccl_global int *ccl_restrict num_indices, - IsActiveOp is_active_op) -{ - int write_index = 0; - for (int state_index = 0; state_index < num_states; state_index++) { - if (is_active_op(state_index)) - indices[write_index++] = state_index; - } - *num_indices = write_index; - return; -} -# endif /* WITH_ONEAPI_SYCL_HOST_ENABLED */ template void gpu_parallel_active_index_array_impl(const uint num_states, @@ -182,18 +166,11 @@ __device__ num_simd_groups, \ simdgroup_offset) #elif defined(__KERNEL_ONEAPI__) -# ifdef WITH_ONEAPI_SYCL_HOST_ENABLED -# define gpu_parallel_active_index_array( \ - blocksize, num_states, indices, num_indices, is_active_op) \ - if (ccl_gpu_global_size_x() == 1) \ - cpu_serial_active_index_array_impl(num_states, indices, num_indices, is_active_op); \ - else \ - gpu_parallel_active_index_array_impl(num_states, indices, num_indices, is_active_op); -# else -# define gpu_parallel_active_index_array( \ - blocksize, num_states, indices, num_indices, is_active_op) \ - gpu_parallel_active_index_array_impl(num_states, indices, num_indices, is_active_op) -# endif + +# define gpu_parallel_active_index_array( \ + blocksize, num_states, indices, num_indices, is_active_op) \ + gpu_parallel_active_index_array_impl(num_states, indices, num_indices, is_active_op) + #else # define gpu_parallel_active_index_array( \ diff --git a/intern/cycles/kernel/device/oneapi/compat.h b/intern/cycles/kernel/device/oneapi/compat.h index 8ae40b0612e..dfaec65130c 100644 --- a/intern/cycles/kernel/device/oneapi/compat.h +++ b/intern/cycles/kernel/device/oneapi/compat.h @@ -55,18 +55,6 @@ #define ccl_gpu_kernel(block_num_threads, thread_num_registers) #define ccl_gpu_kernel_threads(block_num_threads) -#ifdef WITH_ONEAPI_SYCL_HOST_ENABLED -# define KG_ND_ITEMS \ - kg->nd_item_local_id_0 = item.get_local_id(0); \ - kg->nd_item_local_range_0 = item.get_local_range(0); \ - kg->nd_item_group_0 = item.get_group(0); \ - kg->nd_item_group_range_0 = item.get_group_range(0); \ - kg->nd_item_global_id_0 = item.get_global_id(0); \ - kg->nd_item_global_range_0 = item.get_global_range(0); -#else -# define KG_ND_ITEMS -#endif - #define ccl_gpu_kernel_signature(name, ...) \ void oneapi_kernel_##name(KernelGlobalsGPU *ccl_restrict kg, \ size_t kernel_global_size, \ @@ -76,8 +64,7 @@ void oneapi_kernel_##name(KernelGlobalsGPU *ccl_restrict kg, \ (kg); \ cgh.parallel_for( \ sycl::nd_range<1>(kernel_global_size, kernel_local_size), \ - [=](sycl::nd_item<1> item) { \ - KG_ND_ITEMS + [=](sycl::nd_item<1> item) { #define ccl_gpu_kernel_postfix \ }); \ @@ -95,31 +82,17 @@ void oneapi_kernel_##name(KernelGlobalsGPU *ccl_restrict kg, \ } ccl_gpu_kernel_lambda_pass((ONEAPIKernelContext *)kg) /* GPU thread, block, grid size and index */ -#ifndef WITH_ONEAPI_SYCL_HOST_ENABLED -# define ccl_gpu_thread_idx_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_local_id(0)) -# define ccl_gpu_block_dim_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_local_range(0)) -# define ccl_gpu_block_idx_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_group(0)) -# define ccl_gpu_grid_dim_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_group_range(0)) -# define ccl_gpu_warp_size (sycl::ext::oneapi::experimental::this_sub_group().get_local_range()[0]) -# define ccl_gpu_thread_mask(thread_warp) uint(0xFFFFFFFF >> (ccl_gpu_warp_size - thread_warp)) - -# define ccl_gpu_global_id_x() (sycl::ext::oneapi::experimental::this_nd_item<1>().get_global_id(0)) -# define ccl_gpu_global_size_x() (sycl::ext::oneapi::experimental::this_nd_item<1>().get_global_range(0)) -#else -# define ccl_gpu_thread_idx_x (kg->nd_item_local_id_0) -# define ccl_gpu_block_dim_x (kg->nd_item_local_range_0) -# define ccl_gpu_block_idx_x (kg->nd_item_group_0) -# define ccl_gpu_grid_dim_x (kg->nd_item_group_range_0) -# define ccl_gpu_warp_size (sycl::ext::oneapi::experimental::this_sub_group().get_local_range()[0]) -# define ccl_gpu_thread_mask(thread_warp) uint(0xFFFFFFFF >> (ccl_gpu_warp_size - thread_warp)) - -# define ccl_gpu_global_id_x() (kg->nd_item_global_id_0) -# define ccl_gpu_global_size_x() (kg->nd_item_global_range_0) -#endif +#define ccl_gpu_thread_idx_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_local_id(0)) +#define ccl_gpu_block_dim_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_local_range(0)) +#define ccl_gpu_block_idx_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_group(0)) +#define ccl_gpu_grid_dim_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_group_range(0)) +#define ccl_gpu_warp_size (sycl::ext::oneapi::experimental::this_sub_group().get_local_range()[0]) +#define ccl_gpu_thread_mask(thread_warp) uint(0xFFFFFFFF >> (ccl_gpu_warp_size - thread_warp)) +#define ccl_gpu_global_id_x() (sycl::ext::oneapi::experimental::this_nd_item<1>().get_global_id(0)) +#define ccl_gpu_global_size_x() (sycl::ext::oneapi::experimental::this_nd_item<1>().get_global_range(0)) /* GPU warp synchronization */ - #define ccl_gpu_syncthreads() sycl::ext::oneapi::experimental::this_nd_item<1>().barrier() #define ccl_gpu_local_syncthreads() sycl::ext::oneapi::experimental::this_nd_item<1>().barrier(sycl::access::fence_space::local_space) #ifdef __SYCL_DEVICE_ONLY__ diff --git a/intern/cycles/kernel/device/oneapi/globals.h b/intern/cycles/kernel/device/oneapi/globals.h index d60f4f135ba..116620eb725 100644 --- a/intern/cycles/kernel/device/oneapi/globals.h +++ b/intern/cycles/kernel/device/oneapi/globals.h @@ -23,15 +23,6 @@ typedef struct KernelGlobalsGPU { #undef KERNEL_DATA_ARRAY IntegratorStateGPU *integrator_state; const KernelData *__data; -#ifdef WITH_ONEAPI_SYCL_HOST_ENABLED - size_t nd_item_local_id_0; - size_t nd_item_local_range_0; - size_t nd_item_group_0; - size_t nd_item_group_range_0; - - size_t nd_item_global_id_0; - size_t nd_item_global_range_0; -#endif } KernelGlobalsGPU; typedef ccl_global KernelGlobalsGPU *ccl_restrict KernelGlobals; diff --git a/intern/cycles/kernel/device/oneapi/kernel.cpp b/intern/cycles/kernel/device/oneapi/kernel.cpp index 1f32d3406ea..525ae288f0c 100644 --- a/intern/cycles/kernel/device/oneapi/kernel.cpp +++ b/intern/cycles/kernel/device/oneapi/kernel.cpp @@ -230,13 +230,6 @@ bool oneapi_enqueue_kernel(KernelContext *kernel_context, /* NOTE(@nsirgien): As for now non-uniform work-groups don't work on most oneAPI devices, * we extend work size to fit uniformity requirements. */ global_size = groups_count * local_size; - -# ifdef WITH_ONEAPI_SYCL_HOST_ENABLED - if (queue->get_device().is_host()) { - global_size = 1; - local_size = 1; - } -# endif } /* Let the compiler throw an error if there are any kernels missing in this implementation. */ -- cgit v1.2.3 From 0cfac5b0432b619294b3d38fb74e4f7b295ef1cc Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Fri, 21 Oct 2022 13:58:16 +0200 Subject: Cycles: oneAPI: migrate from deprecated APIs, require libSYCL 6.0+ sycl::info::device::ext_intel_* descriptors are deprecated, replaced with sycl::ext::intel::info::device:: that are available from 6.0+, for which we now check version in CMake. --- build_files/cmake/Modules/FindSYCL.cmake | 16 +++++++++++++++- intern/cycles/cmake/external_libs.cmake | 5 ++--- intern/cycles/device/oneapi/device_impl.cpp | 12 ++++++------ 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/build_files/cmake/Modules/FindSYCL.cmake b/build_files/cmake/Modules/FindSYCL.cmake index 7abf074fb7f..1ccbee179fb 100644 --- a/build_files/cmake/Modules/FindSYCL.cmake +++ b/build_files/cmake/Modules/FindSYCL.cmake @@ -88,9 +88,23 @@ FIND_PATH(SYCL_INCLUDE_DIR include ) +IF(EXISTS "${SYCL_INCLUDE_DIR}/sycl/version.hpp") + FILE(STRINGS "${SYCL_INCLUDE_DIR}/sycl/version.hpp" _libsycl_major_version REGEX "^#define __LIBSYCL_MAJOR_VERSION[ \t].*$") + STRING(REGEX MATCHALL "[0-9]+" _libsycl_major_version ${_libsycl_major_version}) + FILE(STRINGS "${SYCL_INCLUDE_DIR}/sycl/version.hpp" _libsycl_minor_version REGEX "^#define __LIBSYCL_MINOR_VERSION[ \t].*$") + STRING(REGEX MATCHALL "[0-9]+" _libsycl_minor_version ${_libsycl_minor_version}) + FILE(STRINGS "${SYCL_INCLUDE_DIR}/sycl/version.hpp" _libsycl_patch_version REGEX "^#define __LIBSYCL_PATCH_VERSION[ \t].*$") + STRING(REGEX MATCHALL "[0-9]+" _libsycl_patch_version ${_libsycl_patch_version}) + + SET(SYCL_VERSION "${_libsycl_major_version}.${_libsycl_minor_version}.${_libsycl_patch_version}") +ENDIF() + INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(SYCL DEFAULT_MSG SYCL_LIBRARY SYCL_INCLUDE_DIR) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SYCL + REQUIRED_VARS SYCL_LIBRARY SYCL_INCLUDE_DIR + VERSION_VAR SYCL_VERSION +) IF(SYCL_FOUND) SET(SYCL_INCLUDE_DIR ${SYCL_INCLUDE_DIR} ${SYCL_INCLUDE_DIR}/sycl) diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake index 9524cda54f5..65a38625e0a 100644 --- a/intern/cycles/cmake/external_libs.cmake +++ b/intern/cycles/cmake/external_libs.cmake @@ -663,8 +663,7 @@ if(WITH_CYCLES_DEVICE_ONEAPI) find_package(SYCL) find_package(LevelZero) - if(SYCL_FOUND AND LEVEL_ZERO_FOUND) - message(STATUS "Found oneAPI: ${SYCL_LIBRARY}") + if(SYCL_FOUND AND SYCL_VERSION VERSION_GREATER_EQUAL 6.0 AND LEVEL_ZERO_FOUND) message(STATUS "Found Level Zero: ${LEVEL_ZERO_LIBRARY}") if(WITH_CYCLES_ONEAPI_BINARIES) @@ -681,7 +680,7 @@ if(WITH_CYCLES_DEVICE_ONEAPI) endif() endif() else() - message(STATUS "oneAPI or Level Zero not found, disabling WITH_CYCLES_DEVICE_ONEAPI") + message(STATUS "SYCL 6.0+ or Level Zero not found, disabling WITH_CYCLES_DEVICE_ONEAPI") set(WITH_CYCLES_DEVICE_ONEAPI OFF) endif() endif() diff --git a/intern/cycles/device/oneapi/device_impl.cpp b/intern/cycles/device/oneapi/device_impl.cpp index 4e7849e6b9a..3588b75713b 100644 --- a/intern/cycles/device/oneapi/device_impl.cpp +++ b/intern/cycles/device/oneapi/device_impl.cpp @@ -698,11 +698,11 @@ std::vector OneapiDevice::available_devices() int number_of_eus = 96; int threads_per_eu = 7; if (device.has(sycl::aspect::ext_intel_gpu_eu_count)) { - number_of_eus = device.get_info(); + number_of_eus = device.get_info(); } if (device.has(sycl::aspect::ext_intel_gpu_hw_threads_per_eu)) { threads_per_eu = - device.get_info(); + device.get_info(); } /* This filters out all Level-Zero supported GPUs from older generation than Arc. */ if (number_of_eus <= 96 && threads_per_eu == 7) { @@ -818,7 +818,7 @@ void OneapiDevice::iterate_devices(OneAPIDeviceIteratorCallback cb, void *user_p std::string name = device.get_info(); std::string id = "ONEAPI_" + platform_name + "_" + name; if (device.has(sycl::aspect::ext_intel_pci_address)) { - id.append("_" + device.get_info()); + id.append("_" + device.get_info()); } (cb)(id.c_str(), name.c_str(), num, user_ptr); num++; @@ -836,7 +836,7 @@ int OneapiDevice::get_num_multiprocessors() { const sycl::device &device = reinterpret_cast(device_queue_)->get_device(); if (device.has(sycl::aspect::ext_intel_gpu_eu_count)) { - return device.get_info(); + return device.get_info(); } else return 0; @@ -847,8 +847,8 @@ int OneapiDevice::get_max_num_threads_per_multiprocessor() const sycl::device &device = reinterpret_cast(device_queue_)->get_device(); if (device.has(sycl::aspect::ext_intel_gpu_eu_simd_width) && device.has(sycl::aspect::ext_intel_gpu_hw_threads_per_eu)) { - return device.get_info() * - device.get_info(); + return device.get_info() * + device.get_info(); } else return 0; -- cgit v1.2.3 From 048f1a1b8b7ccf5b3d618a76a947941bf5d534f2 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 21 Oct 2022 11:57:42 -0300 Subject: GPU: remove unused member from FrameBuffer Accidentally added in rB2510bd3a5f35d14f5e0e098c79a776916d273223 --- source/blender/gpu/intern/gpu_framebuffer_private.hh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/source/blender/gpu/intern/gpu_framebuffer_private.hh b/source/blender/gpu/intern/gpu_framebuffer_private.hh index 76e816e7f65..5afcc102e44 100644 --- a/source/blender/gpu/intern/gpu_framebuffer_private.hh +++ b/source/blender/gpu/intern/gpu_framebuffer_private.hh @@ -94,11 +94,6 @@ class FrameBuffer { void **py_ref = nullptr; #endif - public: - /* Reference of a pointer that needs to be cleaned when deallocating the frame-buffer. - * Points to #BPyGPUFrameBuffer::fb */ - void **ref = nullptr; - public: FrameBuffer(const char *name); virtual ~FrameBuffer(); -- cgit v1.2.3 From 2c108d55031f2b6b5f83810f7f560d1ed81bdc5c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 21 Oct 2022 15:57:53 +0200 Subject: Avoid re-compilation of oneAPI AoT kernels when configuration changes Buildbot infrastructure relies on the fact that it can enable and disable `WITH_CYCLES__BINARIES` without affecting speed of incremental builds. This allows buildbot to skip GPU kernels when doing CI regression tests which do not need GPU kernels, as well as it allows to move GPU kernels compilation to a separate step where all the resources are available to the GPU kernel builders. For the oneAPI compute enabling and disabling AoT kernels has much higher implications due to the kernels being a part of the device implementation from the build target perspective. This change makes it so different target names are used for JIT and AoT configurations, which allows CMake to more fully benefit from "caching" the compiled result. The end goal of this change is to make it so sequential build of the same code base on the buildbot happens super fast, Blender binary still needs to be re-linked when the AOT of oneAPI option is toggled, but that's already the case in the buildbot due to the WITH_BUILDINFO. Differential Revision: https://developer.blender.org/D16312 --- intern/cycles/device/CMakeLists.txt | 9 +++++++-- intern/cycles/kernel/CMakeLists.txt | 12 +++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt index 9c0de57f203..5296d819e42 100644 --- a/intern/cycles/device/CMakeLists.txt +++ b/intern/cycles/device/CMakeLists.txt @@ -187,10 +187,15 @@ if(WITH_CYCLES_DEVICE_METAL) ) endif() if (WITH_CYCLES_DEVICE_ONEAPI) + if(WITH_CYCLES_ONEAPI_BINARIES) + set(cycles_kernel_oneapi_lib_suffix "_aot") + else() + set(cycles_kernel_oneapi_lib_suffix "_jit") + endif() if(WIN32) - set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/cycles_kernel_oneapi.lib) + set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/cycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.lib) else() - set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/libcycles_kernel_oneapi.so) + set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/libcycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.so) endif() list(APPEND LIB ${cycles_kernel_oneapi_lib}) if(WIN32) diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index b6a53117a3b..81c5f593974 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -713,11 +713,17 @@ endif() # oneAPI module if(WITH_CYCLES_DEVICE_ONEAPI) + if(WITH_CYCLES_ONEAPI_BINARIES) + set(cycles_kernel_oneapi_lib_suffix "_aot") + else() + set(cycles_kernel_oneapi_lib_suffix "_jit") + endif() + if(WIN32) - set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi.dll) - set(cycles_kernel_oneapi_linker_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi.lib) + set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.dll) + set(cycles_kernel_oneapi_linker_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.lib) else() - set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/libcycles_kernel_oneapi.so) + set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/libcycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.so) endif() set(cycles_oneapi_kernel_sources -- cgit v1.2.3 From 116d7b0042bba7d6cabd8e04c7d020ac3816caf3 Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Fri, 21 Oct 2022 09:50:14 -0600 Subject: make.bat: update the libraries before calling update_sources.py The issue we ran into a lot is we have a python script that updates git+SVN. Which works fine most of the time, except when we have a python update in SVN, or worse a python version change. Python really doesn't enjoy having its files being deleted or changed while it is running and users generally end up with a corrupted lib folder. This change updates the library folder using svn.exe first before letting the python script run sidestepping the issue in most cases. The python script will still run and do the more elaborate work like updating git and switching SVN branches which could still run into issues cause python still doesn't like being changed while running but there's not a whole lot we can about that, for *most* people however things will just work now. --- build_files/windows/svn_update.cmd | 24 ++++++++++++++++++++++++ make.bat | 10 +++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 build_files/windows/svn_update.cmd diff --git a/build_files/windows/svn_update.cmd b/build_files/windows/svn_update.cmd new file mode 100644 index 00000000000..f91f03f15b3 --- /dev/null +++ b/build_files/windows/svn_update.cmd @@ -0,0 +1,24 @@ +if "%BUILD_VS_YEAR%"=="2019" set BUILD_VS_LIBDIRPOST=vc15 +if "%BUILD_VS_YEAR%"=="2022" set BUILD_VS_LIBDIRPOST=vc15 + +set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST% +set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%" + +cd %BUILD_VS_LIBDIR% +:RETRY +"%SVN%" update +if errorlevel 1 ( + set /p LibRetry= "Error during update, retry? y/n" + if /I "!LibRetry!"=="Y" ( + "%SVN%" cleanup + goto RETRY + ) + echo. + echo Error: Download of external libraries failed. + echo This is needed for building, please manually run 'svn cleanup' and 'svn update' in + echo %BUILD_VS_LIBDIR% , until this is resolved you CANNOT make a successful blender build + echo. + exit /b 1 +) + +cd %BLENDER_DIR% \ No newline at end of file diff --git a/make.bat b/make.bat index ff8059b0754..0be70053ce1 100644 --- a/make.bat +++ b/make.bat @@ -62,9 +62,17 @@ if "%SVN_FIX%" == "1" ( ) if "%BUILD_UPDATE%" == "1" ( + REM First see if the SVN libs are there and check them out if they are not. call "%BLENDER_DIR%\build_files\windows\check_libraries.cmd" if errorlevel 1 goto EOF - + REM Then update SVN platform libraries, since updating python while python is + REM running tends to be problematic. The python script that update_sources + REM calls later on may still try to switch branches and run into trouble, + REM but for *most* people this will side step the problem. + call "%BLENDER_DIR%\build_files\windows\svn_update.cmd" + REM Finally call the python script shared between all platforms that updates git + REM and does any other SVN work like update the tests or branch switches + REM if required. call "%BLENDER_DIR%\build_files\windows\update_sources.cmd" goto EOF ) -- cgit v1.2.3 From 9c20eda0add3e223cd473eb883806a04522d345b Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 21 Oct 2022 14:24:18 -0300 Subject: Fix T101244: Empty point list in shader batch creation cause error Allow empty VBOs in Python GPUBatch creation. --- release/scripts/modules/gpu_extras/batch.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release/scripts/modules/gpu_extras/batch.py b/release/scripts/modules/gpu_extras/batch.py index ba8e3879a8e..6c9ab52c1a3 100644 --- a/release/scripts/modules/gpu_extras/batch.py +++ b/release/scripts/modules/gpu_extras/batch.py @@ -34,13 +34,13 @@ def batch_for_shader(shader, type, content, *, indices=None): return 'I32' def recommended_attr_len(attr_name): - item = content[attr_name][0] attr_len = 1 try: + item = content[attr_name][0] while True: attr_len *= len(item) item = item[0] - except TypeError: + except (TypeError, IndexError): pass return attr_len -- cgit v1.2.3 From 56d1f0772dd0e2b77abef1ad071e2e893cf3bc0a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 30 Sep 2022 18:48:21 +0200 Subject: Fix missing OpenMP in Linux builds OpenSubdiv OpenMP detection was interfering, but we don't use it there anymore so just remove that code. --- build_files/cmake/Modules/FindOpenSubdiv.cmake | 15 --------------- build_files/cmake/platform/platform_win32.cmake | 6 ------ intern/opensubdiv/CMakeLists.txt | 6 ------ 3 files changed, 27 deletions(-) diff --git a/build_files/cmake/Modules/FindOpenSubdiv.cmake b/build_files/cmake/Modules/FindOpenSubdiv.cmake index 37a2cddf3de..66d3b435c46 100644 --- a/build_files/cmake/Modules/FindOpenSubdiv.cmake +++ b/build_files/cmake/Modules/FindOpenSubdiv.cmake @@ -71,21 +71,6 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenSubdiv DEFAULT_MSG IF(OPENSUBDIV_FOUND) SET(OPENSUBDIV_LIBRARIES ${_opensubdiv_LIBRARIES}) SET(OPENSUBDIV_INCLUDE_DIRS ${OPENSUBDIV_INCLUDE_DIR}) - - # Find available compute controllers. - - FIND_PACKAGE(OpenMP) - IF(OPENMP_FOUND) - SET(OPENSUBDIV_HAS_OPENMP TRUE) - ELSE() - SET(OPENSUBDIV_HAS_OPENMP FALSE) - ENDIF() - - OPENSUBDIV_CHECK_CONTROLLER("tbbEvaluator.h" OPENSUBDIV_HAS_TBB) - OPENSUBDIV_CHECK_CONTROLLER("clEvaluator.h" OPENSUBDIV_HAS_OPENCL) - OPENSUBDIV_CHECK_CONTROLLER("cudaEvaluator.h" OPENSUBDIV_HAS_CUDA) - OPENSUBDIV_CHECK_CONTROLLER("glXFBEvaluator.h" OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK) - OPENSUBDIV_CHECK_CONTROLLER("glComputeEvaluator.h" OPENSUBDIV_HAS_GLSL_COMPUTE) ENDIF() MARK_AS_ADVANCED( diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index 32c467b4b46..2816446164a 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -703,12 +703,6 @@ if(WITH_OPENSUBDIV) debug ${OPENSUBDIV_LIBPATH}/osdCPU_d.lib debug ${OPENSUBDIV_LIBPATH}/osdGPU_d.lib ) - set(OPENSUBDIV_HAS_OPENMP TRUE) - set(OPENSUBDIV_HAS_TBB FALSE) - set(OPENSUBDIV_HAS_OPENCL TRUE) - set(OPENSUBDIV_HAS_CUDA FALSE) - set(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK TRUE) - set(OPENSUBDIV_HAS_GLSL_COMPUTE TRUE) endif() endif() diff --git a/intern/opensubdiv/CMakeLists.txt b/intern/opensubdiv/CMakeLists.txt index 1dddd70928a..920b8d5c542 100644 --- a/intern/opensubdiv/CMakeLists.txt +++ b/intern/opensubdiv/CMakeLists.txt @@ -81,12 +81,6 @@ if(WITH_OPENSUBDIV) ) endif() - opensubdiv_define_component(OPENSUBDIV_HAS_OPENMP) - opensubdiv_define_component(OPENSUBDIV_HAS_OPENCL) - opensubdiv_define_component(OPENSUBDIV_HAS_CUDA) - opensubdiv_define_component(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK) - opensubdiv_define_component(OPENSUBDIV_HAS_GLSL_COMPUTE) - if(WIN32) add_definitions(-DNOMINMAX) add_definitions(-D_USE_MATH_DEFINES) -- cgit v1.2.3 From ebe231969294924ff057f5d999d05986f9c97352 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 30 Sep 2022 18:50:03 +0200 Subject: Build: disable JACK option in macOS releases It has not actually been enabled there for a long time in official releases, so this just fixes the warning. Making it work again would be good, but for now JACK is only supported on Linux. --- CMakeLists.txt | 6 ++---- build_files/cmake/config/blender_full.cmake | 4 +--- build_files/cmake/config/blender_release.cmake | 4 +--- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a3ea162d040..e922a3b059a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -336,11 +336,9 @@ if(APPLE) else() set(WITH_COREAUDIO OFF) endif() -if(NOT WIN32) +if(UNIX AND NOT APPLE) option(WITH_JACK "Enable JACK Support (http://www.jackaudio.org)" ON) - if(UNIX AND NOT APPLE) - option(WITH_JACK_DYNLOAD "Enable runtime dynamic JACK libraries loading" OFF) - endif() + option(WITH_JACK_DYNLOAD "Enable runtime dynamic JACK libraries loading" OFF) else() set(WITH_JACK OFF) endif() diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake index 958eb17522b..95304bd64c7 100644 --- a/build_files/cmake/config/blender_full.cmake +++ b/build_files/cmake/config/blender_full.cmake @@ -66,13 +66,11 @@ set(WITH_MEM_JEMALLOC ON CACHE BOOL "" FORCE) if(APPLE) set(WITH_COREAUDIO ON CACHE BOOL "" FORCE) endif() -if(NOT WIN32) - set(WITH_JACK ON CACHE BOOL "" FORCE) -endif() if(WIN32) set(WITH_WASAPI ON CACHE BOOL "" FORCE) endif() if(UNIX AND NOT APPLE) + set(WITH_JACK ON CACHE BOOL "" FORCE) set(WITH_DOC_MANPAGE ON CACHE BOOL "" FORCE) set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE) set(WITH_PULSEAUDIO ON CACHE BOOL "" FORCE) diff --git a/build_files/cmake/config/blender_release.cmake b/build_files/cmake/config/blender_release.cmake index d5f5230862b..74bbcb223c3 100644 --- a/build_files/cmake/config/blender_release.cmake +++ b/build_files/cmake/config/blender_release.cmake @@ -67,13 +67,11 @@ if(APPLE) set(WITH_COREAUDIO ON CACHE BOOL "" FORCE) set(WITH_CYCLES_DEVICE_METAL ON CACHE BOOL "" FORCE) endif() -if(NOT WIN32) - set(WITH_JACK ON CACHE BOOL "" FORCE) -endif() if(WIN32) set(WITH_WASAPI ON CACHE BOOL "" FORCE) endif() if(UNIX AND NOT APPLE) + set(WITH_JACK ON CACHE BOOL "" FORCE) set(WITH_DOC_MANPAGE ON CACHE BOOL "" FORCE) set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE) set(WITH_PULSEAUDIO ON CACHE BOOL "" FORCE) -- cgit v1.2.3 From e7a6917617fbb4f3c224ad89e6a63bedf56e6553 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 29 Sep 2022 19:01:35 +0200 Subject: Build: add option to error when features can't be enabled This is to help ensure buildbot builds are correct, while still gracefully disabling features in user/developer builds. * Add WITH_STRICT_BUILD_OPTIONS to give an error when features can't be enabled due to missing libraries or other reasons. Add new macro set_and_warn_library_found used everywhere features were being automatically disabled. * Remove code from Windows and macOS for various libraries that would automatically disable features. set_and_warn_library_found could be used here also, but we are generally assuming the precompiled libraries are complete and only test for availability when libraries are just added. Differential Revision: https://developer.blender.org/D16104 --- CMakeLists.txt | 22 ++- build_files/cmake/macros.cmake | 18 ++- build_files/cmake/platform/platform_apple.cmake | 89 ++-------- build_files/cmake/platform/platform_unix.cmake | 205 +++++++----------------- build_files/cmake/platform/platform_win32.cmake | 59 ++----- intern/cycles/CMakeLists.txt | 6 +- intern/cycles/cmake/external_libs.cmake | 51 +++--- 7 files changed, 143 insertions(+), 307 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e922a3b059a..f2f34ca3dd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -777,6 +777,8 @@ endif() # ----------------------------------------------------------------------------- # Check for Conflicting/Unsupported Configurations +option(WITH_STRICT_BUILD_OPTIONS "When requirements for a build option are not met, error instead of disabling the option" OFF) + if(NOT WITH_BLENDER AND NOT WITH_CYCLES_STANDALONE AND NOT WITH_CYCLES_HYDRA_RENDER_DELEGATE) message(FATAL_ERROR "At least one of WITH_BLENDER or WITH_CYCLES_STANDALONE " @@ -892,10 +894,7 @@ endif() if(WITH_BUILDINFO) find_package(Git) - if(NOT GIT_FOUND) - message(WARNING "Git was not found, disabling WITH_BUILDINFO") - set(WITH_BUILDINFO OFF) - endif() + set_and_warn_library_found("Git" GIT_FOUND WITH_BUILDINFO) endif() if(WITH_AUDASPACE) @@ -935,9 +934,10 @@ if(WITH_INTERNATIONAL) WARNING "Translation path '${CMAKE_SOURCE_DIR}/release/datafiles/locale' is missing, " "This is a 'git submodule', which are known not to work with bridges to other version " - "control systems, disabling 'WITH_INTERNATIONAL'." + "control systems." ) - set(WITH_INTERNATIONAL OFF) + set(TRANSLATIONS_FOUND OFF) + set_and_warn_library_found("Translations" TRANSLATIONS_FOUND WITH_INTERNATIONAL) endif() endif() @@ -1242,6 +1242,8 @@ if(WITH_OPENMP) find_package(OpenMP) endif() + set_and_warn_library_found("OpenMP" OPENMP_FOUND WITH_OPENMP) + if(OPENMP_FOUND) if(NOT WITH_OPENMP_STATIC) string(APPEND CMAKE_C_FLAGS " ${OpenMP_C_FLAGS}") @@ -1257,9 +1259,6 @@ if(WITH_OPENMP) find_library_static(OpenMP_LIBRARIES gomp ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES}) endif() - else() - message(STATUS "OpenMP not found, disabling WITH_OPENMP") - set(WITH_OPENMP OFF) endif() mark_as_advanced( @@ -1274,10 +1273,7 @@ endif() if(WITH_BULLET AND WITH_SYSTEM_BULLET) find_package(Bullet) - if(NOT BULLET_FOUND) - message(STATUS "Bullet not found, disabling WITH_BULLET") - set(WITH_BULLET OFF) - endif() + set_and_warn_library_found("Bullet" BULLET_FOUND WITH_BULLET) else() set(BULLET_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/extern/bullet2/src") # set(BULLET_LIBRARIES "") diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 3acea19079b..8af45690862 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -1205,11 +1205,27 @@ macro(set_and_warn_dependency _dependency _setting _val) # when $_dependency is disabled, forces $_setting = $_val if(NOT ${${_dependency}} AND ${${_setting}}) - message(STATUS "'${_dependency}' is disabled: forcing 'set(${_setting} ${_val})'") + if(WITH_STRICT_BUILD_OPTIONS) + message(SEND_ERROR "${_dependency} disabled but required by ${_setting}") + else() + message(STATUS "${_dependency} is disabled, setting ${_setting}=${_val}") + endif() set(${_setting} ${_val}) endif() endmacro() +macro(set_and_warn_library_found + _library_name _library_found _setting) + if(NOT ${${_library_found}} AND ${${_setting}}) + if(WITH_STRICT_BUILD_OPTIONS) + message(SEND_ERROR "${_library_name} required but not found") + else() + message(STATUS "${_library_name} not found, disabling ${_setting}") + endif() + set(${_setting} OFF) + endif() +endmacro() + macro(without_system_libs_begin) set(CMAKE_IGNORE_PATH "${CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES};${CMAKE_SYSTEM_INCLUDE_PATH};${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES};${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}") endmacro() diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake index dbcaf9d02d3..c5fe3c908de 100644 --- a/build_files/cmake/platform/platform_apple.cmake +++ b/build_files/cmake/platform/platform_apple.cmake @@ -43,22 +43,18 @@ find_package(BZip2 REQUIRED) list(APPEND ZLIB_LIBRARIES ${BZIP2_LIBRARIES}) if(WITH_OPENAL) - find_package(OpenAL) - if(NOT OPENAL_FOUND) - message(WARNING "OpenAL not found, disabling WITH_OPENAL") - set(WITH_OPENAL OFF) - endif() + find_package(OpenAL REQUIRED) endif() if(WITH_JACK) find_library(JACK_FRAMEWORK NAMES jackmp ) - if(NOT JACK_FRAMEWORK) - message(STATUS "JACK not found, disabling WITH_JACK") - set(WITH_JACK OFF) - else() + + if(JACK_FRAMEWORK) set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers) + else() + set_and_warn_library_found("JACK" JACK_FRAMEWORK WITH_JACK) endif() endif() @@ -101,11 +97,7 @@ if(WITH_ALEMBIC) endif() if(WITH_USD) - find_package(USD) - if(NOT USD_FOUND) - message(STATUS "USD not found, disabling WITH_USD") - set(WITH_USD OFF) - endif() + find_package(USD REQUIRED) endif() if(WITH_OPENSUBDIV) @@ -227,20 +219,12 @@ find_package(JPEG REQUIRED) if(WITH_IMAGE_TIFF) set(TIFF_ROOT ${LIBDIR}/tiff) - find_package(TIFF) - if(NOT TIFF_FOUND) - message(WARNING "TIFF not found, disabling WITH_IMAGE_TIFF") - set(WITH_IMAGE_TIFF OFF) - endif() + find_package(TIFF REQUIRED) endif() if(WITH_IMAGE_WEBP) set(WEBP_ROOT_DIR ${LIBDIR}/webp) - find_package(WebP) - if(NOT WEBP_FOUND) - message(WARNING "WebP not found, disabling WITH_IMAGE_WEBP") - set(WITH_IMAGE_WEBP OFF) - endif() + find_package(WebP REQUIRED) endif() if(WITH_BOOST) @@ -270,11 +254,7 @@ if(WITH_INTERNATIONAL OR WITH_CODEC_FFMPEG) endif() if(WITH_PUGIXML) - find_package(PugiXML) - if(NOT PUGIXML_FOUND) - message(WARNING "PugiXML not found, disabling WITH_PUGIXML") - set(WITH_PUGIXML OFF) - endif() + find_package(PugiXML REQUIRED) endif() if(WITH_OPENIMAGEIO) @@ -292,12 +272,7 @@ if(WITH_OPENIMAGEIO) endif() if(WITH_OPENCOLORIO) - find_package(OpenColorIO 2.0.0) - - if(NOT OPENCOLORIO_FOUND) - set(WITH_OPENCOLORIO OFF) - message(STATUS "OpenColorIO not found, disabling WITH_OPENCOLORIO") - endif() + find_package(OpenColorIO 2.0.0 REQUIRED) endif() if(WITH_OPENVDB) @@ -331,12 +306,7 @@ if(WITH_LLVM) endif() if(WITH_CYCLES AND WITH_CYCLES_OSL) - find_package(OSL) - - if(NOT OSL_FOUND) - message(WARNING "OSL not found, disabling WITH_CYCLES_OSL") - set(WITH_CYCLES_OSL OFF) - endif() + find_package(OSL REQUIRED) endif() if(WITH_CYCLES AND WITH_CYCLES_EMBREE) @@ -354,28 +324,15 @@ if(WITH_CYCLES AND WITH_CYCLES_EMBREE) endif() if(WITH_OPENIMAGEDENOISE) - find_package(OpenImageDenoise) - - if(NOT OPENIMAGEDENOISE_FOUND) - set(WITH_OPENIMAGEDENOISE OFF) - message(STATUS "OpenImageDenoise not found, disabling WITH_OPENIMAGEDENOISE") - endif() + find_package(OpenImageDenoise REQUIRED) endif() if(WITH_TBB) - find_package(TBB) - if(NOT TBB_FOUND) - message(WARNING "TBB not found, disabling WITH_TBB") - set(WITH_TBB OFF) - endif() + find_package(TBB REQUIRED) endif() if(WITH_POTRACE) - find_package(Potrace) - if(NOT POTRACE_FOUND) - message(WARNING "potrace not found, disabling WITH_POTRACE") - set(WITH_POTRACE OFF) - endif() + find_package(Potrace REQUIRED) endif() # CMake FindOpenMP doesn't know about AppleClang before 3.12, so provide custom flags. @@ -395,27 +352,15 @@ if(WITH_OPENMP) endif() if(WITH_XR_OPENXR) - find_package(XR_OpenXR_SDK) - if(NOT XR_OPENXR_SDK_FOUND) - message(WARNING "OpenXR-SDK was not found, disabling WITH_XR_OPENXR") - set(WITH_XR_OPENXR OFF) - endif() + find_package(XR_OpenXR_SDK REQUIRED) endif() if(WITH_GMP) - find_package(GMP) - if(NOT GMP_FOUND) - message(WARNING "GMP not found, disabling WITH_GMP") - set(WITH_GMP OFF) - endif() + find_package(GMP REQUIRED) endif() if(WITH_HARU) - find_package(Haru) - if(NOT HARU_FOUND) - message(WARNING "Haru not found, disabling WITH_HARU") - set(WITH_HARU OFF) - endif() + find_package(Haru REQUIRED) endif() if(WITH_CYCLES AND WITH_CYCLES_PATH_GUIDING) diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake index 7f3acb142ce..424926afe39 100644 --- a/build_files/cmake/platform/platform_unix.cmake +++ b/build_files/cmake/platform/platform_unix.cmake @@ -174,32 +174,24 @@ endif() if(WITH_IMAGE_OPENEXR) find_package_wrapper(OpenEXR) # our own module - if(NOT OPENEXR_FOUND) - set(WITH_IMAGE_OPENEXR OFF) - endif() + set_and_warn_library_found("OpenEXR" OPENEXR_FOUND WITH_IMAGE_OPENEXR) endif() if(WITH_IMAGE_OPENJPEG) find_package_wrapper(OpenJPEG) - if(NOT OPENJPEG_FOUND) - set(WITH_IMAGE_OPENJPEG OFF) - endif() + set_and_warn_library_found("OpenJPEG" OPENJPEG_FOUND WITH_IMAGE_OPENJPEG) endif() if(WITH_IMAGE_TIFF) # XXX Linking errors with debian static tiff :/ # find_package_wrapper(TIFF) find_package(TIFF) - if(NOT TIFF_FOUND) - set(WITH_IMAGE_TIFF OFF) - endif() + set_and_warn_library_found("TIFF" TIFF_FOUND WITH_IMAGE_TIFF) endif() if(WITH_OPENAL) find_package_wrapper(OpenAL) - if(NOT OPENAL_FOUND) - set(WITH_OPENAL OFF) - endif() + set_and_warn_library_found("OpenAL" OPENAL_FOUND WITH_OPENAL) endif() if(WITH_SDL) @@ -221,18 +213,14 @@ if(WITH_SDL) SDL_LIBRARY ) # unset(SDLMAIN_LIBRARY CACHE) - if(NOT SDL_FOUND) - set(WITH_SDL OFF) - endif() + set_and_warn_library_found("SDL" SDL_FOUND WITH_SDL) endif() endif() # Codecs if(WITH_CODEC_SNDFILE) find_package_wrapper(SndFile) - if(NOT SNDFILE_FOUND) - set(WITH_CODEC_SNDFILE OFF) - endif() + set_and_warn_library_found("libsndfile" SNDFILE_FOUND WITH_CODEC_SNDFILE) endif() if(WITH_CODEC_FFMPEG) @@ -260,17 +248,12 @@ if(WITH_CODEC_FFMPEG) endif() find_package(FFmpeg) - if(NOT FFMPEG_FOUND) - set(WITH_CODEC_FFMPEG OFF) - message(STATUS "FFmpeg not found, disabling it") - endif() + set_and_warn_library_found("FFmpeg" FFMPEG_FOUND WITH_CODEC_FFMPEG) endif() if(WITH_FFTW3) find_package_wrapper(Fftw3) - if(NOT FFTW3_FOUND) - set(WITH_FFTW3 OFF) - endif() + set_and_warn_library_found("fftw3" FFTW3_FOUND WITH_FFTW3) endif() if(WITH_OPENCOLLADA) @@ -285,25 +268,23 @@ if(WITH_OPENCOLLADA) endif() find_package_wrapper(XML2) else() - set(WITH_OPENCOLLADA OFF) + set_and_warn_library_found("OpenCollada" OPENCOLLADA_FOUND WITH_OPENCOLLADA) endif() endif() if(WITH_MEM_JEMALLOC) find_package_wrapper(JeMalloc) - if(NOT JEMALLOC_FOUND) - set(WITH_MEM_JEMALLOC OFF) - endif() + set_and_warn_library_found("JeMalloc" JEMALLOC_FOUND WITH_MEM_JEMALLOC) endif() if(WITH_INPUT_NDOF) find_package_wrapper(Spacenav) + set_and_warn_library_found("SpaceNav" SPACENAV_FOUND WITH_INPUT_NDOF) + if(SPACENAV_FOUND) # use generic names within blenders buildsystem. set(NDOF_INCLUDE_DIRS ${SPACENAV_INCLUDE_DIRS}) set(NDOF_LIBRARIES ${SPACENAV_LIBRARIES}) - else() - set(WITH_INPUT_NDOF OFF) endif() endif() @@ -313,6 +294,8 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL) set(OSL_ROOT ${CYCLES_OSL}) endif() find_package_wrapper(OSL) + set_and_warn_library_found("OSL" OSL_FOUND WITH_CYCLES_OSL) + if(OSL_FOUND) if(${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6") # Note: --whole-archive is needed to force loading of all symbols in liboslexec, @@ -323,9 +306,6 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL) -Wl,--no-whole-archive ${OSL_OSLQUERY_LIBRARY} ) endif() - else() - message(STATUS "OSL not found, disabling it from Cycles") - set(WITH_CYCLES_OSL OFF) endif() endif() @@ -351,25 +331,17 @@ endif() if(WITH_OPENVDB) find_package_wrapper(OpenVDB) - find_package_wrapper(Blosc) - - if(NOT OPENVDB_FOUND) - set(WITH_OPENVDB OFF) - set(WITH_OPENVDB_BLOSC OFF) - message(STATUS "OpenVDB not found, disabling it") - elseif(NOT BLOSC_FOUND) - set(WITH_OPENVDB_BLOSC OFF) - message(STATUS "Blosc not found, disabling it for OpenVBD") + set_and_warn_library_found("OpenVDB" OPENVDB_FOUND WITH_OPENVDB) + + if(OPENVDB_FOUND) + find_package_wrapper(Blosc) + set_and_warn_library_found("Blosc" BLOSC_FOUND WITH_OPENVDB_BLOSC) endif() endif() if(WITH_NANOVDB) find_package_wrapper(NanoVDB) - - if(NOT NANOVDB_FOUND) - set(WITH_NANOVDB OFF) - message(STATUS "NanoVDB not found, disabling it") - endif() + set_and_warn_library_found("NanoVDB" NANOVDB_FOUND WITH_NANOVDB) endif() if(WITH_CPU_SIMD AND SUPPORT_NEON_BUILD) @@ -378,18 +350,12 @@ endif() if(WITH_ALEMBIC) find_package_wrapper(Alembic) - - if(NOT ALEMBIC_FOUND) - set(WITH_ALEMBIC OFF) - endif() + set_and_warn_library_found("Alembic" ALEMBIC_FOUND WITH_ALEMBIC) endif() if(WITH_USD) find_package_wrapper(USD) - - if(NOT USD_FOUND) - set(WITH_USD OFF) - endif() + set_and_warn_library_found("USD" USD_FOUND WITH_USD) endif() if(WITH_BOOST) @@ -442,20 +408,13 @@ endif() if(WITH_PUGIXML) find_package_wrapper(PugiXML) - - if(NOT PUGIXML_FOUND) - set(WITH_PUGIXML OFF) - message(STATUS "PugiXML not found, disabling WITH_PUGIXML") - endif() + set_and_warn_library_found("PugiXML" PUGIXML_FOUND WITH_PUGIXML) endif() if(WITH_IMAGE_WEBP) set(WEBP_ROOT_DIR ${LIBDIR}/webp) find_package_wrapper(WebP) - if(NOT WEBP_FOUND) - set(WITH_IMAGE_WEBP OFF) - message(WARNING "WebP not found, disabling WITH_IMAGE_WEBP") - endif() + set_and_warn_library_found("WebP" WEBP_FOUND WITH_IMAGE_WEBP) endif() if(WITH_OPENIMAGEIO) @@ -480,10 +439,7 @@ if(WITH_OPENIMAGEIO) list(APPEND OPENIMAGEIO_LIBRARIES "${WEBP_LIBRARIES}") endif() - if(NOT OPENIMAGEIO_FOUND) - set(WITH_OPENIMAGEIO OFF) - message(STATUS "OpenImageIO not found, disabling WITH_CYCLES") - endif() + set_and_warn_library_found("OPENIMAGEIO" OPENIMAGEIO_FOUND WITH_OPENIMAGEIO) endif() if(WITH_OPENCOLORIO) @@ -493,10 +449,7 @@ if(WITH_OPENCOLORIO) set(OPENCOLORIO_LIBPATH) # TODO, remove and reference the absolute path everywhere set(OPENCOLORIO_DEFINITIONS) - if(NOT OPENCOLORIO_FOUND) - set(WITH_OPENCOLORIO OFF) - message(STATUS "OpenColorIO not found") - endif() + set_and_warn_library_found("OpenColorIO" OPENCOLORIO_FOUND WITH_OPENCOLORIO) endif() if(WITH_CYCLES AND WITH_CYCLES_EMBREE) @@ -505,11 +458,7 @@ endif() if(WITH_OPENIMAGEDENOISE) find_package_wrapper(OpenImageDenoise) - - if(NOT OPENIMAGEDENOISE_FOUND) - set(WITH_OPENIMAGEDENOISE OFF) - message(STATUS "OpenImageDenoise not found") - endif() + set_and_warn_library_found("OpenImageDenoise" OPENIMAGEDENOISE_FOUND WITH_OPENIMAGEDENOISE) endif() if(WITH_LLVM) @@ -518,24 +467,19 @@ if(WITH_LLVM) endif() find_package_wrapper(LLVM) - if(WITH_CLANG) - find_package_wrapper(Clang) - endif() - # Symbol conflicts with same UTF library used by OpenCollada - if(EXISTS ${LIBDIR}) - if(WITH_OPENCOLLADA AND (${LLVM_VERSION} VERSION_LESS "4.0.0")) - list(REMOVE_ITEM OPENCOLLADA_LIBRARIES ${OPENCOLLADA_UTF_LIBRARY}) + set_and_warn_library_found("LLVM" LLVM_FOUND WITH_LLVM) + + if(LLVM_FOUND) + if(WITH_CLANG) + find_package_wrapper(Clang) + set_and_warn_library_found("Clang" CLANG_FOUND WITH_CLANG) endif() - endif() - if(NOT LLVM_FOUND) - set(WITH_LLVM OFF) - set(WITH_CLANG OFF) - message(STATUS "LLVM not found") - else() - if(NOT CLANG_FOUND) - set(WITH_CLANG OFF) - message(STATUS "Clang not found") + # Symbol conflicts with same UTF library used by OpenCollada + if(EXISTS ${LIBDIR}) + if(WITH_OPENCOLLADA AND (${LLVM_VERSION} VERSION_LESS "4.0.0")) + list(REMOVE_ITEM OPENCOLLADA_LIBRARIES ${OPENCOLLADA_UTF_LIBRARY}) + endif() endif() endif() endif() @@ -546,50 +490,32 @@ if(WITH_OPENSUBDIV) set(OPENSUBDIV_LIBRARIES ${OPENSUBDIV_LIBRARIES}) set(OPENSUBDIV_LIBPATH) # TODO, remove and reference the absolute path everywhere - if(NOT OPENSUBDIV_FOUND) - set(WITH_OPENSUBDIV OFF) - message(STATUS "OpenSubdiv not found") - endif() + set_and_warn_library_found("OpenSubdiv" OPENSUBDIV_FOUND WITH_OPENSUBDIV) endif() if(WITH_TBB) find_package_wrapper(TBB) - if(NOT TBB_FOUND) - message(WARNING "TBB not found, disabling WITH_TBB") - set(WITH_TBB OFF) - endif() + set_and_warn_library_found("TBB" TBB_FOUND WITH_TBB) endif() if(WITH_XR_OPENXR) find_package(XR_OpenXR_SDK) - if(NOT XR_OPENXR_SDK_FOUND) - message(WARNING "OpenXR-SDK not found, disabling WITH_XR_OPENXR") - set(WITH_XR_OPENXR OFF) - endif() + set_and_warn_library_found("OpenXR-SDK" XR_OPENXR_SDK_FOUND WITH_XR_OPENXR) endif() if(WITH_GMP) find_package_wrapper(GMP) - if(NOT GMP_FOUND) - message(WARNING "GMP not found, disabling WITH_GMP") - set(WITH_GMP OFF) - endif() + set_and_warn_library_found("GMP" GMP_FOUND WITH_GMP) endif() if(WITH_POTRACE) find_package_wrapper(Potrace) - if(NOT POTRACE_FOUND) - message(WARNING "potrace not found, disabling WITH_POTRACE") - set(WITH_POTRACE OFF) - endif() + set_and_warn_library_found("Potrace" POTRACE_FOUND WITH_POTRACE) endif() if(WITH_HARU) find_package_wrapper(Haru) - if(NOT HARU_FOUND) - message(WARNING "Haru not found, disabling WITH_HARU") - set(WITH_HARU OFF) - endif() + set_and_warn_library_found("Haru" HARU_FOUND WITH_HARU) endif() if(WITH_CYCLES AND WITH_CYCLES_PATH_GUIDING) @@ -676,25 +602,20 @@ endif() # Jack is intended to use the system library. if(WITH_JACK) find_package_wrapper(Jack) - if(NOT JACK_FOUND) - set(WITH_JACK OFF) - endif() + set_and_warn_library_found("JACK" JACK_FOUND WITH_JACK) endif() # Pulse is intended to use the system library. if(WITH_PULSEAUDIO) find_package_wrapper(Pulse) - if(NOT PULSE_FOUND) - set(WITH_PULSEAUDIO OFF) - endif() + set_and_warn_library_found("PulseAudio" PULSE_FOUND WITH_PULSEAUDIO) endif() # Audio IO if(WITH_SYSTEM_AUDASPACE) find_package_wrapper(Audaspace) - if(NOT AUDASPACE_FOUND OR NOT AUDASPACE_C_FOUND) - message(FATAL_ERROR "Audaspace external library not found!") - endif() + set(AUDASPACE_FOUND ${AUDASPACE_FOUND} AND ${AUDASPACE_C_FOUND}) + set_and_warn_library_found("External Audaspace" AUDASPACE_FOUND WITH_SYSTEM_AUDASPACE) endif() if(WITH_GHOST_WAYLAND) @@ -740,30 +661,12 @@ if(WITH_GHOST_WAYLAND) set(wayland-cursor_FOUND ON) endif() - if (NOT wayland-client_FOUND) - message(STATUS "wayland-client not found, disabling WITH_GHOST_WAYLAND") - set(WITH_GHOST_WAYLAND OFF) - endif() - if (NOT wayland-egl_FOUND) - message(STATUS "wayland-egl not found, disabling WITH_GHOST_WAYLAND") - set(WITH_GHOST_WAYLAND OFF) - endif() - if (NOT wayland-scanner_FOUND) - message(STATUS "wayland-scanner not found, disabling WITH_GHOST_WAYLAND") - set(WITH_GHOST_WAYLAND OFF) - endif() - if (NOT wayland-cursor_FOUND) - message(STATUS "wayland-cursor not found, disabling WITH_GHOST_WAYLAND") - set(WITH_GHOST_WAYLAND OFF) - endif() - if (NOT wayland-protocols_FOUND) - message(STATUS "wayland-protocols not found, disabling WITH_GHOST_WAYLAND") - set(WITH_GHOST_WAYLAND OFF) - endif() - if (NOT xkbcommon_FOUND) - message(STATUS "xkbcommon not found, disabling WITH_GHOST_WAYLAND") - set(WITH_GHOST_WAYLAND OFF) - endif() + set_and_warn_library_found("wayland-client" wayland-client_FOUND WITH_GHOST_WAYLAND) + set_and_warn_library_found("wayland-egl" wayland-egl_FOUND WITH_GHOST_WAYLAND) + set_and_warn_library_found("wayland-scanner" wayland-scanner_FOUND WITH_GHOST_WAYLAND) + set_and_warn_library_found("wayland-cursor" wayland-cursor_FOUND WITH_GHOST_WAYLAND) + set_and_warn_library_found("wayland-protocols" wayland-protocols_FOUND WITH_GHOST_WAYLAND) + set_and_warn_library_found("xkbcommon" xkbcommon_FOUND WITH_GHOST_WAYLAND) if(WITH_GHOST_WAYLAND) if(WITH_GHOST_WAYLAND_DBUS) diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index 2816446164a..3818076634a 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -326,18 +326,10 @@ if(WITH_FFTW3) endif() if(WITH_IMAGE_WEBP) - windows_find_package(WebP) - if(NOT WEBP_FOUND) - if(EXISTS ${LIBDIR}/webp) - set(WEBP_INCLUDE_DIRS ${LIBDIR}/webp/include) - set(WEBP_ROOT_DIR ${LIBDIR}/webp) - set(WEBP_LIBRARIES ${LIBDIR}/webp/lib/webp.lib ${LIBDIR}/webp/lib/webpdemux.lib ${LIBDIR}/webp/lib/webpmux.lib) - set(WEBP_FOUND ON) - else() - message(STATUS "WITH_IMAGE_WEBP is ON but WEBP libraries are not found, setting WITH_IMAGE_WEBP=OFF") - set(WITH_IMAGE_WEBP OFF) - endif() - endif() + set(WEBP_INCLUDE_DIRS ${LIBDIR}/webp/include) + set(WEBP_ROOT_DIR ${LIBDIR}/webp) + set(WEBP_LIBRARIES ${LIBDIR}/webp/lib/webp.lib ${LIBDIR}/webp/lib/webpdemux.lib ${LIBDIR}/webp/lib/webpmux.lib) + set(WEBP_FOUND ON) endif() if(WITH_OPENCOLLADA) @@ -792,13 +784,6 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL) endif() find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include) find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin) - - if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER) - set(OSL_FOUND TRUE) - else() - message(STATUS "OSL not found") - set(WITH_CYCLES_OSL OFF) - endif() endif() if(WITH_CYCLES AND WITH_CYCLES_EMBREE) @@ -898,21 +883,16 @@ if(WINDOWS_PYTHON_DEBUG) endif() if(WITH_XR_OPENXR) - if(EXISTS ${LIBDIR}/xr_openxr_sdk) - set(XR_OPENXR_SDK ${LIBDIR}/xr_openxr_sdk) - set(XR_OPENXR_SDK_LIBPATH ${LIBDIR}/xr_openxr_sdk/lib) - set(XR_OPENXR_SDK_INCLUDE_DIR ${XR_OPENXR_SDK}/include) - # This is the old name of this library, it is checked to - # support the transition between the old and new lib versions - # this can be removed after the next lib update. - if(EXISTS ${XR_OPENXR_SDK_LIBPATH}/openxr_loader_d.lib) - set(XR_OPENXR_SDK_LIBRARIES optimized ${XR_OPENXR_SDK_LIBPATH}/openxr_loader.lib debug ${XR_OPENXR_SDK_LIBPATH}/openxr_loader_d.lib) - else() - set(XR_OPENXR_SDK_LIBRARIES optimized ${XR_OPENXR_SDK_LIBPATH}/openxr_loader.lib debug ${XR_OPENXR_SDK_LIBPATH}/openxr_loaderd.lib) - endif() + set(XR_OPENXR_SDK ${LIBDIR}/xr_openxr_sdk) + set(XR_OPENXR_SDK_LIBPATH ${LIBDIR}/xr_openxr_sdk/lib) + set(XR_OPENXR_SDK_INCLUDE_DIR ${XR_OPENXR_SDK}/include) + # This is the old name of this library, it is checked to + # support the transition between the old and new lib versions + # this can be removed after the next lib update. + if(EXISTS ${XR_OPENXR_SDK_LIBPATH}/openxr_loader_d.lib) + set(XR_OPENXR_SDK_LIBRARIES optimized ${XR_OPENXR_SDK_LIBPATH}/openxr_loader.lib debug ${XR_OPENXR_SDK_LIBPATH}/openxr_loader_d.lib) else() - message(WARNING "OpenXR-SDK was not found, disabling WITH_XR_OPENXR") - set(WITH_XR_OPENXR OFF) + set(XR_OPENXR_SDK_LIBRARIES optimized ${XR_OPENXR_SDK_LIBPATH}/openxr_loader.lib debug ${XR_OPENXR_SDK_LIBPATH}/openxr_loaderd.lib) endif() endif() @@ -930,15 +910,10 @@ if(WITH_POTRACE) endif() if(WITH_HARU) - if(EXISTS ${LIBDIR}/haru) - set(HARU_FOUND ON) - set(HARU_ROOT_DIR ${LIBDIR}/haru) - set(HARU_INCLUDE_DIRS ${HARU_ROOT_DIR}/include) - set(HARU_LIBRARIES ${HARU_ROOT_DIR}/lib/libhpdfs.lib) - else() - message(WARNING "Haru was not found, disabling WITH_HARU") - set(WITH_HARU OFF) - endif() + set(HARU_FOUND ON) + set(HARU_ROOT_DIR ${LIBDIR}/haru) + set(HARU_INCLUDE_DIRS ${HARU_ROOT_DIR}/include) + set(HARU_LIBRARIES ${HARU_ROOT_DIR}/lib/libhpdfs.lib) endif() if(WITH_CYCLES AND WITH_CYCLES_PATH_GUIDING) diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index f619e6b104e..329aa3990f6 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -263,8 +263,7 @@ if(WITH_CYCLES_DEVICE_OPTIX) ${OPTIX_INCLUDE_DIR} ) else() - message(STATUS "OptiX not found, disabling it from Cycles") - set(WITH_CYCLES_DEVICE_OPTIX OFF) + set_and_warn_library_found("OptiX" OPTIX_FOUND WITH_CYCLES_DEVICE_OPTIX) endif() endif() @@ -387,8 +386,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER_ID MATCHES "Clang") endif() if(WITH_CYCLES_HYDRA_RENDER_DELEGATE AND (NOT WITH_USD)) - message(STATUS "USD not found, disabling WITH_CYCLES_HYDRA_RENDER_DELEGATE") - set(WITH_CYCLES_HYDRA_RENDER_DELEGATE OFF) + set_and_warn_library_found("USD" WITH_USD WITH_CYCLES_HYDRA_RENDER_DELEGATE) endif() if(WITH_CYCLES_HYDRA_RENDER_DELEGATE AND (NOT WITH_BLENDER) AND (NOT WITH_CYCLES_STANDALONE)) set(CYCLES_INSTALL_PATH ${CYCLES_INSTALL_PATH}/hdCycles/resources) diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake index 65a38625e0a..44542a08156 100644 --- a/intern/cycles/cmake/external_libs.cmake +++ b/intern/cycles/cmake/external_libs.cmake @@ -289,8 +289,7 @@ if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_PATH_GUIDING) endif() get_target_property(OPENPGL_INCLUDE_DIR openpgl::openpgl INTERFACE_INCLUDE_DIRECTORIES) else() - set(WITH_CYCLES_PATH_GUIDING OFF) - message(STATUS "OpenPGL not found, disabling WITH_CYCLES_PATH_GUIDING") + set_and_warn_library_found("OpenPGL" openpgl_FOUND WITH_CYCLES_PATH_GUIDING) endif() endif() @@ -588,16 +587,14 @@ if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI) # We can't use the version from the Blender precompiled libraries because # it does not include the video subsystem. find_package(SDL2 REQUIRED) + set_and_warn_library_found("SDL" SDL2_FOUND WITH_CYCLES_STANDALONE_GUI) - if(NOT SDL2_FOUND) - set(WITH_CYCLES_STANDALONE_GUI OFF) - message(STATUS "SDL not found, disabling Cycles standalone GUI") + if(SDL2_FOUND) + include_directories( + SYSTEM + ${SDL2_INCLUDE_DIRS} + ) endif() - - include_directories( - SYSTEM - ${SDL2_INCLUDE_DIRS} - ) endif() ########################################################################### @@ -606,11 +603,11 @@ endif() if(WITH_CYCLES_DEVICE_CUDA AND (WITH_CYCLES_CUDA_BINARIES OR NOT WITH_CUDA_DYNLOAD)) find_package(CUDA) # Try to auto locate CUDA toolkit + set_and_warn_library_found("CUDA compiler" CUDA_FOUND WITH_CYCLES_CUDA_BINARIES) + if(CUDA_FOUND) message(STATUS "Found CUDA ${CUDA_NVCC_EXECUTABLE} (${CUDA_VERSION})") else() - message(STATUS "CUDA compiler not found, disabling WITH_CYCLES_CUDA_BINARIES") - set(WITH_CYCLES_CUDA_BINARIES OFF) if(NOT WITH_CUDA_DYNLOAD) message(STATUS "Additionally falling back to dynamic CUDA load") set(WITH_CUDA_DYNLOAD ON) @@ -624,11 +621,10 @@ endif() if(WITH_CYCLES_HIP_BINARIES AND WITH_CYCLES_DEVICE_HIP) find_package(HIP) + set_and_warn_library_found("HIP compiler" HIP_FOUND WITH_CYCLES_HIP_BINARIES) + if(HIP_FOUND) message(STATUS "Found HIP ${HIP_HIPCC_EXECUTABLE} (${HIP_VERSION})") - else() - message(STATUS "HIP compiler not found, disabling WITH_CYCLES_HIP_BINARIES") - set(WITH_CYCLES_HIP_BINARIES OFF) endif() endif() @@ -644,13 +640,17 @@ if(WITH_CYCLES_DEVICE_METAL) find_library(METAL_LIBRARY Metal) # This file was added in the 12.0 SDK, use it as a way to detect the version. - if(METAL_LIBRARY AND NOT EXISTS "${METAL_LIBRARY}/Headers/MTLFunctionStitching.h") - message(STATUS "Metal version too old, must be SDK 12.0 or newer, disabling WITH_CYCLES_DEVICE_METAL") - set(WITH_CYCLES_DEVICE_METAL OFF) - elseif(NOT METAL_LIBRARY) - message(STATUS "Metal not found, disabling WITH_CYCLES_DEVICE_METAL") - set(WITH_CYCLES_DEVICE_METAL OFF) - else() + if(METAL_LIBRARY) + if(EXISTS "${METAL_LIBRARY}/Headers/MTLFunctionStitching.h") + set(METAL_FOUND ON) + else() + message(STATUS "Metal version too old, must be SDK 12.0 or newer") + set(METAL_FOUND OFF) + endif() + endif() + + set_and_warn_library_found("Metal" METAL_FOUND WITH_CYCLES_DEVICE_METAL) + if(METAL_FOUND) message(STATUS "Found Metal: ${METAL_LIBRARY}") endif() endif() @@ -662,6 +662,8 @@ endif() if(WITH_CYCLES_DEVICE_ONEAPI) find_package(SYCL) find_package(LevelZero) + set_and_warn_library_found("oneAPI" SYCL_FOUND WITH_CYCLES_DEVICE_ONEAPI) + set_and_warn_library_found("Level Zero" LEVEL_ZERO_FOUND WITH_CYCLES_DEVICE_ONEAPI) if(SYCL_FOUND AND SYCL_VERSION VERSION_GREATER_EQUAL 6.0 AND LEVEL_ZERO_FOUND) message(STATUS "Found Level Zero: ${LEVEL_ZERO_LIBRARY}") @@ -674,9 +676,10 @@ if(WITH_CYCLES_DEVICE_ONEAPI) endif() if(NOT EXISTS ${OCLOC_INSTALL_DIR}) - message(STATUS "oneAPI ocloc not found in ${OCLOC_INSTALL_DIR}, disabling WITH_CYCLES_ONEAPI_BINARIES." + set(OCLOC_FOUND OFF) + message(STATUS "oneAPI ocloc not found in ${OCLOC_INSTALL_DIR}." " A different ocloc directory can be set using OCLOC_INSTALL_DIR cmake variable.") - set(WITH_CYCLES_ONEAPI_BINARIES OFF) + set_and_warn_library_found("ocloc" OCLOC_FOUND WITH_CYCLES_ONEAPI_BINARIES) endif() endif() else() -- cgit v1.2.3 From 04eab0fd01e8c416ce45c95b9e32db4e0ff03d7b Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Fri, 21 Oct 2022 12:48:17 -0600 Subject: deps_builder: expose FORCE_CHECK_HASH as an option The check was already there, but given it was not exposed as an option it didn't show up in my cmakecache and i got tired of having to lookup the exact name all the time. --- build_files/build_environment/cmake/options.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/build_files/build_environment/cmake/options.cmake b/build_files/build_environment/cmake/options.cmake index 6e5f9df20b4..9058e945f6d 100644 --- a/build_files/build_environment/cmake/options.cmake +++ b/build_files/build_environment/cmake/options.cmake @@ -3,6 +3,7 @@ if(WIN32) option(ENABLE_MINGW64 "Enable building of ffmpeg/iconv/libsndfile/fftw3 by installing mingw64" ON) endif() +option(FORCE_CHECK_HASH "Force a check of all hashses during CMake the configure phase" OFF) option(WITH_BOOST_PYTHON "Enable building of boost with python support" OFF) cmake_host_system_information(RESULT NUM_CORES QUERY NUMBER_OF_LOGICAL_CORES) set(MAKE_THREADS ${NUM_CORES} CACHE STRING "Number of threads to run make with") -- cgit v1.2.3 From ea571ddc29e4e7be441a9b58bef50190a4a35c04 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sat, 22 Oct 2022 02:51:52 +0200 Subject: Fix T101969: Crash when using large texture with nonstandard colorspace When the image colorspace is not data, linear or sRGB, the image will be converted to float (and colorspace-converted) during loading. However, if it also needs to be rescaled (due to exceeding the GPU texture size limit), the resizing assumed that it's still a byte texture. --- source/blender/imbuf/intern/util_gpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/imbuf/intern/util_gpu.c b/source/blender/imbuf/intern/util_gpu.c index dd509677d8d..5ed6b2b9843 100644 --- a/source/blender/imbuf/intern/util_gpu.c +++ b/source/blender/imbuf/intern/util_gpu.c @@ -174,6 +174,7 @@ static void *imb_gpu_get_data(const ImBuf *ibuf, /* Other colorspace, store as float texture to avoid precision loss. */ data_rect = MEM_mallocN(sizeof(float[4]) * ibuf->x * ibuf->y, __func__); *r_freedata = freedata = true; + is_float_rect = true; if (data_rect == NULL) { return NULL; -- cgit v1.2.3 From 59a0b49c100b8444a15f4713409004eade9fd321 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Fri, 21 Oct 2022 20:10:17 -0600 Subject: Video rendering: FFMpeg AV1 codec encoding support Previously, the Blender video renderer did not have support for encoding video to AV1 (not to be confused with the container AVI). The proposed solution is to leverage the existing FFMpeg renderer to encode to AV1. Note that avcodec_find_encoder(AV_CODEC_ID_AV1) usually returns "libaom-av1" which is the "reference implementation" for AV1 encoding (the default for FFMpeg, and is slow). "libsvtav1" is faster and preferred so there is extra handling when fetching the AV1 codec for encoding such that "libsvtav1" is used when possible. This commit should only affect the options available for video rendering, which includes the additional AV1 codec to choose from, and setting "-crf". Also note that the current release of FFMpeg for ArchLinux does not support "-crf" for "libsvtav1", but the equivalent option "-qp" is supported and used as a fallback when "libsvtav1" is used (as mentioned here: https://trac.ffmpeg.org/wiki/Encode/AV1#SVT-AV1 ). (Actually, both "-crf" and "-qp" is specified with the same value in the code. When a release of FFMpeg obtains support for "-crf" for "libsvtav1" is released, the code shouldn't be needed to change.) The usage of the AV1 codec should be very similar to the usage of the H264 codec, but is limited to the "mp4" and "mkv" containers. This patch pertains to the "VFX & Video" module, as its main purpose is to supplement the Video Sequencer tool with the additional AV1 codec for encoded video output. Differential Revision: https://developer.blender.org/D14920 Reviewed By: sergey , ISS, zeddb --- intern/ffmpeg/tests/ffmpeg_codecs.cc | 7 + release/scripts/startup/bl_ui/properties_output.py | 16 +- source/blender/blenkernel/BKE_writeffmpeg.h | 2 + source/blender/blenkernel/intern/image_format.cc | 7 +- source/blender/blenkernel/intern/writeavi.c | 3 +- source/blender/blenkernel/intern/writeffmpeg.c | 236 ++++++++++++++++++++- source/blender/makesdna/DNA_scene_types.h | 1 + source/blender/makesrna/intern/rna_scene.c | 1 + 8 files changed, 266 insertions(+), 7 deletions(-) diff --git a/intern/ffmpeg/tests/ffmpeg_codecs.cc b/intern/ffmpeg/tests/ffmpeg_codecs.cc index d0c40736884..e5c33202417 100644 --- a/intern/ffmpeg/tests/ffmpeg_codecs.cc +++ b/intern/ffmpeg/tests/ffmpeg_codecs.cc @@ -130,6 +130,7 @@ FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_DVVIDEO, AV_PIX_FMT_YUV420P) FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_MPEG1VIDEO, AV_PIX_FMT_YUV420P) FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_MPEG2VIDEO, AV_PIX_FMT_YUV420P) FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_FLV1, AV_PIX_FMT_YUV420P) +FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_AV1, AV_PIX_FMT_YUV420P) /* Audio codecs */ @@ -149,6 +150,12 @@ FFMPEG_TEST_VCODEC_NAME(libx264, AV_PIX_FMT_YUV420P) FFMPEG_TEST_VCODEC_NAME(libvpx, AV_PIX_FMT_YUV420P) FFMPEG_TEST_VCODEC_NAME(libopenjpeg, AV_PIX_FMT_YUV420P) FFMPEG_TEST_VCODEC_NAME(libxvid, AV_PIX_FMT_YUV420P) +/* aom's AV1 encoder is "libaom-av1". FFMPEG_TEST_VCODEC_NAME(libaom-av1, ...) + * will not work because the dash will not work with the test macro. */ +TEST(ffmpeg, libaom_av1_AV_PIX_FMT_YUV420P) +{ + EXPECT_TRUE(test_codec_video_by_name("libaom-av1", AV_PIX_FMT_YUV420P)); +} FFMPEG_TEST_ACODEC_NAME(libvorbis, AV_SAMPLE_FMT_FLTP) FFMPEG_TEST_ACODEC_NAME(libopus, AV_SAMPLE_FMT_FLT) FFMPEG_TEST_ACODEC_NAME(libmp3lame, AV_SAMPLE_FMT_FLTP) diff --git a/release/scripts/startup/bl_ui/properties_output.py b/release/scripts/startup/bl_ui/properties_output.py index ca0e698500e..61384f25afb 100644 --- a/release/scripts/startup/bl_ui/properties_output.py +++ b/release/scripts/startup/bl_ui/properties_output.py @@ -380,7 +380,14 @@ class RENDER_PT_encoding_video(RenderOutputButtonsPanel, Panel): layout = self.layout ffmpeg = context.scene.render.ffmpeg - needs_codec = ffmpeg.format in {'AVI', 'QUICKTIME', 'MKV', 'OGG', 'MPEG4', 'WEBM'} + needs_codec = ffmpeg.format in { + 'AVI', + 'QUICKTIME', + 'MKV', + 'OGG', + 'MPEG4', + 'WEBM' + } if needs_codec: layout.prop(ffmpeg, "codec") @@ -391,7 +398,12 @@ class RENDER_PT_encoding_video(RenderOutputButtonsPanel, Panel): layout.prop(ffmpeg, "use_lossless_output") # Output quality - use_crf = needs_codec and ffmpeg.codec in {'H264', 'MPEG4', 'WEBM'} + use_crf = needs_codec and ffmpeg.codec in { + 'H264', + 'MPEG4', + 'WEBM', + 'AV1' + } if use_crf: layout.prop(ffmpeg, "constant_rate_factor") diff --git a/source/blender/blenkernel/BKE_writeffmpeg.h b/source/blender/blenkernel/BKE_writeffmpeg.h index 736f7548bb4..cfe246eb470 100644 --- a/source/blender/blenkernel/BKE_writeffmpeg.h +++ b/source/blender/blenkernel/BKE_writeffmpeg.h @@ -27,6 +27,7 @@ enum { FFMPEG_OGG = 10, FFMPEG_INVALID = 11, FFMPEG_WEBM = 12, + FFMPEG_AV1 = 13, }; enum { @@ -38,6 +39,7 @@ enum { FFMPEG_PRESET_H264 = 5, FFMPEG_PRESET_THEORA = 6, FFMPEG_PRESET_XVID = 7, + FFMPEG_PRESET_AV1 = 8, }; struct RenderData; diff --git a/source/blender/blenkernel/intern/image_format.cc b/source/blender/blenkernel/intern/image_format.cc index 8d1aeac76fb..5b861eff166 100644 --- a/source/blender/blenkernel/intern/image_format.cc +++ b/source/blender/blenkernel/intern/image_format.cc @@ -201,6 +201,7 @@ bool BKE_imtype_is_movie(const char imtype) case R_IMF_IMTYPE_H264: case R_IMF_IMTYPE_THEORA: case R_IMF_IMTYPE_XVID: + case R_IMF_IMTYPE_AV1: return true; } return false; @@ -433,7 +434,8 @@ static bool do_add_image_extension(char *string, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, - R_IMF_IMTYPE_XVID)) { + R_IMF_IMTYPE_XVID, + R_IMF_IMTYPE_AV1)) { if (!BLI_path_extension_check(string, extension_test = ".png")) { extension = extension_test; } @@ -627,7 +629,8 @@ void BKE_image_format_to_imbuf(ImBuf *ibuf, const ImageFormatData *imf) R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, - R_IMF_IMTYPE_XVID)) { + R_IMF_IMTYPE_XVID, + R_IMF_IMTYPE_AV1)) { ibuf->ftype = IMB_FTYPE_PNG; if (imtype == R_IMF_IMTYPE_PNG) { diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index dbdf8cc395d..de2e196c163 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -122,7 +122,8 @@ bMovieHandle *BKE_movie_handle_get(const char imtype) R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_XVID, - R_IMF_IMTYPE_THEORA)) { + R_IMF_IMTYPE_THEORA, + R_IMF_IMTYPE_AV1)) { mh.start_movie = BKE_ffmpeg_start; mh.append_movie = BKE_ffmpeg_append; mh.end_movie = BKE_ffmpeg_end; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 99df07b6105..0d3a790ba00 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -299,6 +299,10 @@ static const char **get_file_extensions(int format) static const char *rv[] = {".webm", NULL}; return rv; } + case FFMPEG_AV1: { + static const char *rv[] = {".mp4", ".mkv", NULL}; + return rv; + } default: return NULL; } @@ -455,6 +459,204 @@ static AVRational calc_time_base(uint den, double num, int codec_id) return time_base; } +static const AVCodec *get_av1_encoder( + FFMpegContext *context, RenderData *rd, AVDictionary **opts, int rectx, int recty) +{ + /* There are three possible encoders for AV1: libaom-av1, librav1e, and libsvtav1. librav1e tends + * to give the best compression quality while libsvtav1 tends to be the fastest encoder. One of + * each will be picked based on the preset setting, and if a particular encoder is not available, + * then use the default returned by FFMpeg. */ + const AVCodec *codec = NULL; + switch (context->ffmpeg_preset) { + case FFM_PRESET_BEST: + /* Default to libaom-av1 for BEST preset due to it performing better than rav1e in terms of + * video quality (VMAF scores). Fallback to rav1e if libaom-av1 isn't available. */ + codec = avcodec_find_encoder_by_name("libaom-av1"); + if (!codec) { + codec = avcodec_find_encoder_by_name("librav1e"); + } + break; + case FFM_PRESET_REALTIME: + codec = avcodec_find_encoder_by_name("libsvtav1"); + break; + case FFM_PRESET_GOOD: + default: + codec = avcodec_find_encoder_by_name("libaom-av1"); + break; + } + + /* Use the default AV1 encoder if the specified encoder wasn't found. */ + if (!codec) { + codec = avcodec_find_encoder(AV_CODEC_ID_AV1); + } + + /* Apply AV1 encoder specific settings. */ + if (codec) { + if (strcmp(codec->name, "librav1e") == 0) { + /* Set "tiles" to 8 to enable multi-threaded encoding. */ + if (rd->threads > 8) { + ffmpeg_dict_set_int(opts, "tiles", rd->threads); + } + else { + ffmpeg_dict_set_int(opts, "tiles", 8); + } + + /* Use a reasonable speed setting based on preset. Speed ranges from 0-10. + * Must check context->ffmpeg_preset again in case this encoder was selected due to the + * absence of another. */ + switch (context->ffmpeg_preset) { + case FFM_PRESET_BEST: + ffmpeg_dict_set_int(opts, "speed", 4); + break; + case FFM_PRESET_REALTIME: + ffmpeg_dict_set_int(opts, "speed", 10); + break; + case FFM_PRESET_GOOD: + default: + ffmpeg_dict_set_int(opts, "speed", 6); + break; + } + if (context->ffmpeg_crf >= 0) { + /* librav1e does not use -crf, but uses -qp in the range of 0-255. Calculates the roughly + * equivalent float, and truncates it to an integer. */ + unsigned int qp_value = ((float)context->ffmpeg_crf) * 255.0F / 51.0F; + if (qp_value > 255) { + qp_value = 255; + } + ffmpeg_dict_set_int(opts, "qp", qp_value); + } + /* Set gop_size as rav1e's "--keyint". */ + char buffer[64]; + BLI_snprintf(buffer, sizeof(buffer), "keyint=%d", context->ffmpeg_gop_size); + av_dict_set(opts, "rav1e-params", buffer, 0); + } + else if (strcmp(codec->name, "libsvtav1") == 0) { + /* Set preset value based on ffmpeg_preset. + * Must check context->ffmpeg_preset again in case this encoder was selected due to the + * absence of another. */ + switch (context->ffmpeg_preset) { + case FFM_PRESET_REALTIME: + ffmpeg_dict_set_int(opts, "preset", 8); + break; + case FFM_PRESET_BEST: + ffmpeg_dict_set_int(opts, "preset", 3); + break; + case FFM_PRESET_GOOD: + default: + ffmpeg_dict_set_int(opts, "preset", 5); + break; + } + if (context->ffmpeg_crf >= 0) { + /* libsvtav1 does not support crf until FFmpeg builds since 2022-02-24, use qp as fallback. + */ + ffmpeg_dict_set_int(opts, "qp", context->ffmpeg_crf); + } + } + else if (strcmp(codec->name, "libaom-av1") == 0) { + /* Speed up libaom-av1 encoding by enabling multithreading and setting tiles. */ + ffmpeg_dict_set_int(opts, "row-mt", 1); + const char *tiles_string = NULL; + bool tiles_string_is_dynamic = false; + if (rd->threads > 0) { + /* See if threads is a square. */ + int threads_sqrt = sqrtf(rd->threads); + if (threads_sqrt < 4) { + /* Ensure a default minimum. */ + threads_sqrt = 4; + } + if (is_power_of_2_i(threads_sqrt) && threads_sqrt * threads_sqrt == rd->threads) { + /* Is a square num, therefore just do "sqrt x sqrt" for tiles parameter. */ + int digits = 0; + for (int t_sqrt_copy = threads_sqrt; t_sqrt_copy > 0; t_sqrt_copy /= 10) { + ++digits; + } + /* A char array need only an alignment of 1. */ + char *tiles_string_mut = (char *)calloc(digits * 2 + 2, 1); + BLI_snprintf(tiles_string_mut, digits * 2 + 2, "%dx%d", threads_sqrt, threads_sqrt); + tiles_string_is_dynamic = true; + tiles_string = tiles_string_mut; + } + else { + /* Is not a square num, set greater side based on longer side, or use a square if both + sides are equal. */ + int sqrt_p2 = power_of_2_min_i(threads_sqrt); + if (sqrt_p2 < 2) { + /* Ensure a default minimum. */ + sqrt_p2 = 2; + } + int sqrt_p2_next = power_of_2_min_i((int)rd->threads / sqrt_p2); + if (sqrt_p2_next < 1) { + sqrt_p2_next = 1; + } + if (sqrt_p2 > sqrt_p2_next) { + /* Ensure sqrt_p2_next is greater or equal to sqrt_p2. */ + int temp = sqrt_p2; + sqrt_p2 = sqrt_p2_next; + sqrt_p2_next = temp; + } + int combined_digits = 0; + for (int sqrt_p2_copy = sqrt_p2; sqrt_p2_copy > 0; sqrt_p2_copy /= 10) { + ++combined_digits; + } + for (int sqrt_p2_copy = sqrt_p2_next; sqrt_p2_copy > 0; sqrt_p2_copy /= 10) { + ++combined_digits; + } + /* A char array need only an alignment of 1. */ + char *tiles_string_mut = (char *)calloc(combined_digits + 2, 1); + if (rectx > recty) { + BLI_snprintf(tiles_string_mut, combined_digits + 2, "%dx%d", sqrt_p2_next, sqrt_p2); + } + else if (rectx < recty) { + BLI_snprintf(tiles_string_mut, combined_digits + 2, "%dx%d", sqrt_p2, sqrt_p2_next); + } + else { + BLI_snprintf(tiles_string_mut, combined_digits + 2, "%dx%d", sqrt_p2, sqrt_p2); + } + tiles_string_is_dynamic = true; + tiles_string = tiles_string_mut; + } + } + else { + /* Thread count unknown, default to 8. */ + if (rectx > recty) { + tiles_string = "4x2"; + } + else if (rectx < recty) { + tiles_string = "2x4"; + } + else { + tiles_string = "2x2"; + } + } + av_dict_set(opts, "tiles", tiles_string, 0); + if (tiles_string_is_dynamic) { + free((void *)tiles_string); + } + /* libaom-av1 uses "cpu-used" instead of "preset" for defining compression quality. + * This value is in a range from 0-8. 0 and 8 are extremes, but we will allow 8. + * Must check context->ffmpeg_preset again in case this encoder was selected due to the + * absence of another. */ + switch (context->ffmpeg_preset) { + case FFM_PRESET_REALTIME: + ffmpeg_dict_set_int(opts, "cpu-used", 8); + break; + case FFM_PRESET_BEST: + ffmpeg_dict_set_int(opts, "cpu-used", 4); + break; + case FFM_PRESET_GOOD: + default: + ffmpeg_dict_set_int(opts, "cpu-used", 6); + break; + } + + /* CRF related settings is similar to H264 for libaom-av1, so we will rely on those settings + * applied later. */ + } + } + + return codec; +} + /* prepare a video stream for the output file */ static AVStream *alloc_video_stream(FFMpegContext *context, @@ -480,7 +682,14 @@ static AVStream *alloc_video_stream(FFMpegContext *context, /* Set up the codec context */ - codec = avcodec_find_encoder(codec_id); + if (codec_id == AV_CODEC_ID_AV1) { + /* Use get_av1_encoder() to get the ideal (hopefully) encoder for AV1 based + * on given parameters, and also set up opts. */ + codec = get_av1_encoder(context, rd, &opts, rectx, recty); + } + else { + codec = avcodec_find_encoder(codec_id); + } if (!codec) { fprintf(stderr, "Couldn't find valid video codec\n"); context->video_codec = NULL; @@ -568,7 +777,9 @@ static AVStream *alloc_video_stream(FFMpegContext *context, default: printf("Unknown preset number %i, ignoring.\n", context->ffmpeg_preset); } - if (preset_name != NULL) { + /* "codec_id != AV_CODEC_ID_AV1" is required due to "preset" already being set by an AV1 codec. + */ + if (preset_name != NULL && codec_id != AV_CODEC_ID_AV1) { av_dict_set(&opts, "preset", preset_name, 0); } if (deadline_name != NULL) { @@ -951,6 +1162,9 @@ static int start_ffmpeg_impl(FFMpegContext *context, case FFMPEG_FLV: video_codec = AV_CODEC_ID_FLV1; break; + case FFMPEG_AV1: + video_codec = AV_CODEC_ID_AV1; + break; default: /* These containers are not restricted to any specific codec types. * Currently we expect these to be .avi, .mov, .mkv, and .mp4. @@ -1481,6 +1695,18 @@ void BKE_ffmpeg_preset_set(RenderData *rd, int preset) rd->ffcodecdata.rc_buffer_size = 224 * 8; rd->ffcodecdata.mux_packet_size = 2048; rd->ffcodecdata.mux_rate = 10080000; + break; + case FFMPEG_PRESET_AV1: + rd->ffcodecdata.type = FFMPEG_AV1; + rd->ffcodecdata.codec = AV_CODEC_ID_AV1; + rd->ffcodecdata.video_bitrate = 6000; + rd->ffcodecdata.gop_size = is_ntsc ? 18 : 15; + rd->ffcodecdata.rc_max_rate = 9000; + rd->ffcodecdata.rc_min_rate = 0; + rd->ffcodecdata.rc_buffer_size = 224 * 8; + rd->ffcodecdata.mux_packet_size = 2048; + rd->ffcodecdata.mux_rate = 10080000; + break; } } @@ -1521,6 +1747,12 @@ void BKE_ffmpeg_image_type_verify(RenderData *rd, const ImageFormatData *imf) audio = 1; } } + else if (imf->imtype == R_IMF_IMTYPE_AV1) { + if (rd->ffcodecdata.codec != AV_CODEC_ID_AV1) { + BKE_ffmpeg_preset_set(rd, FFMPEG_PRESET_AV1); + audio = 1; + } + } if (audio && rd->ffcodecdata.audio_codec < 0) { rd->ffcodecdata.audio_codec = AV_CODEC_ID_NONE; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 5fa5d4c7787..28359038be5 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -472,6 +472,7 @@ typedef struct ImageFormatData { #define R_IMF_IMTYPE_THEORA 33 #define R_IMF_IMTYPE_PSD 34 #define R_IMF_IMTYPE_WEBP 35 +#define R_IMF_IMTYPE_AV1 36 #define R_IMF_IMTYPE_INVALID 255 diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 0eb168ecd8e..58455ff7de5 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -5928,6 +5928,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna) {FFMPEG_MKV, "MKV", 0, "Matroska", ""}, {FFMPEG_FLV, "FLASH", 0, "Flash", ""}, {FFMPEG_WEBM, "WEBM", 0, "WebM", ""}, + {AV_CODEC_ID_AV1, "AV1", 0, "AV1", ""}, {0, NULL, 0, NULL, NULL}, }; -- cgit v1.2.3 From 23c05a916c286a6ec9149b69f7ca5651c2522136 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 22 Oct 2022 16:49:05 +1100 Subject: GHOST/Wayland: support changing seat capabilities at run-time --- intern/ghost/intern/GHOST_SystemWayland.cpp | 162 +++++++++++++++++++--------- 1 file changed, 114 insertions(+), 48 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 68ad028631c..6eef9a48e07 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -84,6 +84,10 @@ static void keyboard_handle_key_repeat_cancel(struct GWL_Seat *seat); static void output_handle_done(void *data, struct wl_output *wl_output); +static void gwl_seat_capability_pointer_disable(GWL_Seat *seat); +static void gwl_seat_capability_keyboard_disable(GWL_Seat *seat); +static void gwl_seat_capability_touch_disable(GWL_Seat *seat); + /* -------------------------------------------------------------------- */ /** \name Local Defines * @@ -808,28 +812,14 @@ static void display_destroy(GWL_Display *display) munmap(seat->cursor.custom_data, seat->cursor.custom_data_size); } - if (seat->wl_pointer) { - if (seat->cursor.wl_surface) { - wl_surface_destroy(seat->cursor.wl_surface); - } - if (seat->cursor.wl_theme) { - wl_cursor_theme_destroy(seat->cursor.wl_theme); - } - if (seat->wl_pointer) { - wl_pointer_destroy(seat->wl_pointer); - } - } - - if (seat->wl_touch) { - wl_touch_destroy(seat->wl_touch); - } - - if (seat->wl_keyboard) { - if (seat->key_repeat.timer) { - keyboard_handle_key_repeat_cancel(seat); - } - wl_keyboard_destroy(seat->wl_keyboard); - } + /* Disable all capabilities as a way to free: + * - `seat.wl_pointer` (and related cursor variables). + * - `seat.wl_touch`. + * - `seat.wl_keyboard`. + */ + gwl_seat_capability_pointer_disable(seat); + gwl_seat_capability_keyboard_disable(seat); + gwl_seat_capability_touch_disable(seat); /* Un-referencing checks for NULL case. */ xkb_state_unref(seat->xkb_state); @@ -3304,6 +3294,83 @@ static const struct zwp_primary_selection_source_v1_listener primary_selection_s static CLG_LogRef LOG_WL_SEAT = {"ghost.wl.handle.seat"}; #define LOG (&LOG_WL_SEAT) +static void gwl_seat_capability_pointer_enable(GWL_Seat *seat) +{ + if (seat->wl_pointer) { + return; + } + seat->wl_pointer = wl_seat_get_pointer(seat->wl_seat); + seat->cursor.wl_surface = wl_compositor_create_surface(seat->system->wl_compositor()); + seat->cursor.visible = true; + seat->cursor.wl_buffer = nullptr; + if (!get_cursor_settings(seat->cursor.theme_name, seat->cursor.theme_size)) { + seat->cursor.theme_name = std::string(); + seat->cursor.theme_size = default_cursor_size; + } + wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat); + + wl_surface_add_listener(seat->cursor.wl_surface, &cursor_surface_listener, seat); + ghost_wl_surface_tag_cursor_pointer(seat->cursor.wl_surface); +} + +static void gwl_seat_capability_pointer_disable(GWL_Seat *seat) +{ + if (!seat->wl_pointer) { + return; + } + if (seat->cursor.wl_surface) { + wl_surface_destroy(seat->cursor.wl_surface); + seat->cursor.wl_surface = nullptr; + } + if (seat->cursor.wl_theme) { + wl_cursor_theme_destroy(seat->cursor.wl_theme); + seat->cursor.wl_theme = nullptr; + } + + wl_pointer_destroy(seat->wl_pointer); + seat->wl_pointer = nullptr; +} + +static void gwl_seat_capability_keyboard_enable(GWL_Seat *seat) +{ + if (seat->wl_keyboard) { + return; + } + seat->wl_keyboard = wl_seat_get_keyboard(seat->wl_seat); + wl_keyboard_add_listener(seat->wl_keyboard, &keyboard_listener, seat); +} + +static void gwl_seat_capability_keyboard_disable(GWL_Seat *seat) +{ + if (!seat->wl_keyboard) { + return; + } + if (seat->key_repeat.timer) { + keyboard_handle_key_repeat_cancel(seat); + } + wl_keyboard_destroy(seat->wl_keyboard); + seat->wl_keyboard = nullptr; +} + +static void gwl_seat_capability_touch_enable(GWL_Seat *seat) +{ + if (seat->wl_touch) { + return; + } + seat->wl_touch = wl_seat_get_touch(seat->wl_seat); + wl_touch_set_user_data(seat->wl_touch, seat); + wl_touch_add_listener(seat->wl_touch, &touch_seat_listener, seat); +} + +static void gwl_seat_capability_touch_disable(GWL_Seat *seat) +{ + if (!seat->wl_touch) { + return; + } + wl_touch_destroy(seat->wl_touch); + seat->wl_touch = nullptr; +} + static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, const uint32_t capabilities) @@ -3316,44 +3383,43 @@ static void seat_handle_capabilities(void *data, (capabilities & WL_SEAT_CAPABILITY_TOUCH) != 0); GWL_Seat *seat = static_cast(data); - seat->wl_pointer = nullptr; - seat->wl_keyboard = nullptr; + GHOST_ASSERT(seat->wl_seat == wl_seat, "Seat mismatch"); if (capabilities & WL_SEAT_CAPABILITY_POINTER) { - seat->wl_pointer = wl_seat_get_pointer(wl_seat); - seat->cursor.wl_surface = wl_compositor_create_surface(seat->system->wl_compositor()); - seat->cursor.visible = true; - seat->cursor.wl_buffer = nullptr; - if (!get_cursor_settings(seat->cursor.theme_name, seat->cursor.theme_size)) { - seat->cursor.theme_name = std::string(); - seat->cursor.theme_size = default_cursor_size; - } - wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, data); + gwl_seat_capability_pointer_enable(seat); + } + else { + gwl_seat_capability_pointer_disable(seat); + } - wl_surface_add_listener(seat->cursor.wl_surface, &cursor_surface_listener, data); - ghost_wl_surface_tag_cursor_pointer(seat->cursor.wl_surface); + if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { + gwl_seat_capability_keyboard_enable(seat); + } + else { + gwl_seat_capability_keyboard_disable(seat); } if (capabilities & WL_SEAT_CAPABILITY_TOUCH) { - seat->wl_touch = wl_seat_get_touch(wl_seat); - wl_touch_set_user_data(seat->wl_touch, seat); - wl_touch_add_listener(seat->wl_touch, &touch_seat_listener, seat); + gwl_seat_capability_touch_enable(seat); } - - if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { - seat->wl_keyboard = wl_seat_get_keyboard(wl_seat); - wl_keyboard_add_listener(seat->wl_keyboard, &keyboard_listener, data); + else { + gwl_seat_capability_touch_disable(seat); } + /* TODO(@campbellbarton): this could be moved out elsewhere. */ if (seat->system) { zwp_primary_selection_device_manager_v1 *primary_selection_device_manager = seat->system->wl_primary_selection_manager(); - seat->primary_selection_device = zwp_primary_selection_device_manager_v1_get_device( - primary_selection_device_manager, seat->wl_seat); - - zwp_primary_selection_device_v1_add_listener(seat->primary_selection_device, - &primary_selection_device_listener, - &seat->primary_selection); + if (primary_selection_device_manager) { + if (seat->primary_selection_device == nullptr) { + seat->primary_selection_device = zwp_primary_selection_device_manager_v1_get_device( + primary_selection_device_manager, seat->wl_seat); + + zwp_primary_selection_device_v1_add_listener(seat->primary_selection_device, + &primary_selection_device_listener, + &seat->primary_selection); + } + } } } -- cgit v1.2.3 From e54ea0f90ee22396147ad6d17d0263bf6b965fd7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 22 Oct 2022 16:49:07 +1100 Subject: Cleanup: use wl_/wp_ prefix to match native Wayland types --- intern/ghost/intern/GHOST_SystemWayland.cpp | 166 ++++++++++++++-------------- intern/ghost/intern/GHOST_SystemWayland.h | 2 +- 2 files changed, 85 insertions(+), 83 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 6eef9a48e07..39f392e62b9 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -522,7 +522,7 @@ struct GWL_PrimarySelection_DataOffer { }; struct GWL_PrimarySelection_DataSource { - struct zwp_primary_selection_source_v1 *wl_source = nullptr; + struct zwp_primary_selection_source_v1 *wp_source = nullptr; GWL_SimpleBuffer buffer_out; }; @@ -553,8 +553,8 @@ static void gwl_primary_selection_discard_source(GWL_PrimarySelection *primary) return; } gwl_simple_buffer_free_data(&data_source->buffer_out); - if (data_source->wl_source) { - zwp_primary_selection_source_v1_destroy(data_source->wl_source); + if (data_source->wp_source) { + zwp_primary_selection_source_v1_destroy(data_source->wp_source); } delete primary->data_source; primary->data_source = nullptr; @@ -568,7 +568,7 @@ struct GWL_Seat { struct wl_pointer *wl_pointer = nullptr; struct wl_touch *wl_touch = nullptr; struct wl_keyboard *wl_keyboard = nullptr; - struct zwp_tablet_seat_v2 *tablet_seat = nullptr; + struct zwp_tablet_seat_v2 *wp_tablet_seat = nullptr; /** All currently active tablet tools (needed for changing the cursor). */ std::unordered_set tablet_tools; @@ -592,9 +592,9 @@ struct GWL_Seat { struct GWL_Cursor cursor; - struct zwp_relative_pointer_v1 *relative_pointer = nullptr; - struct zwp_locked_pointer_v1 *locked_pointer = nullptr; - struct zwp_confined_pointer_v1 *confined_pointer = nullptr; + struct zwp_relative_pointer_v1 *wp_relative_pointer = nullptr; + struct zwp_locked_pointer_v1 *wp_locked_pointer = nullptr; + struct zwp_confined_pointer_v1 *wp_confined_pointer = nullptr; struct xkb_context *xkb_context = nullptr; @@ -637,7 +637,7 @@ struct GWL_Seat { struct wl_surface *wl_surface_focus_dnd = nullptr; - struct wl_data_device *data_device = nullptr; + struct wl_data_device *wl_data_device = nullptr; /** Drag & Drop. */ struct GWL_DataOffer *data_offer_dnd = nullptr; std::mutex data_offer_dnd_mutex; @@ -649,7 +649,7 @@ struct GWL_Seat { struct GWL_DataSource *data_source = nullptr; std::mutex data_source_mutex; - struct zwp_primary_selection_device_v1 *primary_selection_device = nullptr; + struct zwp_primary_selection_device_v1 *wp_primary_selection_device = nullptr; struct GWL_PrimarySelection primary_selection; /** Last device that was active. */ @@ -679,12 +679,12 @@ struct GWL_Display { std::vector outputs; std::vector seats; - struct wl_data_device_manager *data_device_manager = nullptr; - struct zwp_tablet_manager_v2 *tablet_manager = nullptr; - struct zwp_relative_pointer_manager_v1 *relative_pointer_manager = nullptr; - struct zwp_pointer_constraints_v1 *pointer_constraints = nullptr; + struct wl_data_device_manager *wl_data_device_manager = nullptr; + struct zwp_tablet_manager_v2 *wp_tablet_manager = nullptr; + struct zwp_relative_pointer_manager_v1 *wp_relative_pointer_manager = nullptr; + struct zwp_pointer_constraints_v1 *wp_pointer_constraints = nullptr; - struct zwp_primary_selection_device_manager_v1 *primary_selection_device_manager = nullptr; + struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_device_manager = nullptr; GWL_SimpleBuffer clipboard; GWL_SimpleBuffer clipboard_primary; @@ -744,12 +744,12 @@ static GWL_SeatStatePointer *seat_state_pointer_from_cursor_surface(GWL_Seat *se static void display_destroy(GWL_Display *display) { - if (display->data_device_manager) { - wl_data_device_manager_destroy(display->data_device_manager); + if (display->wl_data_device_manager) { + wl_data_device_manager_destroy(display->wl_data_device_manager); } - if (display->tablet_manager) { - zwp_tablet_manager_v2_destroy(display->tablet_manager); + if (display->wp_tablet_manager) { + zwp_tablet_manager_v2_destroy(display->wp_tablet_manager); } for (GWL_Output *output : display->outputs) { @@ -800,12 +800,12 @@ static void display_destroy(GWL_Display *display) gwl_primary_selection_discard_source(primary); } - if (seat->primary_selection_device) { - zwp_primary_selection_device_v1_destroy(seat->primary_selection_device); + if (seat->wp_primary_selection_device) { + zwp_primary_selection_device_v1_destroy(seat->wp_primary_selection_device); } - if (seat->data_device) { - wl_data_device_release(seat->data_device); + if (seat->wl_data_device) { + wl_data_device_release(seat->wl_data_device); } if (seat->cursor.custom_data) { @@ -836,16 +836,16 @@ static void display_destroy(GWL_Display *display) wl_shm_destroy(display->wl_shm); } - if (display->relative_pointer_manager) { - zwp_relative_pointer_manager_v1_destroy(display->relative_pointer_manager); + if (display->wp_relative_pointer_manager) { + zwp_relative_pointer_manager_v1_destroy(display->wp_relative_pointer_manager); } - if (display->pointer_constraints) { - zwp_pointer_constraints_v1_destroy(display->pointer_constraints); + if (display->wp_pointer_constraints) { + zwp_pointer_constraints_v1_destroy(display->wp_pointer_constraints); } - if (display->primary_selection_device_manager) { - zwp_primary_selection_device_manager_v1_destroy(display->primary_selection_device_manager); + if (display->wp_primary_selection_device_manager) { + zwp_primary_selection_device_manager_v1_destroy(display->wp_primary_selection_device_manager); } if (display->wl_compositor) { @@ -1033,9 +1033,9 @@ static int pointer_axis_as_index(const uint32_t axis) } } -static GHOST_TTabletMode tablet_tool_map_type(enum zwp_tablet_tool_v2_type wl_tablet_tool_type) +static GHOST_TTabletMode tablet_tool_map_type(enum zwp_tablet_tool_v2_type wp_tablet_tool_type) { - switch (wl_tablet_tool_type) { + switch (wp_tablet_tool_type) { case ZWP_TABLET_TOOL_V2_TYPE_ERASER: { return GHOST_kTabletModeEraser; } @@ -3273,7 +3273,7 @@ static void primary_selection_source_cancelled(void *data, GWL_PrimarySelection *primary = static_cast(data); - if (source == primary->data_source->wl_source) { + if (source == primary->data_source->wp_source) { gwl_primary_selection_discard_source(primary); } } @@ -3409,13 +3409,13 @@ static void seat_handle_capabilities(void *data, /* TODO(@campbellbarton): this could be moved out elsewhere. */ if (seat->system) { zwp_primary_selection_device_manager_v1 *primary_selection_device_manager = - seat->system->wl_primary_selection_manager(); + seat->system->wp_primary_selection_manager(); if (primary_selection_device_manager) { - if (seat->primary_selection_device == nullptr) { - seat->primary_selection_device = zwp_primary_selection_device_manager_v1_get_device( + if (seat->wp_primary_selection_device == nullptr) { + seat->wp_primary_selection_device = zwp_primary_selection_device_manager_v1_get_device( primary_selection_device_manager, seat->wl_seat); - zwp_primary_selection_device_v1_add_listener(seat->primary_selection_device, + zwp_primary_selection_device_v1_add_listener(seat->wp_primary_selection_device, &primary_selection_device_listener, &seat->primary_selection); } @@ -3776,23 +3776,23 @@ static void global_handle_add(void *data, wl_registry_bind(wl_registry, name, &wl_shm_interface, 1)); } else if (STREQ(interface, wl_data_device_manager_interface.name)) { - display->data_device_manager = static_cast( + display->wl_data_device_manager = static_cast( wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 3)); } else if (STREQ(interface, zwp_tablet_manager_v2_interface.name)) { - display->tablet_manager = static_cast( + display->wp_tablet_manager = static_cast( wl_registry_bind(wl_registry, name, &zwp_tablet_manager_v2_interface, 1)); } else if (STREQ(interface, zwp_relative_pointer_manager_v1_interface.name)) { - display->relative_pointer_manager = static_cast( + display->wp_relative_pointer_manager = static_cast( wl_registry_bind(wl_registry, name, &zwp_relative_pointer_manager_v1_interface, 1)); } else if (STREQ(interface, zwp_pointer_constraints_v1_interface.name)) { - display->pointer_constraints = static_cast( + display->wp_pointer_constraints = static_cast( wl_registry_bind(wl_registry, name, &zwp_pointer_constraints_v1_interface, 1)); } else if (!strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name)) { - display->primary_selection_device_manager = + display->wp_primary_selection_device_manager = static_cast(wl_registry_bind( wl_registry, name, &zwp_primary_selection_device_manager_v1_interface, 1)); } @@ -3915,19 +3915,19 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di } /* Register data device per seat for IPC between Wayland clients. */ - if (display_->data_device_manager) { + if (display_->wl_data_device_manager) { for (GWL_Seat *seat : display_->seats) { - seat->data_device = wl_data_device_manager_get_data_device(display_->data_device_manager, - seat->wl_seat); - wl_data_device_add_listener(seat->data_device, &data_device_listener, seat); + seat->wl_data_device = wl_data_device_manager_get_data_device( + display_->wl_data_device_manager, seat->wl_seat); + wl_data_device_add_listener(seat->wl_data_device, &data_device_listener, seat); } } - if (display_->tablet_manager) { + if (display_->wp_tablet_manager) { for (GWL_Seat *seat : display_->seats) { - seat->tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(display_->tablet_manager, - seat->wl_seat); - zwp_tablet_seat_v2_add_listener(seat->tablet_seat, &tablet_seat_listener, seat); + seat->wp_tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(display_->wp_tablet_manager, + seat->wl_seat); + zwp_tablet_seat_v2_add_listener(seat->wp_tablet_seat, &tablet_seat_listener, seat); } } } @@ -4075,7 +4075,7 @@ char *GHOST_SystemWayland::getClipboard(bool selection) const static void system_clipboard_put_primary_selection(GWL_Display *display, const char *buffer) { - if (!display->primary_selection_device_manager) { + if (!display->wp_primary_selection_device_manager) { return; } GWL_Seat *seat = display->seats[0]; @@ -4091,19 +4091,19 @@ static void system_clipboard_put_primary_selection(GWL_Display *display, const c /* Copy buffer. */ gwl_simple_buffer_set_from_string(&data_source->buffer_out, buffer); - data_source->wl_source = zwp_primary_selection_device_manager_v1_create_source( - display->primary_selection_device_manager); + data_source->wp_source = zwp_primary_selection_device_manager_v1_create_source( + display->wp_primary_selection_device_manager); zwp_primary_selection_source_v1_add_listener( - data_source->wl_source, &primary_selection_source_listener, primary); + data_source->wp_source, &primary_selection_source_listener, primary); for (const std::string &type : mime_send) { - zwp_primary_selection_source_v1_offer(data_source->wl_source, type.c_str()); + zwp_primary_selection_source_v1_offer(data_source->wp_source, type.c_str()); } - if (seat->primary_selection_device) { + if (seat->wp_primary_selection_device) { zwp_primary_selection_device_v1_set_selection( - seat->primary_selection_device, data_source->wl_source, seat->data_source_serial); + seat->wp_primary_selection_device, data_source->wp_source, seat->data_source_serial); } } @@ -4118,7 +4118,8 @@ static void system_clipboard_put(GWL_Display *display, const char *buffer) /* Copy buffer. */ gwl_simple_buffer_set_from_string(&data_source->buffer_out, buffer); - data_source->wl_source = wl_data_device_manager_create_data_source(display->data_device_manager); + data_source->wl_source = wl_data_device_manager_create_data_source( + display->wl_data_device_manager); wl_data_source_add_listener(data_source->wl_source, &data_source_listener, seat); @@ -4126,15 +4127,15 @@ static void system_clipboard_put(GWL_Display *display, const char *buffer) wl_data_source_offer(data_source->wl_source, type.c_str()); } - if (seat->data_device) { + if (seat->wl_data_device) { wl_data_device_set_selection( - seat->data_device, data_source->wl_source, seat->data_source_serial); + seat->wl_data_device, data_source->wl_source, seat->data_source_serial); } } void GHOST_SystemWayland::putClipboard(const char *buffer, bool selection) const { - if (UNLIKELY(!display_->data_device_manager || display_->seats.empty())) { + if (UNLIKELY(!display_->wl_data_device_manager || display_->seats.empty())) { return; } @@ -4171,7 +4172,7 @@ static GHOST_TSuccess setCursorPositionClientRelative_impl(GWL_Seat *seat, /* NOTE: WAYLAND doesn't support warping the cursor. * However when grab is enabled, we already simulate a cursor location * so that can be set to a new location. */ - if (!seat->relative_pointer) { + if (!seat->wp_relative_pointer) { return GHOST_kFailure; } const wl_fixed_t scale = win->scale(); @@ -4886,9 +4887,9 @@ wl_compositor *GHOST_SystemWayland::wl_compositor() return display_->wl_compositor; } -struct zwp_primary_selection_device_manager_v1 *GHOST_SystemWayland::wl_primary_selection_manager() +struct zwp_primary_selection_device_manager_v1 *GHOST_SystemWayland::wp_primary_selection_manager() { - return display_->primary_selection_device_manager; + return display_->wp_primary_selection_device_manager; } #ifdef WITH_GHOST_WAYLAND_LIBDECOR @@ -4980,7 +4981,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod const int scale) { /* Ignore, if the required protocols are not supported. */ - if (UNLIKELY(!display_->relative_pointer_manager || !display_->pointer_constraints)) { + if (UNLIKELY(!display_->wp_relative_pointer_manager || !display_->wp_pointer_constraints)) { return GHOST_kFailure; } @@ -5019,11 +5020,11 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod * in this case disable the current locks as it makes logic confusing, * postpone changing the cursor to avoid flickering. */ if (!grab_state_next.use_lock) { - if (seat->relative_pointer) { - zwp_relative_pointer_v1_destroy(seat->relative_pointer); - seat->relative_pointer = nullptr; + if (seat->wp_relative_pointer) { + zwp_relative_pointer_v1_destroy(seat->wp_relative_pointer); + seat->wp_relative_pointer = nullptr; } - if (seat->locked_pointer) { + if (seat->wp_locked_pointer) { /* Potentially add a motion event so the application has updated X/Y coordinates. */ int32_t xy_motion[2] = {0, 0}; bool xy_motion_create_event = false; @@ -5052,7 +5053,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod seat->pointer.xy[0] = xy_next[0]; seat->pointer.xy[1] = xy_next[1]; - zwp_locked_pointer_v1_set_cursor_position_hint(seat->locked_pointer, UNPACK2(xy_next)); + zwp_locked_pointer_v1_set_cursor_position_hint(seat->wp_locked_pointer, UNPACK2(xy_next)); wl_surface_commit(wl_surface); } else if (mode_current == GHOST_kGrabHide) { @@ -5062,7 +5063,8 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod wl_fixed_from_int(init_grab_xy[0]) / scale, wl_fixed_from_int(init_grab_xy[1]) / scale, }; - zwp_locked_pointer_v1_set_cursor_position_hint(seat->locked_pointer, UNPACK2(xy_next)); + zwp_locked_pointer_v1_set_cursor_position_hint(seat->wp_locked_pointer, + UNPACK2(xy_next)); wl_surface_commit(wl_surface); /* NOTE(@campbellbarton): The new cursor position is a hint, @@ -5076,7 +5078,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod #ifdef USE_GNOME_CONFINE_HACK else if (mode_current == GHOST_kGrabNormal) { if (was_software_confine) { - zwp_locked_pointer_v1_set_cursor_position_hint(seat->locked_pointer, + zwp_locked_pointer_v1_set_cursor_position_hint(seat->wp_locked_pointer, UNPACK2(seat->pointer.xy)); wl_surface_commit(wl_surface); } @@ -5092,15 +5094,15 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod GHOST_TABLET_DATA_NONE)); } - zwp_locked_pointer_v1_destroy(seat->locked_pointer); - seat->locked_pointer = nullptr; + zwp_locked_pointer_v1_destroy(seat->wp_locked_pointer); + seat->wp_locked_pointer = nullptr; } } if (!grab_state_next.use_confine) { - if (seat->confined_pointer) { - zwp_confined_pointer_v1_destroy(seat->confined_pointer); - seat->confined_pointer = nullptr; + if (seat->wp_confined_pointer) { + zwp_confined_pointer_v1_destroy(seat->wp_confined_pointer); + seat->wp_confined_pointer = nullptr; } } @@ -5111,12 +5113,12 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod * possible to support #GHOST_kGrabWrap by pragmatically settings it's coordinates. * An alternative could be to draw the cursor in software (and hide the real cursor), * or just accept a locked cursor on WAYLAND. */ - seat->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer( - display_->relative_pointer_manager, seat->wl_pointer); + seat->wp_relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer( + display_->wp_relative_pointer_manager, seat->wl_pointer); zwp_relative_pointer_v1_add_listener( - seat->relative_pointer, &relative_pointer_listener, seat); - seat->locked_pointer = zwp_pointer_constraints_v1_lock_pointer( - display_->pointer_constraints, + seat->wp_relative_pointer, &relative_pointer_listener, seat); + seat->wp_locked_pointer = zwp_pointer_constraints_v1_lock_pointer( + display_->wp_pointer_constraints, wl_surface, seat->wl_pointer, nullptr, @@ -5133,8 +5135,8 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod } else if (grab_state_next.use_confine) { if (!grab_state_prev.use_confine) { - seat->confined_pointer = zwp_pointer_constraints_v1_confine_pointer( - display_->pointer_constraints, + seat->wp_confined_pointer = zwp_pointer_constraints_v1_confine_pointer( + display_->wp_pointer_constraints, wl_surface, seat->wl_pointer, nullptr, diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index 23ffabf739e..c19791fd792 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -158,7 +158,7 @@ class GHOST_SystemWayland : public GHOST_System { struct wl_display *wl_display(); struct wl_compositor *wl_compositor(); - struct zwp_primary_selection_device_manager_v1 *wl_primary_selection_manager(); + struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_manager(); #ifdef WITH_GHOST_WAYLAND_LIBDECOR libdecor *libdecor_context(); -- cgit v1.2.3 From 8bb211a771642144ac75ba6be0c1897c836a6276 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 22 Oct 2022 16:49:09 +1100 Subject: GHOST/Wayland: multi-touch gesture support Add support for zoom & rotate gestures, hold and swipe may be used in the future although swipe maps to 2D smooth-scroll for Gnome & KDE. Tested to work with Apple track-pad & Wacom tablet on Gnome & KDE. --- intern/ghost/CMakeLists.txt | 4 + intern/ghost/intern/GHOST_SystemWayland.cpp | 322 +++++++++++++++++++++++++++- intern/ghost/intern/GHOST_SystemWayland.h | 1 + 3 files changed, 325 insertions(+), 2 deletions(-) diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index c05f2a327b1..fb10530bfae 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -372,6 +372,10 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND) generate_protocol_bindings( "${WAYLAND_PROTOCOLS_DIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml" ) + # Pointer-gestures (multi-touch). + generate_protocol_bindings( + "${WAYLAND_PROTOCOLS_DIR}/unstable/pointer-gestures/pointer-gestures-unstable-v1.xml" + ) # Tablet. generate_protocol_bindings( "${WAYLAND_PROTOCOLS_DIR}/unstable/tablet/tablet-unstable-v2.xml" diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 39f392e62b9..442e51d4f7c 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -51,6 +51,7 @@ /* Generated by `wayland-scanner`. */ #include +#include #include #include #include @@ -461,6 +462,39 @@ struct GWL_SeatStatePointerScroll { enum wl_pointer_axis_source axis_source = WL_POINTER_AXIS_SOURCE_WHEEL; }; +/** + * Utility struct to access rounded values from a scaled `wl_fixed_t`, + * without loosing information. + * + * As the rounded result is rounded to a lower precision integer, + * the high precision value is accumulated and converted to an integer to + * prevent the accumulation of rounded values giving an inaccurate result. + * + * \note This is simple but doesn't read well when expanded multiple times inline. + */ +struct GWL_ScaledFixedT { + wl_fixed_t value = 0; + wl_fixed_t factor = 1; +}; + +static int gwl_scaled_fixed_t_add_and_calc_rounded_delta(GWL_ScaledFixedT *sf, + const wl_fixed_t add) +{ + const int result_prev = wl_fixed_to_int(sf->value * sf->factor); + sf->value += add; + const int result_curr = wl_fixed_to_int(sf->value * sf->factor); + return result_curr - result_prev; +} + +/** + * Gesture state. + * This is needed so the gesture values can be converted to deltas. + */ +struct GWL_SeatStatePointerGesture_Pinch { + GWL_ScaledFixedT scale; + GWL_ScaledFixedT rotation; +}; + /** * State of the keyboard (in #GWL_Seat). */ @@ -570,6 +604,10 @@ struct GWL_Seat { struct wl_keyboard *wl_keyboard = nullptr; struct zwp_tablet_seat_v2 *wp_tablet_seat = nullptr; + struct zwp_pointer_gesture_hold_v1 *wp_pointer_gesture_hold = nullptr; + struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch = nullptr; + struct zwp_pointer_gesture_swipe_v1 *wp_pointer_gesture_swipe = nullptr; + /** All currently active tablet tools (needed for changing the cursor). */ std::unordered_set tablet_tools; @@ -578,6 +616,7 @@ struct GWL_Seat { GWL_SeatStatePointer pointer; GWL_SeatStatePointerScroll pointer_scroll; + GWL_SeatStatePointerGesture_Pinch pointer_gesture_pinch; /** Mostly this can be interchanged with `pointer` however it can't be locked/confined. */ GWL_SeatStatePointer tablet; @@ -683,6 +722,7 @@ struct GWL_Display { struct zwp_tablet_manager_v2 *wp_tablet_manager = nullptr; struct zwp_relative_pointer_manager_v1 *wp_relative_pointer_manager = nullptr; struct zwp_pointer_constraints_v1 *wp_pointer_constraints = nullptr; + struct zwp_pointer_gestures_v1 *wp_pointer_gestures = nullptr; struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_device_manager = nullptr; @@ -844,8 +884,8 @@ static void display_destroy(GWL_Display *display) zwp_pointer_constraints_v1_destroy(display->wp_pointer_constraints); } - if (display->wp_primary_selection_device_manager) { - zwp_primary_selection_device_manager_v1_destroy(display->wp_primary_selection_device_manager); + if (display->wp_pointer_gestures) { + zwp_pointer_gestures_v1_destroy(display->wp_pointer_gestures); } if (display->wl_compositor) { @@ -2269,6 +2309,223 @@ static const struct wl_pointer_listener pointer_listener = { /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Listener (Pointer Gesture: Hold), #zwp_pointer_gesture_hold_v1_listener + * \{ */ + +static CLG_LogRef LOG_WL_POINTER_GESTURE_HOLD = {"ghost.wl.handle.pointer_gesture.hold"}; +#define LOG (&LOG_WL_POINTER_GESTURE_HOLD) + +static void gesture_hold_handle_begin( + void * /*data*/, + struct zwp_pointer_gesture_hold_v1 * /*zwp_pointer_gesture_hold_v1*/, + uint32_t /*serial*/, + uint32_t /*time*/, + struct wl_surface * /*surface*/, + uint32_t fingers) +{ + CLOG_INFO(LOG, 2, "begin (fingers=%u)", fingers); +} + +static void gesture_hold_handle_end( + void * /*data*/, + struct zwp_pointer_gesture_hold_v1 * /*zwp_pointer_gesture_hold_v1*/, + uint32_t /*serial*/, + uint32_t /*time*/, + int32_t cancelled) +{ + CLOG_INFO(LOG, 2, "end (cancelled=%i)", cancelled); +} + +static const struct zwp_pointer_gesture_hold_v1_listener gesture_hold_listener = { + gesture_hold_handle_begin, + gesture_hold_handle_end, +}; + +#undef LOG + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Listener (Pointer Gesture: Pinch), #zwp_pointer_gesture_pinch_v1_listener + * \{ */ + +static CLG_LogRef LOG_WL_POINTER_GESTURE_PINCH = {"ghost.wl.handle.pointer_gesture.pinch"}; +#define LOG (&LOG_WL_POINTER_GESTURE_PINCH) + +static void gesture_pinch_handle_begin(void *data, + struct zwp_pointer_gesture_pinch_v1 * /*pinch*/, + uint32_t /*serial*/, + uint32_t /*time*/, + struct wl_surface * /*surface*/, + uint32_t fingers) +{ + CLOG_INFO(LOG, 2, "begin (fingers=%u)", fingers); + GWL_Seat *seat = static_cast(data); + /* Reset defaults. */ + seat->pointer_gesture_pinch = GWL_SeatStatePointerGesture_Pinch{}; + + GHOST_WindowWayland *win = nullptr; + if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { + win = ghost_wl_surface_user_data(wl_surface_focus); + } + const wl_fixed_t win_scale = win ? win->scale() : 1; + + /* NOTE(@campbellbarton): Scale factors match Blender's operators & default preferences. + * For these values to work correctly, operator logic will need to be changed not to scale input + * by the region size (as with 3D view zoom) or preference for 3D view orbit sensitivity. + * + * By working "correctly" I mean that a rotation action where the users fingers rotate to + * opposite locations should always rotate the viewport 180d, since users will expect the + * physical location of their fingers to match the viewport. + * Similarly with zoom, the scale value from the pinch action can be mapped to a zoom level + * although unlike rotation, an inexact mapping is less noticeable. + * Users may even prefer the zoom level to be scaled - which could be a preference. */ + seat->pointer_gesture_pinch.scale.value = wl_fixed_from_int(1); + /* The value 300 matches a value used in clip & image zoom operators. + * It seems OK for the 3D view too. */ + seat->pointer_gesture_pinch.scale.factor = 300 * win_scale; + /* The value 5 is used on macOS and roughly maps 1:1 with turntable rotation, + * although preferences can scale the sensitivity (which would be skipped ideally). */ + seat->pointer_gesture_pinch.rotation.factor = 5 * win_scale; +} + +static void gesture_pinch_handle_update(void *data, + struct zwp_pointer_gesture_pinch_v1 * /*pinch*/, + uint32_t /*time*/, + wl_fixed_t dx, + wl_fixed_t dy, + wl_fixed_t scale, + wl_fixed_t rotation) +{ + CLOG_INFO(LOG, + 2, + "update (dx=%.3f, dy=%.3f, scale=%.3f, rotation=%.3f)", + wl_fixed_to_double(dx), + wl_fixed_to_double(dy), + wl_fixed_to_double(scale), + wl_fixed_to_double(rotation)); + + GWL_Seat *seat = static_cast(data); + + GHOST_WindowWayland *win = nullptr; + + if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { + win = ghost_wl_surface_user_data(wl_surface_focus); + } + + /* Scale defaults to `wl_fixed_from_int(1)` which may change while pinching. + * This needs to be converted to a delta. */ + const wl_fixed_t scale_delta = scale - seat->pointer_gesture_pinch.scale.value; + const int scale_as_delta_px = gwl_scaled_fixed_t_add_and_calc_rounded_delta( + &seat->pointer_gesture_pinch.scale, scale_delta); + + /* Rotation in degrees, unlike scale this is a delta. */ + const int rotation_as_delta_px = gwl_scaled_fixed_t_add_and_calc_rounded_delta( + &seat->pointer_gesture_pinch.rotation, rotation); + + if (win) { + const wl_fixed_t win_scale = win->scale(); + const int32_t event_xy[2] = { + wl_fixed_to_int(win_scale * seat->pointer.xy[0]), + wl_fixed_to_int(win_scale * seat->pointer.xy[1]), + }; + if (scale_as_delta_px) { + seat->system->pushEvent(new GHOST_EventTrackpad(seat->system->getMilliSeconds(), + win, + GHOST_kTrackpadEventMagnify, + event_xy[0], + event_xy[1], + scale_as_delta_px, + 0, + false)); + } + + if (rotation_as_delta_px) { + seat->system->pushEvent(new GHOST_EventTrackpad(seat->system->getMilliSeconds(), + win, + GHOST_kTrackpadEventRotate, + event_xy[0], + event_xy[1], + rotation_as_delta_px, + 0, + false)); + } + } +} + +static void gesture_pinch_handle_end(void * /*data*/, + struct zwp_pointer_gesture_pinch_v1 * /*pinch*/, + uint32_t /*serial*/, + uint32_t /*time*/, + int32_t cancelled) +{ + CLOG_INFO(LOG, 2, "end (cancelled=%i)", cancelled); +} + +static const struct zwp_pointer_gesture_pinch_v1_listener gesture_pinch_listener = { + gesture_pinch_handle_begin, + gesture_pinch_handle_update, + gesture_pinch_handle_end, +}; + +#undef LOG + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Listener (Pointer Gesture: Swipe), #zwp_pointer_gesture_swipe_v1 + * + * \note In both Gnome-Shell & KDE this gesture isn't emitted at time of writing, + * instead, high resolution 2D #wl_pointer_listener.axis data is generated which works well. + * There may be some situations where WAYLAND compositors generate this gesture + * (swiping with 3+ fingers, for e.g.). So keep this to allow logging & testing gestures. + * \{ */ + +static CLG_LogRef LOG_WL_POINTER_GESTURE_SWIPE = {"ghost.wl.handle.pointer_gesture.swipe"}; +#define LOG (&LOG_WL_POINTER_GESTURE_SWIPE) + +static void gesture_swipe_handle_begin( + void * /*data*/, + struct zwp_pointer_gesture_swipe_v1 * /*zwp_pointer_gesture_swipe_v1*/, + uint32_t /*serial*/, + uint32_t /*time*/, + struct wl_surface * /*surface*/, + uint32_t fingers) +{ + CLOG_INFO(LOG, 2, "begin (fingers=%u)", fingers); +} + +static void gesture_swipe_handle_update( + void * /*data*/, + struct zwp_pointer_gesture_swipe_v1 * /*zwp_pointer_gesture_swipe_v1*/, + uint32_t /*time*/, + wl_fixed_t dx, + wl_fixed_t dy) +{ + CLOG_INFO(LOG, 2, "update (dx=%.3f, dy=%.3f)", wl_fixed_to_double(dx), wl_fixed_to_double(dy)); +} + +static void gesture_swipe_handle_end( + void * /*data*/, + struct zwp_pointer_gesture_swipe_v1 * /*zwp_pointer_gesture_swipe_v1*/, + uint32_t /*serial*/, + uint32_t /*time*/, + int32_t cancelled) +{ + CLOG_INFO(LOG, 2, "end (cancelled=%i)", cancelled); +} + +static const struct zwp_pointer_gesture_swipe_v1_listener gesture_swipe_listener = { + gesture_swipe_handle_begin, + gesture_swipe_handle_update, + gesture_swipe_handle_end, +}; + +#undef LOG + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Listener (Touch Seat), #wl_touch_listener * @@ -3311,6 +3568,31 @@ static void gwl_seat_capability_pointer_enable(GWL_Seat *seat) wl_surface_add_listener(seat->cursor.wl_surface, &cursor_surface_listener, seat); ghost_wl_surface_tag_cursor_pointer(seat->cursor.wl_surface); + + zwp_pointer_gestures_v1 *pointer_gestures = seat->system->wp_pointer_gestures(); + if (pointer_gestures) { + { /* Hold gesture. */ + struct zwp_pointer_gesture_hold_v1 *gesture = zwp_pointer_gestures_v1_get_hold_gesture( + pointer_gestures, seat->wl_pointer); + zwp_pointer_gesture_hold_v1_set_user_data(gesture, seat); + zwp_pointer_gesture_hold_v1_add_listener(gesture, &gesture_hold_listener, seat); + seat->wp_pointer_gesture_hold = gesture; + } + { /* Pinch gesture. */ + struct zwp_pointer_gesture_pinch_v1 *gesture = zwp_pointer_gestures_v1_get_pinch_gesture( + pointer_gestures, seat->wl_pointer); + zwp_pointer_gesture_pinch_v1_set_user_data(gesture, seat); + zwp_pointer_gesture_pinch_v1_add_listener(gesture, &gesture_pinch_listener, seat); + seat->wp_pointer_gesture_pinch = gesture; + } + { /* Swipe gesture. */ + struct zwp_pointer_gesture_swipe_v1 *gesture = zwp_pointer_gestures_v1_get_swipe_gesture( + pointer_gestures, seat->wl_pointer); + zwp_pointer_gesture_swipe_v1_set_user_data(gesture, seat); + zwp_pointer_gesture_swipe_v1_add_listener(gesture, &gesture_swipe_listener, seat); + seat->wp_pointer_gesture_swipe = gesture; + } + } } static void gwl_seat_capability_pointer_disable(GWL_Seat *seat) @@ -3318,6 +3600,32 @@ static void gwl_seat_capability_pointer_disable(GWL_Seat *seat) if (!seat->wl_pointer) { return; } + + zwp_pointer_gestures_v1 *pointer_gestures = seat->system->wp_pointer_gestures(); + if (pointer_gestures) { + { /* Hold gesture. */ + struct zwp_pointer_gesture_hold_v1 **gesture_p = &seat->wp_pointer_gesture_hold; + if (*gesture_p) { + zwp_pointer_gesture_hold_v1_destroy(*gesture_p); + *gesture_p = nullptr; + } + } + { /* Pinch gesture. */ + struct zwp_pointer_gesture_pinch_v1 **gesture_p = &seat->wp_pointer_gesture_pinch; + if (*gesture_p) { + zwp_pointer_gesture_pinch_v1_destroy(*gesture_p); + *gesture_p = nullptr; + } + } + { /* Swipe gesture. */ + struct zwp_pointer_gesture_swipe_v1 **gesture_p = &seat->wp_pointer_gesture_swipe; + if (*gesture_p) { + zwp_pointer_gesture_swipe_v1_destroy(*gesture_p); + *gesture_p = nullptr; + } + } + } + if (seat->cursor.wl_surface) { wl_surface_destroy(seat->cursor.wl_surface); seat->cursor.wl_surface = nullptr; @@ -3791,6 +4099,11 @@ static void global_handle_add(void *data, display->wp_pointer_constraints = static_cast( wl_registry_bind(wl_registry, name, &zwp_pointer_constraints_v1_interface, 1)); } + else if (STREQ(interface, zwp_pointer_gestures_v1_interface.name)) { + display->wp_pointer_gestures = static_cast( + wl_registry_bind(wl_registry, name, &zwp_pointer_gestures_v1_interface, 3)); + } + else if (!strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name)) { display->wp_primary_selection_device_manager = static_cast(wl_registry_bind( @@ -4892,6 +5205,11 @@ struct zwp_primary_selection_device_manager_v1 *GHOST_SystemWayland::wp_primary_ return display_->wp_primary_selection_device_manager; } +struct zwp_pointer_gestures_v1 *GHOST_SystemWayland::wp_pointer_gestures() +{ + return display_->wp_pointer_gestures; +} + #ifdef WITH_GHOST_WAYLAND_LIBDECOR libdecor *GHOST_SystemWayland::libdecor_context() diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index c19791fd792..f08e9fdcf9c 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -159,6 +159,7 @@ class GHOST_SystemWayland : public GHOST_System { struct wl_display *wl_display(); struct wl_compositor *wl_compositor(); struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_manager(); + struct zwp_pointer_gestures_v1 *wp_pointer_gestures(); #ifdef WITH_GHOST_WAYLAND_LIBDECOR libdecor *libdecor_context(); -- cgit v1.2.3 From 9f560219751240cc15a8de0b2e485e1538fee642 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sat, 22 Oct 2022 17:19:55 +0200 Subject: Fix T101930: NLA Actions Stash remove doesn't work on overriden linked data. Code adding stash track was clearing out track flags, instead of editing them as it should have... Note that there are a lot of other weaknesses in action stash code (like relying on the (translated!!!!!!) name of the track to know whether it's a stah or not). --- source/blender/blenkernel/intern/nla.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index ba63cdff917..24663d6db05 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -1918,7 +1918,7 @@ bool BKE_nla_action_stash(AnimData *adt, const bool is_liboverride) * NOTE: this must be done *after* adding the strip to the track, or else * the strip locking will prevent the strip from getting added */ - nlt->flag = (NLATRACK_MUTED | NLATRACK_PROTECTED); + nlt->flag |= (NLATRACK_MUTED | NLATRACK_PROTECTED); strip->flag &= ~(NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_ACTIVE); /* also mark the strip for auto syncing the length, so that the strips accurately -- cgit v1.2.3 From a7aa0f1a0c240724e533a5b815c8c4d75b117902 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Sat, 22 Oct 2022 12:00:01 -0300 Subject: Fix T101991: "Absolute Grid Snap" not working Error introduced in rB1edebb794b76. In that commit it was kind of forgotten that the snap to grid is also used in 3D views. Also a refactoring and cleanup was applied to simplify the code. --- source/blender/editors/transform/transform.c | 28 ++++++++---------- source/blender/editors/transform/transform.h | 9 ++++-- .../editors/transform/transform_mode_translate.c | 3 +- source/blender/editors/transform/transform_snap.c | 34 +++++++++++----------- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 919f4e5b85c..9fe8cd3df2e 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1721,13 +1721,17 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) } } -static void initSnapSpatial(TransInfo *t, float r_snap[2], float r_snap_y[2]) +static void initSnapSpatial(TransInfo *t, float r_snap[3], float *r_snap_precision) { + /* Default values. */ + r_snap[0] = r_snap[1] = 1.0f; + r_snap[1] = 0.0f; + *r_snap_precision = 0.1f; + if (t->spacetype == SPACE_VIEW3D) { if (t->region->regiondata) { View3D *v3d = t->area->spacedata.first; - r_snap[0] = ED_view3d_grid_view_scale(t->scene, v3d, t->region, NULL) * 1.0f; - r_snap[1] = r_snap[0] * 0.1f; + r_snap[0] = r_snap[1] = r_snap[2] = ED_view3d_grid_view_scale(t->scene, v3d, t->region, NULL); } } else if (t->spacetype == SPACE_IMAGE) { @@ -1741,24 +1745,16 @@ static void initSnapSpatial(TransInfo *t, float r_snap[2], float r_snap_y[2]) ED_space_image_grid_steps(sima, grid_steps_x, grid_steps_y, grid_size); /* Snapping value based on what type of grid is used (adaptive-subdividing or custom-grid). */ r_snap[0] = ED_space_image_increment_snap_value(grid_size, grid_steps_x, zoom_factor); - r_snap[1] = r_snap[0] / 2.0f; - r_snap_y[0] = ED_space_image_increment_snap_value(grid_size, grid_steps_y, zoom_factor); - r_snap_y[1] = r_snap_y[0] / 2.0f; + r_snap[1] = ED_space_image_increment_snap_value(grid_size, grid_steps_y, zoom_factor); + *r_snap_precision = 0.5f; } else if (t->spacetype == SPACE_CLIP) { - r_snap[0] = 0.125f; - r_snap[1] = 0.0625f; + r_snap[0] = r_snap[1] = 0.125f; + *r_snap_precision = 0.5f; } else if (t->spacetype == SPACE_NODE) { r_snap[0] = r_snap[1] = ED_node_grid_size(); } - else if (t->spacetype == SPACE_GRAPH) { - r_snap[0] = 1.0; - r_snap[1] = 0.1f; - } - else { - r_snap[0] = r_snap[1] = 1.0f; - } } bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event, int mode) @@ -1898,7 +1894,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve initSnapping(t, op); /* Initialize snapping data AFTER mode flags */ - initSnapSpatial(t, t->snap_spatial_x, t->snap_spatial_y); + initSnapSpatial(t, t->snap_spatial, &t->snap_spatial_precision); /* EVIL! posemode code can switch translation to rotate when 1 bone is selected. * will be removed (ton) */ diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 95686f12fe2..90f2795184b 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -555,9 +555,12 @@ typedef struct TransInfo { /** Snapping Gears. */ float snap[2]; /** Spatial snapping gears(even when rotating, scaling... etc). */ - float snap_spatial_x[2]; - /** Spatial snapping in the Y coordinate, for non-uniform grid in UV Editor. */ - float snap_spatial_y[2]; + float snap_spatial[3]; + /** + * Precision factor that is multiplied to snap_spatial when precision + * modifier is enabled for snap to grid or incremental snap. + */ + float snap_spatial_precision; /** Mouse side of the current frame, 'L', 'R' or 'B' */ char frame_side; diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index 91388ecd661..b7ffba6ad58 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -590,7 +590,8 @@ void initTranslation(TransInfo *t) t->num.flag = 0; t->num.idx_max = t->idx_max; - copy_v2_v2(t->snap, t->snap_spatial_x); + t->snap[0] = 1.0; + t->snap[1] = t->snap_spatial_precision; copy_v3_fl(t->num.val_inc, t->snap[0]); t->num.unit_sys = t->scene->unit.system; diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 06aec3b45a6..0d27fc1efd4 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -519,16 +519,14 @@ void applyGridAbsolute(TransInfo *t) return; } - float grid_size_x = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_x[1] : t->snap_spatial_x[0]; - float grid_size_y = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_y[1] : t->snap_spatial_y[0]; - float grid_size_z = grid_size_x; - - if (grid_size_y == 0.0f) { - grid_size_y = grid_size_x; /* Just use `grid_size_x` when `grid_size_y` isn't set correctly. */ + float grid_size[3]; + copy_v3_v3(grid_size, t->snap_spatial); + if (t->modifiers & MOD_PRECISION) { + mul_v3_fl(grid_size, t->snap_spatial_precision); } /* Early exit on unusable grid size. */ - if (grid_size_x == 0.0f || grid_size_y == 0.0f || grid_size_z == 0.0f) { + if (is_zero_v3(grid_size)) { return; } @@ -554,9 +552,9 @@ void applyGridAbsolute(TransInfo *t) copy_v3_v3(iloc, td->ob->obmat[3]); } - loc[0] = roundf(iloc[0] / grid_size_x) * grid_size_x; - loc[1] = roundf(iloc[1] / grid_size_y) * grid_size_y; - loc[2] = roundf(iloc[2] / grid_size_z) * grid_size_z; + loc[0] = roundf(iloc[0] / grid_size[0]) * grid_size[0]; + loc[1] = roundf(iloc[1] / grid_size[1]) * grid_size[1]; + loc[2] = grid_size[2] ? roundf(iloc[2] / grid_size[2]) * grid_size[2] : iloc[2]; sub_v3_v3v3(tvec, loc, iloc); mul_m3_v3(td->smtx, tvec); @@ -1660,8 +1658,7 @@ bool snapNodesTransform( static void snap_grid_apply(TransInfo *t, const int max_index, - const float grid_dist_x, - const float grid_dist_y, + const float grid_dist[3], const float loc[3], float r_out[3]) { @@ -1680,7 +1677,7 @@ static void snap_grid_apply(TransInfo *t, } for (int i = 0; i <= max_index; i++) { - const float iter_fac = ((i == 1) ? grid_dist_y : grid_dist_x) * asp[i]; + const float iter_fac = grid_dist[i] * asp[i]; r_out[i] = iter_fac * roundf((in[i] + center_global[i]) / iter_fac) - center_global[i]; } } @@ -1705,15 +1702,18 @@ bool transform_snap_grid(TransInfo *t, float *val) return false; } - float grid_dist_x = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_x[1] : t->snap_spatial_x[0]; - float grid_dist_y = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_y[1] : t->snap_spatial_y[0]; + float grid_dist[3]; + copy_v3_v3(grid_dist, t->snap_spatial); + if (t->modifiers & MOD_PRECISION) { + mul_v3_fl(grid_dist, t->snap_spatial_precision); + } /* Early bailing out if no need to snap */ - if (grid_dist_x == 0.0f || grid_dist_y == 0.0f) { + if (is_zero_v3(grid_dist)) { return false; } - snap_grid_apply(t, t->idx_max, grid_dist_x, grid_dist_y, val, val); + snap_grid_apply(t, t->idx_max, grid_dist, val, val); t->tsnap.snapElem = SCE_SNAP_MODE_GRID; return true; } -- cgit v1.2.3 From e16cea019ee184156a5c1849f2b7f2b762dc9a6e Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Sat, 22 Oct 2022 12:27:59 -0300 Subject: Cleanup: move grid snap functions to files where they are used --- .../editors/transform/transform_convert_node.cc | 55 +++++++- .../editors/transform/transform_mode_translate.c | 100 ++++++++++++++- source/blender/editors/transform/transform_snap.c | 140 +-------------------- source/blender/editors/transform/transform_snap.h | 3 +- 4 files changed, 155 insertions(+), 143 deletions(-) diff --git a/source/blender/editors/transform/transform_convert_node.cc b/source/blender/editors/transform/transform_convert_node.cc index eb5eb822d69..0b5dc73a051 100644 --- a/source/blender/editors/transform/transform_convert_node.cc +++ b/source/blender/editors/transform/transform_convert_node.cc @@ -16,6 +16,7 @@ #include "BKE_context.h" #include "BKE_node.h" #include "BKE_node_tree_update.h" +#include "BKE_object.h" #include "BKE_report.h" #include "ED_node.h" @@ -155,9 +156,61 @@ static void createTransNodeData(bContext * /*C*/, TransInfo *t) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Node Transform Creation +/** \name Flush Transform Nodes * \{ */ +static void applyGridAbsolute(TransInfo *t) +{ + int i; + + if (!(activeSnap(t) && (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)))) { + return; + } + + float grid_size[3]; + copy_v3_v3(grid_size, t->snap_spatial); + if (t->modifiers & MOD_PRECISION) { + mul_v3_fl(grid_size, t->snap_spatial_precision); + } + + /* Early exit on unusable grid size. */ + if (is_zero_v3(grid_size)) { + return; + } + + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td; + + for (i = 0, td = tc->data; i < tc->data_len; i++, td++) { + float iloc[3], loc[3], tvec[3]; + if (td->flag & TD_SKIP) { + continue; + } + + if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) { + continue; + } + + copy_v3_v3(iloc, td->loc); + if (tc->use_local_mat) { + mul_m4_v3(tc->mat, iloc); + } + else if (t->options & CTX_OBJECT) { + BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); + copy_v3_v3(iloc, td->ob->obmat[3]); + } + + loc[0] = roundf(iloc[0] / grid_size[0]) * grid_size[0]; + loc[1] = roundf(iloc[1] / grid_size[1]) * grid_size[1]; + loc[2] = grid_size[2] ? roundf(iloc[2] / grid_size[2]) * grid_size[2] : iloc[2]; + + sub_v3_v3v3(tvec, loc, iloc); + mul_m3_v3(td->smtx, tvec); + add_v3_v3(td->loc, tvec); + } + } +} + static void flushTransNodes(TransInfo *t) { using namespace blender::ed; diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index b7ffba6ad58..6461182afc1 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -170,7 +170,7 @@ static void transdata_elem_translate_fn(void *__restrict iter_data_v, /** \} */ /* -------------------------------------------------------------------- */ -/** \name Transform (Translation) +/** \name Transform (Translation) Header * \{ */ static void translate_dist_to_str(char *r_str, @@ -341,6 +341,96 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_ } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Transform (Translation) Snapping + * \{ */ + +static void translate_snap_target_grid_ensure(TransInfo *t) +{ + /* Only need to calculate once. */ + if ((t->tsnap.status & TARGET_GRID_INIT) == 0) { + if (t->data_type == &TransConvertType_Cursor3D) { + /* Use a fallback when transforming the cursor. + * In this case the center is _not_ derived from the cursor which is being transformed. */ + copy_v3_v3(t->tsnap.snapTargetGrid, TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->data->iloc); + } + else if (t->around == V3D_AROUND_CURSOR) { + /* Use a fallback for cursor selection, + * this isn't useful as a global center for absolute grid snapping + * since its not based on the position of the selection. */ + tranform_snap_target_median_calc(t, t->tsnap.snapTargetGrid); + } + else { + copy_v3_v3(t->tsnap.snapTargetGrid, t->center_global); + } + t->tsnap.status |= TARGET_GRID_INIT; + } +} + +static void translate_snap_grid_apply(TransInfo *t, + const int max_index, + const float grid_dist[3], + const float loc[3], + float r_out[3]) +{ + BLI_assert(max_index <= 2); + translate_snap_target_grid_ensure(t); + const float *center_global = t->tsnap.snapTargetGrid; + const float *asp = t->aspect; + + float in[3]; + if (t->con.mode & CON_APPLY) { + BLI_assert(t->tsnap.snapElem == SCE_SNAP_MODE_NONE); + t->con.applyVec(t, NULL, NULL, loc, in); + } + else { + copy_v3_v3(in, loc); + } + + for (int i = 0; i <= max_index; i++) { + const float iter_fac = grid_dist[i] * asp[i]; + r_out[i] = iter_fac * roundf((in[i] + center_global[i]) / iter_fac) - center_global[i]; + } +} + +static bool translate_snap_grid(TransInfo *t, float *val) +{ + if (!activeSnap(t)) { + return false; + } + + if (!(t->tsnap.mode & SCE_SNAP_MODE_GRID) || validSnap(t)) { + /* Don't do grid snapping if there is a valid snap point. */ + return false; + } + + /* Don't do grid snapping if not in 3D viewport or UV editor */ + if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) { + return false; + } + + if (t->mode != TFM_TRANSLATION) { + return false; + } + + float grid_dist[3]; + copy_v3_v3(grid_dist, t->snap_spatial); + if (t->modifiers & MOD_PRECISION) { + mul_v3_fl(grid_dist, t->snap_spatial_precision); + } + + /* Early bailing out if no need to snap */ + if (is_zero_v3(grid_dist)) { + return false; + } + + translate_snap_grid_apply(t, t->idx_max, grid_dist, val, val); + t->tsnap.snapElem = SCE_SNAP_MODE_GRID; + return true; +} + static void ApplySnapTranslation(TransInfo *t, float vec[3]) { float point[3]; @@ -372,6 +462,12 @@ static void ApplySnapTranslation(TransInfo *t, float vec[3]) } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Transform (Translation) + * \{ */ + static void applyTranslationValue(TransInfo *t, const float vec[3]) { struct TranslateCustomData *custom_data = t->custom.mode.data; @@ -514,7 +610,7 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2])) t->tsnap.snapElem = SCE_SNAP_MODE_NONE; applySnappingAsGroup(t, global_dir); - transform_snap_grid(t, global_dir); + translate_snap_grid(t, global_dir); if (t->con.mode & CON_APPLY) { float in[3]; diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 0d27fc1efd4..672d947936d 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -511,58 +511,6 @@ void applySnappingIndividual(TransInfo *t) } } -void applyGridAbsolute(TransInfo *t) -{ - int i; - - if (!(activeSnap(t) && (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)))) { - return; - } - - float grid_size[3]; - copy_v3_v3(grid_size, t->snap_spatial); - if (t->modifiers & MOD_PRECISION) { - mul_v3_fl(grid_size, t->snap_spatial_precision); - } - - /* Early exit on unusable grid size. */ - if (is_zero_v3(grid_size)) { - return; - } - - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td; - - for (i = 0, td = tc->data; i < tc->data_len; i++, td++) { - float iloc[3], loc[3], tvec[3]; - if (td->flag & TD_SKIP) { - continue; - } - - if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) { - continue; - } - - copy_v3_v3(iloc, td->loc); - if (tc->use_local_mat) { - mul_m4_v3(tc->mat, iloc); - } - else if (t->options & CTX_OBJECT) { - BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); - copy_v3_v3(iloc, td->ob->obmat[3]); - } - - loc[0] = roundf(iloc[0] / grid_size[0]) * grid_size[0]; - loc[1] = roundf(iloc[1] / grid_size[1]) * grid_size[1]; - loc[2] = grid_size[2] ? roundf(iloc[2] / grid_size[2]) * grid_size[2] : iloc[2]; - - sub_v3_v3v3(tvec, loc, iloc); - mul_m3_v3(td->smtx, tvec); - add_v3_v3(td->loc, tvec); - } - } -} - void applySnappingAsGroup(TransInfo *t, float *vec) { if (!activeSnap_SnappingAsGroup(t)) { @@ -1189,7 +1137,7 @@ static void snap_calc_sequencer_fn(TransInfo *t, float *UNUSED(vec)) /** \name Target * \{ */ -static void snap_target_median_impl(TransInfo *t, float r_median[3]) +void tranform_snap_target_median_calc(const TransInfo *t, float r_median[3]) { int i_accum = 0; @@ -1225,28 +1173,6 @@ static void snap_target_median_impl(TransInfo *t, float r_median[3]) // TargetSnapOffset(t, NULL); } -static void snap_target_grid_ensure(TransInfo *t) -{ - /* Only need to calculate once. */ - if ((t->tsnap.status & TARGET_GRID_INIT) == 0) { - if (t->data_type == &TransConvertType_Cursor3D) { - /* Use a fallback when transforming the cursor. - * In this case the center is _not_ derived from the cursor which is being transformed. */ - copy_v3_v3(t->tsnap.snapTargetGrid, TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->data->iloc); - } - else if (t->around == V3D_AROUND_CURSOR) { - /* Use a fallback for cursor selection, - * this isn't useful as a global center for absolute grid snapping - * since its not based on the position of the selection. */ - snap_target_median_impl(t, t->tsnap.snapTargetGrid); - } - else { - copy_v3_v3(t->tsnap.snapTargetGrid, t->center_global); - } - t->tsnap.status |= TARGET_GRID_INIT; - } -} - static void TargetSnapOffset(TransInfo *t, TransData *td) { if (t->spacetype == SPACE_NODE && td != NULL) { @@ -1318,7 +1244,7 @@ static void TargetSnapMedian(TransInfo *t) { /* Only need to calculate once. */ if ((t->tsnap.status & TARGET_INIT) == 0) { - snap_target_median_impl(t, t->tsnap.snapTarget); + tranform_snap_target_median_calc(t, t->tsnap.snapTarget); t->tsnap.status |= TARGET_INIT; } } @@ -1656,68 +1582,6 @@ bool snapNodesTransform( /** \name snap Grid * \{ */ -static void snap_grid_apply(TransInfo *t, - const int max_index, - const float grid_dist[3], - const float loc[3], - float r_out[3]) -{ - BLI_assert(max_index <= 2); - snap_target_grid_ensure(t); - const float *center_global = t->tsnap.snapTargetGrid; - const float *asp = t->aspect; - - float in[3]; - if (t->con.mode & CON_APPLY) { - BLI_assert(t->tsnap.snapElem == SCE_SNAP_MODE_NONE); - t->con.applyVec(t, NULL, NULL, loc, in); - } - else { - copy_v3_v3(in, loc); - } - - for (int i = 0; i <= max_index; i++) { - const float iter_fac = grid_dist[i] * asp[i]; - r_out[i] = iter_fac * roundf((in[i] + center_global[i]) / iter_fac) - center_global[i]; - } -} - -bool transform_snap_grid(TransInfo *t, float *val) -{ - if (!activeSnap(t)) { - return false; - } - - if (!(t->tsnap.mode & SCE_SNAP_MODE_GRID) || validSnap(t)) { - /* Don't do grid snapping if there is a valid snap point. */ - return false; - } - - /* Don't do grid snapping if not in 3D viewport or UV editor */ - if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) { - return false; - } - - if (t->mode != TFM_TRANSLATION) { - return false; - } - - float grid_dist[3]; - copy_v3_v3(grid_dist, t->snap_spatial); - if (t->modifiers & MOD_PRECISION) { - mul_v3_fl(grid_dist, t->snap_spatial_precision); - } - - /* Early bailing out if no need to snap */ - if (is_zero_v3(grid_dist)) { - return false; - } - - snap_grid_apply(t, t->idx_max, grid_dist, val, val); - t->tsnap.snapElem = SCE_SNAP_MODE_GRID; - return true; -} - static void snap_increment_apply_ex(const TransInfo *UNUSED(t), const int max_index, const float increment_val, diff --git a/source/blender/editors/transform/transform_snap.h b/source/blender/editors/transform/transform_snap.h index 2b78c554ad8..16d9062e978 100644 --- a/source/blender/editors/transform/transform_snap.h +++ b/source/blender/editors/transform/transform_snap.h @@ -38,10 +38,10 @@ bool snapNodesTransform(struct TransInfo *t, bool transformModeUseSnap(const TransInfo *t); +void tranform_snap_target_median_calc(const TransInfo *t, float r_median[3]); bool transform_snap_increment_ex(const TransInfo *t, bool use_local_space, float *r_val); bool transform_snap_increment(const TransInfo *t, float *val); float transform_snap_increment_get(const TransInfo *t); -bool transform_snap_grid(TransInfo *t, float *val); bool activeSnap(const TransInfo *t); bool activeSnap_SnappingIndividual(const TransInfo *t); @@ -52,7 +52,6 @@ bool validSnap(const TransInfo *t); void initSnapping(struct TransInfo *t, struct wmOperator *op); void freeSnapping(struct TransInfo *t); void applySnappingIndividual(TransInfo *t); -void applyGridAbsolute(TransInfo *t); void applySnappingAsGroup(TransInfo *t, float *vec); void resetSnapping(TransInfo *t); eRedrawFlag handleSnapping(TransInfo *t, const struct wmEvent *event); -- cgit v1.2.3 From 588db6152aaa8b8db55f8f3180787befc4238684 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Sat, 22 Oct 2022 12:52:22 -0300 Subject: Transform: remove unreachable code The node grid snap only works with 2D coordinates, no transformation matrix and no Objects. Also rename `applyGridAbsolute` to `node_snap_grid_apply`. --- .../editors/transform/transform_convert_node.cc | 30 ++++++++-------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/source/blender/editors/transform/transform_convert_node.cc b/source/blender/editors/transform/transform_convert_node.cc index 0b5dc73a051..6ab0e1fe701 100644 --- a/source/blender/editors/transform/transform_convert_node.cc +++ b/source/blender/editors/transform/transform_convert_node.cc @@ -16,7 +16,6 @@ #include "BKE_context.h" #include "BKE_node.h" #include "BKE_node_tree_update.h" -#include "BKE_object.h" #include "BKE_report.h" #include "ED_node.h" @@ -159,7 +158,7 @@ static void createTransNodeData(bContext * /*C*/, TransInfo *t) /** \name Flush Transform Nodes * \{ */ -static void applyGridAbsolute(TransInfo *t) +static void node_snap_grid_apply(TransInfo *t) { int i; @@ -167,14 +166,14 @@ static void applyGridAbsolute(TransInfo *t) return; } - float grid_size[3]; - copy_v3_v3(grid_size, t->snap_spatial); + float grid_size[2]; + copy_v2_v2(grid_size, t->snap_spatial); if (t->modifiers & MOD_PRECISION) { - mul_v3_fl(grid_size, t->snap_spatial_precision); + mul_v2_fl(grid_size, t->snap_spatial_precision); } /* Early exit on unusable grid size. */ - if (is_zero_v3(grid_size)) { + if (is_zero_v2(grid_size)) { return; } @@ -182,7 +181,7 @@ static void applyGridAbsolute(TransInfo *t) TransData *td; for (i = 0, td = tc->data; i < tc->data_len; i++, td++) { - float iloc[3], loc[3], tvec[3]; + float iloc[2], loc[2], tvec[2]; if (td->flag & TD_SKIP) { continue; } @@ -191,22 +190,13 @@ static void applyGridAbsolute(TransInfo *t) continue; } - copy_v3_v3(iloc, td->loc); - if (tc->use_local_mat) { - mul_m4_v3(tc->mat, iloc); - } - else if (t->options & CTX_OBJECT) { - BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); - copy_v3_v3(iloc, td->ob->obmat[3]); - } + copy_v2_v2(iloc, td->loc); loc[0] = roundf(iloc[0] / grid_size[0]) * grid_size[0]; loc[1] = roundf(iloc[1] / grid_size[1]) * grid_size[1]; - loc[2] = grid_size[2] ? roundf(iloc[2] / grid_size[2]) * grid_size[2] : iloc[2]; - sub_v3_v3v3(tvec, loc, iloc); - mul_m3_v3(td->smtx, tvec); - add_v3_v3(td->loc, tvec); + sub_v2_v2v2(tvec, loc, iloc); + add_v2_v2(td->loc, tvec); } } } @@ -244,7 +234,7 @@ static void flushTransNodes(TransInfo *t) } FOREACH_TRANS_DATA_CONTAINER (t, tc) { - applyGridAbsolute(t); + node_snap_grid_apply(t); /* flush to 2d vector from internally used 3d vector */ for (int i = 0; i < tc->data_len; i++) { -- cgit v1.2.3 From 21fdb0d92b6697cba252a1e8080b19012efa8383 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sat, 22 Oct 2022 18:15:02 +0200 Subject: Fix T101329: EXR 'JPG Preview' doesn't use color space anymore For the JPG preview, the only thing that was changed in the image format was the format itself. However, the colorspace code now also checks the bitdepth through BKE_image_format_is_byte, so the depth needs to be explicitly set to 8-bit for the JPG preview output. --- source/blender/blenkernel/intern/image_save.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/blenkernel/intern/image_save.cc b/source/blender/blenkernel/intern/image_save.cc index 4e47e71fb2b..003211e6288 100644 --- a/source/blender/blenkernel/intern/image_save.cc +++ b/source/blender/blenkernel/intern/image_save.cc @@ -968,6 +968,7 @@ bool BKE_image_render_write(ReportList *reports, /* optional preview images for exr */ if (ok && (image_format.flag & R_IMF_FLAG_PREVIEW_JPG)) { image_format.imtype = R_IMF_IMTYPE_JPEG90; + image_format.depth = R_IMF_CHAN_DEPTH_8; if (BLI_path_extension_check(filepath, ".exr")) { filepath[strlen(filepath) - 4] = 0; @@ -1025,6 +1026,7 @@ bool BKE_image_render_write(ReportList *reports, /* optional preview images for exr */ if (ok && is_exr_rr && (image_format.flag & R_IMF_FLAG_PREVIEW_JPG)) { image_format.imtype = R_IMF_IMTYPE_JPEG90; + image_format.depth = R_IMF_CHAN_DEPTH_8; if (BLI_path_extension_check(filepath, ".exr")) { filepath[strlen(filepath) - 4] = 0; -- cgit v1.2.3 From afec1cd33385109ac1ca41177426e7b72e174cda Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sat, 22 Oct 2022 18:32:06 +0200 Subject: Cleanup: clang-format --- source/blender/editors/transform/transform.c | 3 ++- source/blender/editors/transform/transform_mode_translate.c | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 9fe8cd3df2e..5b194ae7237 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1731,7 +1731,8 @@ static void initSnapSpatial(TransInfo *t, float r_snap[3], float *r_snap_precisi if (t->spacetype == SPACE_VIEW3D) { if (t->region->regiondata) { View3D *v3d = t->area->spacedata.first; - r_snap[0] = r_snap[1] = r_snap[2] = ED_view3d_grid_view_scale(t->scene, v3d, t->region, NULL); + r_snap[0] = r_snap[1] = r_snap[2] = ED_view3d_grid_view_scale( + t->scene, v3d, t->region, NULL); } } else if (t->spacetype == SPACE_IMAGE) { diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index 6461182afc1..c751a68092f 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -370,10 +370,10 @@ static void translate_snap_target_grid_ensure(TransInfo *t) } static void translate_snap_grid_apply(TransInfo *t, - const int max_index, - const float grid_dist[3], - const float loc[3], - float r_out[3]) + const int max_index, + const float grid_dist[3], + const float loc[3], + float r_out[3]) { BLI_assert(max_index <= 2); translate_snap_target_grid_ensure(t); -- cgit v1.2.3 From b70bbfadfecec049ad1ac2de7a949198ca6c15bc Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Sat, 22 Oct 2022 19:31:57 -0300 Subject: Fix T102000: Curve Shrink Fatten doesn't work for zero radius Kind of intentional regression on rB2d1fe736fabd. But the solution now is (theoretically) better than adding a hard coded threshold. For cases with zero radius, the new radius is now the offset of the ratio projected onto the plane of the origin point. --- .../transform/transform_mode_curveshrinkfatten.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c index f7f9e14b8ac..76ce7b29619 100644 --- a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c +++ b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c @@ -8,6 +8,7 @@ #include #include "BLI_math.h" +#include "BLI_math_bits.h" #include "BLI_string.h" #include "BKE_context.h" @@ -62,7 +63,14 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) } if (td->val) { - *td->val = td->ival * ratio; + if (td->ival == 0.0f && ratio > 1.0f) { + /* Allow Shrink/Fatten for zero radius. */ + *td->val = (ratio - 1.0f) * uint_as_float(POINTER_AS_UINT(t->custom.mode.data)); + } + else { + *td->val = td->ival * ratio; + } + /* apply PET */ *td->val = interpf(*td->val, td->ival, td->factor); CLAMP_MIN(*td->val, 0.0f); @@ -92,6 +100,13 @@ void initCurveShrinkFatten(TransInfo *t) t->num.unit_type[0] = B_UNIT_NONE; t->flag |= T_NO_CONSTRAINT; + + if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { + /* Save a factor to multiply the ratio and use in zero radius cases. */ + RegionView3D *rv3d = t->region->regiondata; + float scale_factor = rv3d->pixsize * t->mouse.factor * t->zfac; + t->custom.mode.data = POINTER_FROM_UINT(float_as_uint(scale_factor)); + } } /** \} */ -- cgit v1.2.3 From ca0f4f8c5c5ee049d961d8a65a3da1bedd428ac6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 23 Oct 2022 14:07:22 +1100 Subject: Fix crash on exit when background rendering in wayland Disable libdecor Wayland requirement which would use an X11 fallback. While the crash could be investigated, using libdecor at all makes no sense in background mode. --- intern/ghost/GHOST_ISystem.h | 4 +++- intern/ghost/intern/GHOST_C-api.cpp | 2 +- intern/ghost/intern/GHOST_ISystem.cpp | 8 ++++---- intern/ghost/intern/GHOST_SystemWayland.cpp | 13 ++++++++++++- intern/ghost/intern/GHOST_SystemWayland.h | 3 ++- 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 64b5f4ee496..edaeca1e159 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -118,9 +118,11 @@ class GHOST_ISystem { /** * Creates the one and only system. * \param verbose: report back-ends that were attempted no back-end could be loaded. + * \param background: loading the system for background rendering (no visible windows). * \return An indication of success. */ - static GHOST_TSuccess createSystem(bool verbose); + + static GHOST_TSuccess createSystem(bool verbose, bool background); static GHOST_TSuccess createSystemBackground(); /** diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index aa2363c10b3..0c595b27148 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -24,7 +24,7 @@ GHOST_SystemHandle GHOST_CreateSystem(void) { - GHOST_ISystem::createSystem(true); + GHOST_ISystem::createSystem(true, false); GHOST_ISystem *system = GHOST_ISystem::getSystem(); return (GHOST_SystemHandle)system; diff --git a/intern/ghost/intern/GHOST_ISystem.cpp b/intern/ghost/intern/GHOST_ISystem.cpp index 8e2859ca1e1..696848ce623 100644 --- a/intern/ghost/intern/GHOST_ISystem.cpp +++ b/intern/ghost/intern/GHOST_ISystem.cpp @@ -34,7 +34,7 @@ const char *GHOST_ISystem::m_system_backend_id = nullptr; GHOST_TBacktraceFn GHOST_ISystem::m_backtrace_fn = nullptr; -GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose) +GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose, [[maybe_unused]] bool background) { /* When GHOST fails to start, report the back-ends that were attempted. * A Verbose argument could be supported in printing isn't always desired. */ @@ -61,7 +61,7 @@ GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose) if (has_wayland_libraries) { backends_attempted[backends_attempted_num++] = "WAYLAND"; try { - m_system = new GHOST_SystemWayland(); + m_system = new GHOST_SystemWayland(background); } catch (const std::runtime_error &) { delete m_system; @@ -99,7 +99,7 @@ GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose) if (has_wayland_libraries) { backends_attempted[backends_attempted_num++] = "WAYLAND"; try { - m_system = new GHOST_SystemWayland(); + m_system = new GHOST_SystemWayland(background); } catch (const std::runtime_error &) { delete m_system; @@ -160,7 +160,7 @@ GHOST_TSuccess GHOST_ISystem::createSystemBackground() if (!m_system) { #if !defined(WITH_HEADLESS) /* Try to create a off-screen render surface with the graphical systems. */ - success = createSystem(false); + success = createSystem(false, true); if (success) { return success; } diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 442e51d4f7c..232c17dcde4 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -4162,7 +4162,8 @@ static const struct wl_registry_listener registry_listener = { * WAYLAND specific implementation of the #GHOST_System interface. * \{ */ -GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Display) +GHOST_SystemWayland::GHOST_SystemWayland(bool background) + : GHOST_System(), display_(new GWL_Display) { wl_log_set_handler_client(ghost_wayland_log_handler); @@ -4187,6 +4188,14 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di wl_registry_destroy(registry); #ifdef WITH_GHOST_WAYLAND_LIBDECOR + /* Ignore windowing requirements when running in background mode, + * as it doesn't make sense to fall back to X11 because of windowing functionality + * in background mode, also LIBDECOR is crashing in background mode `blender -b -f 1` + * for e.g. while it could be fixed, requiring the library at all makes no sense . */ + if (background) { + display_->libdecor_required = false; + } + if (display_->libdecor_required) { gwl_xdg_decor_system_destroy(display_->xdg_decor); display_->xdg_decor = nullptr; @@ -4200,6 +4209,8 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di # endif display_destroy(display_); throw std::runtime_error("Wayland: unable to find libdecor!"); + + use_libdecor = true; } } else { diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index f08e9fdcf9c..c27f175002e 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -84,7 +84,8 @@ struct GWL_Output { class GHOST_SystemWayland : public GHOST_System { public: - GHOST_SystemWayland(); + GHOST_SystemWayland(bool background); + GHOST_SystemWayland() : GHOST_SystemWayland(true){}; ~GHOST_SystemWayland() override; -- cgit v1.2.3 From 763ad17769f46f363a3c767deb7bd007509ee7e2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 23 Oct 2022 15:24:06 +1100 Subject: GHOST/Wayland: support building with older versions of pointer-gestures Missing support for the hold gesture broke building on the build-bot. Since this gesture was only logged, it's harmless to leave it off. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 36 ++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 232c17dcde4..2760c3fba8b 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -604,9 +604,15 @@ struct GWL_Seat { struct wl_keyboard *wl_keyboard = nullptr; struct zwp_tablet_seat_v2 *wp_tablet_seat = nullptr; +#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE struct zwp_pointer_gesture_hold_v1 *wp_pointer_gesture_hold = nullptr; +#endif +#ifdef ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch = nullptr; +#endif +#ifdef ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE struct zwp_pointer_gesture_swipe_v1 *wp_pointer_gesture_swipe = nullptr; +#endif /** All currently active tablet tools (needed for changing the cursor). */ std::unordered_set tablet_tools; @@ -2313,8 +2319,9 @@ static const struct wl_pointer_listener pointer_listener = { /** \name Listener (Pointer Gesture: Hold), #zwp_pointer_gesture_hold_v1_listener * \{ */ +#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE static CLG_LogRef LOG_WL_POINTER_GESTURE_HOLD = {"ghost.wl.handle.pointer_gesture.hold"}; -#define LOG (&LOG_WL_POINTER_GESTURE_HOLD) +# define LOG (&LOG_WL_POINTER_GESTURE_HOLD) static void gesture_hold_handle_begin( void * /*data*/, @@ -2342,7 +2349,8 @@ static const struct zwp_pointer_gesture_hold_v1_listener gesture_hold_listener = gesture_hold_handle_end, }; -#undef LOG +# undef LOG +#endif /* ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE */ /** \} */ @@ -2350,8 +2358,9 @@ static const struct zwp_pointer_gesture_hold_v1_listener gesture_hold_listener = /** \name Listener (Pointer Gesture: Pinch), #zwp_pointer_gesture_pinch_v1_listener * \{ */ +#ifdef ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE static CLG_LogRef LOG_WL_POINTER_GESTURE_PINCH = {"ghost.wl.handle.pointer_gesture.pinch"}; -#define LOG (&LOG_WL_POINTER_GESTURE_PINCH) +# define LOG (&LOG_WL_POINTER_GESTURE_PINCH) static void gesture_pinch_handle_begin(void *data, struct zwp_pointer_gesture_pinch_v1 * /*pinch*/, @@ -2469,7 +2478,8 @@ static const struct zwp_pointer_gesture_pinch_v1_listener gesture_pinch_listener gesture_pinch_handle_end, }; -#undef LOG +# undef LOG +#endif /* ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE */ /** \} */ @@ -2482,8 +2492,9 @@ static const struct zwp_pointer_gesture_pinch_v1_listener gesture_pinch_listener * (swiping with 3+ fingers, for e.g.). So keep this to allow logging & testing gestures. * \{ */ +#ifdef ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE static CLG_LogRef LOG_WL_POINTER_GESTURE_SWIPE = {"ghost.wl.handle.pointer_gesture.swipe"}; -#define LOG (&LOG_WL_POINTER_GESTURE_SWIPE) +# define LOG (&LOG_WL_POINTER_GESTURE_SWIPE) static void gesture_swipe_handle_begin( void * /*data*/, @@ -2522,7 +2533,8 @@ static const struct zwp_pointer_gesture_swipe_v1_listener gesture_swipe_listener gesture_swipe_handle_end, }; -#undef LOG +# undef LOG +#endif /* ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE */ /** \} */ @@ -3571,6 +3583,7 @@ static void gwl_seat_capability_pointer_enable(GWL_Seat *seat) zwp_pointer_gestures_v1 *pointer_gestures = seat->system->wp_pointer_gestures(); if (pointer_gestures) { +#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE { /* Hold gesture. */ struct zwp_pointer_gesture_hold_v1 *gesture = zwp_pointer_gestures_v1_get_hold_gesture( pointer_gestures, seat->wl_pointer); @@ -3578,6 +3591,8 @@ static void gwl_seat_capability_pointer_enable(GWL_Seat *seat) zwp_pointer_gesture_hold_v1_add_listener(gesture, &gesture_hold_listener, seat); seat->wp_pointer_gesture_hold = gesture; } +#endif +#ifdef ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE { /* Pinch gesture. */ struct zwp_pointer_gesture_pinch_v1 *gesture = zwp_pointer_gestures_v1_get_pinch_gesture( pointer_gestures, seat->wl_pointer); @@ -3585,6 +3600,8 @@ static void gwl_seat_capability_pointer_enable(GWL_Seat *seat) zwp_pointer_gesture_pinch_v1_add_listener(gesture, &gesture_pinch_listener, seat); seat->wp_pointer_gesture_pinch = gesture; } +#endif +#ifdef ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE { /* Swipe gesture. */ struct zwp_pointer_gesture_swipe_v1 *gesture = zwp_pointer_gestures_v1_get_swipe_gesture( pointer_gestures, seat->wl_pointer); @@ -3592,6 +3609,7 @@ static void gwl_seat_capability_pointer_enable(GWL_Seat *seat) zwp_pointer_gesture_swipe_v1_add_listener(gesture, &gesture_swipe_listener, seat); seat->wp_pointer_gesture_swipe = gesture; } +#endif } } @@ -3603,6 +3621,7 @@ static void gwl_seat_capability_pointer_disable(GWL_Seat *seat) zwp_pointer_gestures_v1 *pointer_gestures = seat->system->wp_pointer_gestures(); if (pointer_gestures) { +#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE { /* Hold gesture. */ struct zwp_pointer_gesture_hold_v1 **gesture_p = &seat->wp_pointer_gesture_hold; if (*gesture_p) { @@ -3610,6 +3629,8 @@ static void gwl_seat_capability_pointer_disable(GWL_Seat *seat) *gesture_p = nullptr; } } +#endif +#ifdef ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE { /* Pinch gesture. */ struct zwp_pointer_gesture_pinch_v1 **gesture_p = &seat->wp_pointer_gesture_pinch; if (*gesture_p) { @@ -3617,6 +3638,8 @@ static void gwl_seat_capability_pointer_disable(GWL_Seat *seat) *gesture_p = nullptr; } } +#endif +#ifdef ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE { /* Swipe gesture. */ struct zwp_pointer_gesture_swipe_v1 **gesture_p = &seat->wp_pointer_gesture_swipe; if (*gesture_p) { @@ -3624,6 +3647,7 @@ static void gwl_seat_capability_pointer_disable(GWL_Seat *seat) *gesture_p = nullptr; } } +#endif } if (seat->cursor.wl_surface) { -- cgit v1.2.3 From 4130cad4891e0ccd568934b0ee5b505d1a933d0f Mon Sep 17 00:00:00 2001 From: Jesse Yurkovich Date: Sat, 22 Oct 2022 20:22:31 -0700 Subject: Fix T101607: Changing Image source inadvertently clears file path This could result in wrong behavior depending on the order in which the Image.filepath and Image.source fields are set from within Python for example. Caused by rB72ab6faf5d80 --- source/blender/blenkernel/intern/image.cc | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/source/blender/blenkernel/intern/image.cc b/source/blender/blenkernel/intern/image.cc index 51d8f02616f..eae8b454189 100644 --- a/source/blender/blenkernel/intern/image.cc +++ b/source/blender/blenkernel/intern/image.cc @@ -3082,16 +3082,10 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal) /* Free all but the first tile. */ image_remove_all_tiles(ima); - /* If the remaining tile is generated, we need to again ensure that we - * wouldn't continue to use the old filepath. - * - * Otherwise, if this used to be a UDIM image, get the concrete filepath associated + /* If this used to be a UDIM image, get the concrete filepath associated * with the remaining tile and use that as the new filepath. */ ImageTile *base_tile = BKE_image_get_tile(ima, 0); - if ((base_tile->gen_flag & IMA_GEN_TILE) != 0) { - ima->filepath[0] = '\0'; - } - else if (BKE_image_is_filename_tokenized(ima->filepath)) { + if (BKE_image_is_filename_tokenized(ima->filepath)) { const bool was_relative = BLI_path_is_rel(ima->filepath); eUDIM_TILE_FORMAT tile_format; @@ -3183,10 +3177,14 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal) * left. */ image_remove_all_tiles(ima); - int remaining_tile_number = ((ImageTile *)ima->tiles.first)->tile_number; + ImageTile *base_tile = BKE_image_get_tile(ima, 0); + int remaining_tile_number = base_tile->tile_number; bool needs_final_cleanup = true; - /* Add in all the new tiles. */ + /* Add in all the new tiles. As the image is proven to be on disk at this point, remove + * the generation flag from the remaining tile in case this was previously a generated + * image. */ + base_tile->gen_flag &= ~IMA_GEN_TILE; LISTBASE_FOREACH (LinkData *, new_tile, &new_tiles) { int new_tile_number = POINTER_AS_INT(new_tile->data); BKE_image_add_tile(ima, new_tile_number, nullptr); @@ -3202,6 +3200,11 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal) } BLI_freelistN(&new_tiles); } + else if (ima->filepath[0] != '\0') { + /* If the filepath is set at this point remove the generation flag. */ + ImageTile *base_tile = BKE_image_get_tile(ima, 0); + base_tile->gen_flag &= ~IMA_GEN_TILE; + } if (iuser) { image_tag_reload(ima, nullptr, iuser, ima); -- cgit v1.2.3 From 6172258250fd137251adffefafdfa066d74d692a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 23 Oct 2022 17:20:23 +1100 Subject: Fix build error when WITH_GHOST_DEBUG is enabled --- intern/ghost/intern/GHOST_SystemWayland.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 2760c3fba8b..67f475a2963 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1096,7 +1096,7 @@ static GHOST_TTabletMode tablet_tool_map_type(enum zwp_tablet_tool_v2_type wp_ta } } - GHOST_PRINT("unknown tablet tool: " << wl_tablet_tool_type << std::endl); + GHOST_PRINT("unknown tablet tool: " << wp_tablet_tool_type << std::endl); return GHOST_kTabletModeStylus; } -- cgit v1.2.3 From da36efdf487b35df20a6110348e919df203dec63 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 23 Oct 2022 17:28:15 +1100 Subject: GHOST: expand GHOST_PRINT/PRINTF without WITH_GHOST_DEBUG It was too easy accidentally break builds without WITH_GHOST_DEBUG enabled because the arguments were ignored. Now they are expanded in an `if (0) {...}` block, so invalid expressions result in errors. --- intern/ghost/intern/GHOST_Debug.h | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h index ec1a0b34be6..64eff7f9aed 100644 --- a/intern/ghost/intern/GHOST_Debug.h +++ b/intern/ghost/intern/GHOST_Debug.h @@ -15,29 +15,41 @@ # endif #endif -#if defined(WITH_GHOST_DEBUG) || (!defined(NDEBUG)) -# include -# include //for printf() -#endif // WITH_GHOST_DEBUG +#include +#include /* For `printf()`. */ #if defined(WITH_GHOST_DEBUG) # define GHOST_PRINT(x) \ { \ std::cout << x; \ } \ - (void)0 + ((void)0) # define GHOST_PRINTF(x, ...) \ { \ printf(x, __VA_ARGS__); \ } \ - (void)0 + ((void)0) #else -# define GHOST_PRINT(x) -# define GHOST_PRINTF(x, ...) +/* Expand even when `WITH_GHOST_DEBUG` is disabled to prevent expressions + * becoming invalid even when the option is disable. */ +# define GHOST_PRINT(x) \ + { \ + if (false) { \ + std::cout << x; \ + } \ + } \ + ((void)0) +# define GHOST_PRINTF(x, ...) \ + { \ + if (false) { \ + printf(x, __VA_ARGS__); \ + } \ + } \ + ((void)0) + #endif /* `!defined(WITH_GHOST_DEBUG)` */ #ifdef WITH_ASSERT_ABORT -# include //for fprintf() # include //for abort() # define GHOST_ASSERT(x, info) \ { \ @@ -48,7 +60,7 @@ abort(); \ } \ } \ - (void)0 + ((void)0) /* Assert in non-release builds too. */ #elif defined(WITH_GHOST_DEBUG) || (!defined(NDEBUG)) # define GHOST_ASSERT(x, info) \ @@ -59,7 +71,7 @@ GHOST_PRINT("\n"); \ } \ } \ - (void)0 + ((void)0) #else /* `defined(WITH_GHOST_DEBUG) || (!defined(NDEBUG))` */ # define GHOST_ASSERT(x, info) ((void)0) #endif /* `defined(WITH_GHOST_DEBUG) || (!defined(NDEBUG))` */ -- cgit v1.2.3 From 93afc50ac3effb384d2fdcdbe193fb9da6191f96 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Sun, 23 Oct 2022 11:34:44 -0300 Subject: Fix large incremental snap values in uv editor Regression in rBa7aa0f1a0c24. The default values of `t->snap` have been changed. --- source/blender/editors/transform/transform_mode_translate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index c751a68092f..59d34c3918b 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -686,8 +686,8 @@ void initTranslation(TransInfo *t) t->num.flag = 0; t->num.idx_max = t->idx_max; - t->snap[0] = 1.0; - t->snap[1] = t->snap_spatial_precision; + t->snap[0] = t->snap_spatial[0]; + t->snap[1] = t->snap_spatial[0] * t->snap_spatial_precision; copy_v3_fl(t->num.val_inc, t->snap[0]); t->num.unit_sys = t->scene->unit.system; -- cgit v1.2.3 From b7c5ce8c2d2df9a06527651cfc301d7f2d45633a Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Mon, 24 Oct 2022 00:16:21 -0300 Subject: Transform: limit zero radius Shrink/Fatten to only 1 curve point rBb70bbfadfece allowed scaling of zero-radius points, but as it behaves differently from other radius, it may not be suitable for multi-point transformation. --- .../editors/transform/transform_mode_curveshrinkfatten.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c index 76ce7b29619..d8f04dea161 100644 --- a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c +++ b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c @@ -101,12 +101,17 @@ void initCurveShrinkFatten(TransInfo *t) t->flag |= T_NO_CONSTRAINT; - if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { - /* Save a factor to multiply the ratio and use in zero radius cases. */ + float scale_factor = 0.0f; + if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW) && + t->data_len_all == 1 || + (t->data_len_all == 3 && TRANS_DATA_CONTAINER_FIRST_OK(t)->data[0].val == NULL)) { + /* For cases where only one point on the curve is being transformed and the radius of that + * point is zero, use the factor to multiply the offset of the ratio and allow scaling. + * Note that for bezier curves, 3 TransData equals 1 point in most cases. */ RegionView3D *rv3d = t->region->regiondata; - float scale_factor = rv3d->pixsize * t->mouse.factor * t->zfac; - t->custom.mode.data = POINTER_FROM_UINT(float_as_uint(scale_factor)); + scale_factor = rv3d->pixsize * t->mouse.factor * t->zfac; } + t->custom.mode.data = POINTER_FROM_UINT(float_as_uint(scale_factor)); } /** \} */ -- cgit v1.2.3 From b27c831e0cdcbd5e9792a8311e53ca31654a1d9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Thu, 20 Oct 2022 14:30:22 +0200 Subject: GPencil: Port draw_cache_impl_gpencil.cc to C++ --- source/blender/draw/CMakeLists.txt | 2 +- .../blender/draw/intern/draw_cache_impl_gpencil.c | 962 -------------------- .../blender/draw/intern/draw_cache_impl_gpencil.cc | 963 +++++++++++++++++++++ 3 files changed, 964 insertions(+), 963 deletions(-) delete mode 100644 source/blender/draw/intern/draw_cache_impl_gpencil.c create mode 100644 source/blender/draw/intern/draw_cache_impl_gpencil.cc diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index a645bd6b6af..1c17f92f073 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -71,7 +71,7 @@ set(SRC intern/draw_attributes.cc intern/draw_cache_impl_curve.cc intern/draw_cache_impl_curves.cc - intern/draw_cache_impl_gpencil.c + intern/draw_cache_impl_gpencil.cc intern/draw_cache_impl_lattice.c intern/draw_cache_impl_mesh.cc intern/draw_cache_impl_particles.c diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c deleted file mode 100644 index 7a43c7ee2e6..00000000000 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.c +++ /dev/null @@ -1,962 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later - * Copyright 2020 Blender Foundation. */ - -/** \file - * \ingroup draw - */ - -#include "DNA_curve_types.h" -#include "DNA_gpencil_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_screen_types.h" - -#include "BKE_deform.h" -#include "BKE_gpencil.h" -#include "BKE_gpencil_geom.h" - -#include "DRW_engine.h" -#include "DRW_render.h" - -#include "ED_gpencil.h" -#include "GPU_batch.h" - -#include "DEG_depsgraph_query.h" - -#include "BLI_hash.h" -#include "BLI_polyfill_2d.h" - -#include "draw_cache.h" -#include "draw_cache_impl.h" - -#include "../engines/gpencil/gpencil_defines.h" - -#define BEZIER_HANDLE (1 << 3) -#define COLOR_SHIFT 5 - -/* -------------------------------------------------------------------- */ -/** \name Internal Types - * \{ */ - -typedef struct GpencilBatchCache { - /** Instancing Data */ - GPUVertBuf *vbo; - GPUVertBuf *vbo_col; - /** Fill Topology */ - GPUIndexBuf *ibo; - /** Instancing Batches */ - GPUBatch *stroke_batch; - GPUBatch *fill_batch; - GPUBatch *lines_batch; - - /** Edit Mode */ - GPUVertBuf *edit_vbo; - GPUBatch *edit_lines_batch; - GPUBatch *edit_points_batch; - /** Edit Curve Mode */ - GPUVertBuf *edit_curve_vbo; - GPUBatch *edit_curve_handles_batch; - GPUBatch *edit_curve_points_batch; - - /** Cache is dirty */ - bool is_dirty; - /** Last cache frame */ - int cache_frame; -} GpencilBatchCache; - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Internal Utilities - * \{ */ - -static bool gpencil_batch_cache_valid(GpencilBatchCache *cache, bGPdata *gpd, int cfra) -{ - bool valid = true; - - if (cache == NULL) { - return false; - } - - if (cfra != cache->cache_frame) { - valid = false; - } - else if (gpd->flag & GP_DATA_CACHE_IS_DIRTY) { - valid = false; - } - else if (cache->is_dirty) { - valid = false; - } - - return valid; -} - -static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra) -{ - bGPdata *gpd = (bGPdata *)ob->data; - - GpencilBatchCache *cache = gpd->runtime.gpencil_cache; - - if (!cache) { - cache = gpd->runtime.gpencil_cache = MEM_callocN(sizeof(*cache), __func__); - } - else { - memset(cache, 0, sizeof(*cache)); - } - - cache->is_dirty = true; - cache->cache_frame = cfra; - - return cache; -} - -static void gpencil_batch_cache_clear(GpencilBatchCache *cache) -{ - if (!cache) { - return; - } - - GPU_BATCH_DISCARD_SAFE(cache->lines_batch); - GPU_BATCH_DISCARD_SAFE(cache->fill_batch); - GPU_BATCH_DISCARD_SAFE(cache->stroke_batch); - GPU_VERTBUF_DISCARD_SAFE(cache->vbo); - GPU_VERTBUF_DISCARD_SAFE(cache->vbo_col); - GPU_INDEXBUF_DISCARD_SAFE(cache->ibo); - - GPU_BATCH_DISCARD_SAFE(cache->edit_lines_batch); - GPU_BATCH_DISCARD_SAFE(cache->edit_points_batch); - GPU_VERTBUF_DISCARD_SAFE(cache->edit_vbo); - - GPU_BATCH_DISCARD_SAFE(cache->edit_curve_handles_batch); - GPU_BATCH_DISCARD_SAFE(cache->edit_curve_points_batch); - GPU_VERTBUF_DISCARD_SAFE(cache->edit_curve_vbo); - - cache->is_dirty = true; -} - -static GpencilBatchCache *gpencil_batch_cache_get(Object *ob, int cfra) -{ - bGPdata *gpd = (bGPdata *)ob->data; - - GpencilBatchCache *cache = gpd->runtime.gpencil_cache; - if (!gpencil_batch_cache_valid(cache, gpd, cfra)) { - gpencil_batch_cache_clear(cache); - return gpencil_batch_cache_init(ob, cfra); - } - - return cache; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name BKE Callbacks - * \{ */ - -void DRW_gpencil_batch_cache_dirty_tag(bGPdata *gpd) -{ - gpd->flag |= GP_DATA_CACHE_IS_DIRTY; -} - -void DRW_gpencil_batch_cache_free(bGPdata *gpd) -{ - gpencil_batch_cache_clear(gpd->runtime.gpencil_cache); - MEM_SAFE_FREE(gpd->runtime.gpencil_cache); - gpd->flag |= GP_DATA_CACHE_IS_DIRTY; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Vertex Formats - * \{ */ - -/* MUST match the format below. */ -typedef struct gpStrokeVert { - int32_t mat, stroke_id, point_id, packed_asp_hard_rot; - /** Position and thickness packed in the same attribute. */ - float pos[3], thickness; - /** UV and strength packed in the same attribute. */ - float uv_fill[2], u_stroke, strength; -} gpStrokeVert; - -static GPUVertFormat *gpencil_stroke_format(void) -{ - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "ma", GPU_COMP_I32, 4, GPU_FETCH_INT); - GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - GPU_vertformat_attr_add(&format, "uv", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - /* IMPORTANT: This means having only 4 attributes - * to fit into GPU module limit of 16 attributes. */ - GPU_vertformat_multiload_enable(&format, 4); - } - return &format; -} - -/* MUST match the format below. */ -typedef struct gpEditVert { - uint vflag; - float weight; -} gpEditVert; - -static GPUVertFormat *gpencil_edit_stroke_format(void) -{ - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "vflag", GPU_COMP_U32, 1, GPU_FETCH_INT); - GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - } - return &format; -} - -/* MUST match the format below. */ -typedef struct gpEditCurveVert { - float pos[3]; - uint32_t data; -} gpEditCurveVert; - -static GPUVertFormat *gpencil_edit_curve_format(void) -{ - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - /* initialize vertex formats */ - GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - GPU_vertformat_attr_add(&format, "data", GPU_COMP_U32, 1, GPU_FETCH_INT); - } - return &format; -} - -/* MUST match the format below. */ -typedef struct gpColorVert { - float vcol[4]; /* Vertex color */ - float fcol[4]; /* Fill color */ -} gpColorVert; - -static GPUVertFormat *gpencil_color_format(void) -{ - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "col", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - GPU_vertformat_attr_add(&format, "fcol", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - /* IMPORTANT: This means having only 4 attributes - * to fit into GPU module limit of 16 attributes. */ - GPU_vertformat_multiload_enable(&format, 4); - } - return &format; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Vertex Buffers - * \{ */ - -typedef struct gpIterData { - bGPdata *gpd; - gpStrokeVert *verts; - gpColorVert *cols; - GPUIndexBufBuilder ibo; - int vert_len; - int tri_len; - int curve_len; -} gpIterData; - -static GPUVertBuf *gpencil_dummy_buffer_get(void) -{ - GPUBatch *batch = DRW_gpencil_dummy_buffer_get(); - return batch->verts[0]; -} - -static int gpencil_stroke_is_cyclic(const bGPDstroke *gps) -{ - return ((gps->flag & GP_STROKE_CYCLIC) != 0) && (gps->totpoints > 2); -} - -BLI_INLINE int32_t pack_rotation_aspect_hardness(float rot, float asp, float hard) -{ - int32_t packed = 0; - /* Aspect uses 9 bits */ - float asp_normalized = (asp > 1.0f) ? (1.0f / asp) : asp; - packed |= (int32_t)unit_float_to_uchar_clamp(asp_normalized); - /* Store if inversed in the 9th bit. */ - if (asp > 1.0f) { - packed |= 1 << 8; - } - /* Rotation uses 9 bits */ - /* Rotation are in [-90°..90°] range, so we can encode the sign of the angle + the cosine - * because the cosine will always be positive. */ - packed |= (int32_t)unit_float_to_uchar_clamp(cosf(rot)) << 9; - /* Store sine sign in 9th bit. */ - if (rot < 0.0f) { - packed |= 1 << 17; - } - /* Hardness uses 8 bits */ - packed |= (int32_t)unit_float_to_uchar_clamp(hard) << 18; - return packed; -} - -static void gpencil_buffer_add_point(gpStrokeVert *verts, - gpColorVert *cols, - const bGPDstroke *gps, - const bGPDspoint *pt, - int v, - bool is_endpoint) -{ - /* NOTE: we use the sign of strength and thickness to pass cap flag. */ - const bool round_cap0 = (gps->caps[0] == GP_STROKE_CAP_ROUND); - const bool round_cap1 = (gps->caps[1] == GP_STROKE_CAP_ROUND); - gpStrokeVert *vert = &verts[v]; - gpColorVert *col = &cols[v]; - copy_v3_v3(vert->pos, &pt->x); - copy_v2_v2(vert->uv_fill, pt->uv_fill); - copy_v4_v4(col->vcol, pt->vert_color); - copy_v4_v4(col->fcol, gps->vert_color_fill); - - /* Encode fill opacity defined by opacity modifier in vertex color alpha. If - * no opacity modifier, the value will be always 1.0f. The opacity factor can be any - * value between 0.0f and 2.0f */ - col->fcol[3] = ((int)(col->fcol[3] * 10000.0f) * 10.0f) + gps->fill_opacity_fac; - - vert->strength = (round_cap0) ? pt->strength : -pt->strength; - vert->u_stroke = pt->uv_fac; - vert->stroke_id = gps->runtime.stroke_start; - vert->point_id = v; - vert->thickness = max_ff(0.0f, gps->thickness * pt->pressure) * (round_cap1 ? 1.0f : -1.0f); - /* Tag endpoint material to -1 so they get discarded by vertex shader. */ - vert->mat = (is_endpoint) ? -1 : (gps->mat_nr % GPENCIL_MATERIAL_BUFFER_LEN); - - float aspect_ratio = gps->aspect_ratio[0] / max_ff(gps->aspect_ratio[1], 1e-8); - - vert->packed_asp_hard_rot = pack_rotation_aspect_hardness( - pt->uv_rot, aspect_ratio, gps->hardeness); -} - -static void gpencil_buffer_add_stroke(gpStrokeVert *verts, - gpColorVert *cols, - const bGPDstroke *gps) -{ - const bGPDspoint *pts = gps->points; - int pts_len = gps->totpoints; - bool is_cyclic = gpencil_stroke_is_cyclic(gps); - int v = gps->runtime.stroke_start; - - /* First point for adjacency (not drawn). */ - int adj_idx = (is_cyclic) ? (pts_len - 1) : min_ii(pts_len - 1, 1); - gpencil_buffer_add_point(verts, cols, gps, &pts[adj_idx], v++, true); - - for (int i = 0; i < pts_len; i++) { - gpencil_buffer_add_point(verts, cols, gps, &pts[i], v++, false); - } - /* Draw line to first point to complete the loop for cyclic strokes. */ - if (is_cyclic) { - gpencil_buffer_add_point(verts, cols, gps, &pts[0], v, false); - /* UV factor needs to be adjusted for the last point to not be equal to the UV factor of the - * first point. It should be the factor of the last point plus the distance from the last point - * to the first. - */ - gpStrokeVert *vert = &verts[v]; - vert->u_stroke = verts[v - 1].u_stroke + len_v3v3(&pts[pts_len - 1].x, &pts[0].x); - v++; - } - /* Last adjacency point (not drawn). */ - adj_idx = (is_cyclic) ? 1 : max_ii(0, pts_len - 2); - gpencil_buffer_add_point(verts, cols, gps, &pts[adj_idx], v++, true); -} - -static void gpencil_buffer_add_fill(GPUIndexBufBuilder *ibo, const bGPDstroke *gps) -{ - int tri_len = gps->tot_triangles; - int v = gps->runtime.stroke_start; - for (int i = 0; i < tri_len; i++) { - uint *tri = gps->triangles[i].verts; - GPU_indexbuf_add_tri_verts(ibo, v + tri[0], v + tri[1], v + tri[2]); - } -} - -static void gpencil_stroke_iter_cb(bGPDlayer *UNUSED(gpl), - bGPDframe *UNUSED(gpf), - bGPDstroke *gps, - void *thunk) -{ - gpIterData *iter = (gpIterData *)thunk; - gpencil_buffer_add_stroke(iter->verts, iter->cols, gps); - if (gps->tot_triangles > 0) { - gpencil_buffer_add_fill(&iter->ibo, gps); - } -} - -static void gpencil_object_verts_count_cb(bGPDlayer *UNUSED(gpl), - bGPDframe *UNUSED(gpf), - bGPDstroke *gps, - void *thunk) -{ - gpIterData *iter = (gpIterData *)thunk; - - /* Store first index offset */ - gps->runtime.stroke_start = iter->vert_len; - gps->runtime.fill_start = iter->tri_len; - iter->vert_len += gps->totpoints + 2 + gpencil_stroke_is_cyclic(gps); - iter->tri_len += gps->tot_triangles; -} - -static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfra) -{ - bGPdata *gpd = (bGPdata *)ob->data; - - if (cache->vbo == NULL) { - /* Should be discarded together. */ - BLI_assert(cache->vbo == NULL && cache->ibo == NULL); - BLI_assert(cache->fill_batch == NULL && cache->stroke_batch == NULL); - /* TODO/PERF: Could be changed to only do it if needed. - * For now it's simpler to assume we always need it - * since multiple viewport could or could not need it. - * Ideally we should have a dedicated onion skin geom batch. */ - /* IMPORTANT: Keep in sync with gpencil_edit_batches_ensure() */ - bool do_onion = true; - - /* First count how many vertices and triangles are needed for the whole object. */ - gpIterData iter = { - .gpd = gpd, - .verts = NULL, - .ibo = {0}, - .vert_len = 1, /* Start at 1 for the gl_InstanceID trick to work (see vert shader). */ - .tri_len = 0, - .curve_len = 0, - }; - BKE_gpencil_visible_stroke_advanced_iter( - NULL, ob, NULL, gpencil_object_verts_count_cb, &iter, do_onion, cfra); - - /* Create VBOs. */ - GPUVertFormat *format = gpencil_stroke_format(); - GPUVertFormat *format_col = gpencil_color_format(); - cache->vbo = GPU_vertbuf_create_with_format(format); - cache->vbo_col = GPU_vertbuf_create_with_format(format_col); - /* Add extra space at the end of the buffer because of quad load. */ - GPU_vertbuf_data_alloc(cache->vbo, iter.vert_len + 2); - GPU_vertbuf_data_alloc(cache->vbo_col, iter.vert_len + 2); - iter.verts = (gpStrokeVert *)GPU_vertbuf_get_data(cache->vbo); - iter.cols = (gpColorVert *)GPU_vertbuf_get_data(cache->vbo_col); - /* Create IBO. */ - GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, iter.vert_len); - - /* Fill buffers with data. */ - BKE_gpencil_visible_stroke_advanced_iter( - NULL, ob, NULL, gpencil_stroke_iter_cb, &iter, do_onion, cfra); - - /* Mark last 2 verts as invalid. */ - for (int i = 0; i < 2; i++) { - iter.verts[iter.vert_len + i].mat = -1; - } - /* Also mark first vert as invalid. */ - iter.verts[0].mat = -1; - - /* Finish the IBO. */ - cache->ibo = GPU_indexbuf_build(&iter.ibo); - - /* Create the batches */ - cache->fill_batch = GPU_batch_create(GPU_PRIM_TRIS, cache->vbo, cache->ibo); - GPU_batch_vertbuf_add(cache->fill_batch, cache->vbo_col); - cache->stroke_batch = GPU_batch_create(GPU_PRIM_TRI_STRIP, gpencil_dummy_buffer_get(), NULL); - GPU_batch_instbuf_add_ex(cache->stroke_batch, cache->vbo, 0); - GPU_batch_instbuf_add_ex(cache->stroke_batch, cache->vbo_col, 0); - - gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY; - cache->is_dirty = false; - } -} - -GPUBatch *DRW_cache_gpencil_strokes_get(Object *ob, int cfra) -{ - GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); - gpencil_batches_ensure(ob, cache, cfra); - - return cache->stroke_batch; -} - -GPUBatch *DRW_cache_gpencil_fills_get(Object *ob, int cfra) -{ - GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); - gpencil_batches_ensure(ob, cache, cfra); - - return cache->fill_batch; -} - -static void gpencil_lines_indices_cb(bGPDlayer *UNUSED(gpl), - bGPDframe *UNUSED(gpf), - bGPDstroke *gps, - void *thunk) -{ - gpIterData *iter = (gpIterData *)thunk; - int pts_len = gps->totpoints + gpencil_stroke_is_cyclic(gps); - - int start = gps->runtime.stroke_start + 1; - int end = start + pts_len; - for (int i = start; i < end; i++) { - GPU_indexbuf_add_generic_vert(&iter->ibo, i); - } - GPU_indexbuf_add_primitive_restart(&iter->ibo); -} - -GPUBatch *DRW_cache_gpencil_face_wireframe_get(Object *ob) -{ - const DRWContextState *draw_ctx = DRW_context_state_get(); - int cfra = DEG_get_ctime(draw_ctx->depsgraph); - - GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); - gpencil_batches_ensure(ob, cache, cfra); - - if (cache->lines_batch == NULL) { - GPUVertBuf *vbo = cache->vbo; - - gpIterData iter = { - .gpd = ob->data, - .ibo = {0}, - }; - - uint vert_len = GPU_vertbuf_get_vertex_len(vbo); - GPU_indexbuf_init_ex(&iter.ibo, GPU_PRIM_LINE_STRIP, vert_len, vert_len); - - /* IMPORTANT: Keep in sync with gpencil_edit_batches_ensure() */ - bool do_onion = true; - BKE_gpencil_visible_stroke_advanced_iter( - NULL, ob, NULL, gpencil_lines_indices_cb, &iter, do_onion, cfra); - - GPUIndexBuf *ibo = GPU_indexbuf_build(&iter.ibo); - - cache->lines_batch = GPU_batch_create_ex(GPU_PRIM_LINE_STRIP, vbo, ibo, GPU_BATCH_OWNS_INDEX); - } - return cache->lines_batch; -} - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Sbuffer stroke batches. - * \{ */ - -bGPDstroke *DRW_cache_gpencil_sbuffer_stroke_data_get(Object *ob) -{ - bGPdata *gpd = (bGPdata *)ob->data; - Brush *brush = gpd->runtime.sbuffer_brush; - /* Convert the sbuffer to a bGPDstroke. */ - if (gpd->runtime.sbuffer_gps == NULL) { - bGPDstroke *gps = MEM_callocN(sizeof(*gps), "bGPDstroke sbuffer"); - gps->totpoints = gpd->runtime.sbuffer_used; - gps->mat_nr = max_ii(0, gpd->runtime.matid - 1); - gps->flag = gpd->runtime.sbuffer_sflag; - gps->thickness = brush->size; - gps->hardeness = brush->gpencil_settings->hardeness; - copy_v2_v2(gps->aspect_ratio, brush->gpencil_settings->aspect_ratio); - - /* Reduce slightly the opacity of fill to make easy fill areas while drawing. */ - gps->fill_opacity_fac = 0.8f; - - gps->tot_triangles = max_ii(0, gpd->runtime.sbuffer_used - 2); - gps->caps[0] = gps->caps[1] = GP_STROKE_CAP_ROUND; - gps->runtime.stroke_start = 1; /* Add one for the adjacency index. */ - copy_v4_v4(gps->vert_color_fill, gpd->runtime.vert_color_fill); - /* Caps. */ - gps->caps[0] = gps->caps[1] = (short)brush->gpencil_settings->caps_type; - - gpd->runtime.sbuffer_gps = gps; - } - return gpd->runtime.sbuffer_gps; -} - -static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_fill) -{ - tGPspoint *tpoints = gpd->runtime.sbuffer; - bGPDstroke *gps = gpd->runtime.sbuffer_gps; - int vert_len = gpd->runtime.sbuffer_used; - - /* DRW_cache_gpencil_sbuffer_stroke_data_get need to have been called previously. */ - BLI_assert(gps != NULL); - - if (do_stroke && (gpd->runtime.sbuffer_stroke_batch == NULL)) { - gps->points = MEM_mallocN(vert_len * sizeof(*gps->points), __func__); - - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - ARegion *region = draw_ctx->region; - Object *ob = draw_ctx->obact; - - BLI_assert(ob && (ob->type == OB_GPENCIL)); - - /* Get origin to reproject points. */ - float origin[3]; - ToolSettings *ts = scene->toolsettings; - ED_gpencil_drawing_reference_get(scene, ob, ts->gpencil_v3d_align, origin); - - for (int i = 0; i < vert_len; i++) { - ED_gpencil_tpoint_to_point(region, origin, &tpoints[i], &gps->points[i]); - mul_m4_v3(ob->imat, &gps->points[i].x); - bGPDspoint *pt = &gps->points[i]; - copy_v4_v4(pt->vert_color, tpoints[i].vert_color); - } - /* Calc uv data along the stroke. */ - BKE_gpencil_stroke_uv_update(gps); - - /* Create VBO. */ - GPUVertFormat *format = gpencil_stroke_format(); - GPUVertFormat *format_color = gpencil_color_format(); - GPUVertBuf *vbo = GPU_vertbuf_create_with_format(format); - GPUVertBuf *vbo_col = GPU_vertbuf_create_with_format(format_color); - /* Add extra space at the end (and start) of the buffer because of quad load and cyclic. */ - GPU_vertbuf_data_alloc(vbo, 1 + vert_len + 1 + 2); - GPU_vertbuf_data_alloc(vbo_col, 1 + vert_len + 1 + 2); - gpStrokeVert *verts = (gpStrokeVert *)GPU_vertbuf_get_data(vbo); - gpColorVert *cols = (gpColorVert *)GPU_vertbuf_get_data(vbo_col); - - /* Fill buffers with data. */ - gpencil_buffer_add_stroke(verts, cols, gps); - - GPUBatch *batch = GPU_batch_create(GPU_PRIM_TRI_STRIP, gpencil_dummy_buffer_get(), NULL); - GPU_batch_instbuf_add_ex(batch, vbo, true); - GPU_batch_instbuf_add_ex(batch, vbo_col, true); - - gpd->runtime.sbuffer_stroke_batch = batch; - - MEM_freeN(gps->points); - } - - if (do_fill && (gpd->runtime.sbuffer_fill_batch == NULL)) { - /* Create IBO. */ - GPUIndexBufBuilder ibo_builder; - GPU_indexbuf_init(&ibo_builder, GPU_PRIM_TRIS, gps->tot_triangles, vert_len); - - if (gps->tot_triangles > 0) { - float(*tpoints2d)[2] = MEM_mallocN(sizeof(*tpoints2d) * vert_len, __func__); - /* Triangulate in 2D. */ - for (int i = 0; i < vert_len; i++) { - copy_v2_v2(tpoints2d[i], tpoints[i].m_xy); - } - /* Compute directly inside the IBO data buffer. */ - /* OPTI: This is a bottleneck if the stroke is very long. */ - BLI_polyfill_calc(tpoints2d, (uint)vert_len, 0, (uint(*)[3])ibo_builder.data); - /* Add stroke start offset. */ - for (int i = 0; i < gps->tot_triangles * 3; i++) { - ibo_builder.data[i] += gps->runtime.stroke_start; - } - /* HACK since we didn't use the builder API to avoid another malloc and copy, - * we need to set the number of indices manually. */ - ibo_builder.index_len = gps->tot_triangles * 3; - - MEM_freeN(tpoints2d); - } - - GPUIndexBuf *ibo = GPU_indexbuf_build(&ibo_builder); - GPUVertBuf *vbo = gpd->runtime.sbuffer_stroke_batch->inst[0]; - GPUVertBuf *vbo_col = gpd->runtime.sbuffer_stroke_batch->inst[1]; - - GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, ibo, GPU_BATCH_OWNS_INDEX); - GPU_batch_vertbuf_add(batch, vbo_col); - - gpd->runtime.sbuffer_fill_batch = batch; - } -} - -GPUBatch *DRW_cache_gpencil_sbuffer_stroke_get(Object *ob) -{ - bGPdata *gpd = (bGPdata *)ob->data; - gpencil_sbuffer_stroke_ensure(gpd, true, false); - - return gpd->runtime.sbuffer_stroke_batch; -} - -GPUBatch *DRW_cache_gpencil_sbuffer_fill_get(Object *ob) -{ - bGPdata *gpd = (bGPdata *)ob->data; - /* Fill batch also need stroke batch to be created (vbo is shared). */ - gpencil_sbuffer_stroke_ensure(gpd, true, true); - - return gpd->runtime.sbuffer_fill_batch; -} - -void DRW_cache_gpencil_sbuffer_clear(Object *ob) -{ - bGPdata *gpd = (bGPdata *)ob->data; - MEM_SAFE_FREE(gpd->runtime.sbuffer_gps); - GPU_BATCH_DISCARD_SAFE(gpd->runtime.sbuffer_fill_batch); - GPU_BATCH_DISCARD_SAFE(gpd->runtime.sbuffer_stroke_batch); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Edit GPencil Batches - * \{ */ - -#define GP_EDIT_POINT_SELECTED (1 << 0) -#define GP_EDIT_STROKE_SELECTED (1 << 1) -#define GP_EDIT_MULTIFRAME (1 << 2) -#define GP_EDIT_STROKE_START (1 << 3) -#define GP_EDIT_STROKE_END (1 << 4) -#define GP_EDIT_POINT_DIMMED (1 << 5) - -typedef struct gpEditIterData { - gpEditVert *verts; - int vgindex; -} gpEditIterData; - -typedef struct gpEditCurveIterData { - gpEditCurveVert *verts; - int vgindex; -} gpEditCurveIterData; - -static uint32_t gpencil_point_edit_flag(const bool layer_lock, - const bGPDspoint *pt, - int v, - int v_len) -{ - uint32_t sflag = 0; - SET_FLAG_FROM_TEST(sflag, (!layer_lock) && pt->flag & GP_SPOINT_SELECT, GP_EDIT_POINT_SELECTED); - SET_FLAG_FROM_TEST(sflag, v == 0, GP_EDIT_STROKE_START); - SET_FLAG_FROM_TEST(sflag, v == (v_len - 1), GP_EDIT_STROKE_END); - SET_FLAG_FROM_TEST(sflag, pt->runtime.pt_orig == NULL, GP_EDIT_POINT_DIMMED); - return sflag; -} - -static float gpencil_point_edit_weight(const MDeformVert *dvert, int v, int vgindex) -{ - return (dvert && dvert[v].dw) ? BKE_defvert_find_weight(&dvert[v], vgindex) : -1.0f; -} - -static void gpencil_edit_stroke_iter_cb(bGPDlayer *gpl, - bGPDframe *gpf, - bGPDstroke *gps, - void *thunk) -{ - gpEditIterData *iter = (gpEditIterData *)thunk; - const int v_len = gps->totpoints; - const int v = gps->runtime.stroke_start + 1; - MDeformVert *dvert = ((iter->vgindex > -1) && gps->dvert) ? gps->dvert : NULL; - gpEditVert *vert_ptr = iter->verts + v; - - const bool layer_lock = (gpl->flag & GP_LAYER_LOCKED); - uint32_t sflag = 0; - SET_FLAG_FROM_TEST( - sflag, (!layer_lock) && gps->flag & GP_STROKE_SELECT, GP_EDIT_STROKE_SELECTED); - SET_FLAG_FROM_TEST(sflag, gpf->runtime.onion_id != 0.0f, GP_EDIT_MULTIFRAME); - - for (int i = 0; i < v_len; i++) { - vert_ptr->vflag = sflag | gpencil_point_edit_flag(layer_lock, &gps->points[i], i, v_len); - vert_ptr->weight = gpencil_point_edit_weight(dvert, i, iter->vgindex); - vert_ptr++; - } - /* Draw line to first point to complete the loop for cyclic strokes. */ - vert_ptr->vflag = sflag | gpencil_point_edit_flag(layer_lock, &gps->points[0], 0, v_len); - vert_ptr->weight = gpencil_point_edit_weight(dvert, 0, iter->vgindex); -} - -static void gpencil_edit_curve_stroke_count_cb(bGPDlayer *gpl, - bGPDframe *UNUSED(gpf), - bGPDstroke *gps, - void *thunk) -{ - if (gpl->flag & GP_LAYER_LOCKED) { - return; - } - - gpIterData *iter = (gpIterData *)thunk; - - if (gps->editcurve == NULL) { - return; - } - - /* Store first index offset */ - gps->runtime.curve_start = iter->curve_len; - iter->curve_len += gps->editcurve->tot_curve_points * 4; -} - -static uint32_t gpencil_beztriple_vflag_get(char flag, - char col_id, - bool handle_point, - const bool handle_selected) -{ - uint32_t vflag = 0; - SET_FLAG_FROM_TEST(vflag, (flag & SELECT), VFLAG_VERT_SELECTED); - SET_FLAG_FROM_TEST(vflag, handle_point, BEZIER_HANDLE); - SET_FLAG_FROM_TEST(vflag, handle_selected, VFLAG_VERT_SELECTED_BEZT_HANDLE); - vflag |= VFLAG_VERT_GPENCIL_BEZT_HANDLE; - - /* Handle color id. */ - vflag |= col_id << COLOR_SHIFT; - return vflag; -} - -static void gpencil_edit_curve_stroke_iter_cb(bGPDlayer *gpl, - bGPDframe *UNUSED(gpf), - bGPDstroke *gps, - void *thunk) -{ - if (gpl->flag & GP_LAYER_LOCKED) { - return; - } - - if (gps->editcurve == NULL) { - return; - } - bGPDcurve *editcurve = gps->editcurve; - gpEditCurveIterData *iter = (gpEditCurveIterData *)thunk; - const int v = gps->runtime.curve_start; - gpEditCurveVert *vert_ptr = iter->verts + v; - /* Hide points when the curve is unselected. Passing the control point - * as handle produces the point shader skip it if you are not in ALL mode. */ - const bool hide = !(editcurve->flag & GP_CURVE_SELECT); - - for (int i = 0; i < editcurve->tot_curve_points; i++) { - BezTriple *bezt = &editcurve->curve_points[i].bezt; - const bool handle_selected = BEZT_ISSEL_ANY(bezt); - const uint32_t vflag[3] = { - gpencil_beztriple_vflag_get(bezt->f1, bezt->h1, true, handle_selected), - gpencil_beztriple_vflag_get(bezt->f2, bezt->h1, hide, handle_selected), - gpencil_beztriple_vflag_get(bezt->f3, bezt->h2, true, handle_selected), - }; - - /* First segment. */ - mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[0]); - vert_ptr->data = vflag[0]; - vert_ptr++; - - mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[1]); - vert_ptr->data = vflag[1]; - vert_ptr++; - - /* Second segment. */ - mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[1]); - vert_ptr->data = vflag[1]; - vert_ptr++; - - mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[2]); - vert_ptr->data = vflag[2]; - vert_ptr++; - } -} - -static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfra) -{ - bGPdata *gpd = (bGPdata *)ob->data; - - if (cache->edit_vbo == NULL) { - /* TODO/PERF: Could be changed to only do it if needed. - * For now it's simpler to assume we always need it - * since multiple viewport could or could not need it. - * Ideally we should have a dedicated onion skin geom batch. */ - /* IMPORTANT: Keep in sync with gpencil_batches_ensure() */ - bool do_onion = true; - - /* Vertex counting has already been done for cache->vbo. */ - BLI_assert(cache->vbo); - int vert_len = GPU_vertbuf_get_vertex_len(cache->vbo); - - gpEditIterData iter; - iter.vgindex = gpd->vertex_group_active_index - 1; - if (!BLI_findlink(&gpd->vertex_group_names, iter.vgindex)) { - iter.vgindex = -1; - } - - /* Create VBO. */ - GPUVertFormat *format = gpencil_edit_stroke_format(); - cache->edit_vbo = GPU_vertbuf_create_with_format(format); - /* Add extra space at the end of the buffer because of quad load. */ - GPU_vertbuf_data_alloc(cache->edit_vbo, vert_len); - iter.verts = (gpEditVert *)GPU_vertbuf_get_data(cache->edit_vbo); - - /* Fill buffers with data. */ - BKE_gpencil_visible_stroke_advanced_iter( - NULL, ob, NULL, gpencil_edit_stroke_iter_cb, &iter, do_onion, cfra); - - /* Create the batches */ - cache->edit_points_batch = GPU_batch_create(GPU_PRIM_POINTS, cache->vbo, NULL); - GPU_batch_vertbuf_add(cache->edit_points_batch, cache->edit_vbo); - - cache->edit_lines_batch = GPU_batch_create(GPU_PRIM_LINE_STRIP, cache->vbo, NULL); - GPU_batch_vertbuf_add(cache->edit_lines_batch, cache->edit_vbo); - } - - /* Curve Handles and Points for Editing. */ - if (cache->edit_curve_vbo == NULL) { - gpIterData iterdata = { - .gpd = gpd, - .verts = NULL, - .ibo = {0}, - .vert_len = 0, - .tri_len = 0, - .curve_len = 0, - }; - - /* Create VBO. */ - GPUVertFormat *format = gpencil_edit_curve_format(); - cache->edit_curve_vbo = GPU_vertbuf_create_with_format(format); - - /* Count data. */ - BKE_gpencil_visible_stroke_advanced_iter( - NULL, ob, NULL, gpencil_edit_curve_stroke_count_cb, &iterdata, false, cfra); - - gpEditCurveIterData iter; - int vert_len = iterdata.curve_len; - if (vert_len > 0) { - - GPU_vertbuf_data_alloc(cache->edit_curve_vbo, vert_len); - iter.verts = (gpEditCurveVert *)GPU_vertbuf_get_data(cache->edit_curve_vbo); - - /* Fill buffers with data. */ - BKE_gpencil_visible_stroke_advanced_iter( - NULL, ob, NULL, gpencil_edit_curve_stroke_iter_cb, &iter, false, cfra); - - cache->edit_curve_handles_batch = GPU_batch_create( - GPU_PRIM_LINES, cache->edit_curve_vbo, NULL); - GPU_batch_vertbuf_add(cache->edit_curve_handles_batch, cache->edit_curve_vbo); - - cache->edit_curve_points_batch = GPU_batch_create( - GPU_PRIM_POINTS, cache->edit_curve_vbo, NULL); - GPU_batch_vertbuf_add(cache->edit_curve_points_batch, cache->edit_curve_vbo); - } - - gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY; - cache->is_dirty = false; - } -} - -GPUBatch *DRW_cache_gpencil_edit_lines_get(Object *ob, int cfra) -{ - GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); - gpencil_batches_ensure(ob, cache, cfra); - gpencil_edit_batches_ensure(ob, cache, cfra); - - return cache->edit_lines_batch; -} - -GPUBatch *DRW_cache_gpencil_edit_points_get(Object *ob, int cfra) -{ - GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); - gpencil_batches_ensure(ob, cache, cfra); - gpencil_edit_batches_ensure(ob, cache, cfra); - - return cache->edit_points_batch; -} - -GPUBatch *DRW_cache_gpencil_edit_curve_handles_get(Object *ob, int cfra) -{ - GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); - gpencil_batches_ensure(ob, cache, cfra); - gpencil_edit_batches_ensure(ob, cache, cfra); - - return cache->edit_curve_handles_batch; -} - -GPUBatch *DRW_cache_gpencil_edit_curve_points_get(Object *ob, int cfra) -{ - GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); - gpencil_batches_ensure(ob, cache, cfra); - gpencil_edit_batches_ensure(ob, cache, cfra); - - return cache->edit_curve_points_batch; -} - -int DRW_gpencil_material_count_get(bGPdata *gpd) -{ - return max_ii(1, gpd->totcol); -} - -/** \} */ diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.cc b/source/blender/draw/intern/draw_cache_impl_gpencil.cc new file mode 100644 index 00000000000..94925bfae71 --- /dev/null +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.cc @@ -0,0 +1,963 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2020 Blender Foundation. */ + +/** \file + * \ingroup draw + */ + +#include "DNA_curve_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_screen_types.h" + +#include "BKE_deform.h" +#include "BKE_gpencil.h" +#include "BKE_gpencil_geom.h" + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "ED_gpencil.h" +#include "GPU_batch.h" + +#include "DEG_depsgraph_query.h" + +#include "BLI_hash.h" +#include "BLI_polyfill_2d.h" + +#include "draw_cache.h" +#include "draw_cache_impl.h" + +#include "../engines/gpencil/gpencil_defines.h" + +#define BEZIER_HANDLE (1 << 3) +#define COLOR_SHIFT 5 + +/* -------------------------------------------------------------------- */ +/** \name Internal Types + * \{ */ + +typedef struct GpencilBatchCache { + /** Instancing Data */ + GPUVertBuf *vbo; + GPUVertBuf *vbo_col; + /** Fill Topology */ + GPUIndexBuf *ibo; + /** Instancing Batches */ + GPUBatch *stroke_batch; + GPUBatch *fill_batch; + GPUBatch *lines_batch; + + /** Edit Mode */ + GPUVertBuf *edit_vbo; + GPUBatch *edit_lines_batch; + GPUBatch *edit_points_batch; + /** Edit Curve Mode */ + GPUVertBuf *edit_curve_vbo; + GPUBatch *edit_curve_handles_batch; + GPUBatch *edit_curve_points_batch; + + /** Cache is dirty */ + bool is_dirty; + /** Last cache frame */ + int cache_frame; +} GpencilBatchCache; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal Utilities + * \{ */ + +static bool gpencil_batch_cache_valid(GpencilBatchCache *cache, bGPdata *gpd, int cfra) +{ + bool valid = true; + + if (cache == NULL) { + return false; + } + + if (cfra != cache->cache_frame) { + valid = false; + } + else if (gpd->flag & GP_DATA_CACHE_IS_DIRTY) { + valid = false; + } + else if (cache->is_dirty) { + valid = false; + } + + return valid; +} + +static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra) +{ + bGPdata *gpd = (bGPdata *)ob->data; + + GpencilBatchCache *cache = gpd->runtime.gpencil_cache; + + if (!cache) { + cache = gpd->runtime.gpencil_cache = (GpencilBatchCache *)MEM_callocN(sizeof(*cache), + __func__); + } + else { + memset(cache, 0, sizeof(*cache)); + } + + cache->is_dirty = true; + cache->cache_frame = cfra; + + return cache; +} + +static void gpencil_batch_cache_clear(GpencilBatchCache *cache) +{ + if (!cache) { + return; + } + + GPU_BATCH_DISCARD_SAFE(cache->lines_batch); + GPU_BATCH_DISCARD_SAFE(cache->fill_batch); + GPU_BATCH_DISCARD_SAFE(cache->stroke_batch); + GPU_VERTBUF_DISCARD_SAFE(cache->vbo); + GPU_VERTBUF_DISCARD_SAFE(cache->vbo_col); + GPU_INDEXBUF_DISCARD_SAFE(cache->ibo); + + GPU_BATCH_DISCARD_SAFE(cache->edit_lines_batch); + GPU_BATCH_DISCARD_SAFE(cache->edit_points_batch); + GPU_VERTBUF_DISCARD_SAFE(cache->edit_vbo); + + GPU_BATCH_DISCARD_SAFE(cache->edit_curve_handles_batch); + GPU_BATCH_DISCARD_SAFE(cache->edit_curve_points_batch); + GPU_VERTBUF_DISCARD_SAFE(cache->edit_curve_vbo); + + cache->is_dirty = true; +} + +static GpencilBatchCache *gpencil_batch_cache_get(Object *ob, int cfra) +{ + bGPdata *gpd = (bGPdata *)ob->data; + + GpencilBatchCache *cache = gpd->runtime.gpencil_cache; + if (!gpencil_batch_cache_valid(cache, gpd, cfra)) { + gpencil_batch_cache_clear(cache); + return gpencil_batch_cache_init(ob, cfra); + } + + return cache; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name BKE Callbacks + * \{ */ + +void DRW_gpencil_batch_cache_dirty_tag(bGPdata *gpd) +{ + gpd->flag |= GP_DATA_CACHE_IS_DIRTY; +} + +void DRW_gpencil_batch_cache_free(bGPdata *gpd) +{ + gpencil_batch_cache_clear(gpd->runtime.gpencil_cache); + MEM_SAFE_FREE(gpd->runtime.gpencil_cache); + gpd->flag |= GP_DATA_CACHE_IS_DIRTY; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Formats + * \{ */ + +/* MUST match the format below. */ +typedef struct gpStrokeVert { + int32_t mat, stroke_id, point_id, packed_asp_hard_rot; + /** Position and thickness packed in the same attribute. */ + float pos[3], thickness; + /** UV and strength packed in the same attribute. */ + float uv_fill[2], u_stroke, strength; +} gpStrokeVert; + +static GPUVertFormat *gpencil_stroke_format(void) +{ + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "ma", GPU_COMP_I32, 4, GPU_FETCH_INT); + GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + GPU_vertformat_attr_add(&format, "uv", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + /* IMPORTANT: This means having only 4 attributes + * to fit into GPU module limit of 16 attributes. */ + GPU_vertformat_multiload_enable(&format, 4); + } + return &format; +} + +/* MUST match the format below. */ +typedef struct gpEditVert { + uint vflag; + float weight; +} gpEditVert; + +static GPUVertFormat *gpencil_edit_stroke_format(void) +{ + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "vflag", GPU_COMP_U32, 1, GPU_FETCH_INT); + GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + } + return &format; +} + +/* MUST match the format below. */ +typedef struct gpEditCurveVert { + float pos[3]; + uint32_t data; +} gpEditCurveVert; + +static GPUVertFormat *gpencil_edit_curve_format(void) +{ + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + /* initialize vertex formats */ + GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + GPU_vertformat_attr_add(&format, "data", GPU_COMP_U32, 1, GPU_FETCH_INT); + } + return &format; +} + +/* MUST match the format below. */ +typedef struct gpColorVert { + float vcol[4]; /* Vertex color */ + float fcol[4]; /* Fill color */ +} gpColorVert; + +static GPUVertFormat *gpencil_color_format(void) +{ + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "col", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + GPU_vertformat_attr_add(&format, "fcol", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + /* IMPORTANT: This means having only 4 attributes + * to fit into GPU module limit of 16 attributes. */ + GPU_vertformat_multiload_enable(&format, 4); + } + return &format; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Buffers + * \{ */ + +typedef struct gpIterData { + bGPdata *gpd; + gpStrokeVert *verts; + gpColorVert *cols; + GPUIndexBufBuilder ibo; + int vert_len; + int tri_len; + int curve_len; +} gpIterData; + +static GPUVertBuf *gpencil_dummy_buffer_get(void) +{ + GPUBatch *batch = DRW_gpencil_dummy_buffer_get(); + return batch->verts[0]; +} + +static int gpencil_stroke_is_cyclic(const bGPDstroke *gps) +{ + return ((gps->flag & GP_STROKE_CYCLIC) != 0) && (gps->totpoints > 2); +} + +BLI_INLINE int32_t pack_rotation_aspect_hardness(float rot, float asp, float hard) +{ + int32_t packed = 0; + /* Aspect uses 9 bits */ + float asp_normalized = (asp > 1.0f) ? (1.0f / asp) : asp; + packed |= (int32_t)unit_float_to_uchar_clamp(asp_normalized); + /* Store if inversed in the 9th bit. */ + if (asp > 1.0f) { + packed |= 1 << 8; + } + /* Rotation uses 9 bits */ + /* Rotation are in [-90°..90°] range, so we can encode the sign of the angle + the cosine + * because the cosine will always be positive. */ + packed |= (int32_t)unit_float_to_uchar_clamp(cosf(rot)) << 9; + /* Store sine sign in 9th bit. */ + if (rot < 0.0f) { + packed |= 1 << 17; + } + /* Hardness uses 8 bits */ + packed |= (int32_t)unit_float_to_uchar_clamp(hard) << 18; + return packed; +} + +static void gpencil_buffer_add_point(gpStrokeVert *verts, + gpColorVert *cols, + const bGPDstroke *gps, + const bGPDspoint *pt, + int v, + bool is_endpoint) +{ + /* NOTE: we use the sign of strength and thickness to pass cap flag. */ + const bool round_cap0 = (gps->caps[0] == GP_STROKE_CAP_ROUND); + const bool round_cap1 = (gps->caps[1] == GP_STROKE_CAP_ROUND); + gpStrokeVert *vert = &verts[v]; + gpColorVert *col = &cols[v]; + copy_v3_v3(vert->pos, &pt->x); + copy_v2_v2(vert->uv_fill, pt->uv_fill); + copy_v4_v4(col->vcol, pt->vert_color); + copy_v4_v4(col->fcol, gps->vert_color_fill); + + /* Encode fill opacity defined by opacity modifier in vertex color alpha. If + * no opacity modifier, the value will be always 1.0f. The opacity factor can be any + * value between 0.0f and 2.0f */ + col->fcol[3] = ((int)(col->fcol[3] * 10000.0f) * 10.0f) + gps->fill_opacity_fac; + + vert->strength = (round_cap0) ? pt->strength : -pt->strength; + vert->u_stroke = pt->uv_fac; + vert->stroke_id = gps->runtime.stroke_start; + vert->point_id = v; + vert->thickness = max_ff(0.0f, gps->thickness * pt->pressure) * (round_cap1 ? 1.0f : -1.0f); + /* Tag endpoint material to -1 so they get discarded by vertex shader. */ + vert->mat = (is_endpoint) ? -1 : (gps->mat_nr % GPENCIL_MATERIAL_BUFFER_LEN); + + float aspect_ratio = gps->aspect_ratio[0] / max_ff(gps->aspect_ratio[1], 1e-8); + + vert->packed_asp_hard_rot = pack_rotation_aspect_hardness( + pt->uv_rot, aspect_ratio, gps->hardeness); +} + +static void gpencil_buffer_add_stroke(gpStrokeVert *verts, + gpColorVert *cols, + const bGPDstroke *gps) +{ + const bGPDspoint *pts = gps->points; + int pts_len = gps->totpoints; + bool is_cyclic = gpencil_stroke_is_cyclic(gps); + int v = gps->runtime.stroke_start; + + /* First point for adjacency (not drawn). */ + int adj_idx = (is_cyclic) ? (pts_len - 1) : min_ii(pts_len - 1, 1); + gpencil_buffer_add_point(verts, cols, gps, &pts[adj_idx], v++, true); + + for (int i = 0; i < pts_len; i++) { + gpencil_buffer_add_point(verts, cols, gps, &pts[i], v++, false); + } + /* Draw line to first point to complete the loop for cyclic strokes. */ + if (is_cyclic) { + gpencil_buffer_add_point(verts, cols, gps, &pts[0], v, false); + /* UV factor needs to be adjusted for the last point to not be equal to the UV factor of the + * first point. It should be the factor of the last point plus the distance from the last point + * to the first. + */ + gpStrokeVert *vert = &verts[v]; + vert->u_stroke = verts[v - 1].u_stroke + len_v3v3(&pts[pts_len - 1].x, &pts[0].x); + v++; + } + /* Last adjacency point (not drawn). */ + adj_idx = (is_cyclic) ? 1 : max_ii(0, pts_len - 2); + gpencil_buffer_add_point(verts, cols, gps, &pts[adj_idx], v++, true); +} + +static void gpencil_buffer_add_fill(GPUIndexBufBuilder *ibo, const bGPDstroke *gps) +{ + int tri_len = gps->tot_triangles; + int v = gps->runtime.stroke_start; + for (int i = 0; i < tri_len; i++) { + uint *tri = gps->triangles[i].verts; + GPU_indexbuf_add_tri_verts(ibo, v + tri[0], v + tri[1], v + tri[2]); + } +} + +static void gpencil_stroke_iter_cb(bGPDlayer *UNUSED(gpl), + bGPDframe *UNUSED(gpf), + bGPDstroke *gps, + void *thunk) +{ + gpIterData *iter = (gpIterData *)thunk; + gpencil_buffer_add_stroke(iter->verts, iter->cols, gps); + if (gps->tot_triangles > 0) { + gpencil_buffer_add_fill(&iter->ibo, gps); + } +} + +static void gpencil_object_verts_count_cb(bGPDlayer *UNUSED(gpl), + bGPDframe *UNUSED(gpf), + bGPDstroke *gps, + void *thunk) +{ + gpIterData *iter = (gpIterData *)thunk; + + /* Store first index offset */ + gps->runtime.stroke_start = iter->vert_len; + gps->runtime.fill_start = iter->tri_len; + iter->vert_len += gps->totpoints + 2 + gpencil_stroke_is_cyclic(gps); + iter->tri_len += gps->tot_triangles; +} + +static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfra) +{ + bGPdata *gpd = (bGPdata *)ob->data; + + if (cache->vbo == NULL) { + /* Should be discarded together. */ + BLI_assert(cache->vbo == NULL && cache->ibo == NULL); + BLI_assert(cache->fill_batch == NULL && cache->stroke_batch == NULL); + /* TODO/PERF: Could be changed to only do it if needed. + * For now it's simpler to assume we always need it + * since multiple viewport could or could not need it. + * Ideally we should have a dedicated onion skin geom batch. */ + /* IMPORTANT: Keep in sync with gpencil_edit_batches_ensure() */ + bool do_onion = true; + + /* First count how many vertices and triangles are needed for the whole object. */ + gpIterData iter = { + .gpd = gpd, + .verts = NULL, + .ibo = {0}, + .vert_len = 1, /* Start at 1 for the gl_InstanceID trick to work (see vert shader). */ + .tri_len = 0, + .curve_len = 0, + }; + BKE_gpencil_visible_stroke_advanced_iter( + NULL, ob, NULL, gpencil_object_verts_count_cb, &iter, do_onion, cfra); + + /* Create VBOs. */ + GPUVertFormat *format = gpencil_stroke_format(); + GPUVertFormat *format_col = gpencil_color_format(); + cache->vbo = GPU_vertbuf_create_with_format(format); + cache->vbo_col = GPU_vertbuf_create_with_format(format_col); + /* Add extra space at the end of the buffer because of quad load. */ + GPU_vertbuf_data_alloc(cache->vbo, iter.vert_len + 2); + GPU_vertbuf_data_alloc(cache->vbo_col, iter.vert_len + 2); + iter.verts = (gpStrokeVert *)GPU_vertbuf_get_data(cache->vbo); + iter.cols = (gpColorVert *)GPU_vertbuf_get_data(cache->vbo_col); + /* Create IBO. */ + GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, iter.vert_len); + + /* Fill buffers with data. */ + BKE_gpencil_visible_stroke_advanced_iter( + NULL, ob, NULL, gpencil_stroke_iter_cb, &iter, do_onion, cfra); + + /* Mark last 2 verts as invalid. */ + for (int i = 0; i < 2; i++) { + iter.verts[iter.vert_len + i].mat = -1; + } + /* Also mark first vert as invalid. */ + iter.verts[0].mat = -1; + + /* Finish the IBO. */ + cache->ibo = GPU_indexbuf_build(&iter.ibo); + + /* Create the batches */ + cache->fill_batch = GPU_batch_create(GPU_PRIM_TRIS, cache->vbo, cache->ibo); + GPU_batch_vertbuf_add(cache->fill_batch, cache->vbo_col); + cache->stroke_batch = GPU_batch_create(GPU_PRIM_TRI_STRIP, gpencil_dummy_buffer_get(), NULL); + GPU_batch_instbuf_add_ex(cache->stroke_batch, cache->vbo, 0); + GPU_batch_instbuf_add_ex(cache->stroke_batch, cache->vbo_col, 0); + + gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY; + cache->is_dirty = false; + } +} + +GPUBatch *DRW_cache_gpencil_strokes_get(Object *ob, int cfra) +{ + GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); + gpencil_batches_ensure(ob, cache, cfra); + + return cache->stroke_batch; +} + +GPUBatch *DRW_cache_gpencil_fills_get(Object *ob, int cfra) +{ + GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); + gpencil_batches_ensure(ob, cache, cfra); + + return cache->fill_batch; +} + +static void gpencil_lines_indices_cb(bGPDlayer *UNUSED(gpl), + bGPDframe *UNUSED(gpf), + bGPDstroke *gps, + void *thunk) +{ + gpIterData *iter = (gpIterData *)thunk; + int pts_len = gps->totpoints + gpencil_stroke_is_cyclic(gps); + + int start = gps->runtime.stroke_start + 1; + int end = start + pts_len; + for (int i = start; i < end; i++) { + GPU_indexbuf_add_generic_vert(&iter->ibo, i); + } + GPU_indexbuf_add_primitive_restart(&iter->ibo); +} + +GPUBatch *DRW_cache_gpencil_face_wireframe_get(Object *ob) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + int cfra = DEG_get_ctime(draw_ctx->depsgraph); + + GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); + gpencil_batches_ensure(ob, cache, cfra); + + if (cache->lines_batch == NULL) { + GPUVertBuf *vbo = cache->vbo; + + gpIterData iter = { + .gpd = (bGPdata *)ob->data, + .ibo = {0}, + }; + + uint vert_len = GPU_vertbuf_get_vertex_len(vbo); + GPU_indexbuf_init_ex(&iter.ibo, GPU_PRIM_LINE_STRIP, vert_len, vert_len); + + /* IMPORTANT: Keep in sync with gpencil_edit_batches_ensure() */ + bool do_onion = true; + BKE_gpencil_visible_stroke_advanced_iter( + NULL, ob, NULL, gpencil_lines_indices_cb, &iter, do_onion, cfra); + + GPUIndexBuf *ibo = GPU_indexbuf_build(&iter.ibo); + + cache->lines_batch = GPU_batch_create_ex(GPU_PRIM_LINE_STRIP, vbo, ibo, GPU_BATCH_OWNS_INDEX); + } + return cache->lines_batch; +} + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Sbuffer stroke batches. + * \{ */ + +bGPDstroke *DRW_cache_gpencil_sbuffer_stroke_data_get(Object *ob) +{ + bGPdata *gpd = (bGPdata *)ob->data; + Brush *brush = gpd->runtime.sbuffer_brush; + /* Convert the sbuffer to a bGPDstroke. */ + if (gpd->runtime.sbuffer_gps == NULL) { + bGPDstroke *gps = (bGPDstroke *)MEM_callocN(sizeof(*gps), "bGPDstroke sbuffer"); + gps->totpoints = gpd->runtime.sbuffer_used; + gps->mat_nr = max_ii(0, gpd->runtime.matid - 1); + gps->flag = gpd->runtime.sbuffer_sflag; + gps->thickness = brush->size; + gps->hardeness = brush->gpencil_settings->hardeness; + copy_v2_v2(gps->aspect_ratio, brush->gpencil_settings->aspect_ratio); + + /* Reduce slightly the opacity of fill to make easy fill areas while drawing. */ + gps->fill_opacity_fac = 0.8f; + + gps->tot_triangles = max_ii(0, gpd->runtime.sbuffer_used - 2); + gps->caps[0] = gps->caps[1] = GP_STROKE_CAP_ROUND; + gps->runtime.stroke_start = 1; /* Add one for the adjacency index. */ + copy_v4_v4(gps->vert_color_fill, gpd->runtime.vert_color_fill); + /* Caps. */ + gps->caps[0] = gps->caps[1] = (short)brush->gpencil_settings->caps_type; + + gpd->runtime.sbuffer_gps = gps; + } + return gpd->runtime.sbuffer_gps; +} + +static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_fill) +{ + tGPspoint *tpoints = (tGPspoint *)gpd->runtime.sbuffer; + bGPDstroke *gps = gpd->runtime.sbuffer_gps; + int vert_len = gpd->runtime.sbuffer_used; + + /* DRW_cache_gpencil_sbuffer_stroke_data_get need to have been called previously. */ + BLI_assert(gps != NULL); + + if (do_stroke && (gpd->runtime.sbuffer_stroke_batch == NULL)) { + gps->points = (bGPDspoint *)MEM_mallocN(vert_len * sizeof(*gps->points), __func__); + + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + ARegion *region = draw_ctx->region; + Object *ob = draw_ctx->obact; + + BLI_assert(ob && (ob->type == OB_GPENCIL)); + + /* Get origin to reproject points. */ + float origin[3]; + ToolSettings *ts = scene->toolsettings; + ED_gpencil_drawing_reference_get(scene, ob, ts->gpencil_v3d_align, origin); + + for (int i = 0; i < vert_len; i++) { + ED_gpencil_tpoint_to_point(region, origin, &tpoints[i], &gps->points[i]); + mul_m4_v3(ob->imat, &gps->points[i].x); + bGPDspoint *pt = &gps->points[i]; + copy_v4_v4(pt->vert_color, tpoints[i].vert_color); + } + /* Calc uv data along the stroke. */ + BKE_gpencil_stroke_uv_update(gps); + + /* Create VBO. */ + GPUVertFormat *format = gpencil_stroke_format(); + GPUVertFormat *format_color = gpencil_color_format(); + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(format); + GPUVertBuf *vbo_col = GPU_vertbuf_create_with_format(format_color); + /* Add extra space at the end (and start) of the buffer because of quad load and cyclic. */ + GPU_vertbuf_data_alloc(vbo, 1 + vert_len + 1 + 2); + GPU_vertbuf_data_alloc(vbo_col, 1 + vert_len + 1 + 2); + gpStrokeVert *verts = (gpStrokeVert *)GPU_vertbuf_get_data(vbo); + gpColorVert *cols = (gpColorVert *)GPU_vertbuf_get_data(vbo_col); + + /* Fill buffers with data. */ + gpencil_buffer_add_stroke(verts, cols, gps); + + GPUBatch *batch = GPU_batch_create(GPU_PRIM_TRI_STRIP, gpencil_dummy_buffer_get(), NULL); + GPU_batch_instbuf_add_ex(batch, vbo, true); + GPU_batch_instbuf_add_ex(batch, vbo_col, true); + + gpd->runtime.sbuffer_stroke_batch = batch; + + MEM_freeN(gps->points); + } + + if (do_fill && (gpd->runtime.sbuffer_fill_batch == NULL)) { + /* Create IBO. */ + GPUIndexBufBuilder ibo_builder; + GPU_indexbuf_init(&ibo_builder, GPU_PRIM_TRIS, gps->tot_triangles, vert_len); + + if (gps->tot_triangles > 0) { + float(*tpoints2d)[2] = (float(*)[2])MEM_mallocN(sizeof(*tpoints2d) * vert_len, __func__); + /* Triangulate in 2D. */ + for (int i = 0; i < vert_len; i++) { + copy_v2_v2(tpoints2d[i], tpoints[i].m_xy); + } + /* Compute directly inside the IBO data buffer. */ + /* OPTI: This is a bottleneck if the stroke is very long. */ + BLI_polyfill_calc(tpoints2d, (uint)vert_len, 0, (uint(*)[3])ibo_builder.data); + /* Add stroke start offset. */ + for (int i = 0; i < gps->tot_triangles * 3; i++) { + ibo_builder.data[i] += gps->runtime.stroke_start; + } + /* HACK since we didn't use the builder API to avoid another malloc and copy, + * we need to set the number of indices manually. */ + ibo_builder.index_len = gps->tot_triangles * 3; + + MEM_freeN(tpoints2d); + } + + GPUIndexBuf *ibo = GPU_indexbuf_build(&ibo_builder); + GPUVertBuf *vbo = gpd->runtime.sbuffer_stroke_batch->inst[0]; + GPUVertBuf *vbo_col = gpd->runtime.sbuffer_stroke_batch->inst[1]; + + GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, ibo, GPU_BATCH_OWNS_INDEX); + GPU_batch_vertbuf_add(batch, vbo_col); + + gpd->runtime.sbuffer_fill_batch = batch; + } +} + +GPUBatch *DRW_cache_gpencil_sbuffer_stroke_get(Object *ob) +{ + bGPdata *gpd = (bGPdata *)ob->data; + gpencil_sbuffer_stroke_ensure(gpd, true, false); + + return gpd->runtime.sbuffer_stroke_batch; +} + +GPUBatch *DRW_cache_gpencil_sbuffer_fill_get(Object *ob) +{ + bGPdata *gpd = (bGPdata *)ob->data; + /* Fill batch also need stroke batch to be created (vbo is shared). */ + gpencil_sbuffer_stroke_ensure(gpd, true, true); + + return gpd->runtime.sbuffer_fill_batch; +} + +void DRW_cache_gpencil_sbuffer_clear(Object *ob) +{ + bGPdata *gpd = (bGPdata *)ob->data; + MEM_SAFE_FREE(gpd->runtime.sbuffer_gps); + GPU_BATCH_DISCARD_SAFE(gpd->runtime.sbuffer_fill_batch); + GPU_BATCH_DISCARD_SAFE(gpd->runtime.sbuffer_stroke_batch); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Edit GPencil Batches + * \{ */ + +#define GP_EDIT_POINT_SELECTED (1 << 0) +#define GP_EDIT_STROKE_SELECTED (1 << 1) +#define GP_EDIT_MULTIFRAME (1 << 2) +#define GP_EDIT_STROKE_START (1 << 3) +#define GP_EDIT_STROKE_END (1 << 4) +#define GP_EDIT_POINT_DIMMED (1 << 5) + +typedef struct gpEditIterData { + gpEditVert *verts; + int vgindex; +} gpEditIterData; + +typedef struct gpEditCurveIterData { + gpEditCurveVert *verts; + int vgindex; +} gpEditCurveIterData; + +static uint32_t gpencil_point_edit_flag(const bool layer_lock, + const bGPDspoint *pt, + int v, + int v_len) +{ + uint32_t sflag = 0; + SET_FLAG_FROM_TEST(sflag, (!layer_lock) && pt->flag & GP_SPOINT_SELECT, GP_EDIT_POINT_SELECTED); + SET_FLAG_FROM_TEST(sflag, v == 0, GP_EDIT_STROKE_START); + SET_FLAG_FROM_TEST(sflag, v == (v_len - 1), GP_EDIT_STROKE_END); + SET_FLAG_FROM_TEST(sflag, pt->runtime.pt_orig == NULL, GP_EDIT_POINT_DIMMED); + return sflag; +} + +static float gpencil_point_edit_weight(const MDeformVert *dvert, int v, int vgindex) +{ + return (dvert && dvert[v].dw) ? BKE_defvert_find_weight(&dvert[v], vgindex) : -1.0f; +} + +static void gpencil_edit_stroke_iter_cb(bGPDlayer *gpl, + bGPDframe *gpf, + bGPDstroke *gps, + void *thunk) +{ + gpEditIterData *iter = (gpEditIterData *)thunk; + const int v_len = gps->totpoints; + const int v = gps->runtime.stroke_start + 1; + MDeformVert *dvert = ((iter->vgindex > -1) && gps->dvert) ? gps->dvert : NULL; + gpEditVert *vert_ptr = iter->verts + v; + + const bool layer_lock = (gpl->flag & GP_LAYER_LOCKED); + uint32_t sflag = 0; + SET_FLAG_FROM_TEST( + sflag, (!layer_lock) && gps->flag & GP_STROKE_SELECT, GP_EDIT_STROKE_SELECTED); + SET_FLAG_FROM_TEST(sflag, gpf->runtime.onion_id != 0.0f, GP_EDIT_MULTIFRAME); + + for (int i = 0; i < v_len; i++) { + vert_ptr->vflag = sflag | gpencil_point_edit_flag(layer_lock, &gps->points[i], i, v_len); + vert_ptr->weight = gpencil_point_edit_weight(dvert, i, iter->vgindex); + vert_ptr++; + } + /* Draw line to first point to complete the loop for cyclic strokes. */ + vert_ptr->vflag = sflag | gpencil_point_edit_flag(layer_lock, &gps->points[0], 0, v_len); + vert_ptr->weight = gpencil_point_edit_weight(dvert, 0, iter->vgindex); +} + +static void gpencil_edit_curve_stroke_count_cb(bGPDlayer *gpl, + bGPDframe *UNUSED(gpf), + bGPDstroke *gps, + void *thunk) +{ + if (gpl->flag & GP_LAYER_LOCKED) { + return; + } + + gpIterData *iter = (gpIterData *)thunk; + + if (gps->editcurve == NULL) { + return; + } + + /* Store first index offset */ + gps->runtime.curve_start = iter->curve_len; + iter->curve_len += gps->editcurve->tot_curve_points * 4; +} + +static uint32_t gpencil_beztriple_vflag_get(char flag, + char col_id, + bool handle_point, + const bool handle_selected) +{ + uint32_t vflag = 0; + SET_FLAG_FROM_TEST(vflag, (flag & SELECT), VFLAG_VERT_SELECTED); + SET_FLAG_FROM_TEST(vflag, handle_point, BEZIER_HANDLE); + SET_FLAG_FROM_TEST(vflag, handle_selected, VFLAG_VERT_SELECTED_BEZT_HANDLE); + vflag |= VFLAG_VERT_GPENCIL_BEZT_HANDLE; + + /* Handle color id. */ + vflag |= col_id << COLOR_SHIFT; + return vflag; +} + +static void gpencil_edit_curve_stroke_iter_cb(bGPDlayer *gpl, + bGPDframe *UNUSED(gpf), + bGPDstroke *gps, + void *thunk) +{ + if (gpl->flag & GP_LAYER_LOCKED) { + return; + } + + if (gps->editcurve == NULL) { + return; + } + bGPDcurve *editcurve = gps->editcurve; + gpEditCurveIterData *iter = (gpEditCurveIterData *)thunk; + const int v = gps->runtime.curve_start; + gpEditCurveVert *vert_ptr = iter->verts + v; + /* Hide points when the curve is unselected. Passing the control point + * as handle produces the point shader skip it if you are not in ALL mode. */ + const bool hide = !(editcurve->flag & GP_CURVE_SELECT); + + for (int i = 0; i < editcurve->tot_curve_points; i++) { + BezTriple *bezt = &editcurve->curve_points[i].bezt; + const bool handle_selected = BEZT_ISSEL_ANY(bezt); + const uint32_t vflag[3] = { + gpencil_beztriple_vflag_get(bezt->f1, bezt->h1, true, handle_selected), + gpencil_beztriple_vflag_get(bezt->f2, bezt->h1, hide, handle_selected), + gpencil_beztriple_vflag_get(bezt->f3, bezt->h2, true, handle_selected), + }; + + /* First segment. */ + mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[0]); + vert_ptr->data = vflag[0]; + vert_ptr++; + + mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[1]); + vert_ptr->data = vflag[1]; + vert_ptr++; + + /* Second segment. */ + mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[1]); + vert_ptr->data = vflag[1]; + vert_ptr++; + + mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[2]); + vert_ptr->data = vflag[2]; + vert_ptr++; + } +} + +static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfra) +{ + bGPdata *gpd = (bGPdata *)ob->data; + + if (cache->edit_vbo == NULL) { + /* TODO/PERF: Could be changed to only do it if needed. + * For now it's simpler to assume we always need it + * since multiple viewport could or could not need it. + * Ideally we should have a dedicated onion skin geom batch. */ + /* IMPORTANT: Keep in sync with gpencil_batches_ensure() */ + bool do_onion = true; + + /* Vertex counting has already been done for cache->vbo. */ + BLI_assert(cache->vbo); + int vert_len = GPU_vertbuf_get_vertex_len(cache->vbo); + + gpEditIterData iter; + iter.vgindex = gpd->vertex_group_active_index - 1; + if (!BLI_findlink(&gpd->vertex_group_names, iter.vgindex)) { + iter.vgindex = -1; + } + + /* Create VBO. */ + GPUVertFormat *format = gpencil_edit_stroke_format(); + cache->edit_vbo = GPU_vertbuf_create_with_format(format); + /* Add extra space at the end of the buffer because of quad load. */ + GPU_vertbuf_data_alloc(cache->edit_vbo, vert_len); + iter.verts = (gpEditVert *)GPU_vertbuf_get_data(cache->edit_vbo); + + /* Fill buffers with data. */ + BKE_gpencil_visible_stroke_advanced_iter( + NULL, ob, NULL, gpencil_edit_stroke_iter_cb, &iter, do_onion, cfra); + + /* Create the batches */ + cache->edit_points_batch = GPU_batch_create(GPU_PRIM_POINTS, cache->vbo, NULL); + GPU_batch_vertbuf_add(cache->edit_points_batch, cache->edit_vbo); + + cache->edit_lines_batch = GPU_batch_create(GPU_PRIM_LINE_STRIP, cache->vbo, NULL); + GPU_batch_vertbuf_add(cache->edit_lines_batch, cache->edit_vbo); + } + + /* Curve Handles and Points for Editing. */ + if (cache->edit_curve_vbo == NULL) { + gpIterData iterdata = { + .gpd = gpd, + .verts = NULL, + .ibo = {0}, + .vert_len = 0, + .tri_len = 0, + .curve_len = 0, + }; + + /* Create VBO. */ + GPUVertFormat *format = gpencil_edit_curve_format(); + cache->edit_curve_vbo = GPU_vertbuf_create_with_format(format); + + /* Count data. */ + BKE_gpencil_visible_stroke_advanced_iter( + NULL, ob, NULL, gpencil_edit_curve_stroke_count_cb, &iterdata, false, cfra); + + gpEditCurveIterData iter; + int vert_len = iterdata.curve_len; + if (vert_len > 0) { + + GPU_vertbuf_data_alloc(cache->edit_curve_vbo, vert_len); + iter.verts = (gpEditCurveVert *)GPU_vertbuf_get_data(cache->edit_curve_vbo); + + /* Fill buffers with data. */ + BKE_gpencil_visible_stroke_advanced_iter( + NULL, ob, NULL, gpencil_edit_curve_stroke_iter_cb, &iter, false, cfra); + + cache->edit_curve_handles_batch = GPU_batch_create( + GPU_PRIM_LINES, cache->edit_curve_vbo, NULL); + GPU_batch_vertbuf_add(cache->edit_curve_handles_batch, cache->edit_curve_vbo); + + cache->edit_curve_points_batch = GPU_batch_create( + GPU_PRIM_POINTS, cache->edit_curve_vbo, NULL); + GPU_batch_vertbuf_add(cache->edit_curve_points_batch, cache->edit_curve_vbo); + } + + gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY; + cache->is_dirty = false; + } +} + +GPUBatch *DRW_cache_gpencil_edit_lines_get(Object *ob, int cfra) +{ + GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); + gpencil_batches_ensure(ob, cache, cfra); + gpencil_edit_batches_ensure(ob, cache, cfra); + + return cache->edit_lines_batch; +} + +GPUBatch *DRW_cache_gpencil_edit_points_get(Object *ob, int cfra) +{ + GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); + gpencil_batches_ensure(ob, cache, cfra); + gpencil_edit_batches_ensure(ob, cache, cfra); + + return cache->edit_points_batch; +} + +GPUBatch *DRW_cache_gpencil_edit_curve_handles_get(Object *ob, int cfra) +{ + GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); + gpencil_batches_ensure(ob, cache, cfra); + gpencil_edit_batches_ensure(ob, cache, cfra); + + return cache->edit_curve_handles_batch; +} + +GPUBatch *DRW_cache_gpencil_edit_curve_points_get(Object *ob, int cfra) +{ + GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); + gpencil_batches_ensure(ob, cache, cfra); + gpencil_edit_batches_ensure(ob, cache, cfra); + + return cache->edit_curve_points_batch; +} + +int DRW_gpencil_material_count_get(bGPdata *gpd) +{ + return max_ii(1, gpd->totcol); +} + +/** \} */ -- cgit v1.2.3 From 0ee9282b5c51066dfcf5a6c7a5ebcd3dd5290673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Fri, 21 Oct 2022 13:09:07 +0200 Subject: GPencil: Use indexed rendering instead of instances This allows using instancing in other ways, like resources indexing. --- .../blender/draw/engines/eevee_next/eevee_sync.cc | 4 +- .../shaders/eevee_geom_gpencil_vert.glsl | 36 +- .../blender/draw/engines/gpencil/gpencil_engine.c | 31 +- .../draw/engines/gpencil/gpencil_shader_shared.h | 3 + .../gpencil/shaders/gpencil_common_lib.glsl | 595 --------------------- .../draw/engines/gpencil/shaders/gpencil_vert.glsl | 21 +- .../engines/gpencil/shaders/infos/gpencil_info.hh | 8 +- .../draw/engines/overlay/overlay_outline.cc | 22 +- .../overlay_outline_prepass_gpencil_vert.glsl | 15 +- source/blender/draw/intern/draw_cache.h | 11 +- .../blender/draw/intern/draw_cache_impl_gpencil.cc | 189 ++++--- source/blender/draw/intern/draw_manager_data.cc | 6 +- .../draw/intern/shaders/common_gpencil_lib.glsl | 88 ++- .../blender/draw/intern/shaders/draw_view_info.hh | 17 +- source/blender/gpu/intern/gpu_texture_private.hh | 2 +- source/blender/gpu/intern/gpu_vertex_format.cc | 8 +- source/blender/makesdna/DNA_gpencil_types.h | 10 +- 17 files changed, 228 insertions(+), 838 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_sync.cc b/source/blender/draw/engines/eevee_next/eevee_sync.cc index 08cda6f47cf..0915dace1e5 100644 --- a/source/blender/draw/engines/eevee_next/eevee_sync.cc +++ b/source/blender/draw/engines/eevee_next/eevee_sync.cc @@ -248,15 +248,15 @@ static void gpencil_stroke_sync(bGPDlayer * /*gpl*/, return; } + GPUBatch *geom = DRW_cache_gpencil_get(iter.ob, iter.cfra); + if (show_fill) { - GPUBatch *geom = DRW_cache_gpencil_fills_get(iter.ob, iter.cfra); int vfirst = gps->runtime.fill_start * 3; int vcount = gps->tot_triangles * 3; gpencil_drawcall_add(iter, geom, material, vfirst, vcount, false); } if (show_stroke) { - GPUBatch *geom = DRW_cache_gpencil_strokes_get(iter.ob, iter.cfra); /* Start one vert before to have gl_InstanceID > 0 (see shader). */ int vfirst = gps->runtime.stroke_start - 1; /* Include "potential" cyclic vertex and start adj vertex (see shader). */ diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_geom_gpencil_vert.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_geom_gpencil_vert.glsl index 38debf14eda..87a5bf71c45 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_geom_gpencil_vert.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_geom_gpencil_vert.glsl @@ -16,30 +16,18 @@ void main() float hardness; vec2 thickness; - gl_Position = gpencil_vertex(ma, - ma1, - ma2, - ma3, - pos, - pos1, - pos2, - pos3, - uv1, - uv2, - col1, - col2, - fcol1, - /* TODO */ - vec4(1024.0, 1024.0, 1.0 / 1024.0, 1.0 / 1024.0), - interp.P, - interp.N, - g_color, - strength, - g_uvs, - sspos, - aspect, - thickness, - hardness); + gl_Position = gpencil_vertex( + /* TODO */ + vec4(1024.0, 1024.0, 1.0 / 1024.0, 1.0 / 1024.0), + interp.P, + interp.N, + g_color, + strength, + g_uvs, + sspos, + aspect, + thickness, + hardness); #ifdef MAT_VELOCITY /* GPencil do not support deformation motion blur. */ vec3 lP_curr = transform_point(ModelMatrixInverse, interp.P); diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index b24e4c605e4..956830e6b4c 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -346,7 +346,7 @@ typedef struct gpIterPopulateData { int vfirst, vcount; } gpIterPopulateData; -#define DISABLE_BATCHING 0 +#define DISABLE_BATCHING 1 static void gpencil_drawcall_flush(gpIterPopulateData *iter) { @@ -377,6 +377,7 @@ static void gpencil_drawcall_add( else { DRW_shgroup_call_range(iter->grp, iter->ob, geom, v_first, v_count); } + return; #endif int last = iter->vfirst + iter->vcount; @@ -516,22 +517,32 @@ static void gpencil_stroke_cache_populate(bGPDlayer *gpl, bool do_sbuffer = (iter->do_sbuffer_call == DRAW_NOW); + GPUBatch *geom = do_sbuffer ? DRW_cache_gpencil_sbuffer_get(iter->ob) : + DRW_cache_gpencil_get(iter->ob, iter->pd->cfra); + if (geom != iter->geom) { + gpencil_drawcall_flush(iter); + + GPUVertBuf *position_tx = do_sbuffer ? + DRW_cache_gpencil_sbuffer_position_buffer_get(iter->ob) : + DRW_cache_gpencil_position_buffer_get(iter->ob, iter->pd->cfra); + GPUVertBuf *color_tx = do_sbuffer ? + DRW_cache_gpencil_sbuffer_color_buffer_get(iter->ob) : + DRW_cache_gpencil_color_buffer_get(iter->ob, iter->pd->cfra); + DRW_shgroup_buffer_texture(iter->grp, "gp_pos_tx", position_tx); + DRW_shgroup_buffer_texture(iter->grp, "gp_col_tx", color_tx); + } + if (show_fill) { - GPUBatch *geom = do_sbuffer ? DRW_cache_gpencil_sbuffer_fill_get(iter->ob) : - DRW_cache_gpencil_fills_get(iter->ob, iter->pd->cfra); int vfirst = gps->runtime.fill_start * 3; int vcount = gps->tot_triangles * 3; gpencil_drawcall_add(iter, geom, false, vfirst, vcount); } if (show_stroke) { - GPUBatch *geom = do_sbuffer ? DRW_cache_gpencil_sbuffer_stroke_get(iter->ob) : - DRW_cache_gpencil_strokes_get(iter->ob, iter->pd->cfra); - /* Start one vert before to have gl_InstanceID > 0 (see shader). */ - int vfirst = gps->runtime.stroke_start - 1; - /* Include "potential" cyclic vertex and start adj vertex (see shader). */ - int vcount = gps->totpoints + 1 + 1; - gpencil_drawcall_add(iter, geom, true, vfirst, vcount); + int vfirst = gps->runtime.stroke_start * 3; + /* Include "potential" cyclic vertex (see shader). */ + int vcount = (gps->totpoints + 1) * 2 * 3; + gpencil_drawcall_add(iter, geom, false, vfirst, vcount); } iter->stroke_index_last = gps->runtime.stroke_start + gps->totpoints + 1; diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_shared.h b/source/blender/draw/engines/gpencil/gpencil_shader_shared.h index 4c621e955b9..3f0f73e7c13 100644 --- a/source/blender/draw/engines/gpencil/gpencil_shader_shared.h +++ b/source/blender/draw/engines/gpencil/gpencil_shader_shared.h @@ -41,6 +41,9 @@ enum gpLightType { GP_LIGHT_TYPE_AMBIENT = 3u, }; +#define GP_IS_STROKE_VERTEX_BIT (1 << 30) +#define GP_VERTEX_ID_SHIFT 2 + /* Avoid compiler funkiness with enum types not being strongly typed in C. */ #ifndef GPU_SHADER # define gpMaterialFlag uint diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl index 7ddfdc5f65c..642939136c8 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl @@ -1,92 +1,4 @@ -/* Must match C declaration. */ -struct gpMaterial { - vec4 stroke_color; - vec4 fill_color; - vec4 fill_mix_color; - vec4 fill_uv_rot_scale; - vec4 fill_uv_offset; - /* Put float/int at the end to avoid padding error */ - /* Some drivers are completely messing the alignment or the fetches here. - * We are forced to pack these into vec4 otherwise we only get 0.0 as value. */ - vec4 gp_mat_packed_1; - // float stroke_texture_mix; - // float stroke_u_scale; - // float fill_texture_mix; - // int gp_flag; - /* Please ensure 16 byte alignment (multiple of vec4). */ -}; - -#define MATERIAL(m) materials[m + gpMaterialOffset] - -#define stroke_texture_mix gp_mat_packed_1.x -#define stroke_u_scale gp_mat_packed_1.y -#define fill_texture_mix gp_mat_packed_1.z -#define GP_FLAG(m) floatBitsToInt(MATERIAL(m).gp_mat_packed_1.w) - -/* flag */ -#define GP_STROKE_ALIGNMENT_STROKE 1 -#define GP_STROKE_ALIGNMENT_OBJECT 2 -#define GP_STROKE_ALIGNMENT_FIXED 3 -#define GP_STROKE_ALIGNMENT 0x3 -#define GP_STROKE_OVERLAP (1 << 2) -#define GP_STROKE_TEXTURE_USE (1 << 3) -#define GP_STROKE_TEXTURE_STENCIL (1 << 4) -#define GP_STROKE_TEXTURE_PREMUL (1 << 5) -#define GP_STROKE_DOTS (1 << 6) -#define GP_STROKE_HOLDOUT (1 << 7) -#define GP_FILL_HOLDOUT (1 << 8) -#define GP_FILL_TEXTURE_USE (1 << 10) -#define GP_FILL_TEXTURE_PREMUL (1 << 11) -#define GP_FILL_TEXTURE_CLIP (1 << 12) -#define GP_FILL_GRADIENT_USE (1 << 13) -#define GP_FILL_GRADIENT_RADIAL (1 << 14) -/* High bits are used to pass material ID to fragment shader. */ -#define GP_MATID_SHIFT 16 - -/* Multiline defines can crash blender with certain GPU drivers. */ -/* clang-format off */ -#define GP_FILL_FLAGS (GP_FILL_TEXTURE_USE | GP_FILL_TEXTURE_PREMUL | GP_FILL_TEXTURE_CLIP | GP_FILL_GRADIENT_USE | GP_FILL_GRADIENT_RADIAL | GP_FILL_HOLDOUT) -/* clang-format on */ - -#define GP_FLAG_TEST(flag, val) (((flag) & (val)) != 0) - -/* Must match C declaration. */ -struct gpLight { - vec4 color_type; - vec4 right; - vec4 up; - vec4 forward; - vec4 position; - /* Please ensure 16 byte alignment (multiple of vec4). */ -}; - -#define spot_size right.w -#define spot_blend up.w - -#define GP_LIGHT_TYPE_POINT 0.0 -#define GP_LIGHT_TYPE_SPOT 1.0 -#define GP_LIGHT_TYPE_SUN 2.0 -#define GP_LIGHT_TYPE_AMBIENT 3.0 - -#ifdef GP_MATERIAL_BUFFER_LEN - -layout(std140) uniform gpMaterialBlock -{ - gpMaterial materials[GP_MATERIAL_BUFFER_LEN]; -}; - -#endif - -#ifdef GPENCIL_LIGHT_BUFFER_LEN - -layout(std140) uniform gpLightBlock -{ - gpLight lights[GPENCIL_LIGHT_BUFFER_LEN]; -}; - -#endif - /* Must match eGPLayerBlendModes */ #define MODE_REGULAR 0 #define MODE_HARDLIGHT 1 @@ -149,510 +61,3 @@ void blend_mode_output( break; } } - -#ifndef USE_GPU_SHADER_CREATE_INFO - -IN_OUT ShaderStageInterface -{ - vec4 finalColorMul; - vec4 finalColorAdd; - vec3 finalPos; - vec2 finalUvs; - noperspective float strokeThickness; - noperspective float unclampedThickness; - noperspective float strokeHardeness; - flat vec2 strokeAspect; - flat vec2 strokePt1; - flat vec2 strokePt2; - flat int matFlag; - flat float depth; -}; - -#endif - -#ifdef GPU_FRAGMENT_SHADER - -# define linearstep(p0, p1, v) (clamp(((v) - (p0)) / abs((p1) - (p0)), 0.0, 1.0)) - -float stroke_round_cap_mask(vec2 p1, vec2 p2, vec2 aspect, float thickness, float hardfac) -{ - /* We create our own uv space to avoid issues with triangulation and linear - * interpolation artifacts. */ - vec2 line = p2.xy - p1.xy; - vec2 pos = gl_FragCoord.xy - p1.xy; - float line_len = length(line); - float half_line_len = line_len * 0.5; - /* Normalize */ - line = (line_len > 0.0) ? (line / line_len) : vec2(1.0, 0.0); - /* Create a uv space that englobe the whole segment into a capsule. */ - vec2 uv_end; - uv_end.x = max(abs(dot(line, pos) - half_line_len) - half_line_len, 0.0); - uv_end.y = dot(vec2(-line.y, line.x), pos); - /* Divide by stroke radius. */ - uv_end /= thickness; - uv_end *= aspect; - - float dist = clamp(1.0 - length(uv_end) * 2.0, 0.0, 1.0); - if (hardfac > 0.999) { - return step(1e-8, dist); - } - else { - /* Modulate the falloff profile */ - float hardness = 1.0 - hardfac; - dist = pow(dist, mix(0.01, 10.0, hardness)); - return smoothstep(0.0, 1.0, dist); - } -} - -#endif - -uniform vec2 sizeViewport; -uniform vec2 sizeViewportInv; - -/* Per Object */ -uniform bool strokeOrder3d; -uniform int gpMaterialOffset; -uniform float thicknessScale; -uniform float thicknessWorldScale; -#define thicknessIsScreenSpace (thicknessWorldScale < 0.0) - -#ifdef GPU_VERTEX_SHADER - -/* Per Layer */ -uniform float thicknessOffset; -uniform float vertexColorOpacity; -uniform vec4 layerTint; -uniform float layerOpacity; /* Used for onion skin. */ -uniform float strokeIndexOffset = 0.0; - -/* All of these attributes are quad loaded the same way - * as GL_LINES_ADJACENCY would feed a geometry shader: - * - ma reference the previous adjacency point. - * - ma1 reference the current line first point. - * - ma2 reference the current line second point. - * - ma3 reference the next adjacency point. - * Note that we are rendering quad instances and not using any index buffer (except for fills). - */ -/* x is material index, y is stroke_id, z is point_id, w is aspect & rotation & hardness packed. */ -in ivec4 ma; -in ivec4 ma1; -in ivec4 ma2; -in ivec4 ma3; -/* Position contains thickness in 4th component. */ -in vec4 pos; /* Prev adj vert */ -in vec4 pos1; /* Current edge */ -in vec4 pos2; /* Current edge */ -in vec4 pos3; /* Next adj vert */ -/* xy is UV for fills, z is U of stroke, w is strength. */ -in vec4 uv1; -in vec4 uv2; -in vec4 col1; -in vec4 col2; -in vec4 fcol1; -/* WARNING: Max attribute count is actually 14 because OSX OpenGL implementation - * considers gl_VertexID and gl_InstanceID as vertex attribute. (see T74536) */ -# define stroke_id1 ma1.y -# define point_id1 ma1.z -# define thickness1 pos1.w -# define thickness2 pos2.w -# define strength1 uv1.w -# define strength2 uv2.w -/* Packed! need to be decoded. */ -# define hardness1 ma1.w -# define hardness2 ma2.w -# define uvrot1 ma1.w -# define aspect1 ma1.w - -vec2 decode_aspect(int packed_data) -{ - float asp = float(uint(packed_data) & 0x1FFu) * (1.0 / 255.0); - return (asp > 1.0) ? vec2(1.0, (asp - 1.0)) : vec2(asp, 1.0); -} - -float decode_uvrot(int packed_data) -{ - uint udata = uint(packed_data); - float uvrot = 1e-8 + float((udata & 0x1FE00u) >> 9u) * (1.0 / 255.0); - return ((udata & 0x20000u) != 0u) ? -uvrot : uvrot; -} - -float decode_hardness(int packed_data) -{ - return float((uint(packed_data) & 0x3FC0000u) >> 18u) * (1.0 / 255.0); -} - -void discard_vert() -{ - /* We set the vertex at the camera origin to generate 0 fragments. */ - gl_Position = vec4(0.0, 0.0, -3e36, 0.0); -} - -vec2 project_to_screenspace(vec4 v) -{ - return ((v.xy / v.w) * 0.5 + 0.5) * sizeViewport; -} - -vec2 rotate_90deg(vec2 v) -{ - /* Counter Clock-Wise. */ - return vec2(-v.y, v.x); -} - -mat4 model_matrix_get() -{ - return ModelMatrix; -} - -vec3 transform_point(mat4 m, vec3 v) -{ - return (m * vec4(v, 1.0)).xyz; -} - -vec2 safe_normalize(vec2 v) -{ - float len_sqr = dot(v, v); - if (len_sqr > 0.0) { - return v / sqrt(len_sqr); - } - else { - return vec2(1.0, 0.0); - } -} - -vec2 safe_normalize_len(vec2 v, out float len) -{ - len = sqrt(dot(v, v)); - if (len > 0.0) { - return v / len; - } - else { - return vec2(1.0, 0.0); - } -} - -float stroke_thickness_modulate(float thickness) -{ - /* Modify stroke thickness by object and layer factors. */ - thickness *= thicknessScale; - thickness += thicknessOffset; - thickness = max(1.0, thickness); - - if (thicknessIsScreenSpace) { - /* Multiply offset by view Z so that offset is constant in screenspace. - * (e.i: does not change with the distance to camera) */ - thickness *= gl_Position.w; - } - else { - /* World space point size. */ - thickness *= thicknessWorldScale * drw_view.winmat[1][1] * sizeViewport.y; - } - return thickness; -} - -float clamp_small_stroke_thickness(float thickness) -{ - /* To avoid aliasing artifacts, we clamp the line thickness and - * reduce its opacity in the fragment shader. */ - float min_thickness = gl_Position.w * 1.3; - thickness = max(min_thickness, thickness); - - return thickness; -} - -# ifdef GP_MATERIAL_BUFFER_LEN -void color_output(vec4 stroke_col, vec4 vert_col, float vert_strength, float mix_tex) -{ - /* Mix stroke with other colors. */ - vec4 mixed_col = stroke_col; - mixed_col.rgb = mix(mixed_col.rgb, vert_col.rgb, vert_col.a * vertexColorOpacity); - mixed_col.rgb = mix(mixed_col.rgb, layerTint.rgb, layerTint.a); - mixed_col.a *= vert_strength * layerOpacity; - /** - * This is what the fragment shader looks like. - * out = col * finalColorMul + col.a * finalColorAdd. - * finalColorMul is how much of the texture color to keep. - * finalColorAdd is how much of the mixed color to add. - * Note that we never add alpha. This is to keep the texture act as a stencil. - * We do however, modulate the alpha (reduce it). - */ - /* We add the mixed color. This is 100% mix (no texture visible). */ - finalColorMul = vec4(mixed_col.aaa, mixed_col.a); - finalColorAdd = vec4(mixed_col.rgb * mixed_col.a, 0.0); - /* Then we blend according to the texture mix factor. - * Note that we keep the alpha modulation. */ - finalColorMul.rgb *= mix_tex; - finalColorAdd.rgb *= 1.0 - mix_tex; -} -# endif - -void stroke_vertex() -{ - int m = ma1.x; - bool is_dot = false; - bool is_squares = false; - -# ifdef GP_MATERIAL_BUFFER_LEN - if (m != -1) { - is_dot = GP_FLAG_TEST(GP_FLAG(m), GP_STROKE_ALIGNMENT); - is_squares = !GP_FLAG_TEST(GP_FLAG(m), GP_STROKE_DOTS); - } -# endif - - /* Special Case. Stroke with single vert are rendered as dots. Do not discard them. */ - if (!is_dot && ma.x == -1 && ma2.x == -1) { - is_dot = true; - is_squares = false; - } - - /* Endpoints, we discard the vertices. */ - if (ma1.x == -1 || (!is_dot && ma2.x == -1)) { - discard_vert(); - return; - } - - mat4 model_mat = model_matrix_get(); - - /* Avoid using a vertex attribute for quad positioning. */ - float x = float(gl_VertexID & 1) * 2.0 - 1.0; /* [-1..1] */ - float y = float(gl_VertexID & 2) - 1.0; /* [-1..1] */ - - bool use_curr = is_dot || (x == -1.0); - - vec3 wpos_adj = transform_point(model_mat, (use_curr) ? pos.xyz : pos3.xyz); - vec3 wpos1 = transform_point(model_mat, pos1.xyz); - vec3 wpos2 = transform_point(model_mat, pos2.xyz); - - vec4 ndc_adj = point_world_to_ndc(wpos_adj); - vec4 ndc1 = point_world_to_ndc(wpos1); - vec4 ndc2 = point_world_to_ndc(wpos2); - - gl_Position = (use_curr) ? ndc1 : ndc2; - finalPos = (use_curr) ? wpos1 : wpos2; - - vec2 ss_adj = project_to_screenspace(ndc_adj); - vec2 ss1 = project_to_screenspace(ndc1); - vec2 ss2 = project_to_screenspace(ndc2); - /* Screenspace Lines tangents. */ - float line_len; - vec2 line = safe_normalize_len(ss2 - ss1, line_len); - vec2 line_adj = safe_normalize((use_curr) ? (ss1 - ss_adj) : (ss_adj - ss2)); - - float thickness = abs((use_curr) ? thickness1 : thickness2); - thickness = stroke_thickness_modulate(thickness); - float clampedThickness = clamp_small_stroke_thickness(thickness); - - finalUvs = vec2(x, y) * 0.5 + 0.5; - strokeHardeness = decode_hardness(use_curr ? hardness1 : hardness2); - - if (is_dot) { -# ifdef GP_MATERIAL_BUFFER_LEN - int alignement = GP_FLAG(m) & GP_STROKE_ALIGNMENT; - /* For one point strokes use object alignment. */ - if (ma.x == -1 && ma2.x == -1 && alignement == GP_STROKE_ALIGNMENT_STROKE) { - alignement = GP_STROKE_ALIGNMENT_OBJECT; - } -# endif - - vec2 x_axis; -# ifdef GP_MATERIAL_BUFFER_LEN - if (alignement == GP_STROKE_ALIGNMENT_STROKE) { - x_axis = (ma2.x == -1) ? line_adj : line; - } - else if (alignement == GP_STROKE_ALIGNMENT_FIXED) { - /* Default for no-material drawing. */ - x_axis = vec2(1.0, 0.0); - } - else -# endif - { /* GP_STROKE_ALIGNMENT_OBJECT */ - vec4 ndc_x = point_world_to_ndc(wpos1 + model_mat[0].xyz); - vec2 ss_x = project_to_screenspace(ndc_x); - x_axis = safe_normalize(ss_x - ss1); - } - - /* Rotation: Encoded as Cos + Sin sign. */ - float uv_rot = decode_uvrot(uvrot1); - float rot_sin = sqrt(max(0.0, 1.0 - uv_rot * uv_rot)) * sign(uv_rot); - float rot_cos = abs(uv_rot); - x_axis = mat2(rot_cos, -rot_sin, rot_sin, rot_cos) * x_axis; - -# ifdef GP_MATERIAL_BUFFER_LEN - if (is_dot) { - float alignment_cos = MATERIAL(m).fill_uv_offset.z; - float alignment_sin = MATERIAL(m).fill_uv_offset.w; - x_axis = mat2(alignment_cos, -alignment_sin, alignment_sin, alignment_cos) * x_axis; - } -# endif - - vec2 y_axis = rotate_90deg(x_axis); - - strokeAspect = decode_aspect(aspect1); - - x *= strokeAspect.x; - y *= strokeAspect.y; - - /* Invert for vertex shader. */ - strokeAspect = 1.0 / strokeAspect; - - gl_Position.xy += (x * x_axis + y * y_axis) * sizeViewportInv.xy * clampedThickness; - - strokePt1 = ss1; - strokePt2 = ss1 + x_axis * 0.5; - strokeThickness = (is_squares) ? 1e18 : (clampedThickness / gl_Position.w); - unclampedThickness = (is_squares) ? 1e18 : (thickness / gl_Position.w); - } - else { - bool is_stroke_start = (ma.x == -1 && x == -1); - bool is_stroke_end = (ma3.x == -1 && x == 1); - - /* Mitter tangent vector. */ - vec2 miter_tan = safe_normalize(line_adj + line); - float miter_dot = dot(miter_tan, line_adj); - /* Break corners after a certain angle to avoid really thick corners. */ - const float miter_limit = 0.5; /* cos(60°) */ - bool miter_break = (miter_dot < miter_limit); - miter_tan = (miter_break || is_stroke_start || is_stroke_end) ? line : (miter_tan / miter_dot); - - vec2 miter = rotate_90deg(miter_tan); - - strokePt1.xy = ss1; - strokePt2.xy = ss2; - strokeThickness = clampedThickness / gl_Position.w; - unclampedThickness = thickness / gl_Position.w; - strokeAspect = vec2(1.0); - - vec2 screen_ofs = miter * y; - - /* Reminder: we packed the cap flag into the sign of strength and thickness sign. */ - if ((is_stroke_start && strength1 > 0.0) || (is_stroke_end && thickness1 > 0.0) || - (miter_break && !is_stroke_start && !is_stroke_end)) { - screen_ofs += line * x; - } - - gl_Position.xy += screen_ofs * sizeViewportInv.xy * clampedThickness; - - finalUvs.x = (use_curr) ? uv1.z : uv2.z; -# ifdef GP_MATERIAL_BUFFER_LEN - finalUvs.x *= MATERIAL(m).stroke_u_scale; -# endif - } - -# ifdef GP_MATERIAL_BUFFER_LEN - vec4 vert_col = (use_curr) ? col1 : col2; - float vert_strength = abs((use_curr) ? strength1 : strength2); - vec4 stroke_col = MATERIAL(m).stroke_color; - float mix_tex = MATERIAL(m).stroke_texture_mix; - - /* Special case: We don't use vertex color if material Holdout. */ - if (GP_FLAG_TEST(GP_FLAG(m), GP_STROKE_HOLDOUT)) { - vert_col = vec4(0.0); - } - - color_output(stroke_col, vert_col, vert_strength, mix_tex); - - matFlag = GP_FLAG(m) & ~GP_FILL_FLAGS; -# endif - - if (strokeOrder3d) { - /* Use the fragment depth (see fragment shader). */ - depth = -1.0; - } -# ifdef GP_MATERIAL_BUFFER_LEN - else if (GP_FLAG_TEST(GP_FLAG(m), GP_STROKE_OVERLAP)) { - /* Use the index of the point as depth. - * This means the stroke can overlap itself. */ - depth = (point_id1 + strokeIndexOffset + 1.0) * 0.0000002; - } -# endif - else { - /* Use the index of first point of the stroke as depth. - * We render using a greater depth test this means the stroke - * cannot overlap itself. - * We offset by one so that the fill can be overlapped by its stroke. - * The offset is ok since we pad the strokes data because of adjacency infos. */ - depth = (stroke_id1 + strokeIndexOffset + 1.0) * 0.0000002; - } -} - -void fill_vertex() -{ - mat4 model_mat = model_matrix_get(); - - vec3 wpos = transform_point(model_mat, pos1.xyz); - gl_Position = point_world_to_ndc(wpos); - finalPos = wpos; - -# ifdef GP_MATERIAL_BUFFER_LEN - int m = ma1.x; - - vec4 fill_col = MATERIAL(m).fill_color; - float mix_tex = MATERIAL(m).fill_texture_mix; - - /* Special case: We don't modulate alpha in gradient mode. */ - if (GP_FLAG_TEST(GP_FLAG(m), GP_FILL_GRADIENT_USE)) { - fill_col.a = 1.0; - } - - /* Decode fill opacity. */ - vec4 fcol_decode = vec4(fcol1.rgb, floor(fcol1.a / 10.0)); - float fill_opacity = fcol1.a - (fcol_decode.a * 10); - fcol_decode.a /= 10000.0; - - /* Special case: We don't use vertex color if material Holdout. */ - if (GP_FLAG_TEST(GP_FLAG(m), GP_FILL_HOLDOUT)) { - fcol_decode = vec4(0.0); - } - - /* Apply opacity. */ - fill_col.a *= fill_opacity; - /* If factor is > 1 force opacity. */ - if (fill_opacity > 1.0) { - fill_col.a += fill_opacity - 1.0; - } - - fill_col.a = clamp(fill_col.a, 0.0, 1.0); - - color_output(fill_col, fcol_decode, 1.0, mix_tex); - - matFlag = GP_FLAG(m) & GP_FILL_FLAGS; - matFlag |= m << GP_MATID_SHIFT; - - vec2 loc = MATERIAL(m).fill_uv_offset.xy; - mat2x2 rot_scale = mat2x2(MATERIAL(m).fill_uv_rot_scale.xy, MATERIAL(m).fill_uv_rot_scale.zw); - finalUvs = rot_scale * uv1.xy + loc; -# endif - - strokeHardeness = 1.0; - strokeThickness = 1e18; - unclampedThickness = 1e20; - strokeAspect = vec2(1.0); - strokePt1 = strokePt2 = vec2(0.0); - - if (strokeOrder3d) { - /* Use the fragment depth (see fragment shader). */ - depth = -1.0; - /* We still offset the fills a little to avoid overlaps */ - gl_Position.z += 0.000002; - } - else { - /* Use the index of first point of the stroke as depth. */ - depth = (stroke_id1 + strokeIndexOffset) * 0.0000002; - } -} - -void gpencil_vertex() -{ - /* Trick to detect if a drawcall is stroke or fill. - * This does mean that we need to draw an empty stroke segment before starting - * to draw the real stroke segments. */ - bool is_fill = (gl_InstanceID == 0); - - if (!is_fill) { - stroke_vertex(); - } - else { - fill_vertex(); - } -} - -#endif diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl index 8ed03b23809..9b1db09ab3c 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl @@ -31,23 +31,11 @@ void main() vec4 vert_color; vec3 vert_N; + ivec4 ma1 = floatBitsToInt(texelFetch(gp_pos_tx, gpencil_stroke_point_id() * 3 + 1)); gpMaterial gp_mat = materials[ma1.x + gpMaterialOffset]; gpMaterialFlag gp_flag = floatBitsToUint(gp_mat._flag); - gl_Position = gpencil_vertex(ma, - ma1, - ma2, - ma3, - pos, - pos1, - pos2, - pos3, - uv1, - uv2, - col1, - col2, - fcol1, - vec4(viewportSize, 1.0 / viewportSize), + gl_Position = gpencil_vertex(vec4(viewportSize, 1.0 / viewportSize), gp_flag, gp_mat._alignment_rot, gp_interp.pos, @@ -60,7 +48,7 @@ void main() gp_interp.thickness, gp_interp.hardness); - if (GPENCIL_IS_STROKE_VERTEX) { + if (gpencil_is_stroke_vertex()) { if (!flag_test(gp_flag, GP_STROKE_ALIGNMENT)) { gp_interp.uv.x *= gp_mat._stroke_u_scale; } @@ -96,6 +84,9 @@ void main() } } else { + int stroke_point_id = gpencil_stroke_point_id(); + vec4 uv1 = texelFetch(gp_col_tx, stroke_point_id * 2 + 2); + vec4 fcol1 = texelFetch(gp_col_tx, stroke_point_id * 2 + 1); vec4 fill_col = gp_mat.fill_color; /* Special case: We don't modulate alpha in gradient mode. */ diff --git a/source/blender/draw/engines/gpencil/shaders/infos/gpencil_info.hh b/source/blender/draw/engines/gpencil/shaders/infos/gpencil_info.hh index edd51e71242..da2776254e6 100644 --- a/source/blender/draw/engines/gpencil/shaders/infos/gpencil_info.hh +++ b/source/blender/draw/engines/gpencil/shaders/infos/gpencil_info.hh @@ -22,10 +22,10 @@ GPU_SHADER_CREATE_INFO(gpencil_geometry) .do_static_compilation(true) .define("GP_LIGHT") .typedef_source("gpencil_defines.h") - .sampler(0, ImageType::FLOAT_2D, "gpFillTexture") - .sampler(1, ImageType::FLOAT_2D, "gpStrokeTexture") - .sampler(2, ImageType::DEPTH_2D, "gpSceneDepthTexture") - .sampler(3, ImageType::FLOAT_2D, "gpMaskTexture") + .sampler(2, ImageType::FLOAT_2D, "gpFillTexture") + .sampler(3, ImageType::FLOAT_2D, "gpStrokeTexture") + .sampler(4, ImageType::DEPTH_2D, "gpSceneDepthTexture") + .sampler(5, ImageType::FLOAT_2D, "gpMaskTexture") .uniform_buf(4, "gpMaterial", "materials[GPENCIL_MATERIAL_BUFFER_LEN]", Frequency::BATCH) .uniform_buf(3, "gpLight", "lights[GPENCIL_LIGHT_BUFFER_LEN]", Frequency::BATCH) .push_constant(Type::VEC2, "viewportSize") diff --git a/source/blender/draw/engines/overlay/overlay_outline.cc b/source/blender/draw/engines/overlay/overlay_outline.cc index 5ea02376b67..50d42effe00 100644 --- a/source/blender/draw/engines/overlay/overlay_outline.cc +++ b/source/blender/draw/engines/overlay/overlay_outline.cc @@ -172,7 +172,6 @@ void OVERLAY_outline_cache_init(OVERLAY_Data *vedata) typedef struct iterData { Object *ob; DRWShadingGroup *stroke_grp; - DRWShadingGroup *fill_grp; int cfra; float plane[4]; } iterData; @@ -193,12 +192,17 @@ static void gpencil_layer_cache_populate(bGPDlayer *gpl, * Convert to world units (by default, 1 meter = 2000 pixels). */ float thickness_scale = (is_screenspace) ? -1.0f : (gpd->pixfactor / 2000.0f); + GPUVertBuf *position_tx = DRW_cache_gpencil_position_buffer_get(iter->ob, iter->cfra); + GPUVertBuf *color_tx = DRW_cache_gpencil_color_buffer_get(iter->ob, iter->cfra); + DRWShadingGroup *grp = iter->stroke_grp = DRW_shgroup_create_sub(iter->stroke_grp); DRW_shgroup_uniform_bool_copy(grp, "gpStrokeOrder3d", is_stroke_order_3d); DRW_shgroup_uniform_float_copy(grp, "gpThicknessScale", object_scale); DRW_shgroup_uniform_float_copy(grp, "gpThicknessOffset", float(gpl->line_change)); DRW_shgroup_uniform_float_copy(grp, "gpThicknessWorldScale", thickness_scale); DRW_shgroup_uniform_vec4_copy(grp, "gpDepthPlane", iter->plane); + DRW_shgroup_buffer_texture(grp, "gp_pos_tx", position_tx); + DRW_shgroup_buffer_texture(grp, "gp_col_tx", color_tx); } static void gpencil_stroke_cache_populate(bGPDlayer * /*gpl*/, @@ -219,20 +223,19 @@ static void gpencil_stroke_cache_populate(bGPDlayer * /*gpl*/, return; } + struct GPUBatch *geom = DRW_cache_gpencil_get(iter->ob, iter->cfra); + if (show_fill) { - struct GPUBatch *geom = DRW_cache_gpencil_fills_get(iter->ob, iter->cfra); int vfirst = gps->runtime.fill_start * 3; int vcount = gps->tot_triangles * 3; - DRW_shgroup_call_range(iter->fill_grp, iter->ob, geom, vfirst, vcount); + DRW_shgroup_call_range(iter->stroke_grp, iter->ob, geom, vfirst, vcount); } if (show_stroke) { - struct GPUBatch *geom = DRW_cache_gpencil_strokes_get(iter->ob, iter->cfra); - /* Start one vert before to have gl_InstanceID > 0 (see shader). */ - int vfirst = gps->runtime.stroke_start - 1; - /* Include "potential" cyclic vertex and start adj vertex (see shader). */ - int vcount = gps->totpoints + 1 + 1; - DRW_shgroup_call_instance_range(iter->stroke_grp, iter->ob, geom, vfirst, vcount); + int vfirst = gps->runtime.stroke_start * 3; + /* Include "potential" cyclic vertex (see shader). */ + int vcount = (gps->totpoints + 1) * 2 * 3; + DRW_shgroup_call_range(iter->stroke_grp, iter->ob, geom, vfirst, vcount); } } @@ -247,7 +250,6 @@ static void OVERLAY_outline_gpencil(OVERLAY_PrivateData *pd, Object *ob) iterData iter{}; iter.ob = ob; iter.stroke_grp = pd->outlines_gpencil_grp; - iter.fill_grp = DRW_shgroup_create_sub(pd->outlines_gpencil_grp); iter.cfra = pd->cfra; if (gpd->draw_mode == GP_DRAWMODE_2D) { diff --git a/source/blender/draw/engines/overlay/shaders/overlay_outline_prepass_gpencil_vert.glsl b/source/blender/draw/engines/overlay/shaders/overlay_outline_prepass_gpencil_vert.glsl index 7d8fb0c2cb8..851e0884354 100644 --- a/source/blender/draw/engines/overlay/shaders/overlay_outline_prepass_gpencil_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/overlay_outline_prepass_gpencil_vert.glsl @@ -34,20 +34,7 @@ void main() float unused_strength; vec2 unused_uv; - gl_Position = gpencil_vertex(ma, - ma1, - ma2, - ma3, - pos, - pos1, - pos2, - pos3, - uv1, - uv2, - col1, - col2, - fcol1, - vec4(sizeViewport, sizeViewportInv), + gl_Position = gpencil_vertex(vec4(sizeViewport, sizeViewportInv), world_pos, unused_N, unused_color, diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 058f28f094d..44abf3c7064 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -13,6 +13,7 @@ extern "C" { struct GPUBatch; struct GPUMaterial; +struct GPUVertBuf; struct ModifierData; struct Object; struct PTCacheEdit; @@ -257,14 +258,16 @@ struct GPUBatch *DRW_cache_volume_selection_surface_get(struct Object *ob); /* GPencil */ -struct GPUBatch *DRW_cache_gpencil_strokes_get(struct Object *ob, int cfra); -struct GPUBatch *DRW_cache_gpencil_fills_get(struct Object *ob, int cfra); +struct GPUBatch *DRW_cache_gpencil_get(struct Object *ob, int cfra); +struct GPUVertBuf *DRW_cache_gpencil_position_buffer_get(struct Object *ob, int cfra); +struct GPUVertBuf *DRW_cache_gpencil_color_buffer_get(struct Object *ob, int cfra); struct GPUBatch *DRW_cache_gpencil_edit_lines_get(struct Object *ob, int cfra); struct GPUBatch *DRW_cache_gpencil_edit_points_get(struct Object *ob, int cfra); struct GPUBatch *DRW_cache_gpencil_edit_curve_handles_get(struct Object *ob, int cfra); struct GPUBatch *DRW_cache_gpencil_edit_curve_points_get(struct Object *ob, int cfra); -struct GPUBatch *DRW_cache_gpencil_sbuffer_stroke_get(struct Object *ob); -struct GPUBatch *DRW_cache_gpencil_sbuffer_fill_get(struct Object *ob); +struct GPUBatch *DRW_cache_gpencil_sbuffer_get(struct Object *ob); +struct GPUVertBuf *DRW_cache_gpencil_sbuffer_position_buffer_get(struct Object *ob); +struct GPUVertBuf *DRW_cache_gpencil_sbuffer_color_buffer_get(struct Object *ob); int DRW_gpencil_material_count_get(struct bGPdata *gpd); struct GPUBatch *DRW_cache_gpencil_face_wireframe_get(struct Object *ob); diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.cc b/source/blender/draw/intern/draw_cache_impl_gpencil.cc index 94925bfae71..eadb7772f4c 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.cc +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.cc @@ -23,12 +23,14 @@ #include "DEG_depsgraph_query.h" #include "BLI_hash.h" +#include "BLI_math_vec_types.hh" #include "BLI_polyfill_2d.h" #include "draw_cache.h" #include "draw_cache_impl.h" #include "../engines/gpencil/gpencil_defines.h" +#include "../engines/gpencil/gpencil_shader_shared.h" #define BEZIER_HANDLE (1 << 3) #define COLOR_SHIFT 5 @@ -41,11 +43,13 @@ typedef struct GpencilBatchCache { /** Instancing Data */ GPUVertBuf *vbo; GPUVertBuf *vbo_col; - /** Fill Topology */ + /** Indices in material order, then stroke order with fill first. + * Strokes can be individually rendered using `gps->runtime.stroke_start` and + * `gps->runtime.stroke_start`. */ GPUIndexBuf *ibo; - /** Instancing Batches */ - GPUBatch *stroke_batch; - GPUBatch *fill_batch; + /** Batches */ + GPUBatch *geom_batch; + /** Stroke lines only */ GPUBatch *lines_batch; /** Edit Mode */ @@ -117,8 +121,7 @@ static void gpencil_batch_cache_clear(GpencilBatchCache *cache) } GPU_BATCH_DISCARD_SAFE(cache->lines_batch); - GPU_BATCH_DISCARD_SAFE(cache->fill_batch); - GPU_BATCH_DISCARD_SAFE(cache->stroke_batch); + GPU_BATCH_DISCARD_SAFE(cache->geom_batch); GPU_VERTBUF_DISCARD_SAFE(cache->vbo); GPU_VERTBUF_DISCARD_SAFE(cache->vbo_col); GPU_INDEXBUF_DISCARD_SAFE(cache->ibo); @@ -173,9 +176,10 @@ void DRW_gpencil_batch_cache_free(bGPdata *gpd) /* MUST match the format below. */ typedef struct gpStrokeVert { - int32_t mat, stroke_id, point_id, packed_asp_hard_rot; /** Position and thickness packed in the same attribute. */ float pos[3], thickness; + /** Material Index, Stroke Index, Point Index, Packed aspect + hardness + rotation. */ + int32_t mat, stroke_id, point_id, packed_asp_hard_rot; /** UV and strength packed in the same attribute. */ float uv_fill[2], u_stroke, strength; } gpStrokeVert; @@ -184,12 +188,9 @@ static GPUVertFormat *gpencil_stroke_format(void) { static GPUVertFormat format = {0}; if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "ma", GPU_COMP_I32, 4, GPU_FETCH_INT); GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + GPU_vertformat_attr_add(&format, "ma", GPU_COMP_I32, 4, GPU_FETCH_INT); GPU_vertformat_attr_add(&format, "uv", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - /* IMPORTANT: This means having only 4 attributes - * to fit into GPU module limit of 16 attributes. */ - GPU_vertformat_multiload_enable(&format, 4); } return &format; } @@ -239,9 +240,6 @@ static GPUVertFormat *gpencil_color_format(void) if (format.attr_len == 0) { GPU_vertformat_attr_add(&format, "col", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); GPU_vertformat_attr_add(&format, "fcol", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - /* IMPORTANT: This means having only 4 attributes - * to fit into GPU module limit of 16 attributes. */ - GPU_vertformat_multiload_enable(&format, 4); } return &format; } @@ -296,7 +294,8 @@ BLI_INLINE int32_t pack_rotation_aspect_hardness(float rot, float asp, float har return packed; } -static void gpencil_buffer_add_point(gpStrokeVert *verts, +static void gpencil_buffer_add_point(GPUIndexBufBuilder *ibo, + gpStrokeVert *verts, gpColorVert *cols, const bGPDstroke *gps, const bGPDspoint *pt, @@ -330,27 +329,36 @@ static void gpencil_buffer_add_point(gpStrokeVert *verts, vert->packed_asp_hard_rot = pack_rotation_aspect_hardness( pt->uv_rot, aspect_ratio, gps->hardeness); + + if (!is_endpoint) { + /* Issue a Quad per point. */ + /* The attribute loading uses a different shader and will undo this bit packing. */ + int v_mat = (v << GP_VERTEX_ID_SHIFT) | GP_IS_STROKE_VERTEX_BIT; + GPU_indexbuf_add_tri_verts(ibo, v_mat + 0, v_mat + 1, v_mat + 2); + GPU_indexbuf_add_tri_verts(ibo, v_mat + 2, v_mat + 1, v_mat + 3); + } } -static void gpencil_buffer_add_stroke(gpStrokeVert *verts, +static void gpencil_buffer_add_stroke(GPUIndexBufBuilder *ibo, + gpStrokeVert *verts, gpColorVert *cols, const bGPDstroke *gps) { const bGPDspoint *pts = gps->points; int pts_len = gps->totpoints; bool is_cyclic = gpencil_stroke_is_cyclic(gps); - int v = gps->runtime.stroke_start; + int v = gps->runtime.vertex_start; /* First point for adjacency (not drawn). */ int adj_idx = (is_cyclic) ? (pts_len - 1) : min_ii(pts_len - 1, 1); - gpencil_buffer_add_point(verts, cols, gps, &pts[adj_idx], v++, true); + gpencil_buffer_add_point(ibo, verts, cols, gps, &pts[adj_idx], v++, true); for (int i = 0; i < pts_len; i++) { - gpencil_buffer_add_point(verts, cols, gps, &pts[i], v++, false); + gpencil_buffer_add_point(ibo, verts, cols, gps, &pts[i], v++, false); } /* Draw line to first point to complete the loop for cyclic strokes. */ if (is_cyclic) { - gpencil_buffer_add_point(verts, cols, gps, &pts[0], v, false); + gpencil_buffer_add_point(ibo, verts, cols, gps, &pts[0], v, false); /* UV factor needs to be adjusted for the last point to not be equal to the UV factor of the * first point. It should be the factor of the last point plus the distance from the last point * to the first. @@ -361,16 +369,20 @@ static void gpencil_buffer_add_stroke(gpStrokeVert *verts, } /* Last adjacency point (not drawn). */ adj_idx = (is_cyclic) ? 1 : max_ii(0, pts_len - 2); - gpencil_buffer_add_point(verts, cols, gps, &pts[adj_idx], v++, true); + gpencil_buffer_add_point(ibo, verts, cols, gps, &pts[adj_idx], v++, true); } static void gpencil_buffer_add_fill(GPUIndexBufBuilder *ibo, const bGPDstroke *gps) { int tri_len = gps->tot_triangles; - int v = gps->runtime.stroke_start; + int v = gps->runtime.vertex_start + 1; for (int i = 0; i < tri_len; i++) { uint *tri = gps->triangles[i].verts; - GPU_indexbuf_add_tri_verts(ibo, v + tri[0], v + tri[1], v + tri[2]); + /* The attribute loading uses a different shader and will undo this bit packing. */ + GPU_indexbuf_add_tri_verts(ibo, + (v + tri[0]) << GP_VERTEX_ID_SHIFT, + (v + tri[1]) << GP_VERTEX_ID_SHIFT, + (v + tri[2]) << GP_VERTEX_ID_SHIFT); } } @@ -380,10 +392,10 @@ static void gpencil_stroke_iter_cb(bGPDlayer *UNUSED(gpl), void *thunk) { gpIterData *iter = (gpIterData *)thunk; - gpencil_buffer_add_stroke(iter->verts, iter->cols, gps); if (gps->tot_triangles > 0) { gpencil_buffer_add_fill(&iter->ibo, gps); } + gpencil_buffer_add_stroke(&iter->ibo, iter->verts, iter->cols, gps); } static void gpencil_object_verts_count_cb(bGPDlayer *UNUSED(gpl), @@ -392,12 +404,15 @@ static void gpencil_object_verts_count_cb(bGPDlayer *UNUSED(gpl), void *thunk) { gpIterData *iter = (gpIterData *)thunk; - - /* Store first index offset */ - gps->runtime.stroke_start = iter->vert_len; + int stroke_vert_len = gps->totpoints + gpencil_stroke_is_cyclic(gps); + gps->runtime.vertex_start = iter->vert_len; + /* Add additional padding at the start and end. */ + iter->vert_len += 1 + stroke_vert_len + 1; + /* Store first index offset. */ gps->runtime.fill_start = iter->tri_len; - iter->vert_len += gps->totpoints + 2 + gpencil_stroke_is_cyclic(gps); iter->tri_len += gps->tot_triangles; + gps->runtime.stroke_start = iter->tri_len; + iter->tri_len += stroke_vert_len * 2; } static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfra) @@ -407,7 +422,7 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr if (cache->vbo == NULL) { /* Should be discarded together. */ BLI_assert(cache->vbo == NULL && cache->ibo == NULL); - BLI_assert(cache->fill_batch == NULL && cache->stroke_batch == NULL); + BLI_assert(cache->geom_batch == NULL); /* TODO/PERF: Could be changed to only do it if needed. * For now it's simpler to assume we always need it * since multiple viewport could or could not need it. @@ -420,25 +435,26 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr .gpd = gpd, .verts = NULL, .ibo = {0}, - .vert_len = 1, /* Start at 1 for the gl_InstanceID trick to work (see vert shader). */ + .vert_len = 0, .tri_len = 0, .curve_len = 0, }; BKE_gpencil_visible_stroke_advanced_iter( NULL, ob, NULL, gpencil_object_verts_count_cb, &iter, do_onion, cfra); + GPUUsageType vbo_flag = GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY; /* Create VBOs. */ GPUVertFormat *format = gpencil_stroke_format(); GPUVertFormat *format_col = gpencil_color_format(); - cache->vbo = GPU_vertbuf_create_with_format(format); - cache->vbo_col = GPU_vertbuf_create_with_format(format_col); + cache->vbo = GPU_vertbuf_create_with_format_ex(format, vbo_flag); + cache->vbo_col = GPU_vertbuf_create_with_format_ex(format_col, vbo_flag); /* Add extra space at the end of the buffer because of quad load. */ GPU_vertbuf_data_alloc(cache->vbo, iter.vert_len + 2); GPU_vertbuf_data_alloc(cache->vbo_col, iter.vert_len + 2); iter.verts = (gpStrokeVert *)GPU_vertbuf_get_data(cache->vbo); iter.cols = (gpColorVert *)GPU_vertbuf_get_data(cache->vbo_col); /* Create IBO. */ - GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, iter.vert_len); + GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, 0xFFFFFFFFu); /* Fill buffers with data. */ BKE_gpencil_visible_stroke_advanced_iter( @@ -453,33 +469,39 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr /* Finish the IBO. */ cache->ibo = GPU_indexbuf_build(&iter.ibo); - /* Create the batches */ - cache->fill_batch = GPU_batch_create(GPU_PRIM_TRIS, cache->vbo, cache->ibo); - GPU_batch_vertbuf_add(cache->fill_batch, cache->vbo_col); - cache->stroke_batch = GPU_batch_create(GPU_PRIM_TRI_STRIP, gpencil_dummy_buffer_get(), NULL); - GPU_batch_instbuf_add_ex(cache->stroke_batch, cache->vbo, 0); - GPU_batch_instbuf_add_ex(cache->stroke_batch, cache->vbo_col, 0); + cache->geom_batch = GPU_batch_create(GPU_PRIM_TRIS, cache->vbo, cache->ibo); + /* Allow creation of buffer texture. */ + GPU_vertbuf_use(cache->vbo); + GPU_vertbuf_use(cache->vbo_col); gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY; cache->is_dirty = false; } } -GPUBatch *DRW_cache_gpencil_strokes_get(Object *ob, int cfra) +GPUBatch *DRW_cache_gpencil_get(Object *ob, int cfra) { GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); gpencil_batches_ensure(ob, cache, cfra); - return cache->stroke_batch; + return cache->geom_batch; } -GPUBatch *DRW_cache_gpencil_fills_get(Object *ob, int cfra) +GPUVertBuf *DRW_cache_gpencil_position_buffer_get(Object *ob, int cfra) { GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); gpencil_batches_ensure(ob, cache, cfra); - return cache->fill_batch; + return cache->vbo; +} + +GPUVertBuf *DRW_cache_gpencil_color_buffer_get(Object *ob, int cfra) +{ + GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); + gpencil_batches_ensure(ob, cache, cfra); + + return cache->vbo_col; } static void gpencil_lines_indices_cb(bGPDlayer *UNUSED(gpl), @@ -490,7 +512,7 @@ static void gpencil_lines_indices_cb(bGPDlayer *UNUSED(gpl), gpIterData *iter = (gpIterData *)thunk; int pts_len = gps->totpoints + gpencil_stroke_is_cyclic(gps); - int start = gps->runtime.stroke_start + 1; + int start = gps->runtime.vertex_start + 1; int end = start + pts_len; for (int i = start; i < end; i++) { GPU_indexbuf_add_generic_vert(&iter->ibo, i); @@ -573,7 +595,7 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_ /* DRW_cache_gpencil_sbuffer_stroke_data_get need to have been called previously. */ BLI_assert(gps != NULL); - if (do_stroke && (gpd->runtime.sbuffer_stroke_batch == NULL)) { + if (do_stroke && (gpd->runtime.sbuffer_batch == NULL)) { gps->points = (bGPDspoint *)MEM_mallocN(vert_len * sizeof(*gps->points), __func__); const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -597,35 +619,24 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_ /* Calc uv data along the stroke. */ BKE_gpencil_stroke_uv_update(gps); + int vert_len = gps->tot_triangles + (gps->totpoints + gpencil_stroke_is_cyclic(gps)) * 2; + /* Create IBO. */ + GPUIndexBufBuilder ibo_builder; + GPU_indexbuf_init(&ibo_builder, GPU_PRIM_TRIS, vert_len, 0xFFFFFFFFu); /* Create VBO. */ + GPUUsageType vbo_flag = GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY; GPUVertFormat *format = gpencil_stroke_format(); GPUVertFormat *format_color = gpencil_color_format(); - GPUVertBuf *vbo = GPU_vertbuf_create_with_format(format); - GPUVertBuf *vbo_col = GPU_vertbuf_create_with_format(format_color); - /* Add extra space at the end (and start) of the buffer because of quad load and cyclic. */ - GPU_vertbuf_data_alloc(vbo, 1 + vert_len + 1 + 2); - GPU_vertbuf_data_alloc(vbo_col, 1 + vert_len + 1 + 2); + GPUVertBuf *vbo = GPU_vertbuf_create_with_format_ex(format, vbo_flag); + GPUVertBuf *vbo_col = GPU_vertbuf_create_with_format_ex(format_color, vbo_flag); + /* Add extra space at the end the buffer because of quad load and cyclic. */ + GPU_vertbuf_data_alloc(vbo, vert_len + 2); + GPU_vertbuf_data_alloc(vbo_col, vert_len + 2); gpStrokeVert *verts = (gpStrokeVert *)GPU_vertbuf_get_data(vbo); gpColorVert *cols = (gpColorVert *)GPU_vertbuf_get_data(vbo_col); - /* Fill buffers with data. */ - gpencil_buffer_add_stroke(verts, cols, gps); - - GPUBatch *batch = GPU_batch_create(GPU_PRIM_TRI_STRIP, gpencil_dummy_buffer_get(), NULL); - GPU_batch_instbuf_add_ex(batch, vbo, true); - GPU_batch_instbuf_add_ex(batch, vbo_col, true); - - gpd->runtime.sbuffer_stroke_batch = batch; - - MEM_freeN(gps->points); - } - - if (do_fill && (gpd->runtime.sbuffer_fill_batch == NULL)) { - /* Create IBO. */ - GPUIndexBufBuilder ibo_builder; - GPU_indexbuf_init(&ibo_builder, GPU_PRIM_TRIS, gps->tot_triangles, vert_len); - - if (gps->tot_triangles > 0) { + /* Create fill indices. */ + if (do_fill && gps->tot_triangles > 0) { float(*tpoints2d)[2] = (float(*)[2])MEM_mallocN(sizeof(*tpoints2d) * vert_len, __func__); /* Triangulate in 2D. */ for (int i = 0; i < vert_len; i++) { @@ -645,40 +656,56 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_ MEM_freeN(tpoints2d); } - GPUIndexBuf *ibo = GPU_indexbuf_build(&ibo_builder); - GPUVertBuf *vbo = gpd->runtime.sbuffer_stroke_batch->inst[0]; - GPUVertBuf *vbo_col = gpd->runtime.sbuffer_stroke_batch->inst[1]; + /* Fill buffers with data. */ + gpencil_buffer_add_stroke(&ibo_builder, verts, cols, gps); + + GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_TRIS, + gpencil_dummy_buffer_get(), + GPU_indexbuf_build(&ibo_builder), + GPU_BATCH_OWNS_INDEX); - GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, ibo, GPU_BATCH_OWNS_INDEX); - GPU_batch_vertbuf_add(batch, vbo_col); + gpd->runtime.sbuffer_position_buf = vbo; + gpd->runtime.sbuffer_color_buf = vbo_col; + gpd->runtime.sbuffer_batch = batch; - gpd->runtime.sbuffer_fill_batch = batch; + MEM_freeN(gps->points); } } -GPUBatch *DRW_cache_gpencil_sbuffer_stroke_get(Object *ob) +GPUBatch *DRW_cache_gpencil_sbuffer_get(Object *ob) +{ + bGPdata *gpd = (bGPdata *)ob->data; + /* Fill batch also need stroke batch to be created (vbo is shared). */ + gpencil_sbuffer_stroke_ensure(gpd, true, true); + + return gpd->runtime.sbuffer_batch; +} + +GPUVertBuf *DRW_cache_gpencil_sbuffer_position_buffer_get(Object *ob) { bGPdata *gpd = (bGPdata *)ob->data; - gpencil_sbuffer_stroke_ensure(gpd, true, false); + /* Fill batch also need stroke batch to be created (vbo is shared). */ + gpencil_sbuffer_stroke_ensure(gpd, true, true); - return gpd->runtime.sbuffer_stroke_batch; + return gpd->runtime.sbuffer_position_buf; } -GPUBatch *DRW_cache_gpencil_sbuffer_fill_get(Object *ob) +GPUVertBuf *DRW_cache_gpencil_sbuffer_color_buffer_get(Object *ob) { bGPdata *gpd = (bGPdata *)ob->data; /* Fill batch also need stroke batch to be created (vbo is shared). */ gpencil_sbuffer_stroke_ensure(gpd, true, true); - return gpd->runtime.sbuffer_fill_batch; + return gpd->runtime.sbuffer_color_buf; } void DRW_cache_gpencil_sbuffer_clear(Object *ob) { bGPdata *gpd = (bGPdata *)ob->data; MEM_SAFE_FREE(gpd->runtime.sbuffer_gps); - GPU_BATCH_DISCARD_SAFE(gpd->runtime.sbuffer_fill_batch); - GPU_BATCH_DISCARD_SAFE(gpd->runtime.sbuffer_stroke_batch); + GPU_BATCH_DISCARD_SAFE(gpd->runtime.sbuffer_batch); + GPU_VERTBUF_DISCARD_SAFE(gpd->runtime.sbuffer_position_buf); + GPU_VERTBUF_DISCARD_SAFE(gpd->runtime.sbuffer_color_buf); } /** \} */ diff --git a/source/blender/draw/intern/draw_manager_data.cc b/source/blender/draw/intern/draw_manager_data.cc index 981206e56fe..b9e0db71122 100644 --- a/source/blender/draw/intern/draw_manager_data.cc +++ b/source/blender/draw/intern/draw_manager_data.cc @@ -589,7 +589,7 @@ void DRW_shgroup_buffer_texture(DRWShadingGroup *shgroup, const char *name, GPUVertBuf *vertex_buffer) { - int location = GPU_shader_get_ssbo(shgroup->shader, name); + int location = GPU_shader_get_texture_binding(shgroup->shader, name); if (location == -1) { return; } @@ -606,7 +606,7 @@ void DRW_shgroup_buffer_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUVertBuf **vertex_buffer) { - int location = GPU_shader_get_ssbo(shgroup->shader, name); + int location = GPU_shader_get_texture_binding(shgroup->shader, name); if (location == -1) { return; } @@ -695,7 +695,7 @@ static void drw_call_obinfos_init(DRWObjectInfos *ob_infos, Object *ob) drw_call_calc_orco(ob, ob_infos->orcotexfac); /* Random float value. */ uint random = (DST.dupli_source) ? - DST.dupli_source->random_id : + DST.dupli_source->random_id : /* TODO(fclem): this is rather costly to do at runtime. Maybe we can * put it in ob->runtime and make depsgraph ensure it is up to date. */ BLI_hash_int_2d(BLI_hash_string(ob->id.name + 2), 0); diff --git a/source/blender/draw/intern/shaders/common_gpencil_lib.glsl b/source/blender/draw/intern/shaders/common_gpencil_lib.glsl index 123c493b572..def841b07aa 100644 --- a/source/blender/draw/intern/shaders/common_gpencil_lib.glsl +++ b/source/blender/draw/intern/shaders/common_gpencil_lib.glsl @@ -90,10 +90,15 @@ float gpencil_clamp_small_stroke_thickness(float thickness, vec4 ndc_pos) #ifdef GPU_VERTEX_SHADER -/* Trick to detect if a drawcall is stroke or fill. - * This does mean that we need to draw an empty stroke segment before starting - * to draw the real stroke segments. */ -# define GPENCIL_IS_STROKE_VERTEX (gl_InstanceID != 0) +int gpencil_stroke_point_id() +{ + return (gl_VertexID & ~GP_IS_STROKE_VERTEX_BIT) >> GP_VERTEX_ID_SHIFT; +} + +bool gpencil_is_stroke_vertex() +{ + return flag_test(gl_VertexID, GP_IS_STROKE_VERTEX_BIT); +} /** * Returns value of gl_Position. @@ -120,20 +125,7 @@ float gpencil_clamp_small_stroke_thickness(float thickness, vec4 ndc_pos) * WARNING: Max attribute count is actually 14 because OSX OpenGL implementation * considers gl_VertexID and gl_InstanceID as vertex attribute. (see T74536) */ -vec4 gpencil_vertex(ivec4 ma, - ivec4 ma1, - ivec4 ma2, - ivec4 ma3, - vec4 pos, - vec4 pos1, - vec4 pos2, - vec4 pos3, - vec4 uv1, - vec4 uv2, - vec4 col1, - vec4 col2, - vec4 fcol1, - vec4 viewport_size, +vec4 gpencil_vertex(vec4 viewport_size, gpMaterialFlag material_flags, vec2 alignment_rot, /* World Position. */ @@ -155,6 +147,24 @@ vec4 gpencil_vertex(ivec4 ma, /* Stroke hardness. */ out float out_hardness) { + int stroke_point_id = (gl_VertexID & ~GP_IS_STROKE_VERTEX_BIT) >> GP_VERTEX_ID_SHIFT; + + /* Attribute Loading. */ + vec4 pos = texelFetch(gp_pos_tx, (stroke_point_id - 1) * 3 + 0); + vec4 pos1 = texelFetch(gp_pos_tx, (stroke_point_id + 0) * 3 + 0); + vec4 pos2 = texelFetch(gp_pos_tx, (stroke_point_id + 1) * 3 + 0); + vec4 pos3 = texelFetch(gp_pos_tx, (stroke_point_id + 2) * 3 + 0); + ivec4 ma = floatBitsToInt(texelFetch(gp_pos_tx, (stroke_point_id - 1) * 3 + 1)); + ivec4 ma1 = floatBitsToInt(texelFetch(gp_pos_tx, (stroke_point_id + 0) * 3 + 1)); + ivec4 ma2 = floatBitsToInt(texelFetch(gp_pos_tx, (stroke_point_id + 1) * 3 + 1)); + ivec4 ma3 = floatBitsToInt(texelFetch(gp_pos_tx, (stroke_point_id + 2) * 3 + 1)); + vec4 uv1 = texelFetch(gp_pos_tx, (stroke_point_id + 0) * 3 + 2); + vec4 uv2 = texelFetch(gp_pos_tx, (stroke_point_id + 1) * 3 + 2); + + vec4 col1 = texelFetch(gp_col_tx, (stroke_point_id + 0) * 2 + 0); + vec4 col2 = texelFetch(gp_col_tx, (stroke_point_id + 1) * 2 + 0); + vec4 fcol1 = texelFetch(gp_col_tx, (stroke_point_id + 0) * 2 + 1); + # define thickness1 pos1.w # define thickness2 pos2.w # define strength1 uv1.w @@ -167,7 +177,7 @@ vec4 gpencil_vertex(ivec4 ma, vec4 out_ndc; - if (GPENCIL_IS_STROKE_VERTEX) { + if (gpencil_is_stroke_vertex()) { bool is_dot = flag_test(material_flags, GP_STROKE_ALIGNMENT); bool is_squares = !flag_test(material_flags, GP_STROKE_DOTS); @@ -177,13 +187,6 @@ vec4 gpencil_vertex(ivec4 ma, is_squares = false; } - /* Endpoints, we discard the vertices. */ - if (ma1.x == -1 || (!is_dot && ma2.x == -1)) { - /* We set the vertex at the camera origin to generate 0 fragments. */ - out_ndc = vec4(0.0, 0.0, -3e36, 0.0); - return out_ndc; - } - /* Avoid using a vertex attribute for quad positioning. */ float x = float(gl_VertexID & 1) * 2.0 - 1.0; /* [-1..1] */ float y = float(gl_VertexID & 2) - 1.0; /* [-1..1] */ @@ -336,8 +339,7 @@ vec4 gpencil_vertex(ivec4 ma, out_N = safe_normalize(N); /* Decode fill opacity. */ - out_color = vec4(fcol1.rgb, floor(fcol1.a / 10.0)); - out_color.a /= 10000.0; + out_color = vec4(fcol1.rgb, floor(fcol1.a / 10.0) / 10000.0); /* We still offset the fills a little to avoid overlaps */ out_ndc.z += 0.000002; @@ -355,20 +357,7 @@ vec4 gpencil_vertex(ivec4 ma, return out_ndc; } -vec4 gpencil_vertex(ivec4 ma, - ivec4 ma1, - ivec4 ma2, - ivec4 ma3, - vec4 pos, - vec4 pos1, - vec4 pos2, - vec4 pos3, - vec4 uv1, - vec4 uv2, - vec4 col1, - vec4 col2, - vec4 fcol1, - vec4 viewport_size, +vec4 gpencil_vertex(vec4 viewport_size, out vec3 out_P, out vec3 out_N, out vec4 out_color, @@ -379,20 +368,7 @@ vec4 gpencil_vertex(ivec4 ma, out vec2 out_thickness, out float out_hardness) { - return gpencil_vertex(ma, - ma1, - ma2, - ma3, - pos, - pos1, - pos2, - pos3, - uv1, - uv2, - col1, - col2, - fcol1, - viewport_size, + return gpencil_vertex(viewport_size, 0u, vec2(1.0, 0.0), out_P, diff --git a/source/blender/draw/intern/shaders/draw_view_info.hh b/source/blender/draw/intern/shaders/draw_view_info.hh index 7b500f66a68..114dbab799f 100644 --- a/source/blender/draw/intern/shaders/draw_view_info.hh +++ b/source/blender/draw/intern/shaders/draw_view_info.hh @@ -122,26 +122,15 @@ GPU_SHADER_CREATE_INFO(draw_volume).additional_info("draw_modelmat", "draw_resou GPU_SHADER_CREATE_INFO(draw_gpencil) .typedef_source("gpencil_shader_shared.h") .define("DRW_GPENCIL_INFO") - .vertex_in(0, Type::IVEC4, "ma") - .vertex_in(1, Type::IVEC4, "ma1") - .vertex_in(2, Type::IVEC4, "ma2") - .vertex_in(3, Type::IVEC4, "ma3") - .vertex_in(4, Type::VEC4, "pos") - .vertex_in(5, Type::VEC4, "pos1") - .vertex_in(6, Type::VEC4, "pos2") - .vertex_in(7, Type::VEC4, "pos3") - .vertex_in(8, Type::VEC4, "uv1") - .vertex_in(9, Type::VEC4, "uv2") - .vertex_in(10, Type::VEC4, "col1") - .vertex_in(11, Type::VEC4, "col2") - .vertex_in(12, Type::VEC4, "fcol1") + .sampler(0, ImageType::FLOAT_BUFFER, "gp_pos_tx") + .sampler(1, ImageType::FLOAT_BUFFER, "gp_col_tx") /* Per Object */ .push_constant(Type::FLOAT, "gpThicknessScale") /* TODO(fclem): Replace with object info. */ .push_constant(Type::FLOAT, "gpThicknessWorldScale") /* TODO(fclem): Same as above. */ .define("gpThicknessIsScreenSpace", "(gpThicknessWorldScale < 0.0)") /* Per Layer */ .push_constant(Type::FLOAT, "gpThicknessOffset") - .additional_info("draw_modelmat", "draw_resource_id_uniform", "draw_object_infos"); + .additional_info("draw_modelmat", "draw_object_infos"); /** \} */ diff --git a/source/blender/gpu/intern/gpu_texture_private.hh b/source/blender/gpu/intern/gpu_texture_private.hh index 2ad31183206..124b1751b96 100644 --- a/source/blender/gpu/intern/gpu_texture_private.hh +++ b/source/blender/gpu/intern/gpu_texture_private.hh @@ -588,7 +588,7 @@ inline eGPUFrameBufferBits to_framebuffer_bits(eGPUTextureFormat tex_format) static inline eGPUTextureFormat to_texture_format(const GPUVertFormat *format) { - if (format->attr_len > 1 || format->attr_len == 0) { + if (format->attr_len == 0) { BLI_assert_msg(0, "Incorrect vertex format for buffer texture"); return GPU_DEPTH_COMPONENT24; } diff --git a/source/blender/gpu/intern/gpu_vertex_format.cc b/source/blender/gpu/intern/gpu_vertex_format.cc index b30e3c358c8..76d95ac1b55 100644 --- a/source/blender/gpu/intern/gpu_vertex_format.cc +++ b/source/blender/gpu/intern/gpu_vertex_format.cc @@ -361,8 +361,12 @@ void VertexFormat_texture_buffer_pack(GPUVertFormat *format) * minimum per-vertex stride, which mandates 4-byte alignment in Metal. * This additional alignment padding caused smaller data types, e.g. U16, * to mis-align. */ - BLI_assert_msg(format->attr_len == 1, - "Texture buffer mode should only use a single vertex attribute."); + for (int i = 0; i < format->attr_len; i++) { + /* The buffer texture setup uses the first attribute for type and size. + * Make sure all attributes use the same size. */ + BLI_assert_msg(format->attrs[i].size == format->attrs[0].size, + "Texture buffer mode should only use a attributes with the same size."); + } /* Pack vertex format without minimum stride, as this is not required by texture buffers. */ VertexFormat_pack_impl(format, 1); diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 26dbb544f52..8b3f4956cfe 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -243,12 +243,15 @@ typedef struct bGPDstroke_Runtime { /** Runtime falloff factor (only for transform). */ float multi_frame_falloff; - /** Vertex offset in the VBO where this stroke starts. */ + /** Triangle offset in the IBO where this stroke starts. */ int stroke_start; /** Triangle offset in the IBO where this fill starts. */ int fill_start; + /** Vertex offset in the VBO where this stroke starts. */ + int vertex_start; /** Curve Handles offset in the IBO where this handle starts. */ int curve_start; + int _pad0; /** Original stroke (used to dereference evaluated data) */ struct bGPDstroke *gps_orig; @@ -613,8 +616,9 @@ typedef struct bGPdata_Runtime { /** Stroke buffer. */ void *sbuffer; /** Temp batches cleared after drawing. */ - struct GPUBatch *sbuffer_stroke_batch; - struct GPUBatch *sbuffer_fill_batch; + struct GPUVertBuf *sbuffer_position_buf; + struct GPUVertBuf *sbuffer_color_buf; + struct GPUBatch *sbuffer_batch; /** Temp stroke used for drawing. */ struct bGPDstroke *sbuffer_gps; -- cgit v1.2.3 From 216e8d887b6c80db4665e58ff91434659c21c5ae Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 24 Oct 2022 20:32:03 +1100 Subject: Cleanup: quiet parentheses warning --- source/blender/editors/transform/transform_mode_curveshrinkfatten.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c index d8f04dea161..0b87b45679a 100644 --- a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c +++ b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c @@ -102,8 +102,8 @@ void initCurveShrinkFatten(TransInfo *t) t->flag |= T_NO_CONSTRAINT; float scale_factor = 0.0f; - if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW) && - t->data_len_all == 1 || + if (((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW) && + (t->data_len_all == 1)) || (t->data_len_all == 3 && TRANS_DATA_CONTAINER_FIRST_OK(t)->data[0].val == NULL)) { /* For cases where only one point on the curve is being transformed and the radius of that * point is zero, use the factor to multiply the offset of the ratio and allow scaling. -- cgit v1.2.3 From 365cce4750906f428b15aabae18f1fd12788f7a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Mon, 24 Oct 2022 12:07:41 +0200 Subject: GPencil: Fix build errors caused by designated initializer in C++ --- .../blender/draw/intern/draw_cache_impl_gpencil.cc | 37 ++++++++++------------ 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.cc b/source/blender/draw/intern/draw_cache_impl_gpencil.cc index eadb7772f4c..1a77793bb5b 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.cc +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.cc @@ -431,14 +431,13 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr bool do_onion = true; /* First count how many vertices and triangles are needed for the whole object. */ - gpIterData iter = { - .gpd = gpd, - .verts = NULL, - .ibo = {0}, - .vert_len = 0, - .tri_len = 0, - .curve_len = 0, - }; + gpIterData iter = {}; + iter.gpd = gpd; + iter.verts = NULL; + iter.ibo = {0}; + iter.vert_len = 0; + iter.tri_len = 0; + iter.curve_len = 0; BKE_gpencil_visible_stroke_advanced_iter( NULL, ob, NULL, gpencil_object_verts_count_cb, &iter, do_onion, cfra); @@ -531,10 +530,9 @@ GPUBatch *DRW_cache_gpencil_face_wireframe_get(Object *ob) if (cache->lines_batch == NULL) { GPUVertBuf *vbo = cache->vbo; - gpIterData iter = { - .gpd = (bGPdata *)ob->data, - .ibo = {0}, - }; + gpIterData iter = {}; + iter.gpd = (bGPdata *)ob->data; + iter.ibo = {0}; uint vert_len = GPU_vertbuf_get_vertex_len(vbo); GPU_indexbuf_init_ex(&iter.ibo, GPU_PRIM_LINE_STRIP, vert_len, vert_len); @@ -904,14 +902,13 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in /* Curve Handles and Points for Editing. */ if (cache->edit_curve_vbo == NULL) { - gpIterData iterdata = { - .gpd = gpd, - .verts = NULL, - .ibo = {0}, - .vert_len = 0, - .tri_len = 0, - .curve_len = 0, - }; + gpIterData iterdata = {}; + iterdata.gpd = gpd; + iterdata.verts = NULL; + iterdata.ibo = {0}; + iterdata.vert_len = 0; + iterdata.tri_len = 0; + iterdata.curve_len = 0; /* Create VBO. */ GPUVertFormat *format = gpencil_edit_curve_format(); -- cgit v1.2.3 From 0584a88046d2a2c069e056e52b37907cd70db8c7 Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Mon, 24 Oct 2022 12:15:22 +0200 Subject: Fix T102008: Images are stretched when texture limit is enabled Currently, if an image exceed the texture limit setup by the user or the GPU backend, it will be scaled down to satisfy the limit. However, scaling happens independently per axis, that means the aspect ratio of the image will not be maintained. This patch corrects the smaller size to maintain the aspect ratio. Differential Revision: https://developer.blender.org/D16327 Reviews By: Clement Foucault --- source/blender/imbuf/intern/util_gpu.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source/blender/imbuf/intern/util_gpu.c b/source/blender/imbuf/intern/util_gpu.c index 5ed6b2b9843..35cdefbaaeb 100644 --- a/source/blender/imbuf/intern/util_gpu.c +++ b/source/blender/imbuf/intern/util_gpu.c @@ -301,6 +301,16 @@ GPUTexture *IMB_create_gpu_texture(const char *name, int size[2] = {GPU_texture_size_with_limit(ibuf->x), GPU_texture_size_with_limit(ibuf->y)}; bool do_rescale = (ibuf->x != size[0]) || (ibuf->y != size[1]); + /* Correct the smaller size to maintain the original aspect ratio of the image. */ + if (do_rescale && ibuf->x != ibuf->y) { + if (size[0] > size[1]) { + size[1] = (int)(ibuf->y * ((float)size[0] / ibuf->x)); + } + else { + size[0] = (int)(ibuf->x * ((float)size[1] / ibuf->y)); + } + } + #ifdef WITH_DDS if (ibuf->ftype == IMB_FTYPE_DDS) { eGPUTextureFormat compressed_format; -- cgit v1.2.3 From 9fc000cc6f55784166be571c06a5f67faba9b47f Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Fri, 21 Oct 2022 16:24:53 +0200 Subject: Fix T101946: Outliner data-block counter treats bones as collection Mistake in own rBb6a35a8153c3 which caused code to always recurse into bone hierarchies (no matter which collapsed level an armature was found). This led to bone counts always being displayed even outside a collapsed armature (e.g. if an armature was somewhere down a object or collection, the collapsed object or collection would show this bonecount). This is inconsistent with other data counting in the Outliner, e.g. vertexgroups or bonegroups do have their indicator at object level, however the counter only shows if `Vertex Groups` or `Bone Groups` line shows (so if the object is not collapsed). And this also led to the bug reported in T101946 which was that the bone counts would be treated as collections when further down a collapsed hierarchy. Background: The whole concept of `MergedIconRow` is based on the concept of counting **objects types or collectinons/groups**. If other things like overrides, vertexgroups or bonegroups are displayed in a counted/ merged manner, then these will always be counted in the array spots that are usually reserved for groups/collections. But for things this is not a problem (since these are only displayed below their respective outliner entry -- and will never be reached otherwise). So to correct all this, we now only recurse into a bone hierarchy if a bone is at the "root-level" of a collapsed subtree (direct child of the collapsed element to merge into). NOTE: there are certainly other candidates for counted/merged display further up the hierarchy (not just bones -- constraints come to my mind here, but that is for another commit) Maniphest Tasks: T101946 Differential Revision: https://developer.blender.org/D16319 --- source/blender/editors/space_outliner/outliner_draw.cc | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc index f76c0980c4f..699dd6d4844 100644 --- a/source/blender/editors/space_outliner/outliner_draw.cc +++ b/source/blender/editors/space_outliner/outliner_draw.cc @@ -3054,6 +3054,7 @@ static void outliner_draw_iconrow(bContext *C, int *offsx, int ys, float alpha_fac, + bool in_bone_hierarchy, MergedIconRow *merged) { eOLDrawState active = OL_DRAWSEL_NONE; @@ -3063,8 +3064,12 @@ static void outliner_draw_iconrow(bContext *C, te->flag &= ~(TE_ICONROW | TE_ICONROW_MERGED); /* object hierarchy always, further constrained on level */ + /* Bones are also hierarchies and get a merged count, but we only start recursing into them if + * an they are at the root level of a collapsed subtree (e.g. not "hidden" in a collapsed + * collection). */ + const bool is_bone = ELEM(tselem->type, TSE_BONE, TSE_EBONE, TSE_POSE_CHANNEL); if ((level < 1) || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) || - ELEM(tselem->type, TSE_BONE, TSE_EBONE, TSE_POSE_CHANNEL)) { + (in_bone_hierarchy && is_bone)) { /* active blocks get white circle */ if (tselem->type == TSE_SOME_ID) { if (te->idcode == ID_OB) { @@ -3107,8 +3112,13 @@ static void outliner_draw_iconrow(bContext *C, } } - /* this tree element always has same amount of branches, so don't draw */ - if (tselem->type != TSE_R_LAYER) { + /* TSE_R_LAYER tree element always has same amount of branches, so don't draw. */ + /* Also only recurse into bone hierarchies if a direct child of the collapsed element to merge + * into. */ + const bool is_root_level_bone = is_bone && (level == 0); + in_bone_hierarchy |= is_root_level_bone; + if (!ELEM(tselem->type, TSE_R_LAYER, TSE_BONE, TSE_EBONE, TSE_POSE_CHANNEL) || + in_bone_hierarchy) { outliner_draw_iconrow(C, block, fstyle, @@ -3120,6 +3130,7 @@ static void outliner_draw_iconrow(bContext *C, offsx, ys, alpha_fac, + in_bone_hierarchy, merged); } } @@ -3381,6 +3392,7 @@ static void outliner_draw_tree_element(bContext *C, &tempx, *starty, alpha_fac, + false, &merged); GPU_blend(GPU_BLEND_NONE); -- cgit v1.2.3 From a8731718a1c476ed0d7a95c2c25cb9da7e90e6be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Mon, 24 Oct 2022 12:55:24 +0200 Subject: GPencil: Fix regressions introduced in rB0ee9282b5c51 Batching was broken / disabled and starting indices were wrong. --- source/blender/draw/engines/gpencil/gpencil_engine.c | 8 ++++---- source/blender/draw/intern/draw_cache_impl_gpencil.cc | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 956830e6b4c..14a3c5a8e7e 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -346,7 +346,7 @@ typedef struct gpIterPopulateData { int vfirst, vcount; } gpIterPopulateData; -#define DISABLE_BATCHING 1 +#define DISABLE_BATCHING 0 static void gpencil_drawcall_flush(gpIterPopulateData *iter) { @@ -382,7 +382,7 @@ static void gpencil_drawcall_add( int last = iter->vfirst + iter->vcount; /* Interrupt draw-call grouping if the sequence is not consecutive. */ - if ((geom != iter->geom) || (v_first - last > 3)) { + if ((geom != iter->geom) || (v_first - last > 0)) { gpencil_drawcall_flush(iter); } iter->geom = geom; @@ -540,8 +540,8 @@ static void gpencil_stroke_cache_populate(bGPDlayer *gpl, if (show_stroke) { int vfirst = gps->runtime.stroke_start * 3; - /* Include "potential" cyclic vertex (see shader). */ - int vcount = (gps->totpoints + 1) * 2 * 3; + bool is_cyclic = ((gps->flag & GP_STROKE_CYCLIC) != 0) && (gps->totpoints > 2); + int vcount = (gps->totpoints + (int)is_cyclic) * 2 * 3; gpencil_drawcall_add(iter, geom, false, vfirst, vcount); } diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.cc b/source/blender/draw/intern/draw_cache_impl_gpencil.cc index 1a77793bb5b..bc01ab24947 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.cc +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.cc @@ -653,6 +653,9 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_ MEM_freeN(tpoints2d); } + gps->runtime.stroke_start = do_fill ? gps->tot_triangles : 0; + gps->runtime.fill_start = 0; + gps->runtime.vertex_start = 0; /* Fill buffers with data. */ gpencil_buffer_add_stroke(&ibo_builder, verts, cols, gps); -- cgit v1.2.3 From b4007173267255cbfafdce3f4ccb4a8fd82e850b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Mon, 24 Oct 2022 15:28:49 +0200 Subject: GPencil: Fix regression with stroke buffer introduced in rB0ee9282b5c51 --- .../blender/draw/engines/gpencil/gpencil_engine.c | 36 +++++++++------------- source/blender/draw/intern/draw_cache.h | 7 +++-- .../blender/draw/intern/draw_cache_impl_gpencil.cc | 29 ++++++++--------- 3 files changed, 34 insertions(+), 38 deletions(-) diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 14a3c5a8e7e..525d166dba6 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -342,7 +342,6 @@ typedef struct gpIterPopulateData { int stroke_index_offset; /* Infos for call batching. */ struct GPUBatch *geom; - bool instancing; int vfirst, vcount; } gpIterPopulateData; @@ -352,12 +351,7 @@ static void gpencil_drawcall_flush(gpIterPopulateData *iter) { #if !DISABLE_BATCHING if (iter->geom != NULL) { - if (iter->instancing) { - DRW_shgroup_call_instance_range(iter->grp, iter->ob, iter->geom, iter->vfirst, iter->vcount); - } - else { - DRW_shgroup_call_range(iter->grp, iter->ob, iter->geom, iter->vfirst, iter->vcount); - } + DRW_shgroup_call_range(iter->grp, iter->ob, iter->geom, iter->vfirst, iter->vcount); } #endif @@ -367,16 +361,13 @@ static void gpencil_drawcall_flush(gpIterPopulateData *iter) } /* Group draw-calls that are consecutive and with the same type. Reduces GPU driver overhead. */ -static void gpencil_drawcall_add( - gpIterPopulateData *iter, struct GPUBatch *geom, bool instancing, int v_first, int v_count) +static void gpencil_drawcall_add(gpIterPopulateData *iter, + struct GPUBatch *geom, + int v_first, + int v_count) { #if DISABLE_BATCHING - if (instancing) { - DRW_shgroup_call_instance_range(iter->grp, iter->ob, geom, v_first, v_count); - } - else { - DRW_shgroup_call_range(iter->grp, iter->ob, geom, v_first, v_count); - } + DRW_shgroup_call_range(iter->grp, iter->ob, geom, v_first, v_count); return; #endif @@ -386,7 +377,6 @@ static void gpencil_drawcall_add( gpencil_drawcall_flush(iter); } iter->geom = geom; - iter->instancing = instancing; if (iter->vfirst == -1) { iter->vfirst = v_first; } @@ -517,16 +507,17 @@ static void gpencil_stroke_cache_populate(bGPDlayer *gpl, bool do_sbuffer = (iter->do_sbuffer_call == DRAW_NOW); - GPUBatch *geom = do_sbuffer ? DRW_cache_gpencil_sbuffer_get(iter->ob) : + GPUBatch *geom = do_sbuffer ? DRW_cache_gpencil_sbuffer_get(iter->ob, show_fill) : DRW_cache_gpencil_get(iter->ob, iter->pd->cfra); if (geom != iter->geom) { gpencil_drawcall_flush(iter); GPUVertBuf *position_tx = do_sbuffer ? - DRW_cache_gpencil_sbuffer_position_buffer_get(iter->ob) : + DRW_cache_gpencil_sbuffer_position_buffer_get(iter->ob, + show_fill) : DRW_cache_gpencil_position_buffer_get(iter->ob, iter->pd->cfra); GPUVertBuf *color_tx = do_sbuffer ? - DRW_cache_gpencil_sbuffer_color_buffer_get(iter->ob) : + DRW_cache_gpencil_sbuffer_color_buffer_get(iter->ob, show_fill) : DRW_cache_gpencil_color_buffer_get(iter->ob, iter->pd->cfra); DRW_shgroup_buffer_texture(iter->grp, "gp_pos_tx", position_tx); DRW_shgroup_buffer_texture(iter->grp, "gp_col_tx", color_tx); @@ -535,14 +526,17 @@ static void gpencil_stroke_cache_populate(bGPDlayer *gpl, if (show_fill) { int vfirst = gps->runtime.fill_start * 3; int vcount = gps->tot_triangles * 3; - gpencil_drawcall_add(iter, geom, false, vfirst, vcount); + if (do_sbuffer) { + printf("draw_fill vfirst %d vcount %d\n", vfirst, vcount); + } + gpencil_drawcall_add(iter, geom, vfirst, vcount); } if (show_stroke) { int vfirst = gps->runtime.stroke_start * 3; bool is_cyclic = ((gps->flag & GP_STROKE_CYCLIC) != 0) && (gps->totpoints > 2); int vcount = (gps->totpoints + (int)is_cyclic) * 2 * 3; - gpencil_drawcall_add(iter, geom, false, vfirst, vcount); + gpencil_drawcall_add(iter, geom, vfirst, vcount); } iter->stroke_index_last = gps->runtime.stroke_start + gps->totpoints + 1; diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 44abf3c7064..45154b41670 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -265,9 +265,10 @@ struct GPUBatch *DRW_cache_gpencil_edit_lines_get(struct Object *ob, int cfra); struct GPUBatch *DRW_cache_gpencil_edit_points_get(struct Object *ob, int cfra); struct GPUBatch *DRW_cache_gpencil_edit_curve_handles_get(struct Object *ob, int cfra); struct GPUBatch *DRW_cache_gpencil_edit_curve_points_get(struct Object *ob, int cfra); -struct GPUBatch *DRW_cache_gpencil_sbuffer_get(struct Object *ob); -struct GPUVertBuf *DRW_cache_gpencil_sbuffer_position_buffer_get(struct Object *ob); -struct GPUVertBuf *DRW_cache_gpencil_sbuffer_color_buffer_get(struct Object *ob); +struct GPUBatch *DRW_cache_gpencil_sbuffer_get(struct Object *ob, bool show_fill); +struct GPUVertBuf *DRW_cache_gpencil_sbuffer_position_buffer_get(struct Object *ob, + bool show_fill); +struct GPUVertBuf *DRW_cache_gpencil_sbuffer_color_buffer_get(struct Object *ob, bool show_fill); int DRW_gpencil_material_count_get(struct bGPdata *gpd); struct GPUBatch *DRW_cache_gpencil_face_wireframe_get(struct Object *ob); diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.cc b/source/blender/draw/intern/draw_cache_impl_gpencil.cc index bc01ab24947..33cd62bd33f 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.cc +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.cc @@ -574,7 +574,9 @@ bGPDstroke *DRW_cache_gpencil_sbuffer_stroke_data_get(Object *ob) gps->tot_triangles = max_ii(0, gpd->runtime.sbuffer_used - 2); gps->caps[0] = gps->caps[1] = GP_STROKE_CAP_ROUND; - gps->runtime.stroke_start = 1; /* Add one for the adjacency index. */ + gps->runtime.vertex_start = 0; + gps->runtime.fill_start = 0; + gps->runtime.stroke_start = 0; copy_v4_v4(gps->vert_color_fill, gpd->runtime.vert_color_fill); /* Caps. */ gps->caps[0] = gps->caps[1] = (short)brush->gpencil_settings->caps_type; @@ -584,7 +586,7 @@ bGPDstroke *DRW_cache_gpencil_sbuffer_stroke_data_get(Object *ob) return gpd->runtime.sbuffer_gps; } -static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_fill) +static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_fill) { tGPspoint *tpoints = (tGPspoint *)gpd->runtime.sbuffer; bGPDstroke *gps = gpd->runtime.sbuffer_gps; @@ -593,7 +595,7 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_ /* DRW_cache_gpencil_sbuffer_stroke_data_get need to have been called previously. */ BLI_assert(gps != NULL); - if (do_stroke && (gpd->runtime.sbuffer_batch == NULL)) { + if (gpd->runtime.sbuffer_batch == NULL) { gps->points = (bGPDspoint *)MEM_mallocN(vert_len * sizeof(*gps->points), __func__); const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -643,19 +645,18 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_ /* Compute directly inside the IBO data buffer. */ /* OPTI: This is a bottleneck if the stroke is very long. */ BLI_polyfill_calc(tpoints2d, (uint)vert_len, 0, (uint(*)[3])ibo_builder.data); - /* Add stroke start offset. */ + /* Add stroke start offset and shift. */ for (int i = 0; i < gps->tot_triangles * 3; i++) { - ibo_builder.data[i] += gps->runtime.stroke_start; + ibo_builder.data[i] = (ibo_builder.data[i] + 1) << GP_VERTEX_ID_SHIFT; } /* HACK since we didn't use the builder API to avoid another malloc and copy, * we need to set the number of indices manually. */ ibo_builder.index_len = gps->tot_triangles * 3; + gps->runtime.stroke_start = gps->tot_triangles; + MEM_freeN(tpoints2d); } - gps->runtime.stroke_start = do_fill ? gps->tot_triangles : 0; - gps->runtime.fill_start = 0; - gps->runtime.vertex_start = 0; /* Fill buffers with data. */ gpencil_buffer_add_stroke(&ibo_builder, verts, cols, gps); @@ -673,29 +674,29 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_ } } -GPUBatch *DRW_cache_gpencil_sbuffer_get(Object *ob) +GPUBatch *DRW_cache_gpencil_sbuffer_get(Object *ob, bool show_fill) { bGPdata *gpd = (bGPdata *)ob->data; /* Fill batch also need stroke batch to be created (vbo is shared). */ - gpencil_sbuffer_stroke_ensure(gpd, true, true); + gpencil_sbuffer_stroke_ensure(gpd, show_fill); return gpd->runtime.sbuffer_batch; } -GPUVertBuf *DRW_cache_gpencil_sbuffer_position_buffer_get(Object *ob) +GPUVertBuf *DRW_cache_gpencil_sbuffer_position_buffer_get(Object *ob, bool show_fill) { bGPdata *gpd = (bGPdata *)ob->data; /* Fill batch also need stroke batch to be created (vbo is shared). */ - gpencil_sbuffer_stroke_ensure(gpd, true, true); + gpencil_sbuffer_stroke_ensure(gpd, show_fill); return gpd->runtime.sbuffer_position_buf; } -GPUVertBuf *DRW_cache_gpencil_sbuffer_color_buffer_get(Object *ob) +GPUVertBuf *DRW_cache_gpencil_sbuffer_color_buffer_get(Object *ob, bool show_fill) { bGPdata *gpd = (bGPdata *)ob->data; /* Fill batch also need stroke batch to be created (vbo is shared). */ - gpencil_sbuffer_stroke_ensure(gpd, true, true); + gpencil_sbuffer_stroke_ensure(gpd, show_fill); return gpd->runtime.sbuffer_color_buf; } -- cgit v1.2.3 From 4c6e07230f76c21e67f0d5ef15464ca7d55c404a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Mon, 24 Oct 2022 16:25:04 +0200 Subject: Pencil: Fix regression (part2) with stroke buffer introduced in rB0ee9282b5c51 `vert_len` was being shadowed and index_min & max wasn't correctly set. --- source/blender/draw/engines/gpencil/gpencil_engine.c | 3 --- source/blender/draw/intern/draw_cache_impl_gpencil.cc | 7 +++++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 525d166dba6..78e658d35eb 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -526,9 +526,6 @@ static void gpencil_stroke_cache_populate(bGPDlayer *gpl, if (show_fill) { int vfirst = gps->runtime.fill_start * 3; int vcount = gps->tot_triangles * 3; - if (do_sbuffer) { - printf("draw_fill vfirst %d vcount %d\n", vfirst, vcount); - } gpencil_drawcall_add(iter, geom, vfirst, vcount); } diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.cc b/source/blender/draw/intern/draw_cache_impl_gpencil.cc index 33cd62bd33f..b46a4907da8 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.cc +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.cc @@ -619,10 +619,10 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_fill) /* Calc uv data along the stroke. */ BKE_gpencil_stroke_uv_update(gps); - int vert_len = gps->tot_triangles + (gps->totpoints + gpencil_stroke_is_cyclic(gps)) * 2; + int tri_len = gps->tot_triangles + (gps->totpoints + gpencil_stroke_is_cyclic(gps)) * 2; /* Create IBO. */ GPUIndexBufBuilder ibo_builder; - GPU_indexbuf_init(&ibo_builder, GPU_PRIM_TRIS, vert_len, 0xFFFFFFFFu); + GPU_indexbuf_init(&ibo_builder, GPU_PRIM_TRIS, tri_len, 0xFFFFFFFFu); /* Create VBO. */ GPUUsageType vbo_flag = GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY; GPUVertFormat *format = gpencil_stroke_format(); @@ -652,6 +652,9 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_fill) /* HACK since we didn't use the builder API to avoid another malloc and copy, * we need to set the number of indices manually. */ ibo_builder.index_len = gps->tot_triangles * 3; + ibo_builder.index_min = 0; + /* For this case, do not allow index compaction to avoid yet another preprocessing step. */ + ibo_builder.index_max = 0xFFFFFFFFu - 1u; gps->runtime.stroke_start = gps->tot_triangles; -- cgit v1.2.3 From 8dd7b5b26b394207b5941d49750f7e3abadaf82a Mon Sep 17 00:00:00 2001 From: Michael Jones Date: Mon, 24 Oct 2022 10:23:56 +0100 Subject: Cycles: Metal integrator state size tuning This patch tunes the integrator state sizing for Metal (`num_concurrent_states` and `num_concurrent_busy_states`). On all GPUs architecture, we adjust the busy:total states ratio to be 1:4 which gives better rendering performance than the previous 1:16 ratio (independent of total state count). This gives a small performance uplift (e.g. 2-3% on M1 Ultra). Additionally for M2 architectures, we double the overall state size if there is available headroom. Inclusive of the first change, we can expect uplift of close to 10% in future, as this results in larger dispatch sizes and minimises work submission overheads. In order to make an accurate determination of available headroom, we defer the calculation of `num_concurrent_states` and `num_concurrent_busy_states` until the time of integrator state allocation (i.e. after all of the scene data has been allocated). We also refactor `alloc_integrator_soa` to calculate an *exact* single-state-size in a first pass, right before allocating the integrator SoA buffers in a second pass. Reviewed By: brecht Differential Revision: https://developer.blender.org/D16313 --- intern/cycles/device/cuda/queue.cpp | 2 +- intern/cycles/device/cuda/queue.h | 2 +- intern/cycles/device/hip/queue.cpp | 2 +- intern/cycles/device/hip/queue.h | 2 +- intern/cycles/device/metal/device_impl.mm | 2 + intern/cycles/device/metal/kernel.mm | 7 ++++ intern/cycles/device/metal/queue.h | 2 +- intern/cycles/device/metal/queue.mm | 51 +++++++++++++++--------- intern/cycles/device/oneapi/queue.cpp | 2 +- intern/cycles/device/oneapi/queue.h | 2 +- intern/cycles/device/queue.h | 2 +- intern/cycles/integrator/path_trace_work_gpu.cpp | 31 +++++++++----- 12 files changed, 70 insertions(+), 37 deletions(-) diff --git a/intern/cycles/device/cuda/queue.cpp b/intern/cycles/device/cuda/queue.cpp index 84b0a1e0dd6..69fae03e32c 100644 --- a/intern/cycles/device/cuda/queue.cpp +++ b/intern/cycles/device/cuda/queue.cpp @@ -49,7 +49,7 @@ int CUDADeviceQueue::num_concurrent_states(const size_t state_size) const return num_states; } -int CUDADeviceQueue::num_concurrent_busy_states() const +int CUDADeviceQueue::num_concurrent_busy_states(const size_t /*state_size*/) const { const int max_num_threads = cuda_device_->get_num_multiprocessors() * cuda_device_->get_max_num_threads_per_multiprocessor(); diff --git a/intern/cycles/device/cuda/queue.h b/intern/cycles/device/cuda/queue.h index b450f5b3592..7107afe70c9 100644 --- a/intern/cycles/device/cuda/queue.h +++ b/intern/cycles/device/cuda/queue.h @@ -23,7 +23,7 @@ class CUDADeviceQueue : public DeviceQueue { ~CUDADeviceQueue(); virtual int num_concurrent_states(const size_t state_size) const override; - virtual int num_concurrent_busy_states() const override; + virtual int num_concurrent_busy_states(const size_t state_size) const override; virtual void init_execution() override; diff --git a/intern/cycles/device/hip/queue.cpp b/intern/cycles/device/hip/queue.cpp index 3f8b6267100..e93a9b4df3a 100644 --- a/intern/cycles/device/hip/queue.cpp +++ b/intern/cycles/device/hip/queue.cpp @@ -49,7 +49,7 @@ int HIPDeviceQueue::num_concurrent_states(const size_t state_size) const return num_states; } -int HIPDeviceQueue::num_concurrent_busy_states() const +int HIPDeviceQueue::num_concurrent_busy_states(const size_t /*state_size*/) const { const int max_num_threads = hip_device_->get_num_multiprocessors() * hip_device_->get_max_num_threads_per_multiprocessor(); diff --git a/intern/cycles/device/hip/queue.h b/intern/cycles/device/hip/queue.h index 729d8a19acb..df0678108af 100644 --- a/intern/cycles/device/hip/queue.h +++ b/intern/cycles/device/hip/queue.h @@ -23,7 +23,7 @@ class HIPDeviceQueue : public DeviceQueue { ~HIPDeviceQueue(); virtual int num_concurrent_states(const size_t state_size) const override; - virtual int num_concurrent_busy_states() const override; + virtual int num_concurrent_busy_states(const size_t state_size) const override; virtual void init_execution() override; diff --git a/intern/cycles/device/metal/device_impl.mm b/intern/cycles/device/metal/device_impl.mm index 4b929b6bc0a..6f1042b1e55 100644 --- a/intern/cycles/device/metal/device_impl.mm +++ b/intern/cycles/device/metal/device_impl.mm @@ -296,9 +296,11 @@ void MetalDevice::make_source(MetalPipelineType pso_type, const uint kernel_feat } source = global_defines + source; +# if 0 metal_printf("================\n%s================\n\%s================\n", global_defines.c_str(), baked_constants.c_str()); +# endif /* Generate an MD5 from the source and include any baked constants. This is used when caching * PSOs. */ diff --git a/intern/cycles/device/metal/kernel.mm b/intern/cycles/device/metal/kernel.mm index 8ccc50e57a3..55938d1a03a 100644 --- a/intern/cycles/device/metal/kernel.mm +++ b/intern/cycles/device/metal/kernel.mm @@ -162,6 +162,13 @@ bool ShaderCache::should_load_kernel(DeviceKernel device_kernel, } } + if (device_kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE) { + if ((device->kernel_features & KERNEL_FEATURE_MNEE) == 0) { + /* Skip shade_surface_mnee kernel if the scene doesn't require it. */ + return false; + } + } + if (pso_type != PSO_GENERIC) { /* Only specialize kernels where it can make an impact. */ if (device_kernel < DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST || diff --git a/intern/cycles/device/metal/queue.h b/intern/cycles/device/metal/queue.h index fc32740f3e1..2a6c12e2a60 100644 --- a/intern/cycles/device/metal/queue.h +++ b/intern/cycles/device/metal/queue.h @@ -23,7 +23,7 @@ class MetalDeviceQueue : public DeviceQueue { ~MetalDeviceQueue(); virtual int num_concurrent_states(const size_t) const override; - virtual int num_concurrent_busy_states() const override; + virtual int num_concurrent_busy_states(const size_t) const override; virtual int num_sort_partition_elements() const override; virtual void init_execution() override; diff --git a/intern/cycles/device/metal/queue.mm b/intern/cycles/device/metal/queue.mm index 5ac63a16c61..c0df2c8553f 100644 --- a/intern/cycles/device/metal/queue.mm +++ b/intern/cycles/device/metal/queue.mm @@ -264,33 +264,46 @@ MetalDeviceQueue::~MetalDeviceQueue() } } -int MetalDeviceQueue::num_concurrent_states(const size_t /*state_size*/) const +int MetalDeviceQueue::num_concurrent_states(const size_t state_size) const { - /* METAL_WIP */ - /* TODO: compute automatically. */ - /* TODO: must have at least num_threads_per_block. */ - int result = 1048576; - if (metal_device_->device_vendor == METAL_GPU_AMD) { - result *= 2; + static int result = 0; + if (result) { + return result; } - else if (metal_device_->device_vendor == METAL_GPU_APPLE) { + + result = 1048576; + if (metal_device_->device_vendor == METAL_GPU_APPLE) { result *= 4; + + if (MetalInfo::get_apple_gpu_architecture(metal_device_->mtlDevice) == APPLE_M2) { + size_t system_ram = system_physical_ram(); + size_t allocated_so_far = [metal_device_->mtlDevice currentAllocatedSize]; + size_t max_recommended_working_set = [metal_device_->mtlDevice recommendedMaxWorkingSetSize]; + + /* Determine whether we can double the state count, and leave enough GPU-available memory + * (1/8 the system RAM or 1GB - whichever is largest). Enlarging the state size allows us to + * keep dispatch sizes high and minimize work submission overheads. */ + size_t min_headroom = std::max(system_ram / 8, size_t(1024 * 1024 * 1024)); + size_t total_state_size = result * state_size; + if (max_recommended_working_set - allocated_so_far - total_state_size * 2 >= min_headroom) { + result *= 2; + metal_printf("Doubling state count to exploit available RAM (new size = %d)\n", result); + } + } + } + else if (metal_device_->device_vendor == METAL_GPU_AMD) { + /* METAL_WIP */ + /* TODO: compute automatically. */ + /* TODO: must have at least num_threads_per_block. */ + result *= 2; } return result; } -int MetalDeviceQueue::num_concurrent_busy_states() const +int MetalDeviceQueue::num_concurrent_busy_states(const size_t state_size) const { - /* METAL_WIP */ - /* TODO: compute automatically. */ - int result = 65536; - if (metal_device_->device_vendor == METAL_GPU_AMD) { - result *= 2; - } - else if (metal_device_->device_vendor == METAL_GPU_APPLE) { - result *= 4; - } - return result; + /* A 1:4 busy:total ratio gives best rendering performance, independent of total state count. */ + return num_concurrent_states(state_size) / 4; } int MetalDeviceQueue::num_sort_partition_elements() const diff --git a/intern/cycles/device/oneapi/queue.cpp b/intern/cycles/device/oneapi/queue.cpp index 9632b14d485..3d019661aa8 100644 --- a/intern/cycles/device/oneapi/queue.cpp +++ b/intern/cycles/device/oneapi/queue.cpp @@ -43,7 +43,7 @@ int OneapiDeviceQueue::num_concurrent_states(const size_t state_size) const return num_states; } -int OneapiDeviceQueue::num_concurrent_busy_states() const +int OneapiDeviceQueue::num_concurrent_busy_states(const size_t /*state_size*/) const { const int max_num_threads = oneapi_device_->get_num_multiprocessors() * oneapi_device_->get_max_num_threads_per_multiprocessor(); diff --git a/intern/cycles/device/oneapi/queue.h b/intern/cycles/device/oneapi/queue.h index 32363bf2a6e..bbd947b49cb 100644 --- a/intern/cycles/device/oneapi/queue.h +++ b/intern/cycles/device/oneapi/queue.h @@ -25,7 +25,7 @@ class OneapiDeviceQueue : public DeviceQueue { virtual int num_concurrent_states(const size_t state_size) const override; - virtual int num_concurrent_busy_states() const override; + virtual int num_concurrent_busy_states(const size_t state_size) const override; virtual void init_execution() override; diff --git a/intern/cycles/device/queue.h b/intern/cycles/device/queue.h index 1d6a8d736b7..e27e081a407 100644 --- a/intern/cycles/device/queue.h +++ b/intern/cycles/device/queue.h @@ -103,7 +103,7 @@ class DeviceQueue { /* Number of states which keeps the device occupied with work without losing performance. * The renderer will add more work (when available) when number of active paths falls below this * value. */ - virtual int num_concurrent_busy_states() const = 0; + virtual int num_concurrent_busy_states(const size_t state_size) const = 0; /* Number of elements in a partition of sorted shaders, that improves memory locality of * integrator state fetch at the cost of decreased coherence for shader kernel execution. */ diff --git a/intern/cycles/integrator/path_trace_work_gpu.cpp b/intern/cycles/integrator/path_trace_work_gpu.cpp index ee250a6916b..48f6cf3c903 100644 --- a/intern/cycles/integrator/path_trace_work_gpu.cpp +++ b/intern/cycles/integrator/path_trace_work_gpu.cpp @@ -18,13 +18,15 @@ CCL_NAMESPACE_BEGIN -static size_t estimate_single_state_size() +static size_t estimate_single_state_size(const uint kernel_features) { size_t state_size = 0; #define KERNEL_STRUCT_BEGIN(name) for (int array_index = 0;; array_index++) { -#define KERNEL_STRUCT_MEMBER(parent_struct, type, name, feature) state_size += sizeof(type); -#define KERNEL_STRUCT_ARRAY_MEMBER(parent_struct, type, name, feature) state_size += sizeof(type); +#define KERNEL_STRUCT_MEMBER(parent_struct, type, name, feature) \ + state_size += (kernel_features & (feature)) ? sizeof(type) : 0; +#define KERNEL_STRUCT_ARRAY_MEMBER(parent_struct, type, name, feature) \ + state_size += (kernel_features & (feature)) ? sizeof(type) : 0; #define KERNEL_STRUCT_END(name) \ break; \ } @@ -76,16 +78,11 @@ PathTraceWorkGPU::PathTraceWorkGPU(Device *device, num_queued_paths_(device, "num_queued_paths", MEM_READ_WRITE), work_tiles_(device, "work_tiles", MEM_READ_WRITE), display_rgba_half_(device, "display buffer half", MEM_READ_WRITE), - max_num_paths_(queue_->num_concurrent_states(estimate_single_state_size())), - min_num_active_main_paths_(queue_->num_concurrent_busy_states()), + max_num_paths_(0), + min_num_active_main_paths_(0), max_active_main_path_index_(0) { memset(&integrator_state_gpu_, 0, sizeof(integrator_state_gpu_)); - - /* Limit number of active paths to the half of the overall state. This is due to the logic in the - * path compaction which relies on the fact that regeneration does not happen sooner than half of - * the states are available again. */ - min_num_active_main_paths_ = min(min_num_active_main_paths_, max_num_paths_ / 2); } void PathTraceWorkGPU::alloc_integrator_soa() @@ -103,6 +100,20 @@ void PathTraceWorkGPU::alloc_integrator_soa() integrator_state_soa_volume_stack_size_ = max(integrator_state_soa_volume_stack_size_, requested_volume_stack_size); + /* Deterine the number of path states. Deferring this for as long as possible allows the backend + * to make better decisions about memory availability. */ + if (max_num_paths_ == 0) { + size_t single_state_size = estimate_single_state_size(kernel_features); + + max_num_paths_ = queue_->num_concurrent_states(single_state_size); + min_num_active_main_paths_ = queue_->num_concurrent_busy_states(single_state_size); + + /* Limit number of active paths to the half of the overall state. This is due to the logic in + * the path compaction which relies on the fact that regeneration does not happen sooner than + * half of the states are available again. */ + min_num_active_main_paths_ = min(min_num_active_main_paths_, max_num_paths_ / 2); + } + /* Allocate a device only memory buffer before for each struct member, and then * write the pointers into a struct that resides in constant memory. * -- cgit v1.2.3 From 63675b8d70ad7a1ef74e23a6605983e135294cd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Mon, 24 Oct 2022 18:16:29 +0200 Subject: GPencil: Fix regression (part3) with edit mode introduced in rB0ee9282b5c51 Vertex indexing has not been updated and stroke_start usage was wrong. Update all `stroke_start` usage. --- source/blender/draw/engines/eevee_next/eevee_sync.cc | 2 +- source/blender/draw/engines/gpencil/gpencil_engine.c | 2 +- source/blender/draw/intern/draw_cache_impl_gpencil.cc | 15 +++++++++------ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_sync.cc b/source/blender/draw/engines/eevee_next/eevee_sync.cc index 0915dace1e5..cbd735ec29c 100644 --- a/source/blender/draw/engines/eevee_next/eevee_sync.cc +++ b/source/blender/draw/engines/eevee_next/eevee_sync.cc @@ -258,7 +258,7 @@ static void gpencil_stroke_sync(bGPDlayer * /*gpl*/, if (show_stroke) { /* Start one vert before to have gl_InstanceID > 0 (see shader). */ - int vfirst = gps->runtime.stroke_start - 1; + int vfirst = gps->runtime.stroke_start * 3; /* Include "potential" cyclic vertex and start adj vertex (see shader). */ int vcount = gps->totpoints + 1 + 1; gpencil_drawcall_add(iter, geom, material, vfirst, vcount, true); diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 78e658d35eb..21e536ffbd4 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -536,7 +536,7 @@ static void gpencil_stroke_cache_populate(bGPDlayer *gpl, gpencil_drawcall_add(iter, geom, vfirst, vcount); } - iter->stroke_index_last = gps->runtime.stroke_start + gps->totpoints + 1; + iter->stroke_index_last = gps->runtime.vertex_start + gps->totpoints + 1; } static void gpencil_sbuffer_cache_populate_fast(GPENCIL_Data *vedata, gpIterPopulateData *iter) diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.cc b/source/blender/draw/intern/draw_cache_impl_gpencil.cc index b46a4907da8..667ae380ae4 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.cc +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.cc @@ -45,7 +45,7 @@ typedef struct GpencilBatchCache { GPUVertBuf *vbo_col; /** Indices in material order, then stroke order with fill first. * Strokes can be individually rendered using `gps->runtime.stroke_start` and - * `gps->runtime.stroke_start`. */ + * `gps->runtime.fill_start`. */ GPUIndexBuf *ibo; /** Batches */ GPUBatch *geom_batch; @@ -319,7 +319,7 @@ static void gpencil_buffer_add_point(GPUIndexBufBuilder *ibo, vert->strength = (round_cap0) ? pt->strength : -pt->strength; vert->u_stroke = pt->uv_fac; - vert->stroke_id = gps->runtime.stroke_start; + vert->stroke_id = gps->runtime.vertex_start; vert->point_id = v; vert->thickness = max_ff(0.0f, gps->thickness * pt->pressure) * (round_cap1 ? 1.0f : -1.0f); /* Tag endpoint material to -1 so they get discarded by vertex shader. */ @@ -761,7 +761,7 @@ static void gpencil_edit_stroke_iter_cb(bGPDlayer *gpl, { gpEditIterData *iter = (gpEditIterData *)thunk; const int v_len = gps->totpoints; - const int v = gps->runtime.stroke_start + 1; + const int v = gps->runtime.vertex_start + 1; MDeformVert *dvert = ((iter->vgindex > -1) && gps->dvert) ? gps->dvert : NULL; gpEditVert *vert_ptr = iter->verts + v; @@ -776,9 +776,12 @@ static void gpencil_edit_stroke_iter_cb(bGPDlayer *gpl, vert_ptr->weight = gpencil_point_edit_weight(dvert, i, iter->vgindex); vert_ptr++; } - /* Draw line to first point to complete the loop for cyclic strokes. */ - vert_ptr->vflag = sflag | gpencil_point_edit_flag(layer_lock, &gps->points[0], 0, v_len); - vert_ptr->weight = gpencil_point_edit_weight(dvert, 0, iter->vgindex); + + if (gpencil_stroke_is_cyclic(gps)) { + /* Draw line to first point to complete the loop for cyclic strokes. */ + vert_ptr->vflag = sflag | gpencil_point_edit_flag(layer_lock, &gps->points[0], 0, v_len); + vert_ptr->weight = gpencil_point_edit_weight(dvert, 0, iter->vgindex); + } } static void gpencil_edit_curve_stroke_count_cb(bGPDlayer *gpl, -- cgit v1.2.3 From 53795877727d67185de858a480c8090ca7eb8e36 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 24 Oct 2022 19:00:27 +0200 Subject: Fix T101210: invalid internal node links lead to crash Internal links are run-time/derived data. Therefore it is not necessary to load them from .blend files where invalid internal links may be stored. They will be regenerated after a node tree is loaded anyway. --- source/blender/blenkernel/intern/node.cc | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 8028f990c42..3e3a8355f98 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -516,10 +516,6 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree) write_node_socket(writer, sock); } - LISTBASE_FOREACH (bNodeLink *, link, &node->internal_links) { - BLO_write_struct(writer, bNodeLink, link); - } - if (node->storage) { if (ELEM(ntree->type, NTREE_SHADER, NTREE_GEOMETRY) && ELEM(node->type, SH_NODE_CURVE_VEC, SH_NODE_CURVE_RGB, SH_NODE_CURVE_FLOAT)) { @@ -703,13 +699,7 @@ void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree) BLO_read_data_address(reader, &node->prop); IDP_BlendDataRead(reader, &node->prop); - BLO_read_list(reader, &node->internal_links); - LISTBASE_FOREACH (bNodeLink *, link, &node->internal_links) { - BLO_read_data_address(reader, &link->fromnode); - BLO_read_data_address(reader, &link->fromsock); - BLO_read_data_address(reader, &link->tonode); - BLO_read_data_address(reader, &link->tosock); - } + BLI_listbase_clear(&node->internal_links); if (node->type == CMP_NODE_MOVIEDISTORTION) { /* Do nothing, this is runtime cache and hence handled by generic code using -- cgit v1.2.3 From a67876103a6bb4554317f09ebd57c1997a45ed89 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Mon, 24 Oct 2022 19:40:39 +0200 Subject: Fix T101981: Incorrect playback of AVI files Commit bcc56253e26e introduced 3 frame negative offset for seeking. This can result in negative seek values. Ensure, that seek value is always positive. --- source/blender/imbuf/intern/anim_movie.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index 71e0d0fe11e..94c0555dcf0 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -1100,7 +1100,12 @@ static int64_t ffmpeg_get_seek_pts(struct anim *anim, int64_t pts_to_search) * experimentally. Note: Too big offset can impact performance. Current 3 frame offset has no * measurable impact. */ - return pts_to_search - (ffmpeg_steps_per_frame_get(anim) * 3); + int64_t seek_pts = pts_to_search - (ffmpeg_steps_per_frame_get(anim) * 3); + + if (seek_pts < 0) { + seek_pts = 0; + } + return seek_pts; } /* This gives us an estimate of which pts our requested frame will have. -- cgit v1.2.3 From 4e9a8109b2219a9cddc3943d13a1d3ae231fdd50 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Mon, 24 Oct 2022 14:51:07 -0300 Subject: Fix T100571: Subdivision disabled with Orbit Around Selection The bug has existed since crasy space was implemented. rBbf8a26b7453d made the error even worse as the `modifiers_disable_subsurf_temporary` function, which works like a toggle, did not temporarily re-enable subsurf. The main problem is that the derived mesh is modified but not marked as dirty at the end. --- source/blender/blenkernel/intern/crazyspace.cc | 35 +++++++++++++------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/source/blender/blenkernel/intern/crazyspace.cc b/source/blender/blenkernel/intern/crazyspace.cc index 190e2d3bb7e..f83c321c4ae 100644 --- a/source/blender/blenkernel/intern/crazyspace.cc +++ b/source/blender/blenkernel/intern/crazyspace.cc @@ -70,47 +70,48 @@ static void set_crazy_vertex_quat(float r_quat[4], sub_qt_qtqt(r_quat, q2, q1); } -static bool modifiers_disable_subsurf_temporary(struct Scene *scene, Object *ob) +static bool modifiers_disable_subsurf_temporary(Object *ob, const int cageIndex) { - bool disabled = false; - int cageIndex = BKE_modifiers_get_cage_index(scene, ob, nullptr, true); + bool changed = false; ModifierData *md = static_cast(ob->modifiers.first); for (int i = 0; md && i <= cageIndex; i++, md = md->next) { if (md->type == eModifierType_Subsurf) { md->mode ^= eModifierMode_DisableTemporary; - disabled = true; + changed = true; } } - return disabled; + return changed; } float (*BKE_crazyspace_get_mapped_editverts(struct Depsgraph *depsgraph, Object *obedit))[3] { - Scene *scene = DEG_get_input_scene(depsgraph); Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit); - Mesh *mesh_eval = static_cast(obedit_eval->data); - BMEditMesh *editmesh_eval = mesh_eval->edit_mesh; + const int cageIndex = BKE_modifiers_get_cage_index(scene_eval, obedit_eval, nullptr, true); - /* disable subsurf temporal, get mapped cos, and enable it */ - if (modifiers_disable_subsurf_temporary(scene_eval, obedit_eval)) { - /* Need to make new derived-mesh. */ + /* Disable subsurf temporal, get mapped cos, and enable it. */ + if (modifiers_disable_subsurf_temporary(obedit_eval, cageIndex)) { + /* Need to make new cage. + * TODO: Avoid losing original evaluated geometry. */ makeDerivedMesh(depsgraph, scene_eval, obedit_eval, &CD_MASK_BAREMESH); } - /* now get the cage */ - Mesh *mesh_eval_cage = editbmesh_get_eval_cage_from_orig( - depsgraph, scene, obedit, &CD_MASK_BAREMESH); + /* Now get the cage. */ + BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval); + Mesh *mesh_eval_cage = editbmesh_get_eval_cage( + depsgraph, scene_eval, obedit_eval, em_eval, &CD_MASK_BAREMESH); - const int nverts = editmesh_eval->bm->totvert; + const int nverts = em_eval->bm->totvert; float(*vertexcos)[3] = static_cast( MEM_mallocN(sizeof(*vertexcos) * nverts, "vertexcos map")); mesh_get_mapped_verts_coords(mesh_eval_cage, vertexcos, nverts); - /* set back the flag, no new cage needs to be built, transform does it */ - modifiers_disable_subsurf_temporary(scene_eval, obedit_eval); + /* Set back the flag, and ensure new cage needs to be built. */ + if (modifiers_disable_subsurf_temporary(obedit_eval, cageIndex)) { + DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + } return vertexcos; } -- cgit v1.2.3 From 583ae0caaa495adcc4af2494a4a87d19ae4eb645 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Mon, 24 Oct 2022 19:57:53 +0200 Subject: VSE: Don't use timecodes if not explicitly enabled UI panel may suggest, that disabling "Proxy & timecode" would cause timecodes not being used, but this was not the case. Now timecodes will be used only if the checkbox is checked. --- source/blender/sequencer/intern/render.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c index dbbece73695..e3fd9216842 100644 --- a/source/blender/sequencer/intern/render.c +++ b/source/blender/sequencer/intern/render.c @@ -1026,6 +1026,15 @@ static ImBuf *seq_render_movie_strip_custom_file_proxy(const SeqRenderData *cont return IMB_anim_absolute(proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE); } +static IMB_Timecode_Type seq_render_movie_strip_timecode_get(Sequence *seq) +{ + bool use_timecodes = (seq->flag & SEQ_USE_PROXY) != 0; + if (!use_timecodes) { + return IMB_TC_NONE; + } + return seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_NONE; +} + /** * Render individual view for multi-view or single (default view) for mono-view. */ @@ -1049,7 +1058,7 @@ static ImBuf *seq_render_movie_strip_view(const SeqRenderData *context, else { ibuf = IMB_anim_absolute(sanim->anim, frame_index + seq->anim_startofs, - seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN, + seq_render_movie_strip_timecode_get(seq), psize); } @@ -1062,7 +1071,7 @@ static ImBuf *seq_render_movie_strip_view(const SeqRenderData *context, if (ibuf == NULL) { ibuf = IMB_anim_absolute(sanim->anim, frame_index + seq->anim_startofs, - seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN, + seq_render_movie_strip_timecode_get(seq), IMB_PROXY_NONE); } if (ibuf == NULL) { -- cgit v1.2.3 From 954b834053f17f1c0ff1f3096030b81d0d9ea7ec Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Mon, 24 Oct 2022 11:59:24 -0600 Subject: Fix T102015: AV1 - No valid formats found I did a poor master merge in D14920 before landing and AV_CODEC_ID_AV1 accidentally ended up in `ffmpeg_format_items` rather than `ffmpeg_codec_items` --- source/blender/makesrna/intern/rna_scene.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 58455ff7de5..fde8fcf651c 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -5928,7 +5928,6 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna) {FFMPEG_MKV, "MKV", 0, "Matroska", ""}, {FFMPEG_FLV, "FLASH", 0, "Flash", ""}, {FFMPEG_WEBM, "WEBM", 0, "WebM", ""}, - {AV_CODEC_ID_AV1, "AV1", 0, "AV1", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -5947,6 +5946,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna) {AV_CODEC_ID_QTRLE, "QTRLE", 0, "QT rle / QT Animation", ""}, {AV_CODEC_ID_THEORA, "THEORA", 0, "Theora", ""}, {AV_CODEC_ID_VP9, "WEBM", 0, "WebM / VP9", ""}, + {AV_CODEC_ID_AV1, "AV1", 0, "AV1", ""}, {0, NULL, 0, NULL, NULL}, }; -- cgit v1.2.3 From e2d06eb68ab4bb474694ffd96b5d11dbb6741bb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Mon, 24 Oct 2022 21:09:40 +0200 Subject: GPencil: Fix missing fills For some reason stroke_id needs to be the triangle index, not the vertex index. --- source/blender/draw/engines/gpencil/gpencil_engine.c | 2 +- source/blender/draw/intern/draw_cache_impl_gpencil.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 21e536ffbd4..78e658d35eb 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -536,7 +536,7 @@ static void gpencil_stroke_cache_populate(bGPDlayer *gpl, gpencil_drawcall_add(iter, geom, vfirst, vcount); } - iter->stroke_index_last = gps->runtime.vertex_start + gps->totpoints + 1; + iter->stroke_index_last = gps->runtime.stroke_start + gps->totpoints + 1; } static void gpencil_sbuffer_cache_populate_fast(GPENCIL_Data *vedata, gpIterPopulateData *iter) diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.cc b/source/blender/draw/intern/draw_cache_impl_gpencil.cc index 667ae380ae4..9dbab8fef02 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.cc +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.cc @@ -319,7 +319,7 @@ static void gpencil_buffer_add_point(GPUIndexBufBuilder *ibo, vert->strength = (round_cap0) ? pt->strength : -pt->strength; vert->u_stroke = pt->uv_fac; - vert->stroke_id = gps->runtime.vertex_start; + vert->stroke_id = gps->runtime.stroke_start; vert->point_id = v; vert->thickness = max_ff(0.0f, gps->thickness * pt->pressure) * (round_cap1 ? 1.0f : -1.0f); /* Tag endpoint material to -1 so they get discarded by vertex shader. */ -- cgit v1.2.3 From 5d5e0f1b0ecbe0aa3b047dfe7b1f3f4d2bf32cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Mon, 24 Oct 2022 21:42:08 +0200 Subject: GPencil: Fix crash when using circle or rectangle tool This was caused by a wrongly sized vertex buffer for the stroke buffer. --- source/blender/draw/intern/draw_cache_impl_gpencil.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.cc b/source/blender/draw/intern/draw_cache_impl_gpencil.cc index 9dbab8fef02..6c38b23f44f 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.cc +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.cc @@ -629,9 +629,9 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_fill) GPUVertFormat *format_color = gpencil_color_format(); GPUVertBuf *vbo = GPU_vertbuf_create_with_format_ex(format, vbo_flag); GPUVertBuf *vbo_col = GPU_vertbuf_create_with_format_ex(format_color, vbo_flag); - /* Add extra space at the end the buffer because of quad load and cyclic. */ - GPU_vertbuf_data_alloc(vbo, vert_len + 2); - GPU_vertbuf_data_alloc(vbo_col, vert_len + 2); + /* Add extra space at the start and end the buffer because of quad load and cyclic. */ + GPU_vertbuf_data_alloc(vbo, 1 + vert_len + 1 + 2); + GPU_vertbuf_data_alloc(vbo_col, 1 + vert_len + 1 + 2); gpStrokeVert *verts = (gpStrokeVert *)GPU_vertbuf_get_data(vbo); gpColorVert *cols = (gpColorVert *)GPU_vertbuf_get_data(vbo_col); -- cgit v1.2.3 From 97414fb484fe37b8da69a2b570a659535bbf2a0f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 24 Oct 2022 20:33:33 +1100 Subject: GHOST/Wayland: support adding/removing global objects at runtime Share logic for adding/removing global objects and freeing them on exit. Refactor object registration add/remove into an array of callbacks to localize logic into generic functions for each kind of interface. Also corrects own error where the primary clipboard manager wasn't being destroyed on exit. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 890 ++++++++++++++++++++++------ 1 file changed, 698 insertions(+), 192 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 67f475a2963..65b4e890d88 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -89,6 +89,15 @@ static void gwl_seat_capability_pointer_disable(GWL_Seat *seat); static void gwl_seat_capability_keyboard_disable(GWL_Seat *seat); static void gwl_seat_capability_touch_disable(GWL_Seat *seat); +static bool gwl_registry_entry_remove_by_name(GWL_Display *display, + uint32_t name, + int *r_interface_slot); + +struct GWL_RegistryHandler; +static int gwl_registry_handler_interface_slot_max(); +static const struct GWL_RegistryHandler *gwl_registry_handler_from_interface_slot( + int interface_slot); + /* -------------------------------------------------------------------- */ /** \name Local Defines * @@ -138,6 +147,8 @@ static bool use_gnome_confine_hack = false; # define USE_GNOME_NEEDS_LIBDECOR_HACK #endif +#define WL_NAME_UNSET uint32_t(-1) + /** \} */ /* -------------------------------------------------------------------- */ @@ -527,6 +538,7 @@ static void gwl_libdecor_system_destroy(GWL_LibDecor_System *decor) { if (decor->context) { libdecor_unref(decor->context); + decor->context = nullptr; } delete decor; } @@ -534,16 +546,21 @@ static void gwl_libdecor_system_destroy(GWL_LibDecor_System *decor) struct GWL_XDG_Decor_System { struct xdg_wm_base *shell = nullptr; + uint32_t shell_name = WL_NAME_UNSET; + struct zxdg_decoration_manager_v1 *manager = nullptr; + uint32_t manager_name = WL_NAME_UNSET; }; -static void gwl_xdg_decor_system_destroy(GWL_XDG_Decor_System *decor) +static void gwl_xdg_decor_system_destroy(struct GWL_Display *display, GWL_XDG_Decor_System *decor) { if (decor->manager) { - zxdg_decoration_manager_v1_destroy(decor->manager); + gwl_registry_entry_remove_by_name(display, decor->manager_name, nullptr); + GHOST_ASSERT(decor->manager == nullptr, "Internal registry error"); } if (decor->shell) { - xdg_wm_base_destroy(decor->shell); + gwl_registry_entry_remove_by_name(display, decor->shell_name, nullptr); + GHOST_ASSERT(decor->shell == nullptr, "Internal registry error"); } delete decor; } @@ -707,9 +724,13 @@ struct GWL_Seat { /** \name Internal #GWL_Display Type (#wl_display & #wl_compositor wrapper) * \{ */ +struct GWL_RegistryEntry; + struct GWL_Display { GHOST_SystemWayland *system = nullptr; + struct GWL_RegistryEntry *registry_entry = nullptr; + struct wl_display *wl_display = nullptr; struct wl_compositor *wl_compositor = nullptr; @@ -738,6 +759,178 @@ struct GWL_Display { /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Internal #GWL_RegistryHandler + * \{ */ + +struct GWL_RegisteryAdd_Params { + struct GWL_Display *display = nullptr; + struct wl_registry *wl_registry = nullptr; + uint32_t name = 0; + uint32_t version = 0; + /** Index within `gwl_registry_handlers`. */ + int interface_slot = 0; +}; + +/** + * Add callback for object registry. + * \param display: The display which holes a reference to the global object. + * \param params: Various arguments needed for registration. + */ +using GWL_RegistryHandler_AddFn = void (*)(GWL_Display *display, + const GWL_RegisteryAdd_Params *params); + +/** + * Remove callback for object registry. + * \param display: The display which holes a reference to the global object. + * \param user_data: Optional reference to a sub element of `display`, + * use for outputs or seats for e.g. when the display may hold multiple references. + * \param on_exit: Enabled when freeing on exit. + * When true the consistency of references between objects should be kept valid. + * Otherwise it can be assumed that all objects will be freed and none will be used again, + * so there is no need to ensure a valid state. + */ +using GWL_RegistryEntry_FreeFn = void (*)(GWL_Display *display, void *user_data, bool on_exit); + +struct GWL_RegistryHandler { + /** Pointer to the name (not the name it's self), needed as the values aren't set on startup. */ + const char *const *interface_p = nullptr; + + GWL_RegistryHandler_AddFn add_fn = nullptr; + GWL_RegistryEntry_FreeFn remove_fn = nullptr; +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal #GWL_RegistryEntry + * \{ */ + +/** + * Registered global objects can be removed by the compositor, + * these entries are a registry of objects and callbacks to properly remove them. + * These are also used to remove all registered objects before exiting. + */ +struct GWL_RegistryEntry { + GWL_RegistryEntry *next = nullptr; + /** + * Optional pointer passed to `remove_fn`, typically the container in #GWL_Display + * in cases multiple instances of the same interface are supported. + */ + void *user_data = nullptr; + /** + * A unique identifier used as a handle by `wl_registry_listener.global_remove`. + */ + uint32_t name = WL_NAME_UNSET; + /** + * The index in `gwl_registry_handlers`, + * useful for accessing the interface name (for logging for example). + */ + int interface_slot = 0; +}; + +static void gwl_registry_entry_add(GWL_Display *display, + const int interface_slot, + const uint32_t name, + void *user_data) +{ + GWL_RegistryEntry *reg = new GWL_RegistryEntry; + + reg->interface_slot = interface_slot; + reg->name = name; + reg->user_data = user_data; + + reg->next = display->registry_entry; + display->registry_entry = reg; +} + +static bool gwl_registry_entry_remove_by_name(GWL_Display *display, + uint32_t name, + int *r_interface_slot) +{ + GWL_RegistryEntry *reg = display->registry_entry; + GWL_RegistryEntry **reg_link_p = &display->registry_entry; + bool found = false; + + if (r_interface_slot) { + *r_interface_slot = -1; + } + + while (reg) { + if (reg->name == name) { + GWL_RegistryEntry *reg_next = reg->next; + const GWL_RegistryHandler *handler = gwl_registry_handler_from_interface_slot( + reg->interface_slot); + handler->remove_fn(display, reg->user_data, false); + if (r_interface_slot) { + *r_interface_slot = reg->interface_slot; + } + delete reg; + *reg_link_p = reg_next; + found = true; + break; + } + reg_link_p = ®->next; + reg = reg->next; + } + return found; +} + +static bool gwl_registry_entry_remove_by_interface_slot(GWL_Display *display, + int interface_slot, + bool on_exit) +{ + GWL_RegistryEntry *reg = display->registry_entry; + GWL_RegistryEntry **reg_link_p = &display->registry_entry; + bool found = false; + + while (reg) { + if (reg->interface_slot == interface_slot) { + GWL_RegistryEntry *reg_next = reg->next; + const GWL_RegistryHandler *handler = gwl_registry_handler_from_interface_slot( + interface_slot); + handler->remove_fn(display, reg->user_data, on_exit); + delete reg; + *reg_link_p = reg_next; + reg = reg_next; + found = true; + continue; + } + reg_link_p = ®->next; + reg = reg->next; + } + return found; +} + +/** + * Remove all global objects (on exit). + */ +static void gwl_registry_entry_remove_all(GWL_Display *display) +{ + const bool on_exit = true; + + /* NOTE(@campbellbarton): Free by slot instead of simply looping over + * `display->registry_entry` so the order of freeing is always predictable. + * Otherwise global objects would be feed in the order they are registered. + * While this works in my tests, it could cause difficult to reproduce bugs + * where lesser used compositors or changes to existing compositors could + * crash on exit based on the order of freeing objects is out of our control. + * + * To give a concrete example of how this could fail, it's possible removing + * a tablet interface could reference the pointer interface, or the output interface. + * Even though references between interfaces shouldn't be necessary in most cases + * when `on_exit` is enabled. */ + int interface_slot = gwl_registry_handler_interface_slot_max(); + while (interface_slot--) { + gwl_registry_entry_remove_by_interface_slot(display, interface_slot, on_exit); + } + + GHOST_ASSERT(display->registry_entry == nullptr, "Failed to remove all entries!"); + display->registry_entry = nullptr; +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Private Utility Functions * \{ */ @@ -790,125 +983,22 @@ static GWL_SeatStatePointer *seat_state_pointer_from_cursor_surface(GWL_Seat *se static void display_destroy(GWL_Display *display) { - if (display->wl_data_device_manager) { - wl_data_device_manager_destroy(display->wl_data_device_manager); - } - - if (display->wp_tablet_manager) { - zwp_tablet_manager_v2_destroy(display->wp_tablet_manager); - } - - for (GWL_Output *output : display->outputs) { - wl_output_destroy(output->wl_output); - delete output; - } - - for (GWL_Seat *seat : display->seats) { - - /* First handle members that require locking. - * While highly unlikely, it's possible they are being used while this function runs. */ - { - std::lock_guard lock{seat->data_source_mutex}; - if (seat->data_source) { - gwl_simple_buffer_free_data(&seat->data_source->buffer_out); - if (seat->data_source->wl_source) { - wl_data_source_destroy(seat->data_source->wl_source); - } - delete seat->data_source; - } - } - - { - std::lock_guard lock{seat->data_offer_dnd_mutex}; - if (seat->data_offer_dnd) { - wl_data_offer_destroy(seat->data_offer_dnd->id); - delete seat->data_offer_dnd; - } - } - - { - std::lock_guard lock{seat->data_offer_copy_paste_mutex}; - if (seat->data_offer_copy_paste) { - wl_data_offer_destroy(seat->data_offer_copy_paste->id); - delete seat->data_offer_copy_paste; - } - } - - { - GWL_PrimarySelection *primary = &seat->primary_selection; - std::lock_guard lock{primary->data_offer_mutex}; - gwl_primary_selection_discard_offer(primary); - } - - { - GWL_PrimarySelection *primary = &seat->primary_selection; - std::lock_guard lock{primary->data_source_mutex}; - gwl_primary_selection_discard_source(primary); - } - - if (seat->wp_primary_selection_device) { - zwp_primary_selection_device_v1_destroy(seat->wp_primary_selection_device); - } - - if (seat->wl_data_device) { - wl_data_device_release(seat->wl_data_device); - } - - if (seat->cursor.custom_data) { - munmap(seat->cursor.custom_data, seat->cursor.custom_data_size); - } - - /* Disable all capabilities as a way to free: - * - `seat.wl_pointer` (and related cursor variables). - * - `seat.wl_touch`. - * - `seat.wl_keyboard`. - */ - gwl_seat_capability_pointer_disable(seat); - gwl_seat_capability_keyboard_disable(seat); - gwl_seat_capability_touch_disable(seat); - - /* Un-referencing checks for NULL case. */ - xkb_state_unref(seat->xkb_state); - xkb_state_unref(seat->xkb_state_empty); - xkb_state_unref(seat->xkb_state_empty_with_numlock); - - xkb_context_unref(seat->xkb_context); - - wl_seat_destroy(seat->wl_seat); - delete seat; - } - - if (display->wl_shm) { - wl_shm_destroy(display->wl_shm); - } - - if (display->wp_relative_pointer_manager) { - zwp_relative_pointer_manager_v1_destroy(display->wp_relative_pointer_manager); - } - - if (display->wp_pointer_constraints) { - zwp_pointer_constraints_v1_destroy(display->wp_pointer_constraints); - } - - if (display->wp_pointer_gestures) { - zwp_pointer_gestures_v1_destroy(display->wp_pointer_gestures); - } - - if (display->wl_compositor) { - wl_compositor_destroy(display->wl_compositor); - } + /* Unregister items in reverse order. */ + gwl_registry_entry_remove_all(display); #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { if (display->libdecor) { gwl_libdecor_system_destroy(display->libdecor); + display->libdecor = nullptr; } } else #endif { if (display->xdg_decor) { - gwl_xdg_decor_system_destroy(display->xdg_decor); + gwl_xdg_decor_system_destroy(display, display->xdg_decor); + display->xdg_decor = nullptr; } } @@ -4043,100 +4133,508 @@ static struct libdecor_interface libdecor_interface = { static CLG_LogRef LOG_WL_REGISTRY = {"ghost.wl.handle.registry"}; #define LOG (&LOG_WL_REGISTRY) -static void global_handle_add(void *data, - struct wl_registry *wl_registry, - const uint32_t name, - const char *interface, - const uint32_t version) +/* #GWL_Display.wl_compositor */ + +static void gwl_registry_compositor_add(GWL_Display *display, + const GWL_RegisteryAdd_Params *params) { - /* Log last since it can be noted if the interface was handled or not. */ - bool found = true; - - struct GWL_Display *display = static_cast(data); - if (STREQ(interface, wl_compositor_interface.name)) { - display->wl_compositor = static_cast( - wl_registry_bind(wl_registry, name, &wl_compositor_interface, 3)); - } - else if (STREQ(interface, xdg_wm_base_interface.name)) { - GWL_XDG_Decor_System &decor = *display->xdg_decor; - decor.shell = static_cast( - wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1)); - xdg_wm_base_add_listener(decor.shell, &shell_listener, nullptr); - } - else if (STREQ(interface, zxdg_decoration_manager_v1_interface.name)) { - GWL_XDG_Decor_System &decor = *display->xdg_decor; - decor.manager = static_cast( - wl_registry_bind(wl_registry, name, &zxdg_decoration_manager_v1_interface, 1)); - } - else if (STREQ(interface, zxdg_output_manager_v1_interface.name)) { - display->xdg_output_manager = static_cast( - wl_registry_bind(wl_registry, name, &zxdg_output_manager_v1_interface, 2)); - for (GWL_Output *output : display->outputs) { - output->xdg_output = zxdg_output_manager_v1_get_xdg_output(display->xdg_output_manager, - output->wl_output); - zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output); - } + display->wl_compositor = static_cast( + wl_registry_bind(params->wl_registry, params->name, &wl_compositor_interface, 3)); + + gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); +} +static void gwl_registry_compositor_remove(GWL_Display *display, + void * /*user_data*/, + const bool /*on_exit*/) +{ + struct wl_compositor **value_p = &display->wl_compositor; + wl_compositor_destroy(*value_p); + *value_p = nullptr; +} + +/* #GWL_Display.xdg_decor.shell */ + +static void gwl_registry_xdg_wm_base_add(GWL_Display *display, + const GWL_RegisteryAdd_Params *params) +{ + GWL_XDG_Decor_System &decor = *display->xdg_decor; + decor.shell = static_cast( + wl_registry_bind(params->wl_registry, params->name, &xdg_wm_base_interface, 1)); + xdg_wm_base_add_listener(decor.shell, &shell_listener, nullptr); + decor.shell_name = params->name; + + gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); +} +static void gwl_registry_xdg_wm_base_remove(GWL_Display *display, + void * /*user_data*/, + const bool /*on_exit*/) +{ + GWL_XDG_Decor_System &decor = *display->xdg_decor; + struct xdg_wm_base **value_p = &decor.shell; + uint32_t *name_p = &decor.shell_name; + xdg_wm_base_destroy(*value_p); + *value_p = nullptr; + *name_p = WL_NAME_UNSET; +} + +/* #GWL_Display.xdg_decor.manager */ + +static void gwl_registry_xdg_decoration_manager_add(GWL_Display *display, + const GWL_RegisteryAdd_Params *params) +{ + GWL_XDG_Decor_System &decor = *display->xdg_decor; + decor.manager = static_cast(wl_registry_bind( + params->wl_registry, params->name, &zxdg_decoration_manager_v1_interface, 1)); + decor.manager_name = params->name; + + gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); +} +static void gwl_registry_xdg_decoration_manager_remove(GWL_Display *display, + void * /*user_data*/, + const bool /*on_exit*/) +{ + GWL_XDG_Decor_System &decor = *display->xdg_decor; + struct zxdg_decoration_manager_v1 **value_p = &decor.manager; + uint32_t *name_p = &decor.manager_name; + zxdg_decoration_manager_v1_destroy(*value_p); + *value_p = nullptr; + *name_p = WL_NAME_UNSET; +} + +/* #GWL_Display.xdg_output_manager */ + +static void gwl_registry_xdg_output_manager_add(GWL_Display *display, + const GWL_RegisteryAdd_Params *params) +{ + display->xdg_output_manager = static_cast( + wl_registry_bind(params->wl_registry, params->name, &zxdg_output_manager_v1_interface, 2)); + for (GWL_Output *output : display->outputs) { + output->xdg_output = zxdg_output_manager_v1_get_xdg_output(display->xdg_output_manager, + output->wl_output); + zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output); } - else if (STREQ(interface, wl_output_interface.name)) { - GWL_Output *output = new GWL_Output; - output->wl_output = static_cast( - wl_registry_bind(wl_registry, name, &wl_output_interface, 2)); - ghost_wl_output_tag(output->wl_output); - wl_output_set_user_data(output->wl_output, output); - display->outputs.push_back(output); - wl_output_add_listener(output->wl_output, &output_listener, output); + gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); +} +static void gwl_registry_xdg_output_manager_remove(GWL_Display *display, + void * /*user_data*/, + const bool /*on_exit*/) +{ + struct zxdg_output_manager_v1 **value_p = &display->xdg_output_manager; + zxdg_output_manager_v1_destroy(*value_p); + *value_p = nullptr; + + for (GWL_Output *output : display->outputs) { + output->xdg_output = nullptr; + } +} + +/* #GWL_Display.wl_output */ - if (display->xdg_output_manager) { - output->xdg_output = zxdg_output_manager_v1_get_xdg_output(display->xdg_output_manager, - output->wl_output); - zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output); +static void gwl_registry_wl_output_add(GWL_Display *display, const GWL_RegisteryAdd_Params *params) +{ + GWL_Output *output = new GWL_Output; + output->wl_output = static_cast( + wl_registry_bind(params->wl_registry, params->name, &wl_output_interface, 2)); + ghost_wl_output_tag(output->wl_output); + wl_output_set_user_data(output->wl_output, output); + + display->outputs.push_back(output); + wl_output_add_listener(output->wl_output, &output_listener, output); + + if (display->xdg_output_manager) { + output->xdg_output = zxdg_output_manager_v1_get_xdg_output(display->xdg_output_manager, + output->wl_output); + zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output); + } + + gwl_registry_entry_add( + display, params->interface_slot, params->name, static_cast(output)); +} +static void gwl_registry_wl_output_remove(GWL_Display *display, + void *user_data, + const bool /*on_exit*/) +{ + GWL_Output *output = static_cast(user_data); + wl_output_destroy(output->wl_output); + std::vector::iterator iter = std::find( + display->outputs.begin(), display->outputs.end(), output); + const int index = (iter != display->outputs.cend()) ? + std::distance(display->outputs.begin(), iter) : + -1; + GHOST_ASSERT(index != -1, "invalid internal state"); + /* NOTE: always erase even when `on_exit` because `output->xdg_output` is cleared later. */ + display->outputs.erase(display->outputs.begin() + index); + delete output; +} + +/* #GWL_Display.seats */ + +static void gwl_registry_wl_seat_add(GWL_Display *display, const GWL_RegisteryAdd_Params *params) +{ + GWL_Seat *seat = new GWL_Seat; + seat->system = display->system; + seat->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + seat->data_source = new GWL_DataSource; + seat->wl_seat = static_cast( + wl_registry_bind(params->wl_registry, params->name, &wl_seat_interface, 5)); + display->seats.push_back(seat); + wl_seat_add_listener(seat->wl_seat, &seat_listener, seat); + + gwl_registry_entry_add(display, params->interface_slot, params->name, static_cast(seat)); +} +static void gwl_registry_wl_seat_remove(GWL_Display *display, void *user_data, const bool on_exit) +{ + GWL_Seat *seat = static_cast(user_data); + + /* First handle members that require locking. + * While highly unlikely, it's possible they are being used while this function runs. */ + { + std::lock_guard lock{seat->data_source_mutex}; + if (seat->data_source) { + gwl_simple_buffer_free_data(&seat->data_source->buffer_out); + if (seat->data_source->wl_source) { + wl_data_source_destroy(seat->data_source->wl_source); + } + delete seat->data_source; } } - else if (STREQ(interface, wl_seat_interface.name)) { - GWL_Seat *seat = new GWL_Seat; - seat->system = display->system; - seat->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - seat->data_source = new GWL_DataSource; - seat->wl_seat = static_cast( - wl_registry_bind(wl_registry, name, &wl_seat_interface, 5)); - display->seats.push_back(seat); - wl_seat_add_listener(seat->wl_seat, &seat_listener, seat); + + { + std::lock_guard lock{seat->data_offer_dnd_mutex}; + if (seat->data_offer_dnd) { + wl_data_offer_destroy(seat->data_offer_dnd->id); + delete seat->data_offer_dnd; + } } - else if (STREQ(interface, wl_shm_interface.name)) { - display->wl_shm = static_cast( - wl_registry_bind(wl_registry, name, &wl_shm_interface, 1)); + + { + std::lock_guard lock{seat->data_offer_copy_paste_mutex}; + if (seat->data_offer_copy_paste) { + wl_data_offer_destroy(seat->data_offer_copy_paste->id); + delete seat->data_offer_copy_paste; + } } - else if (STREQ(interface, wl_data_device_manager_interface.name)) { - display->wl_data_device_manager = static_cast( - wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 3)); + + { + GWL_PrimarySelection *primary = &seat->primary_selection; + std::lock_guard lock{primary->data_offer_mutex}; + gwl_primary_selection_discard_offer(primary); } - else if (STREQ(interface, zwp_tablet_manager_v2_interface.name)) { - display->wp_tablet_manager = static_cast( - wl_registry_bind(wl_registry, name, &zwp_tablet_manager_v2_interface, 1)); + + { + GWL_PrimarySelection *primary = &seat->primary_selection; + std::lock_guard lock{primary->data_source_mutex}; + gwl_primary_selection_discard_source(primary); } - else if (STREQ(interface, zwp_relative_pointer_manager_v1_interface.name)) { - display->wp_relative_pointer_manager = static_cast( - wl_registry_bind(wl_registry, name, &zwp_relative_pointer_manager_v1_interface, 1)); + + if (seat->wp_primary_selection_device) { + zwp_primary_selection_device_v1_destroy(seat->wp_primary_selection_device); } - else if (STREQ(interface, zwp_pointer_constraints_v1_interface.name)) { - display->wp_pointer_constraints = static_cast( - wl_registry_bind(wl_registry, name, &zwp_pointer_constraints_v1_interface, 1)); + + if (seat->wl_data_device) { + wl_data_device_release(seat->wl_data_device); } - else if (STREQ(interface, zwp_pointer_gestures_v1_interface.name)) { - display->wp_pointer_gestures = static_cast( - wl_registry_bind(wl_registry, name, &zwp_pointer_gestures_v1_interface, 3)); + + if (seat->cursor.custom_data) { + munmap(seat->cursor.custom_data, seat->cursor.custom_data_size); } - else if (!strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name)) { - display->wp_primary_selection_device_manager = - static_cast(wl_registry_bind( - wl_registry, name, &zwp_primary_selection_device_manager_v1_interface, 1)); + /* Disable all capabilities as a way to free: + * - `seat.wl_pointer` (and related cursor variables). + * - `seat.wl_touch`. + * - `seat.wl_keyboard`. + */ + gwl_seat_capability_pointer_disable(seat); + gwl_seat_capability_keyboard_disable(seat); + gwl_seat_capability_touch_disable(seat); + + /* Un-referencing checks for NULL case. */ + xkb_state_unref(seat->xkb_state); + xkb_state_unref(seat->xkb_state_empty); + xkb_state_unref(seat->xkb_state_empty_with_numlock); + + xkb_context_unref(seat->xkb_context); + + /* Remove the seat. */ + wl_seat_destroy(seat->wl_seat); + + std::vector::iterator iter = std::find( + display->seats.begin(), display->seats.end(), seat); + const int index = (iter != display->seats.cend()) ? std::distance(display->seats.begin(), iter) : + -1; + GHOST_ASSERT(index != -1, "invalid internal state"); + + if (!on_exit) { + display->seats.erase(display->seats.begin() + index); } + delete seat; +} - else { - found = false; +/* #GWL_Display.wl_shm */ + +static void gwl_registry_wl_shm_add(GWL_Display *display, const GWL_RegisteryAdd_Params *params) +{ + display->wl_shm = static_cast( + wl_registry_bind(params->wl_registry, params->name, &wl_shm_interface, 1)); + + gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); +} +static void gwl_registry_wl_shm_remove(GWL_Display *display, + void * /*user_data*/, + const bool /*on_exit*/) +{ + struct wl_shm **value_p = &display->wl_shm; + wl_shm_destroy(*value_p); + *value_p = nullptr; +} + +/* #GWL_Display.wl_data_device_manager */ + +static void gwl_registry_wl_data_device_manager_add(GWL_Display *display, + const GWL_RegisteryAdd_Params *params) +{ + display->wl_data_device_manager = static_cast( + wl_registry_bind(params->wl_registry, params->name, &wl_data_device_manager_interface, 3)); + + gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); +} +static void gwl_registry_wl_data_device_manager_remove(GWL_Display *display, + void * /*user_data*/, + const bool /*on_exit*/) +{ + struct wl_data_device_manager **value_p = &display->wl_data_device_manager; + wl_data_device_manager_destroy(*value_p); + *value_p = nullptr; +} + +/* #GWL_Display.wp_tablet_manager */ + +static void gwl_registry_wp_tablet_manager_add(GWL_Display *display, + const GWL_RegisteryAdd_Params *params) +{ + display->wp_tablet_manager = static_cast( + wl_registry_bind(params->wl_registry, params->name, &zwp_tablet_manager_v2_interface, 1)); + + gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); +} +static void gwl_registry_wp_tablet_manager_remove(GWL_Display *display, + void * /*user_data*/, + const bool /*on_exit*/) +{ + struct zwp_tablet_manager_v2 **value_p = &display->wp_tablet_manager; + zwp_tablet_manager_v2_destroy(*value_p); + *value_p = nullptr; +} + +/* #GWL_Display.wp_relative_pointer_manager */ + +static void gwl_registry_wp_relative_pointer_manager_add(GWL_Display *display, + const GWL_RegisteryAdd_Params *params) +{ + display->wp_relative_pointer_manager = static_cast( + wl_registry_bind( + params->wl_registry, params->name, &zwp_relative_pointer_manager_v1_interface, 1)); + + gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); +} +static void gwl_registry_wp_relative_pointer_manager_remove(GWL_Display *display, + void * /*user_data*/, + const bool /*on_exit*/) +{ + struct zwp_relative_pointer_manager_v1 **value_p = &display->wp_relative_pointer_manager; + zwp_relative_pointer_manager_v1_destroy(*value_p); + *value_p = nullptr; +} + +/* #GWL_Display.wp_pointer_constraints */ + +static void gwl_registry_wp_pointer_constraints_add(GWL_Display *display, + const GWL_RegisteryAdd_Params *params) +{ + display->wp_pointer_constraints = static_cast(wl_registry_bind( + params->wl_registry, params->name, &zwp_pointer_constraints_v1_interface, 1)); + gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); +} +static void gwl_registry_wp_pointer_constraints_remove(GWL_Display *display, + void * /*user_data*/, + const bool /*on_exit*/) +{ + struct zwp_pointer_constraints_v1 **value_p = &display->wp_pointer_constraints; + zwp_pointer_constraints_v1_destroy(*value_p); + *value_p = nullptr; +} + +/* #GWL_Display.wp_pointer_gestures */ + +static void gwl_registry_wp_pointer_gestures_add(GWL_Display *display, + const GWL_RegisteryAdd_Params *params) +{ + display->wp_pointer_gestures = static_cast( + wl_registry_bind(params->wl_registry, params->name, &zwp_pointer_gestures_v1_interface, 3)); + + gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); +} +static void gwl_registry_wp_pointer_gestures_remove(GWL_Display *display, + void * /*user_data*/, + const bool /*on_exit*/) +{ + struct zwp_pointer_gestures_v1 **value_p = &display->wp_pointer_gestures; + zwp_pointer_gestures_v1_destroy(*value_p); + *value_p = nullptr; +} + +/* #GWL_Display.wp_primary_selection_device_manager */ + +static void gwl_registry_wp_primary_selection_device_manager_add( + struct GWL_Display *display, const GWL_RegisteryAdd_Params *params) +{ + display->wp_primary_selection_device_manager = + static_cast( + wl_registry_bind(params->wl_registry, + params->name, + &zwp_primary_selection_device_manager_v1_interface, + 1)); + + gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); +} +static void gwl_registry_wp_primary_selection_device_manager_remove(GWL_Display *display, + void * /*user_data*/, + const bool /*on_exit*/) +{ + struct zwp_primary_selection_device_manager_v1 **value_p = + &display->wp_primary_selection_device_manager; + zwp_primary_selection_device_manager_v1_destroy(*value_p); + *value_p = nullptr; +} + +/** + * Map interfaces to to initialization functions. + * + * \note This list also defines the order interfaces are freed: from last to first, + * so the most fundamental objects such as the compositor are freed last. + */ +static const GWL_RegistryHandler gwl_registry_handlers[] = { + { + &wl_compositor_interface.name, + gwl_registry_compositor_add, + gwl_registry_compositor_remove, + }, + { + &xdg_wm_base_interface.name, + gwl_registry_xdg_wm_base_add, + gwl_registry_xdg_wm_base_remove, + }, + { + &zxdg_decoration_manager_v1_interface.name, + gwl_registry_xdg_decoration_manager_add, + gwl_registry_xdg_decoration_manager_remove, + }, + { + &zxdg_output_manager_v1_interface.name, + gwl_registry_xdg_output_manager_add, + gwl_registry_xdg_output_manager_remove, + }, + { + &wl_output_interface.name, + gwl_registry_wl_output_add, + gwl_registry_wl_output_remove, + }, + { + &wl_seat_interface.name, + gwl_registry_wl_seat_add, + gwl_registry_wl_seat_remove, + }, + { + &wl_shm_interface.name, + gwl_registry_wl_shm_add, + gwl_registry_wl_shm_remove, + }, + { + &wl_data_device_manager_interface.name, + gwl_registry_wl_data_device_manager_add, + gwl_registry_wl_data_device_manager_remove, + }, + { + &zwp_tablet_manager_v2_interface.name, + gwl_registry_wp_tablet_manager_add, + gwl_registry_wp_tablet_manager_remove, + }, + { + &zwp_relative_pointer_manager_v1_interface.name, + gwl_registry_wp_relative_pointer_manager_add, + gwl_registry_wp_relative_pointer_manager_remove, + }, + { + &zwp_pointer_constraints_v1_interface.name, + gwl_registry_wp_pointer_constraints_add, + gwl_registry_wp_pointer_constraints_remove, + }, + { + &zwp_pointer_gestures_v1_interface.name, + gwl_registry_wp_pointer_gestures_add, + gwl_registry_wp_pointer_gestures_remove, + }, + { + &zwp_primary_selection_device_manager_v1_interface.name, + gwl_registry_wp_primary_selection_device_manager_add, + gwl_registry_wp_primary_selection_device_manager_remove, + }, + {nullptr, nullptr, nullptr}, +}; + +/** + * Workaround for `gwl_registry_handlers` order of declaration, + * preventing `ARRAY_SIZE(gwl_registry_handlers) - 1` being used. + */ +static int gwl_registry_handler_interface_slot_max() +{ + return ARRAY_SIZE(gwl_registry_handlers) - 1; +} + +static const GWL_RegistryHandler *gwl_registry_handler_from_interface_slot(int interface_slot) +{ + GHOST_ASSERT(uint32_t(interface_slot) < uint32_t(gwl_registry_handler_interface_slot_max()), + "Index out of range"); + return &gwl_registry_handlers[interface_slot]; +} + +static void global_handle_add(void *data, + struct wl_registry *wl_registry, + const uint32_t name, + const char *interface, + const uint32_t version) +{ + /* Log last since it's useful to know if the interface was handled or not. */ + + GWL_Display *display = static_cast(data); + /* The interface name that is ensured not to be freed. */ + GWL_RegisteryAdd_Params params = { + .wl_registry = wl_registry, + .name = name, + .version = version, + .interface_slot = 0, + }; + + bool found = false, added = false; + for (const GWL_RegistryHandler *handler = gwl_registry_handlers; handler->interface_p != nullptr; + handler++) { + if (!STREQ(interface, *handler->interface_p)) { + continue; + } + const GWL_RegistryEntry *registry_entry_prev = display->registry_entry; + params.interface_slot = int(handler - gwl_registry_handlers); + + handler->add_fn(display, ¶ms); + + added = display->registry_entry != registry_entry_prev; + found = true; + break; + } + + /* Not found. */ + if (!found) { #ifdef USE_GNOME_NEEDS_LIBDECOR_HACK if (STRPREFIX(interface, "gtk_shell")) { /* `gtk_shell1` at time of writing. */ /* Only require `libdecor` when built with X11 support, @@ -4149,7 +4647,7 @@ static void global_handle_add(void *data, CLOG_INFO(LOG, 2, "add %s(interface=%s, version=%u, name=%u)", - found ? "" : "(skipped), ", + found ? (added ? "" : "(found but not added)") : "(skipped), ", interface, version, name); @@ -4164,11 +4662,19 @@ static void global_handle_add(void *data, * name is no longer available. If the client bound to the global * using the bind request, the client should now destroy that object. */ -static void global_handle_remove(void * /*data*/, +static void global_handle_remove(void *data, struct wl_registry * /*wl_registry*/, const uint32_t name) { - CLOG_INFO(LOG, 2, "remove (name=%u)", name); + GWL_Display *display = static_cast(data); + int interface_slot = 0; + bool found = gwl_registry_entry_remove_by_name(display, name, &interface_slot); + CLOG_INFO(LOG, + 2, + "remove (name=%u, interface=%s), %s", + name, + *gwl_registry_handlers[interface_slot].interface_p, + found ? "(known)" : "(unknown)"); } static const struct wl_registry_listener registry_listener = { @@ -4221,7 +4727,7 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background) } if (display_->libdecor_required) { - gwl_xdg_decor_system_destroy(display_->xdg_decor); + gwl_xdg_decor_system_destroy(display_, display_->xdg_decor); display_->xdg_decor = nullptr; if (!has_libdecor) { -- cgit v1.2.3 From c1768507a9b5cd1606f4d8b9f61a46f0015761a4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 25 Oct 2022 13:24:56 +1100 Subject: Correct naming in 97414fb484fe37b8da69a2b570a659535bbf2a0f --- intern/ghost/intern/GHOST_SystemWayland.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 65b4e890d88..ea2975d1c19 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -790,14 +790,14 @@ using GWL_RegistryHandler_AddFn = void (*)(GWL_Display *display, * Otherwise it can be assumed that all objects will be freed and none will be used again, * so there is no need to ensure a valid state. */ -using GWL_RegistryEntry_FreeFn = void (*)(GWL_Display *display, void *user_data, bool on_exit); +using GWL_RegistryEntry_RemoveFn = void (*)(GWL_Display *display, void *user_data, bool on_exit); struct GWL_RegistryHandler { /** Pointer to the name (not the name it's self), needed as the values aren't set on startup. */ const char *const *interface_p = nullptr; GWL_RegistryHandler_AddFn add_fn = nullptr; - GWL_RegistryEntry_FreeFn remove_fn = nullptr; + GWL_RegistryEntry_RemoveFn remove_fn = nullptr; }; /** \} */ -- cgit v1.2.3 From bf0ae05d25eab9e937b2b56ef5a931eb57e09d9d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 13 Oct 2022 11:28:10 +1100 Subject: Fix T82412: Space-mouse not registering (WIN32) Using the 3DConnexion Universal Wireless Receiver on MS-Windows caused a different ID to be reported. While I'm not sure of the cause of this, adding the ID doesn't conflict with other devices and fixes the problem. --- intern/ghost/intern/GHOST_NDOFManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 9e9b9f14c43..5484da82a18 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -302,6 +302,7 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) switch (product_id) { case 0xC62E: /* Plugged in. */ case 0xC62F: /* Wireless. */ + case 0xC658: /* Wireless (3DConnexion Universal Wireless Receiver in WIN32), see T82412. */ { device_type_ = NDOF_SpaceMouseWireless; hid_map_button_num_ = 2; -- cgit v1.2.3 From 71079d49e2f0e6a649e32ad3b2651eb27da75be7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 25 Oct 2022 15:00:02 +1100 Subject: Cleanup: move ghost/wayland local methods after type declarations Also correct prefix naming. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 155 ++++++++++++++-------------- intern/ghost/intern/GHOST_WindowWayland.cpp | 8 +- 2 files changed, 82 insertions(+), 81 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index ea2975d1c19..f565dad3284 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -92,6 +92,7 @@ static void gwl_seat_capability_touch_disable(GWL_Seat *seat); static bool gwl_registry_entry_remove_by_name(GWL_Display *display, uint32_t name, int *r_interface_slot); +static void gwl_registry_entry_remove_all(GWL_Display *display); struct GWL_RegistryHandler; static int gwl_registry_handler_interface_slot_max(); @@ -718,6 +719,30 @@ struct GWL_Seat { uint32_t data_source_serial = 0; }; +static GWL_SeatStatePointer *gwl_seat_state_pointer_active(GWL_Seat *seat) +{ + if (seat->pointer.serial == seat->cursor_source_serial) { + return &seat->pointer; + } + if (seat->tablet.serial == seat->cursor_source_serial) { + return &seat->tablet; + } + return nullptr; +} + +static GWL_SeatStatePointer *gwl_seat_state_pointer_from_cursor_surface( + GWL_Seat *seat, const wl_surface *wl_surface) +{ + if (ghost_wl_surface_own_cursor_pointer(wl_surface)) { + return &seat->pointer; + } + if (ghost_wl_surface_own_cursor_tablet(wl_surface)) { + return &seat->tablet; + } + GHOST_ASSERT(0, "Surface found without pointer/tablet tag"); + return nullptr; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -726,6 +751,9 @@ struct GWL_Seat { struct GWL_RegistryEntry; +/** Check this lock before accessing #GHOST_SystemWayland::clipboard_ from a thread. */ +static std::mutex system_clipboard_mutex; + struct GWL_Display { GHOST_SystemWayland *system = nullptr; @@ -757,6 +785,44 @@ struct GWL_Display { GWL_SimpleBuffer clipboard_primary; }; +static void gwl_display_destroy(GWL_Display *display) +{ + /* Unregister items in reverse order. */ + gwl_registry_entry_remove_all(display); + +#ifdef WITH_GHOST_WAYLAND_LIBDECOR + if (use_libdecor) { + if (display->libdecor) { + gwl_libdecor_system_destroy(display->libdecor); + display->libdecor = nullptr; + } + } + else +#endif + { + if (display->xdg_decor) { + gwl_xdg_decor_system_destroy(display, display->xdg_decor); + display->xdg_decor = nullptr; + } + } + + if (eglGetDisplay) { + ::eglTerminate(eglGetDisplay(EGLNativeDisplayType(display->wl_display))); + } + + if (display->wl_display) { + wl_display_disconnect(display->wl_display); + } + + { + std::lock_guard lock{system_clipboard_mutex}; + gwl_simple_buffer_free_data(&display->clipboard); + gwl_simple_buffer_free_data(&display->clipboard_primary); + } + + delete display; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -937,9 +1003,6 @@ static void gwl_registry_entry_remove_all(GWL_Display *display) static GHOST_WindowManager *window_manager = nullptr; -/** Check this lock before accessing #GHOST_SystemWayland::clipboard_ from a thread. */ -static std::mutex system_clipboard_mutex; - /** * Callback for WAYLAND to run when there is an error. * @@ -957,68 +1020,6 @@ static void ghost_wayland_log_handler(const char *msg, va_list arg) } } -static GWL_SeatStatePointer *seat_state_pointer_active(GWL_Seat *seat) -{ - if (seat->pointer.serial == seat->cursor_source_serial) { - return &seat->pointer; - } - if (seat->tablet.serial == seat->cursor_source_serial) { - return &seat->tablet; - } - return nullptr; -} - -static GWL_SeatStatePointer *seat_state_pointer_from_cursor_surface(GWL_Seat *seat, - const wl_surface *wl_surface) -{ - if (ghost_wl_surface_own_cursor_pointer(wl_surface)) { - return &seat->pointer; - } - if (ghost_wl_surface_own_cursor_tablet(wl_surface)) { - return &seat->tablet; - } - GHOST_ASSERT(0, "Surface found without pointer/tablet tag"); - return nullptr; -} - -static void display_destroy(GWL_Display *display) -{ - /* Unregister items in reverse order. */ - gwl_registry_entry_remove_all(display); - -#ifdef WITH_GHOST_WAYLAND_LIBDECOR - if (use_libdecor) { - if (display->libdecor) { - gwl_libdecor_system_destroy(display->libdecor); - display->libdecor = nullptr; - } - } - else -#endif - { - if (display->xdg_decor) { - gwl_xdg_decor_system_destroy(display, display->xdg_decor); - display->xdg_decor = nullptr; - } - } - - if (eglGetDisplay) { - ::eglTerminate(eglGetDisplay(EGLNativeDisplayType(display->wl_display))); - } - - if (display->wl_display) { - wl_display_disconnect(display->wl_display); - } - - { - std::lock_guard lock{system_clipboard_mutex}; - gwl_simple_buffer_free_data(&display->clipboard); - gwl_simple_buffer_free_data(&display->clipboard_primary); - } - - delete display; -} - static GHOST_TKey xkb_map_gkey(const xkb_keysym_t sym) { @@ -2097,8 +2098,8 @@ static void cursor_surface_handle_enter(void *data, CLOG_INFO(LOG, 2, "handle_enter"); GWL_Seat *seat = static_cast(data); - GWL_SeatStatePointer *seat_state_pointer = seat_state_pointer_from_cursor_surface(seat, - wl_surface); + GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_from_cursor_surface( + seat, wl_surface); const GWL_Output *reg_output = ghost_wl_output_user_data(wl_output); seat_state_pointer->outputs.insert(reg_output); update_cursor_scale(seat->cursor, seat->system->wl_shm(), seat_state_pointer, wl_surface); @@ -2115,8 +2116,8 @@ static void cursor_surface_handle_leave(void *data, CLOG_INFO(LOG, 2, "handle_leave"); GWL_Seat *seat = static_cast(data); - GWL_SeatStatePointer *seat_state_pointer = seat_state_pointer_from_cursor_surface(seat, - wl_surface); + GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_from_cursor_surface( + seat, wl_surface); const GWL_Output *reg_output = ghost_wl_output_user_data(wl_output); seat_state_pointer->outputs.erase(reg_output); update_cursor_scale(seat->cursor, seat->system->wl_shm(), seat_state_pointer, wl_surface); @@ -4701,7 +4702,7 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background) /* Connect to the Wayland server. */ display_->wl_display = wl_display_connect(nullptr); if (!display_->wl_display) { - display_destroy(display_); + gwl_display_destroy(display_); throw std::runtime_error("Wayland: unable to connect to display!"); } @@ -4737,7 +4738,7 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background) "WAYLAND found but libdecor was not, install libdecor for Wayland support, " "falling back to X11\n"); # endif - display_destroy(display_); + gwl_display_destroy(display_); throw std::runtime_error("Wayland: unable to find libdecor!"); use_libdecor = true; @@ -4754,7 +4755,7 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background) GWL_LibDecor_System &decor = *display_->libdecor; decor.context = libdecor_new(display_->wl_display, &libdecor_interface); if (!decor.context) { - display_destroy(display_); + gwl_display_destroy(display_); throw std::runtime_error("Wayland: unable to create window decorations!"); } } @@ -4763,7 +4764,7 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background) { GWL_XDG_Decor_System &decor = *display_->xdg_decor; if (!decor.shell) { - display_destroy(display_); + gwl_display_destroy(display_); throw std::runtime_error("Wayland: unable to access xdg_shell!"); } } @@ -4788,7 +4789,7 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background) GHOST_SystemWayland::~GHOST_SystemWayland() { - display_destroy(display_); + gwl_display_destroy(display_); } GHOST_TSuccess GHOST_SystemWayland::init() @@ -4909,7 +4910,7 @@ GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const return GHOST_kFailure; } GWL_Seat *seat = display_->seats[0]; - GWL_SeatStatePointer *seat_state_pointer = seat_state_pointer_active(seat); + GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_active(seat); if (!seat_state_pointer) { return GHOST_kFailure; } @@ -5049,7 +5050,7 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorPositionClientRelative(const GHOST_ return GHOST_kFailure; } GWL_Seat *seat = display_->seats[0]; - GWL_SeatStatePointer *seat_state_pointer = seat_state_pointer_active(seat); + GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_active(seat); if (!seat_state_pointer || !seat_state_pointer->wl_surface) { return GHOST_kFailure; } @@ -5075,7 +5076,7 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(int32_t &x, int32_t &y) co return GHOST_kFailure; } GWL_Seat *seat = display_->seats[0]; - GWL_SeatStatePointer *seat_state_pointer = seat_state_pointer_active(seat); + GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_active(seat); if (!seat_state_pointer) { return GHOST_kFailure; } diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp index 986e18d7a87..f9d7f5c25e2 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.cpp +++ b/intern/ghost/intern/GHOST_WindowWayland.cpp @@ -53,7 +53,7 @@ struct WGL_LibDecor_Window { bool configured = false; }; -static void wgl_libdecor_window_destroy(WGL_LibDecor_Window *decor) +static void gwl_libdecor_window_destroy(WGL_LibDecor_Window *decor) { libdecor_frame_unref(decor->frame); delete decor; @@ -67,7 +67,7 @@ struct WGL_XDG_Decor_Window { enum zxdg_toplevel_decoration_v1_mode mode = (enum zxdg_toplevel_decoration_v1_mode)0; }; -static void wgl_xdg_decor_window_destroy(WGL_XDG_Decor_Window *decor) +static void gwl_xdg_decor_window_destroy(WGL_XDG_Decor_Window *decor) { if (decor->toplevel_decor) { zxdg_toplevel_decoration_v1_destroy(decor->toplevel_decor); @@ -727,12 +727,12 @@ GHOST_WindowWayland::~GHOST_WindowWayland() #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { - wgl_libdecor_window_destroy(window_->libdecor); + gwl_libdecor_window_destroy(window_->libdecor); } else #endif { - wgl_xdg_decor_window_destroy(window_->xdg_decor); + gwl_xdg_decor_window_destroy(window_->xdg_decor); } /* Clear any pointers to this window. This is needed because there are no guarantees -- cgit v1.2.3 From dd08b490afc9224d700eb08c39a4a1a5aa2317a9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 25 Oct 2022 15:00:03 +1100 Subject: Cleanup: move singleton pointers into the system Avoid top level global pointers, remove the window_manager pointer and move the clipboard mutex along side the clipboard data. Also skip updating window DPI if the window doesn't use the output that changed it's scale. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 32 +++++++++++++++++------------ intern/ghost/intern/GHOST_SystemWayland.h | 4 ++++ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index f565dad3284..60247660a9c 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -751,9 +751,6 @@ static GWL_SeatStatePointer *gwl_seat_state_pointer_from_cursor_surface( struct GWL_RegistryEntry; -/** Check this lock before accessing #GHOST_SystemWayland::clipboard_ from a thread. */ -static std::mutex system_clipboard_mutex; - struct GWL_Display { GHOST_SystemWayland *system = nullptr; @@ -783,6 +780,7 @@ struct GWL_Display { GWL_SimpleBuffer clipboard; GWL_SimpleBuffer clipboard_primary; + std::mutex clipboard_mutex; }; static void gwl_display_destroy(GWL_Display *display) @@ -815,7 +813,7 @@ static void gwl_display_destroy(GWL_Display *display) } { - std::lock_guard lock{system_clipboard_mutex}; + std::lock_guard lock{display->clipboard_mutex}; gwl_simple_buffer_free_data(&display->clipboard); gwl_simple_buffer_free_data(&display->clipboard_primary); } @@ -1001,8 +999,6 @@ static void gwl_registry_entry_remove_all(GWL_Display *display) /** \name Private Utility Functions * \{ */ -static GHOST_WindowManager *window_manager = nullptr; - /** * Callback for WAYLAND to run when there is an error. * @@ -2004,7 +2000,8 @@ static void data_device_handle_selection(void *data, data_offer, mime_receive.c_str(), &seat->data_offer_copy_paste_mutex, &data_len); { - std::lock_guard lock{system_clipboard_mutex}; + std::mutex &clipboard_mutex = system->clipboard_mutex(); + std::lock_guard lock{clipboard_mutex}; GWL_SimpleBuffer *buf = system->clipboard_data(false); gwl_simple_buffer_set_and_take_ownership(buf, data, data_len); } @@ -3581,7 +3578,8 @@ static void primary_selection_device_handle_selection( data_offer, mime_receive.c_str(), &primary->data_offer_mutex, &data_len); { - std::lock_guard lock{system_clipboard_mutex}; + std::mutex &clipboard_mutex = system->clipboard_mutex(); + std::lock_guard lock{clipboard_mutex}; GWL_SimpleBuffer *buf = system->clipboard_data(true); gwl_simple_buffer_set_and_take_ownership(buf, data, data_len); } @@ -4052,11 +4050,17 @@ static void output_handle_done(void *data, struct wl_output * /*wl_output*/) static void output_handle_scale(void *data, struct wl_output * /*wl_output*/, const int32_t factor) { CLOG_INFO(LOG, 2, "scale"); - static_cast(data)->scale = factor; + GWL_Output *output = static_cast(data); + output->scale = factor; + GHOST_WindowManager *window_manager = output->system->getWindowManager(); if (window_manager) { for (GHOST_IWindow *iwin : window_manager->getWindows()) { GHOST_WindowWayland *win = static_cast(iwin); + const std::vector &outputs = win->outputs(); + if (std::find(outputs.begin(), outputs.end(), output) == outputs.cend()) { + continue; + } win->outputs_changed_update_scale(); } } @@ -4235,6 +4239,7 @@ static void gwl_registry_xdg_output_manager_remove(GWL_Display *display, static void gwl_registry_wl_output_add(GWL_Display *display, const GWL_RegisteryAdd_Params *params) { GWL_Output *output = new GWL_Output; + output->system = display->system; output->wl_output = static_cast( wl_registry_bind(params->wl_registry, params->name, &wl_output_interface, 2)); ghost_wl_output_tag(output->wl_output); @@ -5226,10 +5231,6 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title, const GHOST_IWindow *parentWindow) { /* Globally store pointer to window manager. */ - if (!window_manager) { - window_manager = getWindowManager(); - } - GHOST_WindowWayland *window = new GHOST_WindowWayland( this, title, @@ -6020,6 +6021,11 @@ struct GWL_SimpleBuffer *GHOST_SystemWayland::clipboard_data(bool selection) con return selection ? &display_->clipboard_primary : &display_->clipboard; } +struct std::mutex &GHOST_SystemWayland::clipboard_mutex() const +{ + return display_->clipboard_mutex; +} + #ifdef WITH_GHOST_WAYLAND_LIBDECOR bool GHOST_SystemWayland::use_libdecor_runtime() { diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index c27f175002e..7c5459fc461 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -23,6 +23,7 @@ # include #endif +#include #include class GHOST_WindowWayland; @@ -51,6 +52,8 @@ void ghost_wl_dynload_libraries_exit(); #endif struct GWL_Output { + GHOST_SystemWayland *system = nullptr; + struct wl_output *wl_output = nullptr; struct zxdg_output_v1 *xdg_output = nullptr; /** Dimensions in pixels. */ @@ -187,6 +190,7 @@ class GHOST_SystemWayland : public GHOST_System { int scale); struct GWL_SimpleBuffer *clipboard_data(bool selection) const; + struct std::mutex &clipboard_mutex() const; #ifdef WITH_GHOST_WAYLAND_LIBDECOR static bool use_libdecor_runtime(); -- cgit v1.2.3 From 059d9631924366ba66b0cacf50cb5dad95889fe2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 25 Oct 2022 15:25:26 +1100 Subject: GHOST/Wayland: store fractional scaling in each window instead of DPI This makes it possible to access the fractional scaling for a window, there is no need to store the DPI which can be returned by getDPIHint(). --- intern/ghost/intern/GHOST_WindowWayland.cpp | 51 +++++++++++++---------------- intern/ghost/intern/GHOST_WindowWayland.h | 4 ++- 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp index f9d7f5c25e2..edcbcc14a37 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.cpp +++ b/intern/ghost/intern/GHOST_WindowWayland.cpp @@ -90,13 +90,8 @@ struct GWL_Window { /** The scale value written to #wl_surface_set_buffer_scale. */ int scale = 0; - /** - * The DPI, either: - * - `scale * base_dpi` - * - `wl_fixed_to_int(scale_fractional * base_dpi)` - * When fractional scaling is available. - */ - uint32_t dpi = 0; + /** The fractional scale used to calculate the DPI. */ + wl_fixed_t scale_fractional = 0; #ifdef WITH_GHOST_WAYLAND_LIBDECOR WGL_LibDecor_Window *libdecor = nullptr; @@ -147,7 +142,7 @@ static int output_scale_cmp(const GWL_Output *output_a, const GWL_Output *output static int outputs_max_scale_or_default(const std::vector &outputs, const int32_t scale_default, - uint32_t *r_dpi) + wl_fixed_t *r_scale_fractional) { const GWL_Output *output_max = nullptr; for (const GWL_Output *reg_output : outputs) { @@ -157,18 +152,16 @@ static int outputs_max_scale_or_default(const std::vector &outputs } if (output_max) { - if (r_dpi) { - *r_dpi = output_max->has_scale_fractional ? - /* Fractional DPI. */ - wl_fixed_to_int(output_max->scale_fractional * base_dpi) : - /* Simple non-fractional DPI. */ - (output_max->scale * base_dpi); + if (r_scale_fractional) { + *r_scale_fractional = output_max->has_scale_fractional ? + output_max->scale_fractional : + wl_fixed_from_int(output_max->scale); } return output_max->scale; } - if (r_dpi) { - *r_dpi = scale_default * base_dpi; + if (r_scale_fractional) { + *r_scale_fractional = wl_fixed_from_int(scale_default); } return scale_default; } @@ -479,7 +472,7 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system, * * Using the maximum scale is best as it results in the window first being smaller, * avoiding a large window flashing before it's made smaller. */ - window_->scale = outputs_max_scale_or_default(system_->outputs(), 1, &window_->dpi); + window_->scale = outputs_max_scale_or_default(system_->outputs(), 1, &window_->scale_fractional); /* Window surfaces. */ window_->wl_surface = wl_compositor_create_surface(system_->wl_compositor()); @@ -751,7 +744,9 @@ GHOST_WindowWayland::~GHOST_WindowWayland() uint16_t GHOST_WindowWayland::getDPIHint() { - return window_->dpi; + /* Using the physical DPI will cause wrong scaling of the UI + * use a multiplier for the default DPI as a workaround. */ + return wl_fixed_to_int(window_->scale_fractional * base_dpi); } GHOST_TSuccess GHOST_WindowWayland::setWindowCursorVisibility(bool visible) @@ -962,14 +957,14 @@ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType * Expose some members via methods. * \{ */ -uint16_t GHOST_WindowWayland::dpi() const +int GHOST_WindowWayland::scale() const { - return window_->dpi; + return window_->scale; } -int GHOST_WindowWayland::scale() const +wl_fixed_t GHOST_WindowWayland::scale_fractional() const { - return window_->scale; + return window_->scale_fractional; } wl_surface *GHOST_WindowWayland::wl_surface() const @@ -1035,13 +1030,13 @@ GHOST_TSuccess GHOST_WindowWayland::notify_size() */ bool GHOST_WindowWayland::outputs_changed_update_scale() { - uint32_t dpi_next; - const int scale_next = outputs_max_scale_or_default(outputs(), 0, &dpi_next); + wl_fixed_t scale_fractional_next = 0; + const int scale_next = outputs_max_scale_or_default(outputs(), 0, &scale_fractional_next); if (UNLIKELY(scale_next == 0)) { return false; } - const uint32_t dpi_curr = window_->dpi; + const wl_fixed_t scale_fractional_curr = window_->scale_fractional; const int scale_curr = window_->scale; bool changed = false; @@ -1055,10 +1050,8 @@ bool GHOST_WindowWayland::outputs_changed_update_scale() changed = true; } - if (dpi_next != dpi_curr) { - /* Using the real DPI will cause wrong scaling of the UI - * use a multiplier for the default DPI as workaround. */ - window_->dpi = dpi_next; + if (scale_fractional_next != scale_fractional_curr) { + window_->scale_fractional = scale_fractional_next; changed = true; /* As this is a low-level function, we might want adding this event to be optional, diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h index e95f5386310..ec473c4a710 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.h +++ b/intern/ghost/intern/GHOST_WindowWayland.h @@ -12,6 +12,8 @@ #include +#include /* For #wl_fixed_t */ + class GHOST_SystemWayland; struct GWL_Output; @@ -95,8 +97,8 @@ class GHOST_WindowWayland : public GHOST_Window { /* WAYLAND direct-data access. */ - uint16_t dpi() const; int scale() const; + wl_fixed_t scale_fractional() const; struct wl_surface *wl_surface() const; const std::vector &outputs(); -- cgit v1.2.3 From 3e292404d27dc5aaddc2fcca67ceedf7e30d2cbc Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 25 Oct 2022 17:49:14 +1100 Subject: Build: fix/workaround for the opencollada.diff not applying on Linux --- build_files/build_environment/cmake/opencollada.cmake | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/build_files/build_environment/cmake/opencollada.cmake b/build_files/build_environment/cmake/opencollada.cmake index 9473aafbe88..b1a3028debd 100644 --- a/build_files/build_environment/cmake/opencollada.cmake +++ b/build_files/build_environment/cmake/opencollada.cmake @@ -4,6 +4,18 @@ if(UNIX) set(OPENCOLLADA_EXTRA_ARGS -DLIBXML2_INCLUDE_DIR=${LIBDIR}/xml2/include/libxml2 -DLIBXML2_LIBRARIES=${LIBDIR}/xml2/lib/libxml2.a) + + # WARNING: the patch contains mixed UNIX and DOS line endings + # as does the OPENCOLLADA package, if this can be corrected upstream that would be better. + # For now use `sed` to force UNIX line endings so the patch applies. + # Needed as neither ignoring white-space or applying as a binary resolve this problem. + set(PATCH_MAYBE_DOS2UNIX_CMD + sed -i "s/\\r//" + ${PATCH_DIR}/opencollada.diff + ${BUILD_DIR}/opencollada/src/external_opencollada/CMakeLists.txt + ${BUILD_DIR}/opencollada/src/external_opencollada/Externals/LibXML/CMakeLists.txt && + ) + else() set(OPENCOLLADA_EXTRA_ARGS -DCMAKE_DEBUG_POSTFIX=_d @@ -14,6 +26,7 @@ else() else() list(APPEND OPENCOLLADA_EXTRA_ARGS -DLIBXML2_LIBRARIES=${LIBDIR}/xml2/lib/libxml2sd.lib) endif() + set(PATCH_MAYBE_DOS2UNIX_CMD) endif() ExternalProject_Add(external_opencollada @@ -21,11 +34,14 @@ ExternalProject_Add(external_opencollada DOWNLOAD_DIR ${DOWNLOAD_DIR} URL_HASH ${OPENCOLLADA_HASH_TYPE}=${OPENCOLLADA_HASH} PREFIX ${BUILD_DIR}/opencollada - PATCH_COMMAND ${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/opencollada/src/external_opencollada < ${PATCH_DIR}/opencollada.diff + PATCH_COMMAND + ${PATCH_MAYBE_DOS2UNIX_CMD} + ${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/opencollada/src/external_opencollada < ${PATCH_DIR}/opencollada.diff CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/opencollada ${DEFAULT_CMAKE_FLAGS} ${OPENCOLLADA_EXTRA_ARGS} INSTALL_DIR ${LIBDIR}/opencollada ) +unset(PATCH_MAYBE_DOS2UNIX_CMD) add_dependencies( external_opencollada -- cgit v1.2.3 From 7e3e4751b544bce290288de4af8651847d230655 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Tue, 25 Oct 2022 10:15:24 +0200 Subject: UI: Fix count on node editor/group header when fake user The number of node groups was including the fake user count. I was ignoring the Fake User, and how it affects the id->us count. This problem was present since the initial commit: 84825e4ed2e09895. --- source/blender/editors/interface/interface_context_path.cc | 2 +- source/blender/editors/space_node/node_draw.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/interface/interface_context_path.cc b/source/blender/editors/interface/interface_context_path.cc index 91b2f9613de..74a07d6edc8 100644 --- a/source/blender/editors/interface/interface_context_path.cc +++ b/source/blender/editors/interface/interface_context_path.cc @@ -45,7 +45,7 @@ void context_path_add_generic(Vector &path, if (&rna_type == &RNA_NodeTree) { ID *id = (ID *)ptr; - path.append({name, int(icon), id->us}); + path.append({name, int(icon), ID_REAL_USERS(id)}); } else { path.append({name, int(icon), 1}); diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 98b2cacd162..5ae6573df7c 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -2146,7 +2146,7 @@ static void node_draw_basis(const bContext &C, ""); UI_but_func_set(but, node_toggle_button_cb, &node, (void *)"NODE_OT_group_edit"); if (node.id) { - UI_but_icon_indicator_number_set(but, node.id->us); + UI_but_icon_indicator_number_set(but, ID_REAL_USERS(node.id)); } UI_block_emboss_set(&block, UI_EMBOSS); } -- cgit v1.2.3 From c4f9e4afab8c51e271fc6a313ccd2dd0b8d3186c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 25 Oct 2022 20:42:46 +1100 Subject: GHOST/Wayland: swap tablet middle/right mouse buttons There looks to be an inconsistency between Gnome/KDE here, match KDE and Gnome applications under X11 (even XWayland) by making the button closest to the nib MMB, and the other button RMB. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 60247660a9c..f09678374fa 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -174,9 +174,14 @@ static bool use_gnome_confine_hack = false; /** * Tablet events. + * + * \note Gnome/GTK swap middle/right, where the same application in X11 will swap the middle/right + * mouse button when running under WAYLAND. KDE doesn't do this, and according to artists + * at the Blender studio, having the button closest to the nib be MMB is preferable, + * so use this as a default. If needs be - swapping these could be a preference. */ -#define BTN_STYLUS 0x14b /* Use as right-mouse. */ -#define BTN_STYLUS2 0x14c /* Use as middle-mouse. */ +#define BTN_STYLUS 0x14b /* Use as middle-mouse. */ +#define BTN_STYLUS2 0x14c /* Use as right-mouse. */ /* NOTE(@campbellbarton): Map to an additional button (not sure which hardware uses this). */ #define BTN_STYLUS3 0x149 @@ -2969,10 +2974,10 @@ static void tablet_tool_handle_button(void *data, GHOST_TButton ebutton = GHOST_kButtonMaskLeft; switch (button) { case BTN_STYLUS: - ebutton = GHOST_kButtonMaskRight; + ebutton = GHOST_kButtonMaskMiddle; break; case BTN_STYLUS2: - ebutton = GHOST_kButtonMaskMiddle; + ebutton = GHOST_kButtonMaskRight; break; case BTN_STYLUS3: ebutton = GHOST_kButtonMaskButton4; -- cgit v1.2.3 From 78b13ab3db70cca977585e29407445d2d1502fbf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 25 Oct 2022 22:27:12 +1100 Subject: Fix T102048: Tablet cursor remains hidden under KDE/Wayland --- intern/ghost/intern/GHOST_SystemWayland.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index f09678374fa..23f7c5060c0 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -139,6 +139,13 @@ static bool use_gnome_confine_hack = false; */ #define USE_GNOME_KEYBOARD_SUPPRESS_WARNING +/** + * KDE (plasma 5.26.1) has a bug where the cursor surface needs to be committed + * (via `wl_surface_commit`) when it was hidden and is being set to visible again, see: T102048. + * TODO: report this bug up-stream. + */ +#define USE_KDE_TABLET_HIDDEN_CURSOR_HACK + /** * When GNOME is found, require `libdecor`. * This is a hack because it seems there is no way to check if the compositor supports @@ -5297,6 +5304,9 @@ static void cursor_buffer_show(const GWL_Seat *seat) tablet_tool->wl_surface_cursor, hotspot_x, hotspot_y); +#ifdef USE_KDE_TABLET_HIDDEN_CURSOR_HACK + wl_surface_commit(tablet_tool->wl_surface_cursor); +#endif } } } -- cgit v1.2.3 From 2240ca3e7bbf07c1d417f288af3ab3fa2ef68df9 Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Mon, 24 Oct 2022 10:34:54 +0200 Subject: Fix T101933: pick deselecting bones in empty space deactivates armature As a consequence of this, subsequent box-selection of bones would not show correctly in Animation Editors (not showing the channels there because of the lack of an active object). The bug was caused by rBba6d59a85a38. Prior to said commit, code logic was relying on the check for `basact` being NULL to determine if object selection changes need to happen. After that commit, this was handled by a `handled` variable, but this was not set correctly if `basact` is actually NULL after the initial pick (aka deselection by picking). Maniphest Tasks: T101933 Differential Revision: https://developer.blender.org/D16326 --- source/blender/editors/space_view3d/view3d_select.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc index cba85097071..2a84d61c561 100644 --- a/source/blender/editors/space_view3d/view3d_select.cc +++ b/source/blender/editors/space_view3d/view3d_select.cc @@ -2704,7 +2704,10 @@ static bool ed_object_select_pick(bContext *C, /* When there is no `baseact` this will have operated on `oldbasact`, * allowing #SelectPick_Params.deselect_all work in pose-mode. * In this case no object operations are needed. */ - if (basact != nullptr) { + if (basact == nullptr) { + handled = true; + } + else { /* By convention the armature-object is selected when in pose-mode. * While leaving it unselected will work, leaving pose-mode would leave the object * active + unselected which isn't ideal when performing other actions on the object. */ -- cgit v1.2.3 From fb424db2b7bb95a6d917d1aa562609682123274a Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Tue, 25 Oct 2022 12:14:39 +0200 Subject: Fix T99603: node body colors colormanagement issue This led to the color actually looking different on the node body itself vs. in the panel, also using the colorpicker gave unexpected results. UI colors should use PROP_COLOR_GAMMA to avoid being affected by scene color management (clarification by @brecht). Maniphest Tasks: T99603 Differential Revision: https://developer.blender.org/D16334 --- source/blender/makesrna/intern/rna_nodetree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 0b0970a835e..865399df9ef 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -12230,7 +12230,7 @@ static void rna_def_node(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Custom Color", "Use custom color for the node"); RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL); - prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR); + prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Color", "Custom color of the node body"); -- cgit v1.2.3 From ffdb41a8bc4764042a1ee2f91c40bdf594bbdb87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Tue, 25 Oct 2022 10:43:47 +0200 Subject: DRW: Pointcloud: Refactor drawing to remove instancing This change the attribute binding scheme to something similar to the curves objects. Attributes are now buffer textures sampled per points. The actual geometry is now rendered using an index buffer that avoid too many vertex shader invocation. Drawcall is wrapped in a DRW function to reduce complexity of future changes. --- source/blender/draw/CMakeLists.txt | 1 + .../draw/engines/eevee/shaders/shadow_vert.glsl | 2 +- .../draw/engines/eevee/shaders/surface_vert.glsl | 2 +- .../draw/engines/overlay/overlay_outline.cc | 28 +- .../engines/overlay/overlay_viewer_attribute.cc | 14 +- .../shaders/infos/overlay_viewer_attribute_info.hh | 2 +- .../overlay_viewer_attribute_pointcloud_vert.glsl | 2 +- .../draw/engines/workbench/workbench_engine.c | 9 +- .../draw/engines/workbench/workbench_private.h | 5 + source/blender/draw/intern/draw_cache.c | 29 +- source/blender/draw/intern/draw_cache.h | 6 - source/blender/draw/intern/draw_cache_impl.h | 10 +- .../draw/intern/draw_cache_impl_pointcloud.cc | 403 ++++++++++++++------- source/blender/draw/intern/draw_common.h | 8 + source/blender/draw/intern/draw_manager.c | 7 + source/blender/draw/intern/draw_pointcloud.cc | 103 ++++++ .../blender/draw/intern/draw_pointcloud_private.hh | 19 + .../draw/intern/shaders/common_pointcloud_lib.glsl | 78 +++- .../blender/draw/intern/shaders/draw_view_info.hh | 4 +- 19 files changed, 517 insertions(+), 215 deletions(-) create mode 100644 source/blender/draw/intern/draw_pointcloud.cc create mode 100644 source/blender/draw/intern/draw_pointcloud_private.hh diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 1c17f92f073..4010b491141 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -95,6 +95,7 @@ set(SRC intern/draw_manager_text.cc intern/draw_manager_texture.c intern/draw_pbvh.cc + intern/draw_pointcloud.cc intern/draw_select_buffer.c intern/draw_shader.cc intern/draw_texture_pool.cc diff --git a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl index 062a40f35c2..ccf6d6e2042 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl @@ -30,7 +30,7 @@ void main() vec3 world_pos = pos; #elif defined(POINTCLOUD_SHADER) pointcloud_get_pos_and_radius(pointPosition, pointRadius); - pointID = gl_VertexID; + pointID = pointcloud_get_point_id(); #else vec3 world_pos = point_object_to_world(pos); #endif diff --git a/source/blender/draw/engines/eevee/shaders/surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/surface_vert.glsl index 8f49c7bd265..7a22b2c53d7 100644 --- a/source/blender/draw/engines/eevee/shaders/surface_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/surface_vert.glsl @@ -37,7 +37,7 @@ void main() vec3 world_pos = pos; #elif defined(POINTCLOUD_SHADER) pointcloud_get_pos_and_radius(pointPosition, pointRadius); - pointID = gl_VertexID; + pointID = pointcloud_get_point_id(); #else vec3 world_pos = point_object_to_world(pos); #endif diff --git a/source/blender/draw/engines/overlay/overlay_outline.cc b/source/blender/draw/engines/overlay/overlay_outline.cc index 50d42effe00..a091bbe539b 100644 --- a/source/blender/draw/engines/overlay/overlay_outline.cc +++ b/source/blender/draw/engines/overlay/overlay_outline.cc @@ -138,6 +138,7 @@ void OVERLAY_outline_cache_init(OVERLAY_Data *vedata) DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); GPUShader *sh_curves = OVERLAY_shader_outline_prepass_curves(); + pd->outlines_curves_grp = grp = DRW_shgroup_create(sh_curves, psl->outlines_prepass_ps); DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); @@ -282,6 +283,18 @@ static void OVERLAY_outline_curves(OVERLAY_PrivateData *pd, Object *ob) DRW_shgroup_curves_create_sub(ob, shgroup, nullptr); } +static void OVERLAY_outline_pointcloud(OVERLAY_PrivateData *pd, Object *ob) +{ + if (pd->wireframe_mode) { + /* Looks bad in this case. Could be relaxed if we draw a + * wireframe of some sort in the future. */ + return; + } + + DRWShadingGroup *shgroup = pd->outlines_ptcloud_grp; + DRW_shgroup_pointcloud_create_sub(ob, shgroup, nullptr); +} + void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata, Object *ob, OVERLAY_DupliData *dupli, @@ -313,9 +326,8 @@ void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata, return; } - if (ob->type == OB_POINTCLOUD && pd->wireframe_mode) { - /* Looks bad in this case. Could be relaxed if we draw a - * wireframe of some sort in the future. */ + if (ob->type == OB_POINTCLOUD) { + OVERLAY_outline_pointcloud(pd, ob); return; } @@ -338,18 +350,12 @@ void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata, } if (geom) { - shgroup = (ob->type == OB_POINTCLOUD) ? pd->outlines_ptcloud_grp : pd->outlines_grp; + shgroup = pd->outlines_grp; } } if (shgroup && geom) { - if (ob->type == OB_POINTCLOUD) { - /* Draw range to avoid drawcall batching messing up the instance attribute. */ - DRW_shgroup_call_instance_range(shgroup, ob, geom, 0, 0); - } - else { - DRW_shgroup_call(shgroup, geom, ob); - } + DRW_shgroup_call(shgroup, geom, ob); } if (init_dupli) { diff --git a/source/blender/draw/engines/overlay/overlay_viewer_attribute.cc b/source/blender/draw/engines/overlay/overlay_viewer_attribute.cc index d57ea08d888..84bbf2ae351 100644 --- a/source/blender/draw/engines/overlay/overlay_viewer_attribute.cc +++ b/source/blender/draw/engines/overlay/overlay_viewer_attribute.cc @@ -81,11 +81,9 @@ static void populate_cache_for_instance(Object &object, break; } case OB_POINTCLOUD: { - DRWShadingGroup *sub_grp = DRW_shgroup_create_sub( - pd.viewer_attribute_instance_pointcloud_grp); + DRWShadingGroup *sub_grp = DRW_shgroup_pointcloud_create_sub( + &object, pd.viewer_attribute_pointcloud_grp, nullptr); DRW_shgroup_uniform_vec4_copy(sub_grp, "ucolor", color); - GPUBatch *batch = DRW_cache_pointcloud_surface_get(&object); - DRW_shgroup_call_instance_range(sub_grp, &object, batch, 0, 0); break; } case OB_CURVES_LEGACY: { @@ -123,9 +121,11 @@ static void populate_cache_for_geometry(Object &object, case OB_POINTCLOUD: { PointCloud *pointcloud = static_cast(object.data); if (pointcloud->attributes().contains(".viewer")) { - GPUBatch *batch = DRW_cache_pointcloud_surface_viewer_attribute_get(&object); - DRW_shgroup_uniform_float_copy(pd.viewer_attribute_pointcloud_grp, "opacity", opacity); - DRW_shgroup_call_instance_range(pd.viewer_attribute_pointcloud_grp, &object, batch, 0, 0); + GPUVertBuf **vertbuf = DRW_pointcloud_evaluated_attribute(pointcloud, ".viewer"); + DRWShadingGroup *grp = DRW_shgroup_pointcloud_create_sub( + &object, pd.viewer_attribute_pointcloud_grp, nullptr); + DRW_shgroup_uniform_float_copy(grp, "opacity", opacity); + DRW_shgroup_buffer_texture_ref(grp, "attribute_tx", vertbuf); } break; } diff --git a/source/blender/draw/engines/overlay/shaders/infos/overlay_viewer_attribute_info.hh b/source/blender/draw/engines/overlay/shaders/infos/overlay_viewer_attribute_info.hh index 20d4797b76f..6a0bd03f030 100644 --- a/source/blender/draw/engines/overlay/shaders/infos/overlay_viewer_attribute_info.hh +++ b/source/blender/draw/engines/overlay/shaders/infos/overlay_viewer_attribute_info.hh @@ -27,7 +27,7 @@ GPU_SHADER_CREATE_INFO(overlay_viewer_attribute_pointcloud) .fragment_source("overlay_viewer_attribute_frag.glsl") .fragment_out(0, Type::VEC4, "out_color") .fragment_out(1, Type::VEC4, "lineOutput") - .vertex_in(3, Type::VEC4, "attribute_value") + .sampler(3, ImageType::FLOAT_BUFFER, "attribute_tx") .vertex_out(overlay_viewer_attribute_iface) .additional_info("overlay_viewer_attribute_common", "draw_pointcloud"); diff --git a/source/blender/draw/engines/overlay/shaders/overlay_viewer_attribute_pointcloud_vert.glsl b/source/blender/draw/engines/overlay/shaders/overlay_viewer_attribute_pointcloud_vert.glsl index e706e8f9033..e7b7cafd898 100644 --- a/source/blender/draw/engines/overlay/shaders/overlay_viewer_attribute_pointcloud_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/overlay_viewer_attribute_pointcloud_vert.glsl @@ -6,5 +6,5 @@ void main() { vec3 world_pos = pointcloud_get_pos(); gl_Position = point_world_to_ndc(world_pos); - finalColor = attribute_value; + finalColor = pointcloud_get_customdata_vec4(attribute_tx); } diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c index fecdad5802c..8dbddb4265d 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.c +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -27,6 +27,7 @@ #include "DNA_mesh_types.h" #include "DNA_modifier_types.h" #include "DNA_node_types.h" +#include "DNA_pointcloud_types.h" #include "ED_paint.h" @@ -418,7 +419,7 @@ void workbench_cache_populate(void *ved, Object *ob) return; } - if (ELEM(ob->type, OB_MESH, OB_POINTCLOUD)) { + if (ob->type == OB_MESH) { bool use_sculpt_pbvh, use_texpaint_mode, draw_shadow, has_transp_mat = false; eV3DShadingColorType color_type = workbench_color_type_get( wpd, ob, &use_sculpt_pbvh, &use_texpaint_mode, &draw_shadow); @@ -442,6 +443,12 @@ void workbench_cache_populate(void *ved, Object *ob) DRWShadingGroup *grp = workbench_material_hair_setup(wpd, ob, CURVES_MATERIAL_NR, color_type); DRW_shgroup_curves_create_sub(ob, grp, NULL); } + else if (ob->type == OB_POINTCLOUD) { + int color_type = workbench_color_type_get(wpd, ob, NULL, NULL, NULL); + DRWShadingGroup *grp = workbench_material_ptcloud_setup( + wpd, ob, POINTCLOUD_MATERIAL_NR, color_type); + DRW_shgroup_pointcloud_create_sub(ob, grp, NULL); + } else if (ob->type == OB_VOLUME) { if (wpd->shading.type != OB_WIRE) { int color_type = workbench_color_type_get(wpd, ob, NULL, NULL, NULL); diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 492bce1e571..4aedaf443b9 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -511,6 +511,11 @@ DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd, #define workbench_image_hair_setup(wpd, ob, mat_nr, ima, iuser, interp) \ workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, interp, WORKBENCH_DATATYPE_HAIR) +#define workbench_material_ptcloud_setup(wpd, ob, mat_nr, color_type) \ + workbench_material_setup_ex(wpd, ob, mat_nr, color_type, WORKBENCH_DATATYPE_POINTCLOUD, 0) +#define workbench_image_ptcloud_setup(wpd, ob, mat_nr, ima, iuser, interp) \ + workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, interp, WORKBENCH_DATATYPE_POINTCLOUD) + /* workbench_data.c */ void workbench_private_data_alloc(WORKBENCH_StorageList *stl); diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 8c6a51442e1..00ac2563c43 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -899,8 +899,6 @@ GPUBatch *DRW_cache_object_surface_get(Object *ob) switch (ob->type) { case OB_MESH: return DRW_cache_mesh_surface_get(ob); - case OB_POINTCLOUD: - return DRW_cache_pointcloud_surface_get(ob); default: return NULL; } @@ -959,8 +957,6 @@ GPUBatch **DRW_cache_object_surface_material_get(struct Object *ob, switch (ob->type) { case OB_MESH: return DRW_cache_mesh_surface_shaded_get(ob, gpumat_array, gpumat_array_len); - case OB_POINTCLOUD: - return DRW_cache_pointcloud_surface_shaded_get(ob, gpumat_array, gpumat_array_len); default: return NULL; } @@ -3006,24 +3002,6 @@ GPUBatch *DRW_cache_lattice_vert_overlay_get(Object *ob) /** \name PointCloud * \{ */ -GPUBatch *DRW_cache_pointcloud_get_dots(Object *object) -{ - BLI_assert(object->type == OB_POINTCLOUD); - return DRW_pointcloud_batch_cache_get_dots(object); -} - -GPUBatch *DRW_cache_pointcloud_surface_get(Object *object) -{ - BLI_assert(object->type == OB_POINTCLOUD); - return DRW_pointcloud_batch_cache_get_surface(object); -} - -GPUBatch *DRW_cache_pointcloud_surface_viewer_attribute_get(Object *object) -{ - BLI_assert(object->type == OB_POINTCLOUD); - return DRW_pointcloud_batch_cache_get_surface_viewer_attribute(object); -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -3308,6 +3286,9 @@ void drw_batch_cache_generate_requested(Object *ob) case OB_CURVES: DRW_curves_batch_cache_create_requested(ob); break; + case OB_POINTCLOUD: + DRW_pointcloud_batch_cache_create_requested(ob); + break; /* TODO: all cases. */ default: break; @@ -3358,7 +3339,9 @@ void DRW_batch_cache_free_old(Object *ob, int ctime) case OB_CURVES: DRW_curves_batch_cache_free_old((Curves *)ob->data, ctime); break; - /* TODO: all cases. */ + case OB_POINTCLOUD: + DRW_pointcloud_batch_cache_free_old((PointCloud *)ob->data, ctime); + break; default: break; } diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 45154b41670..772cf3b12a5 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -225,12 +225,6 @@ struct GPUBatch **DRW_cache_curves_surface_shaded_get(struct Object *ob, struct GPUBatch *DRW_cache_curves_face_wireframe_get(struct Object *ob); struct GPUBatch *DRW_cache_curves_edge_detection_get(struct Object *ob, bool *r_is_manifold); -/* PointCloud */ - -struct GPUBatch *DRW_cache_pointcloud_get_dots(struct Object *obj); -struct GPUBatch *DRW_cache_pointcloud_surface_get(struct Object *obj); -struct GPUBatch *DRW_cache_pointcloud_surface_viewer_attribute_get(struct Object *obj); - /* Volume */ typedef struct DRWVolumeGrid { diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index c6e8539121f..e9b1b4c7d16 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -80,6 +80,7 @@ void DRW_batch_cache_free_old(struct Object *ob, int ctime); */ void DRW_mesh_batch_cache_free_old(struct Mesh *me, int ctime); void DRW_curves_batch_cache_free_old(struct Curves *curves, int ctime); +void DRW_pointcloud_batch_cache_free_old(struct PointCloud *pointcloud, int ctime); /** \} */ @@ -147,12 +148,11 @@ void DRW_curves_batch_cache_create_requested(struct Object *ob); int DRW_pointcloud_material_count_get(struct PointCloud *pointcloud); +struct GPUVertBuf **DRW_pointcloud_evaluated_attribute(struct PointCloud *pointcloud, + const char *name); struct GPUBatch *DRW_pointcloud_batch_cache_get_dots(struct Object *ob); -struct GPUBatch *DRW_pointcloud_batch_cache_get_surface(struct Object *ob); -struct GPUBatch *DRW_pointcloud_batch_cache_get_surface_viewer_attribute(struct Object *ob); -struct GPUBatch **DRW_cache_pointcloud_surface_shaded_get(struct Object *ob, - struct GPUMaterial **gpumat_array, - uint gpumat_array_len); + +void DRW_pointcloud_batch_cache_create_requested(struct Object *ob); /** \} */ diff --git a/source/blender/draw/intern/draw_cache_impl_pointcloud.cc b/source/blender/draw/intern/draw_cache_impl_pointcloud.cc index 98531637e57..d64fc581942 100644 --- a/source/blender/draw/intern/draw_cache_impl_pointcloud.cc +++ b/source/blender/draw/intern/draw_cache_impl_pointcloud.cc @@ -23,30 +23,64 @@ #include "BKE_pointcloud.h" #include "GPU_batch.h" +#include "GPU_material.h" -#include "draw_cache_impl.h" /* own include */ +#include "draw_attributes.h" +#include "draw_cache_impl.h" +#include "draw_cache_inline.h" +#include "draw_pointcloud_private.hh" /* own include */ -/* ---------------------------------------------------------------------- */ -/* PointCloud GPUBatch Cache */ +using namespace blender; -struct PointCloudBatchCache { - GPUVertBuf *pos; /* Position and radius. */ - GPUVertBuf *geom; /* Instanced geometry for each point in the cloud (small sphere). */ - GPUVertBuf *attr_viewer; - GPUIndexBuf *geom_indices; +/** \} */ +/* -------------------------------------------------------------------- */ +/** \name GPUBatch cache management + * \{ */ + +struct PointCloudBatchCache { + /* Dot primitive types. */ GPUBatch *dots; + /* Triangle primitive types. */ GPUBatch *surface; GPUBatch **surface_per_mat; - GPUBatch *surface_viewer_attribute; + /* Triangles indices to draw the points. */ + GPUIndexBuf *geom_indices; + + /* Position and radius. */ + GPUVertBuf *pos_rad; + /* Active attribute in 3D view. */ + GPUVertBuf *attr_viewer; + /* Requested attributes */ + GPUVertBuf *attributes_buf[GPU_MAX_ATTR]; + + /** Attributes currently being drawn or about to be drawn. */ + DRW_Attributes attr_used; + /** + * Attributes that were used at some point. This is used for garbage collection, to remove + * attributes that are not used in shaders anymore due to user edits. + */ + DRW_Attributes attr_used_over_time; + + /** + * The last time in seconds that the `attr_used` and `attr_used_over_time` were exactly the same. + * If the delta between this time and the current scene time is greater than the timeout set in + * user preferences (`U.vbotimeout`) then garbage collection is performed. + */ + int last_attr_matching_time; /* settings to determine if cache is invalid */ bool is_dirty; int mat_len; -}; -/* GPUBatch cache management. */ + /** + * The draw cache extraction is currently not multi-threaded for multiple objects, but if it was, + * some locking would be necessary because multiple objects can use the same object data with + * different materials, etc. This is a placeholder to make multi-threading easier in the future. + */ + std::mutex render_mutex; +}; static PointCloudBatchCache *pointcloud_batch_cache_get(PointCloud &pointcloud) { @@ -71,7 +105,7 @@ static void pointcloud_batch_cache_init(PointCloud &pointcloud) PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud); if (!cache) { - cache = MEM_cnew(__func__); + cache = MEM_new(__func__); pointcloud.batch_cache = cache; } else { @@ -100,6 +134,15 @@ void DRW_pointcloud_batch_cache_dirty_tag(PointCloud *pointcloud, int mode) } } +static void pointcloud_discard_attributes(PointCloudBatchCache &cache) +{ + for (const int j : IndexRange(GPU_MAX_ATTR)) { + GPU_VERTBUF_DISCARD_SAFE(cache.attributes_buf[j]); + } + + drw_attributes_clear(&cache.attr_used); +} + static void pointcloud_batch_cache_clear(PointCloud &pointcloud) { PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud); @@ -109,8 +152,7 @@ static void pointcloud_batch_cache_clear(PointCloud &pointcloud) GPU_BATCH_DISCARD_SAFE(cache->dots); GPU_BATCH_DISCARD_SAFE(cache->surface); - GPU_VERTBUF_DISCARD_SAFE(cache->pos); - GPU_VERTBUF_DISCARD_SAFE(cache->geom); + GPU_VERTBUF_DISCARD_SAFE(cache->pos_rad); GPU_VERTBUF_DISCARD_SAFE(cache->attr_viewer); GPU_INDEXBUF_DISCARD_SAFE(cache->geom_indices); @@ -119,8 +161,9 @@ static void pointcloud_batch_cache_clear(PointCloud &pointcloud) GPU_BATCH_DISCARD_SAFE(cache->surface_per_mat[i]); } } - GPU_BATCH_DISCARD_SAFE(cache->surface_viewer_attribute); MEM_SAFE_FREE(cache->surface_per_mat); + + pointcloud_discard_attributes(*cache); } void DRW_pointcloud_batch_cache_validate(PointCloud *pointcloud) @@ -137,61 +180,35 @@ void DRW_pointcloud_batch_cache_free(PointCloud *pointcloud) MEM_SAFE_FREE(pointcloud->batch_cache); } -static void pointcloud_batch_cache_ensure_pos(const PointCloud &pointcloud, - PointCloudBatchCache &cache) +void DRW_pointcloud_batch_cache_free_old(PointCloud *pointcloud, int ctime) { - using namespace blender; - if (cache.pos != nullptr) { + PointCloudBatchCache *cache = pointcloud_batch_cache_get(*pointcloud); + if (!cache) { return; } - const bke::AttributeAccessor attributes = pointcloud.attributes(); - const VArraySpan positions = attributes.lookup("position", ATTR_DOMAIN_POINT); - const VArray radii = attributes.lookup("radius", ATTR_DOMAIN_POINT); - /* From the opengl wiki: - * Note that size does not have to exactly match the size used by the vertex shader. If the - * vertex shader has fewer components than the attribute provides, then the extras are ignored. - * If the vertex shader has more components than the array provides, the extras are given - * values from the vector (0, 0, 0, 1) for the missing XYZW components. */ - if (radii) { - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - } - cache.pos = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(cache.pos, positions.size()); - const VArraySpan radii_span(radii); - MutableSpan vbo_data{static_cast(GPU_vertbuf_get_data(cache.pos)), - pointcloud.totpoint}; - threading::parallel_for(vbo_data.index_range(), 4096, [&](IndexRange range) { - for (const int i : range) { - vbo_data[i].x = positions[i].x; - vbo_data[i].y = positions[i].y; - vbo_data[i].z = positions[i].z; - /* TODO(fclem): remove multiplication. Here only for keeping the size correct for now. */ - vbo_data[i].w = radii_span[i] * 100.0f; - } - }); + bool do_discard = false; + + if (drw_attributes_overlap(&cache->attr_used_over_time, &cache->attr_used)) { + cache->last_attr_matching_time = ctime; } - else { - static GPUVertFormat format = {0}; - static uint pos; - if (format.attr_len == 0) { - pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - } - cache.pos = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(cache.pos, positions.size()); - GPU_vertbuf_attr_fill(cache.pos, pos, positions.data()); + + if (ctime - cache->last_attr_matching_time > U.vbotimeout) { + do_discard = true; + } + + drw_attributes_clear(&cache->attr_used_over_time); + + if (do_discard) { + pointcloud_discard_attributes(*cache); } } -static const float half_octahedron_normals[5][3] = { - {0.0f, 0.0f, 1.0f}, - {1.0f, 0.0f, 0.0f}, - {0.0f, 1.0f, 0.0f}, - {-1.0f, 0.0f, 0.0f}, - {0.0f, -1.0f, 0.0f}, -}; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name PointCloud extraction + * \{ */ static const uint half_octahedron_tris[4][3] = { {0, 1, 2}, @@ -200,130 +217,236 @@ static const uint half_octahedron_tris[4][3] = { {0, 4, 1}, }; -static void pointcloud_batch_cache_ensure_geom(PointCloudBatchCache &cache) +static void pointcloud_extract_indices(const PointCloud &pointcloud, PointCloudBatchCache &cache) { - if (cache.geom != nullptr) { - return; + /** \note: Avoid modulo by non-power-of-two in shader. */ + uint32_t vertid_max = pointcloud.totpoint * 32; + uint32_t index_len = pointcloud.totpoint * ARRAY_SIZE(half_octahedron_tris); + + GPUIndexBufBuilder builder; + GPU_indexbuf_init(&builder, GPU_PRIM_TRIS, index_len, vertid_max); + + for (int p = 0; p < pointcloud.totpoint; p++) { + for (int i = 0; i < ARRAY_SIZE(half_octahedron_tris); i++) { + GPU_indexbuf_add_tri_verts(&builder, + half_octahedron_tris[i][0] + p * 32, + half_octahedron_tris[i][1] + p * 32, + half_octahedron_tris[i][2] + p * 32); + } } + GPU_indexbuf_build_in_place(&builder, cache.geom_indices); +} + +static void pointcloud_extract_position_and_radius(const PointCloud &pointcloud, + PointCloudBatchCache &cache) +{ + using namespace blender; + + const bke::AttributeAccessor attributes = pointcloud.attributes(); + const VArraySpan positions = attributes.lookup("position", ATTR_DOMAIN_POINT); + const VArray radii = attributes.lookup("radius", ATTR_DOMAIN_POINT); static GPUVertFormat format = {0}; - static uint pos; if (format.attr_len == 0) { - pos = GPU_vertformat_attr_add(&format, "pos_inst", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - GPU_vertformat_alias_add(&format, "nor"); + GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); } - cache.geom = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(cache.geom, ARRAY_SIZE(half_octahedron_normals)); - - GPU_vertbuf_attr_fill(cache.geom, pos, half_octahedron_normals); - - GPUIndexBufBuilder builder; - GPU_indexbuf_init(&builder, - GPU_PRIM_TRIS, - ARRAY_SIZE(half_octahedron_tris), - ARRAY_SIZE(half_octahedron_normals)); + GPUUsageType usage_flag = GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY; + GPU_vertbuf_init_with_format_ex(cache.pos_rad, &format, usage_flag); - for (int i = 0; i < ARRAY_SIZE(half_octahedron_tris); i++) { - GPU_indexbuf_add_tri_verts(&builder, UNPACK3(half_octahedron_tris[i])); + GPU_vertbuf_data_alloc(cache.pos_rad, positions.size()); + MutableSpan vbo_data{static_cast(GPU_vertbuf_get_data(cache.pos_rad)), + pointcloud.totpoint}; + if (radii) { + const VArraySpan radii_span(radii); + threading::parallel_for(vbo_data.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + vbo_data[i].x = positions[i].x; + vbo_data[i].y = positions[i].y; + vbo_data[i].z = positions[i].z; + /* TODO(fclem): remove multiplication. Here only for keeping the size correct for now. */ + vbo_data[i].w = radii_span[i] * 100.0f; + } + }); + } + else { + threading::parallel_for(vbo_data.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + vbo_data[i].x = positions[i].x; + vbo_data[i].y = positions[i].y; + vbo_data[i].z = positions[i].z; + vbo_data[i].w = 1.0f; + } + }); } - - cache.geom_indices = GPU_indexbuf_build(&builder); } -static void pointcloud_batch_cache_ensure_attribute_overlay(const PointCloud &pointcloud, - PointCloudBatchCache &cache) +static void pointcloud_extract_attribute(const PointCloud &pointcloud, + PointCloudBatchCache &cache, + const DRW_AttributeRequest &request, + int index) { using namespace blender; - if (cache.attr_viewer != nullptr) { - return; - } + + GPUVertBuf *&attr_buf = cache.attributes_buf[index]; const bke::AttributeAccessor attributes = pointcloud.attributes(); - const VArray colors = attributes.lookup_or_default( - ".viewer", ATTR_DOMAIN_POINT, {1.0f, 0.0f, 1.0f, 1.0f}); + + /* TODO(@kevindietrich): float4 is used for scalar attributes as the implicit conversion done + * by OpenGL to vec4 for a scalar `s` will produce a `vec4(s, 0, 0, 1)`. However, following + * the Blender convention, it should be `vec4(s, s, s, 1)`. This could be resolved using a + * similar texture state swizzle to map the attribute correctly as for volume attributes, so we + * can control the conversion ourselves. */ + VArray attribute = attributes.lookup_or_default( + request.attribute_name, request.domain, {0.0f, 0.0f, 0.0f, 1.0f}); static GPUVertFormat format = {0}; if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "attribute_value", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + GPU_vertformat_attr_add(&format, "attr", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); } - cache.attr_viewer = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(cache.attr_viewer, pointcloud.totpoint); + GPUUsageType usage_flag = GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY; + GPU_vertbuf_init_with_format_ex(attr_buf, &format, usage_flag); + GPU_vertbuf_data_alloc(attr_buf, pointcloud.totpoint); + MutableSpan vbo_data{ - static_cast(GPU_vertbuf_get_data(cache.attr_viewer)), - pointcloud.totpoint}; - colors.materialize(vbo_data); + static_cast(GPU_vertbuf_get_data(attr_buf)), pointcloud.totpoint}; + attribute.materialize(vbo_data); } -GPUBatch *DRW_pointcloud_batch_cache_get_dots(Object *ob) -{ - PointCloud &pointcloud = *static_cast(ob->data); - PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud); +/** \} */ - if (cache->dots == nullptr) { - pointcloud_batch_cache_ensure_pos(pointcloud, *cache); - cache->dots = GPU_batch_create(GPU_PRIM_POINTS, cache->pos, nullptr); - } +/* -------------------------------------------------------------------- */ +/** \name Private API + * \{ */ - return cache->dots; +GPUVertBuf *pointcloud_position_and_radius_get(PointCloud *pointcloud) +{ + PointCloudBatchCache *cache = pointcloud_batch_cache_get(*pointcloud); + DRW_vbo_request(nullptr, &cache->pos_rad); + return cache->pos_rad; } -GPUBatch *DRW_pointcloud_batch_cache_get_surface(Object *ob) +GPUBatch **pointcloud_surface_shaded_get(PointCloud *pointcloud, + GPUMaterial **gpu_materials, + int mat_len) { - PointCloud &pointcloud = *static_cast(ob->data); - PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud); + PointCloudBatchCache *cache = pointcloud_batch_cache_get(*pointcloud); + DRW_Attributes attrs_needed; + drw_attributes_clear(&attrs_needed); + + for (GPUMaterial *gpu_material : Span(gpu_materials, mat_len)) { + ListBase gpu_attrs = GPU_material_attributes(gpu_material); + LISTBASE_FOREACH (GPUMaterialAttribute *, gpu_attr, &gpu_attrs) { + const char *name = gpu_attr->name; + + int layer_index; + eCustomDataType type; + eAttrDomain domain = ATTR_DOMAIN_POINT; + if (!drw_custom_data_match_attribute(&pointcloud->pdata, name, &layer_index, &type)) { + continue; + } - if (cache->surface == nullptr) { - pointcloud_batch_cache_ensure_pos(pointcloud, *cache); - pointcloud_batch_cache_ensure_geom(*cache); + drw_attributes_add_request(&attrs_needed, name, type, layer_index, domain); + } + } - cache->surface = GPU_batch_create(GPU_PRIM_TRIS, cache->geom, cache->geom_indices); - GPU_batch_instbuf_add_ex(cache->surface, cache->pos, false); + if (!drw_attributes_overlap(&cache->attr_used, &attrs_needed)) { + /* Some new attributes have been added, free all and start over. */ + for (const int i : IndexRange(GPU_MAX_ATTR)) { + GPU_VERTBUF_DISCARD_SAFE(cache->attributes_buf[i]); + } + drw_attributes_merge(&cache->attr_used, &attrs_needed, cache->render_mutex); } + drw_attributes_merge(&cache->attr_used_over_time, &attrs_needed, cache->render_mutex); + + DRW_batch_request(&cache->surface_per_mat[0]); + return cache->surface_per_mat; +} - return cache->surface; +GPUBatch *pointcloud_surface_get(PointCloud *pointcloud) +{ + PointCloudBatchCache *cache = pointcloud_batch_cache_get(*pointcloud); + return DRW_batch_request(&cache->surface); } -GPUBatch *DRW_pointcloud_batch_cache_get_surface_viewer_attribute(Object *ob) +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name API + * \{ */ + +GPUBatch *DRW_pointcloud_batch_cache_get_dots(Object *ob) { PointCloud &pointcloud = *static_cast(ob->data); PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud); + return DRW_batch_request(&cache->dots); +} - if (cache->surface_viewer_attribute == nullptr) { - pointcloud_batch_cache_ensure_pos(pointcloud, *cache); - pointcloud_batch_cache_ensure_geom(*cache); - pointcloud_batch_cache_ensure_attribute_overlay(pointcloud, *cache); +GPUVertBuf **DRW_pointcloud_evaluated_attribute(PointCloud *pointcloud, const char *name) +{ + PointCloudBatchCache &cache = *pointcloud_batch_cache_get(*pointcloud); + + int layer_index; + eCustomDataType type; + eAttrDomain domain = ATTR_DOMAIN_POINT; + if (drw_custom_data_match_attribute(&pointcloud->pdata, name, &layer_index, &type)) { + DRW_Attributes attributes{}; + drw_attributes_add_request(&attributes, name, type, layer_index, domain); + drw_attributes_merge(&cache.attr_used, &attributes, cache.render_mutex); + } - cache->surface_viewer_attribute = GPU_batch_create( - GPU_PRIM_TRIS, cache->geom, cache->geom_indices); - GPU_batch_instbuf_add_ex(cache->surface_viewer_attribute, cache->attr_viewer, false); - GPU_batch_instbuf_add_ex(cache->surface_viewer_attribute, cache->pos, false); + int request_i = -1; + for (const int i : IndexRange(cache.attr_used.num_requests)) { + if (STREQ(cache.attr_used.requests[i].attribute_name, name)) { + request_i = i; + break; + } + } + if (request_i == -1) { + return nullptr; } + return &cache.attributes_buf[request_i]; +} - return cache->surface_viewer_attribute; +int DRW_pointcloud_material_count_get(PointCloud *pointcloud) +{ + return max_ii(1, pointcloud->totcol); } -GPUBatch **DRW_cache_pointcloud_surface_shaded_get(Object *ob, - struct GPUMaterial ** /*gpumat_array*/, - uint gpumat_array_len) +void DRW_pointcloud_batch_cache_create_requested(Object *ob) { - PointCloud &pointcloud = *static_cast(ob->data); - PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud); - BLI_assert(cache->mat_len == gpumat_array_len); - UNUSED_VARS(gpumat_array_len); + PointCloud *pointcloud = static_cast(ob->data); + PointCloudBatchCache &cache = *pointcloud_batch_cache_get(*pointcloud); - if (cache->surface_per_mat[0] == nullptr) { - pointcloud_batch_cache_ensure_pos(pointcloud, *cache); - pointcloud_batch_cache_ensure_geom(*cache); + if (DRW_batch_requested(cache.dots, GPU_PRIM_POINTS)) { + DRW_vbo_request(cache.dots, &cache.pos_rad); + } - cache->surface_per_mat[0] = GPU_batch_create(GPU_PRIM_TRIS, cache->geom, cache->geom_indices); - GPU_batch_instbuf_add_ex(cache->surface_per_mat[0], cache->pos, false); + if (DRW_batch_requested(cache.surface, GPU_PRIM_TRIS)) { + DRW_ibo_request(cache.surface, &cache.geom_indices); + DRW_vbo_request(cache.surface, &cache.pos_rad); + } + for (int i = 0; i < cache.mat_len; i++) { + if (DRW_batch_requested(cache.surface_per_mat[i], GPU_PRIM_TRIS)) { + /* TODO(fclem): Per material ranges. */ + DRW_ibo_request(cache.surface_per_mat[i], &cache.geom_indices); + } } + for (int j = 0; j < cache.attr_used.num_requests; j++) { + DRW_vbo_request(nullptr, &cache.attributes_buf[j]); - return cache->surface_per_mat; -} + if (DRW_vbo_requested(cache.attributes_buf[j])) { + pointcloud_extract_attribute(*pointcloud, cache, cache.attr_used.requests[j], j); + } + } -int DRW_pointcloud_material_count_get(PointCloud *pointcloud) -{ - return max_ii(1, pointcloud->totcol); + if (DRW_ibo_requested(cache.geom_indices)) { + pointcloud_extract_indices(*pointcloud, cache); + } + + if (DRW_vbo_requested(cache.pos_rad)) { + pointcloud_extract_position_and_radius(*pointcloud, cache); + } } + +/** \} */ diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index b5e9b3ee8bd..07d245e7dfe 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -88,6 +88,14 @@ void DRW_curves_ubos_pool_free(struct CurvesUniformBufPool *pool); void DRW_curves_update(void); void DRW_curves_free(void); +/* draw_pointcloud.cc */ + +struct DRWShadingGroup *DRW_shgroup_pointcloud_create_sub(struct Object *object, + struct DRWShadingGroup *shgrp_parent, + struct GPUMaterial *gpu_material); +void DRW_pointcloud_init(void); +void DRW_pointcloud_free(void); + /* draw_volume.cc */ /** diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index b9a9780e651..d0290426af3 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1690,6 +1690,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, DRW_globals_update(); drw_debug_init(); + DRW_pointcloud_init(); DRW_curves_init(DST.vmempool); DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); @@ -2053,6 +2054,7 @@ void DRW_render_object_iter( void (*callback)(void *vedata, Object *ob, RenderEngine *engine, struct Depsgraph *depsgraph)) { const DRWContextState *draw_ctx = DRW_context_state_get(); + DRW_pointcloud_init(); DRW_curves_init(DST.vmempool); DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); @@ -2113,6 +2115,7 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type, drw_manager_init(&DST, NULL, NULL); + DRW_pointcloud_init(); DRW_curves_init(DST.vmempool); DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); @@ -2148,6 +2151,7 @@ void DRW_cache_restart(void) DST.buffer_finish_called = false; + DRW_pointcloud_init(); DRW_curves_init(DST.vmempool); DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); @@ -2473,6 +2477,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, /* Init engines */ drw_engines_init(); + DRW_pointcloud_init(); DRW_curves_init(DST.vmempool); DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); @@ -2654,6 +2659,7 @@ void DRW_draw_depth_loop(struct Depsgraph *depsgraph, /* Init engines */ drw_engines_init(); + DRW_pointcloud_init(); DRW_curves_init(DST.vmempool); DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); @@ -3068,6 +3074,7 @@ void DRW_engines_free(void) GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_depth_only); DRW_shaders_free(); + DRW_pointcloud_free(); DRW_curves_free(); DRW_volume_free(); DRW_shape_cache_free(); diff --git a/source/blender/draw/intern/draw_pointcloud.cc b/source/blender/draw/intern/draw_pointcloud.cc new file mode 100644 index 00000000000..cf46e53129a --- /dev/null +++ b/source/blender/draw/intern/draw_pointcloud.cc @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2017 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup draw + * + * \brief Contains procedural GPU hair drawing methods. + */ + +#include "BLI_string_utils.h" +#include "BLI_utildefines.h" + +#include "DNA_customdata_types.h" +#include "DNA_pointcloud_types.h" + +#include "BKE_curves.hh" +#include "BKE_geometry_set.hh" + +#include "GPU_batch.h" +#include "GPU_capabilities.h" +#include "GPU_compute.h" +#include "GPU_material.h" +#include "GPU_shader.h" +#include "GPU_texture.h" +#include "GPU_vertex_buffer.h" + +#include "DRW_gpu_wrapper.hh" +#include "DRW_render.h" + +#include "draw_attributes.h" +#include "draw_cache_impl.h" +#include "draw_common.h" +#include "draw_manager.h" +#include "draw_pointcloud_private.hh" + +static GPUVertBuf *g_dummy_vbo = nullptr; + +void DRW_pointcloud_init() +{ + if (g_dummy_vbo == nullptr) { + /* initialize vertex format */ + GPUVertFormat format = {0}; + uint dummy_id = GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + + g_dummy_vbo = GPU_vertbuf_create_with_format_ex( + &format, GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY); + + const float vert[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_vertbuf_data_alloc(g_dummy_vbo, 1); + GPU_vertbuf_attr_fill(g_dummy_vbo, dummy_id, vert); + } +} + +DRWShadingGroup *DRW_shgroup_pointcloud_create_sub(Object *object, + DRWShadingGroup *shgrp_parent, + GPUMaterial *gpu_material) +{ + PointCloud &pointcloud = *static_cast(object->data); + + DRWShadingGroup *shgrp = DRW_shgroup_create_sub(shgrp_parent); + + /* Fix issue with certain driver not drawing anything if there is no texture bound to + * "ac", "au", "u" or "c". */ + DRW_shgroup_buffer_texture(shgrp, "u", g_dummy_vbo); + DRW_shgroup_buffer_texture(shgrp, "au", g_dummy_vbo); + DRW_shgroup_buffer_texture(shgrp, "c", g_dummy_vbo); + DRW_shgroup_buffer_texture(shgrp, "ac", g_dummy_vbo); + + GPUVertBuf *pos_rad_buf = pointcloud_position_and_radius_get(&pointcloud); + DRW_shgroup_buffer_texture(shgrp, "ptcloud_pos_rad_tx", pos_rad_buf); + + if (gpu_material != nullptr) { + + // const DRW_Attributes &attrs = cache->attr_used; + // for (int i = 0; i < attrs.num_requests; i++) { + // const DRW_AttributeRequest &request = attrs.requests[i]; + + // char sampler_name[32]; + // /* \note reusing curve attribute function. */ + // drw_curves_get_attribute_sampler_name(request.attribute_name, sampler_name); + + // GPUTexture *attribute_buf = DRW_pointcloud_evaluated_attribute(&pointcloud); + // if (!cache->attributes_tex[i]) { + // continue; + // } + // DRW_shgroup_buffer_texture_ref(shgrp, sampler_name, attribute_buf); + // } + + /* Only single material supported for now. */ + GPUBatch **geom = pointcloud_surface_shaded_get(&pointcloud, &gpu_material, 1); + DRW_shgroup_call(shgrp, geom[0], object); + } + else { + GPUBatch *geom = pointcloud_surface_get(&pointcloud); + DRW_shgroup_call(shgrp, geom, object); + } + return shgrp; +} + +void DRW_pointcloud_free() +{ + GPU_VERTBUF_DISCARD_SAFE(g_dummy_vbo); +} diff --git a/source/blender/draw/intern/draw_pointcloud_private.hh b/source/blender/draw/intern/draw_pointcloud_private.hh new file mode 100644 index 00000000000..9422d7fbc99 --- /dev/null +++ b/source/blender/draw/intern/draw_pointcloud_private.hh @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2021 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup draw + */ + +#pragma once + +struct PointCloud; +struct GPUBatch; +struct GPUVertBuf; +struct GPUMaterial; + +GPUVertBuf *pointcloud_position_and_radius_get(PointCloud *pointcloud); +GPUBatch **pointcloud_surface_shaded_get(PointCloud *pointcloud, + GPUMaterial **gpu_materials, + int mat_len); +GPUBatch *pointcloud_surface_get(PointCloud *pointcloud); diff --git a/source/blender/draw/intern/shaders/common_pointcloud_lib.glsl b/source/blender/draw/intern/shaders/common_pointcloud_lib.glsl index dd725ad327f..8725e036435 100644 --- a/source/blender/draw/intern/shaders/common_pointcloud_lib.glsl +++ b/source/blender/draw/intern/shaders/common_pointcloud_lib.glsl @@ -2,16 +2,10 @@ /* NOTE: To be used with UNIFORM_RESOURCE_ID and INSTANCED_ATTR as define. */ #pragma BLENDER_REQUIRE(common_view_lib.glsl) -#ifndef DRW_SHADER_SHARED_H - -in vec4 pos; /* Position and radius. */ - -/* ---- Instanced attribs ---- */ - -in vec3 pos_inst; -in vec3 nor; - -#endif +int pointcloud_get_point_id() +{ + return gl_VertexID / 32; +} mat3 pointcloud_get_facing_matrix(vec3 p) { @@ -25,8 +19,10 @@ mat3 pointcloud_get_facing_matrix(vec3 p) /* Returns world center position and radius. */ void pointcloud_get_pos_and_radius(out vec3 outpos, out float outradius) { - outpos = point_object_to_world(pos.xyz); - outradius = dot(abs(mat3(ModelMatrix) * pos.www), vec3(1.0 / 3.0)); + int id = pointcloud_get_point_id(); + vec4 pos_rad = texelFetch(ptcloud_pos_rad_tx, id); + outpos = point_object_to_world(pos_rad.xyz); + outradius = dot(abs(mat3(ModelMatrix) * pos_rad.www), vec3(1.0 / 3.0)); } /* Return world position and normal. */ @@ -38,15 +34,67 @@ void pointcloud_get_pos_and_nor(out vec3 outpos, out vec3 outnor) mat3 facing_mat = pointcloud_get_facing_matrix(p); + /** \note: Avoid modulo by non-power-of-two in shader. See Index buffer setup. */ + int vert_id = gl_VertexID % 32; + vec3 pos_inst = vec3(0.0); + + switch (vert_id) { + case 0: + pos_inst.z = 1.0; + break; + case 1: + pos_inst.x = 1.0; + break; + case 2: + pos_inst.y = 1.0; + break; + case 3: + pos_inst.x = -1.0; + break; + case 4: + pos_inst.y = -1.0; + break; + } + /* TODO(fclem): remove multiplication here. Here only for keeping the size correct for now. */ radius *= 0.01; - outpos = p + (facing_mat * pos_inst) * radius; - outnor = facing_mat * nor; + outnor = facing_mat * pos_inst; + outpos = p + outnor * radius; } -vec3 pointcloud_get_pos(void) +vec3 pointcloud_get_pos() { vec3 outpos, outnor; pointcloud_get_pos_and_nor(outpos, outnor); return outpos; } + +float pointcloud_get_customdata_float(const samplerBuffer cd_buf) +{ + int id = pointcloud_get_point_id(); + return texelFetch(cd_buf, id).r; +} + +vec2 pointcloud_get_customdata_vec2(const samplerBuffer cd_buf) +{ + int id = pointcloud_get_point_id(); + return texelFetch(cd_buf, id).rg; +} + +vec3 pointcloud_get_customdata_vec3(const samplerBuffer cd_buf) +{ + int id = pointcloud_get_point_id(); + return texelFetch(cd_buf, id).rgb; +} + +vec4 pointcloud_get_customdata_vec4(const samplerBuffer cd_buf) +{ + int id = pointcloud_get_point_id(); + return texelFetch(cd_buf, id).rgba; +} + +vec2 pointcloud_get_barycentric(void) +{ + /* TODO: To be implemented. */ + return vec2(0.0); +} diff --git a/source/blender/draw/intern/shaders/draw_view_info.hh b/source/blender/draw/intern/shaders/draw_view_info.hh index 114dbab799f..23892a39062 100644 --- a/source/blender/draw/intern/shaders/draw_view_info.hh +++ b/source/blender/draw/intern/shaders/draw_view_info.hh @@ -112,9 +112,7 @@ GPU_SHADER_CREATE_INFO(draw_hair) .additional_info("draw_modelmat", "draw_resource_id"); GPU_SHADER_CREATE_INFO(draw_pointcloud) - .vertex_in(0, Type::VEC4, "pos") - .vertex_in(1, Type::VEC3, "pos_inst") - .vertex_in(2, Type::VEC3, "nor") + .sampler(0, ImageType::FLOAT_BUFFER, "ptcloud_pos_rad_tx", Frequency::BATCH) .additional_info("draw_modelmat_instanced_attr", "draw_resource_id_uniform"); GPU_SHADER_CREATE_INFO(draw_volume).additional_info("draw_modelmat", "draw_resource_id_uniform"); -- cgit v1.2.3 From 7522c05076b40d77e40ad459d91569ba60bcc98d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Tue, 25 Oct 2022 16:12:17 +0200 Subject: Fix T102052 GPencil: stroke outline glitches in object mode Was caused by an extra point per stroke being drawn. --- source/blender/draw/engines/overlay/overlay_outline.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/draw/engines/overlay/overlay_outline.cc b/source/blender/draw/engines/overlay/overlay_outline.cc index a091bbe539b..3213fe144e9 100644 --- a/source/blender/draw/engines/overlay/overlay_outline.cc +++ b/source/blender/draw/engines/overlay/overlay_outline.cc @@ -234,8 +234,8 @@ static void gpencil_stroke_cache_populate(bGPDlayer * /*gpl*/, if (show_stroke) { int vfirst = gps->runtime.stroke_start * 3; - /* Include "potential" cyclic vertex (see shader). */ - int vcount = (gps->totpoints + 1) * 2 * 3; + bool is_cyclic = ((gps->flag & GP_STROKE_CYCLIC) != 0) && (gps->totpoints > 2); + int vcount = (gps->totpoints + (int)is_cyclic) * 2 * 3; DRW_shgroup_call_range(iter->stroke_grp, iter->ob, geom, vfirst, vcount); } } -- cgit v1.2.3 From 601995c3b86986cf8f8e5b6e5a65bcfa7f8f2e32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Tue, 25 Oct 2022 16:16:58 +0200 Subject: Cleanup: Curves: Remove GPUTexture wrappers for buffer texture These are unecessary now that we can bind buffers as textures directly. --- .../draw/engines/overlay/overlay_sculpt_curves.cc | 4 +- .../engines/overlay/overlay_viewer_attribute.cc | 4 +- source/blender/draw/intern/draw_cache_impl.h | 2 +- .../blender/draw/intern/draw_cache_impl_curves.cc | 58 ++-------------------- .../draw/intern/draw_cache_impl_particles.c | 43 ++-------------- source/blender/draw/intern/draw_curves.cc | 50 +++++++++---------- source/blender/draw/intern/draw_curves_private.h | 7 --- source/blender/draw/intern/draw_hair.cc | 12 ++--- source/blender/draw/intern/draw_hair_private.h | 5 -- source/blender/draw/intern/draw_pointcloud.cc | 2 +- 10 files changed, 46 insertions(+), 141 deletions(-) diff --git a/source/blender/draw/engines/overlay/overlay_sculpt_curves.cc b/source/blender/draw/engines/overlay/overlay_sculpt_curves.cc index 1bba2a366a5..68de5dcd11d 100644 --- a/source/blender/draw/engines/overlay/overlay_sculpt_curves.cc +++ b/source/blender/draw/engines/overlay/overlay_sculpt_curves.cc @@ -64,7 +64,7 @@ void OVERLAY_sculpt_curves_cache_populate(OVERLAY_Data *vedata, Object *object) ".selection_curve_float"; bool is_point_domain; - GPUTexture **texture = DRW_curves_texture_for_evaluated_attribute( + GPUVertBuf **texture = DRW_curves_texture_for_evaluated_attribute( curves, name, &is_point_domain); if (texture == nullptr) { return; @@ -78,7 +78,7 @@ void OVERLAY_sculpt_curves_cache_populate(OVERLAY_Data *vedata, Object *object) } DRW_shgroup_uniform_bool_copy(grp, "is_point_domain", is_point_domain); - DRW_shgroup_uniform_texture(grp, "selection_tx", *texture); + DRW_shgroup_buffer_texture(grp, "selection_tx", *texture); } void OVERLAY_sculpt_curves_draw(OVERLAY_Data *vedata) diff --git a/source/blender/draw/engines/overlay/overlay_viewer_attribute.cc b/source/blender/draw/engines/overlay/overlay_viewer_attribute.cc index 84bbf2ae351..c0d74ea73f3 100644 --- a/source/blender/draw/engines/overlay/overlay_viewer_attribute.cc +++ b/source/blender/draw/engines/overlay/overlay_viewer_attribute.cc @@ -144,13 +144,13 @@ static void populate_cache_for_geometry(Object &object, const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry); if (curves.attributes().contains(".viewer")) { bool is_point_domain; - GPUTexture **texture = DRW_curves_texture_for_evaluated_attribute( + GPUVertBuf **texture = DRW_curves_texture_for_evaluated_attribute( curves_id, ".viewer", &is_point_domain); DRWShadingGroup *grp = DRW_shgroup_curves_create_sub( &object, pd.viewer_attribute_curves_grp, nullptr); DRW_shgroup_uniform_float_copy(pd.viewer_attribute_curves_grp, "opacity", opacity); DRW_shgroup_uniform_bool_copy(grp, "is_point_domain", is_point_domain); - DRW_shgroup_uniform_texture(grp, "color_tx", *texture); + DRW_shgroup_buffer_texture(grp, "color_tx", *texture); } break; } diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index e9b1b4c7d16..5aa2203ca68 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -132,7 +132,7 @@ int DRW_curves_material_count_get(struct Curves *curves); * \return A pointer to location where the texture will be * stored, which will be filled by #DRW_shgroup_curves_create_sub. */ -struct GPUTexture **DRW_curves_texture_for_evaluated_attribute(struct Curves *curves, +struct GPUVertBuf **DRW_curves_texture_for_evaluated_attribute(struct Curves *curves, const char *name, bool *r_is_point_domain); diff --git a/source/blender/draw/intern/draw_cache_impl_curves.cc b/source/blender/draw/intern/draw_cache_impl_curves.cc index 85dd9ca8695..c36b90ec32e 100644 --- a/source/blender/draw/intern/draw_cache_impl_curves.cc +++ b/source/blender/draw/intern/draw_cache_impl_curves.cc @@ -88,13 +88,11 @@ static void curves_discard_attributes(CurvesEvalCache &curves_cache) { for (const int i : IndexRange(GPU_MAX_ATTR)) { GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_attributes_buf[i]); - DRW_TEXTURE_FREE_SAFE(curves_cache.proc_attributes_tex[i]); } for (const int i : IndexRange(MAX_HAIR_SUBDIV)) { for (const int j : IndexRange(GPU_MAX_ATTR)) { GPU_VERTBUF_DISCARD_SAFE(curves_cache.final[i].attributes_buf[j]); - DRW_TEXTURE_FREE_SAFE(curves_cache.final[i].attributes_tex[j]); } drw_attributes_clear(&curves_cache.final[i].attr_used); @@ -107,17 +105,12 @@ static void curves_batch_cache_clear_data(CurvesEvalCache &curves_cache) GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_point_buf); GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_length_buf); GPU_VERTBUF_DISCARD_SAFE(curves_cache.data_edit_points); - DRW_TEXTURE_FREE_SAFE(curves_cache.point_tex); - DRW_TEXTURE_FREE_SAFE(curves_cache.length_tex); GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_strand_buf); GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_strand_seg_buf); - DRW_TEXTURE_FREE_SAFE(curves_cache.strand_tex); - DRW_TEXTURE_FREE_SAFE(curves_cache.strand_seg_tex); for (const int i : IndexRange(MAX_HAIR_SUBDIV)) { GPU_VERTBUF_DISCARD_SAFE(curves_cache.final[i].proc_buf); - DRW_TEXTURE_FREE_SAFE(curves_cache.final[i].proc_tex); for (const int j : IndexRange(MAX_THICKRES)) { GPU_BATCH_DISCARD_SAFE(curves_cache.final[i].proc_hairs[j]); } @@ -286,21 +279,6 @@ static void curves_batch_cache_ensure_procedural_pos(const Curves &curves, cache.strands_len}; curves_batch_cache_fill_segments_proc_pos(curves, posTime_data, hairLength_data); - - /* Create vbo immediately to bind to texture buffer. */ - GPU_vertbuf_use(cache.proc_point_buf); - cache.point_tex = GPU_texture_create_from_vertbuf("hair_point", cache.proc_point_buf); - } - - if (gpu_material && cache.proc_length_buf != nullptr && cache.length_tex) { - ListBase gpu_attrs = GPU_material_attributes(gpu_material); - LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &gpu_attrs) { - if (attr->type == CD_HAIRLENGTH) { - GPU_vertbuf_use(cache.proc_length_buf); - cache.length_tex = GPU_texture_create_from_vertbuf("hair_length", cache.proc_length_buf); - break; - } - } } } @@ -363,12 +341,6 @@ static void curves_batch_cache_ensure_procedural_final_attr(CurvesEvalCache &cac /* Those are points! not line segments. */ GPU_vertbuf_data_alloc(final_cache.attributes_buf[index], final_cache.strands_res * cache.strands_len); - - /* Create vbo immediately to bind to texture buffer. */ - GPU_vertbuf_use(final_cache.attributes_buf[index]); - - final_cache.attributes_tex[index] = GPU_texture_create_from_vertbuf( - name, final_cache.attributes_buf[index]); } static void curves_batch_ensure_attribute(const Curves &curves, @@ -379,7 +351,6 @@ static void curves_batch_ensure_attribute(const Curves &curves, { using namespace blender; GPU_VERTBUF_DISCARD_SAFE(cache.proc_attributes_buf[index]); - DRW_TEXTURE_FREE_SAFE(cache.proc_attributes_tex[index]); char sampler_name[32]; drw_curves_get_attribute_sampler_name(request.attribute_name, sampler_name); @@ -414,13 +385,9 @@ static void curves_batch_ensure_attribute(const Curves &curves, attribute.materialize(vbo_span); - GPU_vertbuf_use(attr_vbo); - cache.proc_attributes_tex[index] = GPU_texture_create_from_vertbuf(sampler_name, attr_vbo); - /* Existing final data may have been for a different attribute (with a different name or domain), * free the data. */ GPU_VERTBUF_DISCARD_SAFE(cache.final[subdiv].attributes_buf[index]); - DRW_TEXTURE_FREE_SAFE(cache.final[subdiv].attributes_tex[index]); /* Ensure final data for points. */ if (request.domain == ATTR_DOMAIN_POINT) { @@ -466,19 +433,11 @@ static void curves_batch_cache_ensure_procedural_strand_data(Curves &curves, GPU_vertbuf_attr_get_raw_data(cache.proc_strand_seg_buf, seg_id, &seg_step); curves_batch_cache_fill_strands_data(curves, data_step, seg_step); - - /* Create vbo immediately to bind to texture buffer. */ - GPU_vertbuf_use(cache.proc_strand_buf); - cache.strand_tex = GPU_texture_create_from_vertbuf("curves_strand", cache.proc_strand_buf); - - GPU_vertbuf_use(cache.proc_strand_seg_buf); - cache.strand_seg_tex = GPU_texture_create_from_vertbuf("curves_strand_seg", - cache.proc_strand_seg_buf); } static void curves_batch_cache_ensure_procedural_final_points(CurvesEvalCache &cache, int subdiv) { - /* Same format as point_tex. */ + /* Same format as proc_point_buf. */ GPUVertFormat format = {0}; GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); @@ -489,12 +448,6 @@ static void curves_batch_cache_ensure_procedural_final_points(CurvesEvalCache &c /* Those are points! not line segments. */ GPU_vertbuf_data_alloc(cache.final[subdiv].proc_buf, cache.final[subdiv].strands_res * cache.strands_len); - - /* Create vbo immediately to bind to texture buffer. */ - GPU_vertbuf_use(cache.final[subdiv].proc_buf); - - cache.final[subdiv].proc_tex = GPU_texture_create_from_vertbuf("hair_proc", - cache.final[subdiv].proc_buf); } static void curves_batch_cache_fill_segments_indices(const Curves &curves, @@ -583,7 +536,6 @@ static bool curves_ensure_attributes(const Curves &curves, /* Some new attributes have been added, free all and start over. */ for (const int i : IndexRange(GPU_MAX_ATTR)) { GPU_VERTBUF_DISCARD_SAFE(cache.curves_cache.proc_attributes_buf[i]); - DRW_TEXTURE_FREE_SAFE(cache.curves_cache.proc_attributes_tex[i]); } drw_attributes_merge(&final_cache.attr_used, &attrs_needed, cache.render_mutex); } @@ -631,7 +583,7 @@ bool curves_ensure_procedural_data(Curves *curves, } /* Refreshed if active layer or custom data changes. */ - if ((*r_hair_cache)->strand_tex == nullptr) { + if ((*r_hair_cache)->proc_strand_buf == nullptr) { curves_batch_cache_ensure_procedural_strand_data(*curves, cache.curves_cache); } @@ -689,7 +641,7 @@ static void request_attribute(Curves &curves, const char *name) drw_attributes_merge(&final_cache.attr_used, &attributes, cache.render_mutex); } -GPUTexture **DRW_curves_texture_for_evaluated_attribute(Curves *curves, +GPUVertBuf **DRW_curves_texture_for_evaluated_attribute(Curves *curves, const char *name, bool *r_is_point_domain) { @@ -715,10 +667,10 @@ GPUTexture **DRW_curves_texture_for_evaluated_attribute(Curves *curves, switch (final_cache.attr_used.requests[request_i].domain) { case ATTR_DOMAIN_POINT: *r_is_point_domain = true; - return &final_cache.attributes_tex[request_i]; + return &final_cache.attributes_buf[request_i]; case ATTR_DOMAIN_CURVE: *r_is_point_domain = false; - return &cache.curves_cache.proc_attributes_tex[request_i]; + return &cache.curves_cache.proc_attributes_buf[request_i]; default: BLI_assert_unreachable(); return nullptr; diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c index 9c1784b1de2..8facea4333f 100644 --- a/source/blender/draw/intern/draw_cache_impl_particles.c +++ b/source/blender/draw/intern/draw_cache_impl_particles.c @@ -173,13 +173,9 @@ static void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache) /* TODO: more granular update tagging. */ GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_point_buf); GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_length_buf); - DRW_TEXTURE_FREE_SAFE(hair_cache->point_tex); - DRW_TEXTURE_FREE_SAFE(hair_cache->length_tex); GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_strand_buf); GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_strand_seg_buf); - DRW_TEXTURE_FREE_SAFE(hair_cache->strand_tex); - DRW_TEXTURE_FREE_SAFE(hair_cache->strand_seg_tex); for (int i = 0; i < MAX_MTFACE; i++) { GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_uv_buf[i]); @@ -192,7 +188,6 @@ static void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache) for (int i = 0; i < MAX_HAIR_SUBDIV; i++) { GPU_VERTBUF_DISCARD_SAFE(hair_cache->final[i].proc_buf); - DRW_TEXTURE_FREE_SAFE(hair_cache->final[i].proc_tex); for (int j = 0; j < MAX_THICKRES; j++) { GPU_BATCH_DISCARD_SAFE(hair_cache->final[i].proc_hairs[j]); } @@ -810,7 +805,7 @@ static int particle_batch_cache_fill_strands_data(ParticleSystem *psys, static void particle_batch_cache_ensure_procedural_final_points(ParticleHairCache *cache, int subdiv) { - /* Same format as point_tex. */ + /* Same format as proc_point_buf. */ GPUVertFormat format = {0}; GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); @@ -823,12 +818,6 @@ static void particle_batch_cache_ensure_procedural_final_points(ParticleHairCach /* Those are points! not line segments. */ GPU_vertbuf_data_alloc(cache->final[subdiv].proc_buf, cache->final[subdiv].strands_res * cache->strands_len); - - /* Create vbo immediately to bind to texture buffer. */ - GPU_vertbuf_use(cache->final[subdiv].proc_buf); - - cache->final[subdiv].proc_tex = GPU_texture_create_from_vertbuf("part_proc", - cache->final[subdiv].proc_buf); } static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit, @@ -1034,14 +1023,6 @@ static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit MEM_freeN(parent_mcol); } - /* Create vbo immediately to bind to texture buffer. */ - GPU_vertbuf_use(cache->proc_strand_buf); - cache->strand_tex = GPU_texture_create_from_vertbuf("part_strand", cache->proc_strand_buf); - - GPU_vertbuf_use(cache->proc_strand_seg_buf); - cache->strand_seg_tex = GPU_texture_create_from_vertbuf("part_strand_seg", - cache->proc_strand_seg_buf); - for (int i = 0; i < cache->num_uv_layers; i++) { GPU_vertbuf_use(cache->proc_uv_buf[i]); cache->uv_tex[i] = GPU_texture_create_from_vertbuf("part_uv", cache->proc_uv_buf[i]); @@ -1107,7 +1088,7 @@ static void particle_batch_cache_ensure_procedural_indices(PTCacheEdit *edit, static void particle_batch_cache_ensure_procedural_pos(PTCacheEdit *edit, ParticleSystem *psys, ParticleHairCache *cache, - GPUMaterial *gpu_material) + GPUMaterial *UNUSED(gpu_material)) { if (cache->proc_point_buf == NULL) { /* initialize vertex format */ @@ -1149,22 +1130,6 @@ static void particle_batch_cache_ensure_procedural_pos(PTCacheEdit *edit, psys->childcache, child_count, &pos_step, &length_step); } } - - /* Create vbo immediately to bind to texture buffer. */ - GPU_vertbuf_use(cache->proc_point_buf); - cache->point_tex = GPU_texture_create_from_vertbuf("part_point", cache->proc_point_buf); - } - - /* Checking hair length separately, only allocating gpu memory when needed. */ - if (gpu_material && cache->proc_length_buf != NULL && cache->length_tex == NULL) { - ListBase gpu_attrs = GPU_material_attributes(gpu_material); - LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &gpu_attrs) { - if (attr->type == CD_HAIRLENGTH) { - GPU_vertbuf_use(cache->proc_length_buf); - cache->length_tex = GPU_texture_create_from_vertbuf("hair_length", cache->proc_length_buf); - break; - } - } } } @@ -1722,7 +1687,7 @@ bool particles_ensure_procedural_data(Object *object, /* Refreshed on combing and simulation. */ if ((*r_hair_cache)->proc_point_buf == NULL || - (gpu_material && (*r_hair_cache)->length_tex == NULL)) { + (gpu_material && (*r_hair_cache)->proc_length_buf == NULL)) { ensure_seg_pt_count(source.edit, source.psys, &cache->hair); particle_batch_cache_ensure_procedural_pos( source.edit, source.psys, &cache->hair, gpu_material); @@ -1730,7 +1695,7 @@ bool particles_ensure_procedural_data(Object *object, } /* Refreshed if active layer or custom data changes. */ - if ((*r_hair_cache)->strand_tex == NULL) { + if ((*r_hair_cache)->proc_strand_buf == NULL) { particle_batch_cache_ensure_procedural_strand_data( source.edit, source.psys, source.md, &cache->hair); } diff --git a/source/blender/draw/intern/draw_curves.cc b/source/blender/draw/intern/draw_curves.cc index 8847e3f6016..ee9045696be 100644 --- a/source/blender/draw/intern/draw_curves.cc +++ b/source/blender/draw/intern/draw_curves.cc @@ -129,25 +129,25 @@ void DRW_curves_ubos_pool_free(CurvesUniformBufPool *pool) static void drw_curves_cache_shgrp_attach_resources(DRWShadingGroup *shgrp, CurvesEvalCache *cache, - GPUTexture *tex, + GPUVertBuf *point_buf, const int subdiv) { - DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", tex); - DRW_shgroup_uniform_texture(shgrp, "hairStrandBuffer", cache->strand_tex); - DRW_shgroup_uniform_texture(shgrp, "hairStrandSegBuffer", cache->strand_seg_tex); + DRW_shgroup_buffer_texture(shgrp, "hairPointBuffer", point_buf); + DRW_shgroup_buffer_texture(shgrp, "hairStrandBuffer", cache->proc_strand_buf); + DRW_shgroup_buffer_texture(shgrp, "hairStrandSegBuffer", cache->proc_strand_seg_buf); DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &cache->final[subdiv].strands_res, 1); } static void drw_curves_cache_update_compute(CurvesEvalCache *cache, const int subdiv, const int strands_len, - GPUVertBuf *buffer, - GPUTexture *tex) + GPUVertBuf *output_buf, + GPUVertBuf *input_buf) { GPUShader *shader = curves_eval_shader_get(CURVES_EVAL_CATMULL_ROM); DRWShadingGroup *shgrp = DRW_shgroup_create(shader, g_tf_pass); - drw_curves_cache_shgrp_attach_resources(shgrp, cache, tex, subdiv); - DRW_shgroup_vertex_buffer(shgrp, "posTime", buffer); + drw_curves_cache_shgrp_attach_resources(shgrp, cache, input_buf, subdiv); + DRW_shgroup_vertex_buffer(shgrp, "posTime", output_buf); const int max_strands_per_call = GPU_max_work_group_count(0); int strands_start = 0; @@ -169,7 +169,7 @@ static void drw_curves_cache_update_compute(CurvesEvalCache *cache, const int su } drw_curves_cache_update_compute( - cache, subdiv, strands_len, cache->final[subdiv].proc_buf, cache->point_tex); + cache, subdiv, strands_len, cache->final[subdiv].proc_buf, cache->proc_point_buf); const DRW_Attributes &attrs = cache->final[subdiv].attr_used; for (int i = 0; i < attrs.num_requests; i++) { @@ -182,13 +182,13 @@ static void drw_curves_cache_update_compute(CurvesEvalCache *cache, const int su subdiv, strands_len, cache->final[subdiv].attributes_buf[i], - cache->proc_attributes_tex[i]); + cache->proc_attributes_buf[i]); } } static void drw_curves_cache_update_transform_feedback(CurvesEvalCache *cache, - GPUVertBuf *vbo, - GPUTexture *tex, + GPUVertBuf *output_buf, + GPUVertBuf *input_buf, const int subdiv, const int final_points_len) { @@ -196,14 +196,14 @@ static void drw_curves_cache_update_transform_feedback(CurvesEvalCache *cache, DRWShadingGroup *tf_shgrp = nullptr; if (GPU_transform_feedback_support()) { - tf_shgrp = DRW_shgroup_transform_feedback_create(tf_shader, g_tf_pass, vbo); + tf_shgrp = DRW_shgroup_transform_feedback_create(tf_shader, g_tf_pass, output_buf); } else { tf_shgrp = DRW_shgroup_create(tf_shader, g_tf_pass); CurvesEvalCall *pr_call = MEM_new(__func__); pr_call->next = g_tf_calls; - pr_call->vbo = vbo; + pr_call->vbo = output_buf; pr_call->shgrp = tf_shgrp; pr_call->vert_len = final_points_len; g_tf_calls = pr_call; @@ -213,7 +213,7 @@ static void drw_curves_cache_update_transform_feedback(CurvesEvalCache *cache, } BLI_assert(tf_shgrp != nullptr); - drw_curves_cache_shgrp_attach_resources(tf_shgrp, cache, tex, subdiv); + drw_curves_cache_shgrp_attach_resources(tf_shgrp, cache, input_buf, subdiv); DRW_shgroup_call_procedural_points(tf_shgrp, nullptr, final_points_len); } @@ -225,7 +225,7 @@ static void drw_curves_cache_update_transform_feedback(CurvesEvalCache *cache, c } drw_curves_cache_update_transform_feedback( - cache, cache->final[subdiv].proc_buf, cache->point_tex, subdiv, final_points_len); + cache, cache->final[subdiv].proc_buf, cache->proc_point_buf, subdiv, final_points_len); const DRW_Attributes &attrs = cache->final[subdiv].attr_used; for (int i = 0; i < attrs.num_requests; i++) { @@ -236,7 +236,7 @@ static void drw_curves_cache_update_transform_feedback(CurvesEvalCache *cache, c drw_curves_cache_update_transform_feedback(cache, cache->final[subdiv].attributes_buf[i], - cache->proc_attributes_tex[i], + cache->proc_attributes_buf[i], subdiv, final_points_len); } @@ -346,9 +346,9 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object, 1.0f); } - DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", curves_cache->final[subdiv].proc_tex); - if (curves_cache->length_tex) { - DRW_shgroup_uniform_texture(shgrp, "hairLen", curves_cache->length_tex); + DRW_shgroup_buffer_texture(shgrp, "hairPointBuffer", curves_cache->final[subdiv].proc_buf); + if (curves_cache->proc_length_buf) { + DRW_shgroup_buffer_texture(shgrp, "hairLen", curves_cache->proc_length_buf); } const DRW_Attributes &attrs = curves_cache->final[subdiv].attr_used; @@ -359,18 +359,18 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object, drw_curves_get_attribute_sampler_name(request.attribute_name, sampler_name); if (request.domain == ATTR_DOMAIN_CURVE) { - if (!curves_cache->proc_attributes_tex[i]) { + if (!curves_cache->proc_attributes_buf[i]) { continue; } - DRW_shgroup_uniform_texture(shgrp, sampler_name, curves_cache->proc_attributes_tex[i]); + DRW_shgroup_buffer_texture(shgrp, sampler_name, curves_cache->proc_attributes_buf[i]); } else { - if (!curves_cache->final[subdiv].attributes_tex[i]) { + if (!curves_cache->final[subdiv].attributes_buf[i]) { continue; } - DRW_shgroup_uniform_texture( - shgrp, sampler_name, curves_cache->final[subdiv].attributes_tex[i]); + DRW_shgroup_buffer_texture( + shgrp, sampler_name, curves_cache->final[subdiv].attributes_buf[i]); } /* Some attributes may not be used in the shader anymore and were not garbage collected yet, so diff --git a/source/blender/draw/intern/draw_curves_private.h b/source/blender/draw/intern/draw_curves_private.h index a74878ec674..715706fd7a6 100644 --- a/source/blender/draw/intern/draw_curves_private.h +++ b/source/blender/draw/intern/draw_curves_private.h @@ -34,7 +34,6 @@ typedef enum CurvesEvalShader { typedef struct CurvesEvalFinalCache { /* Output of the subdivision stage: vertex buffer sized to subdiv level. */ GPUVertBuf *proc_buf; - GPUTexture *proc_tex; /** Just contains a huge index buffer used to draw the final curves. */ GPUBatch *proc_hairs[MAX_THICKRES]; @@ -61,35 +60,29 @@ typedef struct CurvesEvalFinalCache { /* Output of the subdivision stage: vertex buffers sized to subdiv level. This is only attributes * on point domain. */ GPUVertBuf *attributes_buf[GPU_MAX_ATTR]; - GPUTexture *attributes_tex[GPU_MAX_ATTR]; } CurvesEvalFinalCache; /* Curves procedural display: Evaluation is done on the GPU. */ typedef struct CurvesEvalCache { /* Input control point positions combined with parameter data. */ GPUVertBuf *proc_point_buf; - GPUTexture *point_tex; /* Editmode data (such as selection flags) used by overlay_edit_curve_point.glsl */ GPUVertBuf *data_edit_points; /** Info of control points strands (segment count and base index) */ GPUVertBuf *proc_strand_buf; - GPUTexture *strand_tex; /* Curve length data. */ GPUVertBuf *proc_length_buf; - GPUTexture *length_tex; GPUVertBuf *proc_strand_seg_buf; - GPUTexture *strand_seg_tex; CurvesEvalFinalCache final[MAX_HAIR_SUBDIV]; /* For point attributes, which need subdivision, these buffers contain the input data. * For curve domain attributes, which do not need subdivision, these are the final data. */ GPUVertBuf *proc_attributes_buf[GPU_MAX_ATTR]; - GPUTexture *proc_attributes_tex[GPU_MAX_ATTR]; int strands_len; int elems_len; diff --git a/source/blender/draw/intern/draw_hair.cc b/source/blender/draw/intern/draw_hair.cc index 281e58ea230..08e5d780cba 100644 --- a/source/blender/draw/intern/draw_hair.cc +++ b/source/blender/draw/intern/draw_hair.cc @@ -105,9 +105,9 @@ static void drw_hair_particle_cache_shgrp_attach_resources(DRWShadingGroup *shgr ParticleHairCache *cache, const int subdiv) { - DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", cache->point_tex); - DRW_shgroup_uniform_texture(shgrp, "hairStrandBuffer", cache->strand_tex); - DRW_shgroup_uniform_texture(shgrp, "hairStrandSegBuffer", cache->strand_seg_tex); + DRW_shgroup_buffer_texture(shgrp, "hairPointBuffer", cache->proc_point_buf); + DRW_shgroup_buffer_texture(shgrp, "hairStrandBuffer", cache->proc_strand_buf); + DRW_shgroup_buffer_texture(shgrp, "hairStrandSegBuffer", cache->proc_strand_seg_buf); DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &cache->final[subdiv].strands_res, 1); } @@ -280,9 +280,9 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object, float hair_rad_tip = part->rad_tip * part->rad_scale * 0.5f; bool hair_close_tip = (part->shape_flag & PART_SHAPE_CLOSE_TIP) != 0; - DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", hair_cache->final[subdiv].proc_tex); - if (hair_cache->length_tex) { - DRW_shgroup_uniform_texture(shgrp, "l", hair_cache->length_tex); + DRW_shgroup_buffer_texture(shgrp, "hairPointBuffer", hair_cache->final[subdiv].proc_buf); + if (hair_cache->proc_length_buf) { + DRW_shgroup_buffer_texture(shgrp, "l", hair_cache->proc_length_buf); } DRW_shgroup_uniform_block(shgrp, "drw_curves", *g_dummy_curves_info); diff --git a/source/blender/draw/intern/draw_hair_private.h b/source/blender/draw/intern/draw_hair_private.h index c7e9e1e22de..a3019ab5aa5 100644 --- a/source/blender/draw/intern/draw_hair_private.h +++ b/source/blender/draw/intern/draw_hair_private.h @@ -29,7 +29,6 @@ struct ParticleSystem; typedef struct ParticleHairFinalCache { /* Output of the subdivision stage: vertex buff sized to subdiv level. */ GPUVertBuf *proc_buf; - GPUTexture *proc_tex; /* Just contains a huge index buffer used to draw the final hair. */ GPUBatch *proc_hairs[MAX_THICKRES]; @@ -44,18 +43,14 @@ typedef struct ParticleHairCache { /* Hair Procedural display: Interpolation is done on the GPU. */ GPUVertBuf *proc_point_buf; /* Input control points */ - GPUTexture *point_tex; /** Infos of control points strands (segment count and base index) */ GPUVertBuf *proc_strand_buf; - GPUTexture *strand_tex; /* Hair Length */ GPUVertBuf *proc_length_buf; - GPUTexture *length_tex; GPUVertBuf *proc_strand_seg_buf; - GPUTexture *strand_seg_tex; GPUVertBuf *proc_uv_buf[MAX_MTFACE]; GPUTexture *uv_tex[MAX_MTFACE]; diff --git a/source/blender/draw/intern/draw_pointcloud.cc b/source/blender/draw/intern/draw_pointcloud.cc index cf46e53129a..582dc690cee 100644 --- a/source/blender/draw/intern/draw_pointcloud.cc +++ b/source/blender/draw/intern/draw_pointcloud.cc @@ -80,7 +80,7 @@ DRWShadingGroup *DRW_shgroup_pointcloud_create_sub(Object *object, // drw_curves_get_attribute_sampler_name(request.attribute_name, sampler_name); // GPUTexture *attribute_buf = DRW_pointcloud_evaluated_attribute(&pointcloud); - // if (!cache->attributes_tex[i]) { + // if (!cache->attributes_buf[i]) { // continue; // } // DRW_shgroup_buffer_texture_ref(shgrp, sampler_name, attribute_buf); -- cgit v1.2.3 From 7da85ea35abafd60777009c680c06a44c39cbdb9 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 24 Oct 2022 14:44:42 +0200 Subject: Fix Cycles build error on 32bit x86 --- intern/cycles/util/transform_inverse.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/util/transform_inverse.h b/intern/cycles/util/transform_inverse.h index b72bbc5f680..bb410a6daef 100644 --- a/intern/cycles/util/transform_inverse.h +++ b/intern/cycles/util/transform_inverse.h @@ -11,7 +11,7 @@ CCL_NAMESPACE_BEGIN ccl_device_forceinline float3 transform_inverse_cross(const float3 a, const float3 b) { -#ifdef __AVX2__ +#if defined(__AVX2__) && defined(__KERNEL_SSE2__) const ssef sse_a = (const __m128 &)a; const ssef sse_b = (const __m128 &)b; const ssef r = shuffle<1, 2, 0, 3>( -- cgit v1.2.3 From 9d188740834017992967a9b91286e2e9b366edd3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 26 Oct 2022 01:58:06 +1100 Subject: Fix window flickering when moving windows between monitors in Wayland Moving widows between monitors with different scale set could flicker in a feedback loop because the bounds of the window resizing could cause the bounds of the windows to overlap different monitors. Now the window is resized immediately, instead of letting the change to the windows surface scale resize the window. --- intern/ghost/intern/GHOST_WindowWayland.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp index edcbcc14a37..6ee1fb8b27f 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.cpp +++ b/intern/ghost/intern/GHOST_WindowWayland.cpp @@ -1041,12 +1041,23 @@ bool GHOST_WindowWayland::outputs_changed_update_scale() bool changed = false; if (scale_next != scale_curr) { - /* Unlikely but possible there is a pending size change is set. */ - window_->size_pending[0] = (window_->size_pending[0] / scale_curr) * scale_next; - window_->size_pending[1] = (window_->size_pending[1] / scale_curr) * scale_next; - window_->scale = scale_next; wl_surface_set_buffer_scale(window_->wl_surface, scale_next); + + /* It's important to resize the window immediately, to avoid the window changing size + * and flickering in a constant feedback loop (in some bases). */ + if ((window_->size_pending[0] != 0) && (window_->size_pending[1] != 0)) { + /* Unlikely but possible there is a pending size change is set. */ + window_->size[0] = window_->size_pending[0]; + window_->size[1] = window_->size_pending[1]; + window_->size_pending[0] = 0; + window_->size_pending[1] = 0; + } + window_->size[0] = (window_->size[0] / scale_curr) * scale_next; + window_->size[1] = (window_->size[1] / scale_curr) * scale_next; + wl_egl_window_resize(window_->egl_window, UNPACK2(window_->size), 0, 0); + window_->ghost_window->notify_size(); + changed = true; } -- cgit v1.2.3 From 4a87f8107ebbb4da33ea278a1e7dcd75aba96b7b Mon Sep 17 00:00:00 2001 From: Chris Blackbourn Date: Wed, 26 Oct 2022 09:33:22 +1300 Subject: Cleanup: format --- source/blender/draw/intern/draw_manager_data.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/draw/intern/draw_manager_data.cc b/source/blender/draw/intern/draw_manager_data.cc index b9e0db71122..792db9d0a6b 100644 --- a/source/blender/draw/intern/draw_manager_data.cc +++ b/source/blender/draw/intern/draw_manager_data.cc @@ -695,7 +695,7 @@ static void drw_call_obinfos_init(DRWObjectInfos *ob_infos, Object *ob) drw_call_calc_orco(ob, ob_infos->orcotexfac); /* Random float value. */ uint random = (DST.dupli_source) ? - DST.dupli_source->random_id : + DST.dupli_source->random_id : /* TODO(fclem): this is rather costly to do at runtime. Maybe we can * put it in ob->runtime and make depsgraph ensure it is up to date. */ BLI_hash_int_2d(BLI_hash_string(ob->id.name + 2), 0); -- cgit v1.2.3 From 14c218b3fd9e936423a5bc3269063aca76f61681 Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Tue, 25 Oct 2022 17:00:48 -0600 Subject: deps_builder: fix hardcoded path the windows builder has 2 different build folders for the debug and release libs, hardcoding the path like this leads to an extra 1GB of downloaded files. The windows builder supplies a single PACKAGE_DIR for both but gets ignored. This change promotes PACKAGE_DIR to be cached in CMakeCache so it can be changed if needed. Differential Revision: https://developer.blender.org/D16213 Reviewed by; brecht, dfelinto --- build_files/build_environment/cmake/options.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build_files/build_environment/cmake/options.cmake b/build_files/build_environment/cmake/options.cmake index 9058e945f6d..13e7fb58be2 100644 --- a/build_files/build_environment/cmake/options.cmake +++ b/build_files/build_environment/cmake/options.cmake @@ -21,8 +21,8 @@ else() endif() set(DOWNLOAD_DIR "${CMAKE_CURRENT_BINARY_DIR}/downloads" CACHE STRING "Path for downloaded files") -# This path must be hard-coded like this, so that the GNUmakefile knows where it is and can pass it to make_source_archive.py: -set(PACKAGE_DIR "${CMAKE_CURRENT_BINARY_DIR}/packages") + +set(PACKAGE_DIR "${CMAKE_CURRENT_BINARY_DIR}/packages" CACHE PATH "default path for downloaded packages") option(PACKAGE_USE_UPSTREAM_SOURCES "Use sources upstream to download the package sources, when OFF the blender mirror will be used" ON) file(TO_CMAKE_PATH ${DOWNLOAD_DIR} DOWNLOAD_DIR) -- cgit v1.2.3 From 9fe9705bc0af9d881905d75957c8dd467f8c8cb3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 26 Oct 2022 11:39:49 +1100 Subject: GHOST/Wayland: use a predictable order for interface registration Defer interface registration so all known interfaces can be called in the order defined by the array of supported types. Without this, the compositor defined the order of registration so it wasn't possible to rely on registration functions to depend on other interfaces. This caused initialization for 'seats' to be moved out of the register callback to ensure multiple interfaces were initialized. This isn't good for readability or maintenance since it meant the add/remove callbacks didn't act on matching data. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 245 ++++++++++++++++++---------- 1 file changed, 159 insertions(+), 86 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 23f7c5060c0..4e3689ddfc2 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -96,6 +96,7 @@ static void gwl_registry_entry_remove_all(GWL_Display *display); struct GWL_RegistryHandler; static int gwl_registry_handler_interface_slot_max(); +static int gwl_registry_handler_interface_slot_from_string(const char *interface); static const struct GWL_RegistryHandler *gwl_registry_handler_from_interface_slot( int interface_slot); @@ -142,7 +143,7 @@ static bool use_gnome_confine_hack = false; /** * KDE (plasma 5.26.1) has a bug where the cursor surface needs to be committed * (via `wl_surface_commit`) when it was hidden and is being set to visible again, see: T102048. - * TODO: report this bug up-stream. + * See: https://bugs.kde.org/show_bug.cgi?id=461001 */ #define USE_KDE_TABLET_HIDDEN_CURSOR_HACK @@ -762,10 +763,17 @@ static GWL_SeatStatePointer *gwl_seat_state_pointer_from_cursor_surface( * \{ */ struct GWL_RegistryEntry; +struct GWL_RegistryAdd_Deferred; struct GWL_Display { GHOST_SystemWayland *system = nullptr; + /** + * An array of registration arguments aligned with `gwl_registry_handlers`. + * Only used during registration at startup. + */ + struct GWL_RegistryAdd_Deferred **registry_add_deferred = nullptr; + /** Registry entries, kept to allow removal at run-time. */ struct GWL_RegistryEntry *registry_entry = nullptr; struct wl_display *wl_display = nullptr; @@ -2641,8 +2649,9 @@ static const struct zwp_pointer_gesture_swipe_v1_listener gesture_swipe_listener /* -------------------------------------------------------------------- */ /** \name Listener (Touch Seat), #wl_touch_listener * - * TODO(@campbellbarton): Only setup the callbacks for now as I don't have - * hardware that generates touch events. + * NOTE(@campbellbarton): It's not clear if this interface is used by popular compositors. + * It looks like GNOME/KDE only support `zwp_pointer_gestures_v1_interface`. + * If this isn't used anywhere, it could be removed. * \{ */ static CLG_LogRef LOG_WL_TOUCH = {"ghost.wl.handle.touch"}; @@ -3838,22 +3847,6 @@ static void seat_handle_capabilities(void *data, else { gwl_seat_capability_touch_disable(seat); } - - /* TODO(@campbellbarton): this could be moved out elsewhere. */ - if (seat->system) { - zwp_primary_selection_device_manager_v1 *primary_selection_device_manager = - seat->system->wp_primary_selection_manager(); - if (primary_selection_device_manager) { - if (seat->wp_primary_selection_device == nullptr) { - seat->wp_primary_selection_device = zwp_primary_selection_device_manager_v1_get_device( - primary_selection_device_manager, seat->wl_seat); - - zwp_primary_selection_device_v1_add_listener(seat->wp_primary_selection_device, - &primary_selection_device_listener, - &seat->primary_selection); - } - } - } } static void seat_handle_name(void *data, struct wl_seat * /*wl_seat*/, const char *name) @@ -4299,6 +4292,30 @@ static void gwl_registry_wl_seat_add(GWL_Display *display, const GWL_RegisteryAd display->seats.push_back(seat); wl_seat_add_listener(seat->wl_seat, &seat_listener, seat); + /* Register data device per seat for IPC between Wayland clients. */ + if (display->wl_data_device_manager) { + seat->wl_data_device = wl_data_device_manager_get_data_device(display->wl_data_device_manager, + seat->wl_seat); + wl_data_device_add_listener(seat->wl_data_device, &data_device_listener, seat); + } + + if (display->wp_tablet_manager) { + seat->wp_tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(display->wp_tablet_manager, + seat->wl_seat); + zwp_tablet_seat_v2_add_listener(seat->wp_tablet_seat, &tablet_seat_listener, seat); + } + + if (display->wp_primary_selection_device_manager) { + if (seat->wp_primary_selection_device == nullptr) { + seat->wp_primary_selection_device = zwp_primary_selection_device_manager_v1_get_device( + display->wp_primary_selection_device_manager, seat->wl_seat); + + zwp_primary_selection_device_v1_add_listener(seat->wp_primary_selection_device, + &primary_selection_device_listener, + &seat->primary_selection); + } + } + gwl_registry_entry_add(display, params->interface_slot, params->name, static_cast(seat)); } static void gwl_registry_wl_seat_remove(GWL_Display *display, void *user_data, const bool on_exit) @@ -4530,20 +4547,34 @@ static void gwl_registry_wp_primary_selection_device_manager_remove(GWL_Display /** * Map interfaces to to initialization functions. * - * \note This list also defines the order interfaces are freed: from last to first, - * so the most fundamental objects such as the compositor are freed last. + * \note This list also defines the order interfaces added & removed. + * - On startup interface registration is performed from first to last. + * - On exit interface removal runs from last to first. + * + * In general fundamental, low level objects such as the compositor and shared memory + * should be declared earlier and other interfaces that may use them should be declared later. + * + * This is useful for predictable registration, especially when one interface depends on another. + * It also helps avoid potential bugs caused by undefined order of removal. */ static const GWL_RegistryHandler gwl_registry_handlers[] = { + /* Low level interfaces. */ { &wl_compositor_interface.name, gwl_registry_compositor_add, gwl_registry_compositor_remove, }, + { + &wl_shm_interface.name, + gwl_registry_wl_shm_add, + gwl_registry_wl_shm_remove, + }, { &xdg_wm_base_interface.name, gwl_registry_xdg_wm_base_add, gwl_registry_xdg_wm_base_remove, }, + /* Managers. */ { &zxdg_decoration_manager_v1_interface.name, gwl_registry_xdg_decoration_manager_add, @@ -4554,26 +4585,16 @@ static const GWL_RegistryHandler gwl_registry_handlers[] = { gwl_registry_xdg_output_manager_add, gwl_registry_xdg_output_manager_remove, }, - { - &wl_output_interface.name, - gwl_registry_wl_output_add, - gwl_registry_wl_output_remove, - }, - { - &wl_seat_interface.name, - gwl_registry_wl_seat_add, - gwl_registry_wl_seat_remove, - }, - { - &wl_shm_interface.name, - gwl_registry_wl_shm_add, - gwl_registry_wl_shm_remove, - }, { &wl_data_device_manager_interface.name, gwl_registry_wl_data_device_manager_add, gwl_registry_wl_data_device_manager_remove, }, + { + &zwp_primary_selection_device_manager_v1_interface.name, + gwl_registry_wp_primary_selection_device_manager_add, + gwl_registry_wp_primary_selection_device_manager_remove, + }, { &zwp_tablet_manager_v2_interface.name, gwl_registry_wp_tablet_manager_add, @@ -4584,6 +4605,7 @@ static const GWL_RegistryHandler gwl_registry_handlers[] = { gwl_registry_wp_relative_pointer_manager_add, gwl_registry_wp_relative_pointer_manager_remove, }, + /* Higher level interfaces. */ { &zwp_pointer_constraints_v1_interface.name, gwl_registry_wp_pointer_constraints_add, @@ -4594,10 +4616,19 @@ static const GWL_RegistryHandler gwl_registry_handlers[] = { gwl_registry_wp_pointer_gestures_add, gwl_registry_wp_pointer_gestures_remove, }, + /* Display outputs. */ { - &zwp_primary_selection_device_manager_v1_interface.name, - gwl_registry_wp_primary_selection_device_manager_add, - gwl_registry_wp_primary_selection_device_manager_remove, + &wl_output_interface.name, + gwl_registry_wl_output_add, + gwl_registry_wl_output_remove, + }, + /* Seats. + * Keep the seat near the end to ensure other types are created first. + * as the seat creates data based on other interfaces. */ + { + &wl_seat_interface.name, + gwl_registry_wl_seat_add, + gwl_registry_wl_seat_remove, }, {nullptr, nullptr, nullptr}, }; @@ -4611,6 +4642,17 @@ static int gwl_registry_handler_interface_slot_max() return ARRAY_SIZE(gwl_registry_handlers) - 1; } +static int gwl_registry_handler_interface_slot_from_string(const char *interface) +{ + for (const GWL_RegistryHandler *handler = gwl_registry_handlers; handler->interface_p != nullptr; + handler++) { + if (STREQ(interface, *handler->interface_p)) { + return int(handler - gwl_registry_handlers); + } + } + return -1; +} + static const GWL_RegistryHandler *gwl_registry_handler_from_interface_slot(int interface_slot) { GHOST_ASSERT(uint32_t(interface_slot) < uint32_t(gwl_registry_handler_interface_slot_max()), @@ -4618,6 +4660,20 @@ static const GWL_RegistryHandler *gwl_registry_handler_from_interface_slot(int i return &gwl_registry_handlers[interface_slot]; } +/** + * Support deferred registration, needed so interface registration order on startup is predictable. + * (defined by the interface order in `gwl_registry_handlers`) + */ +struct GWL_RegistryAdd_Deferred { + GWL_RegistryAdd_Deferred *next = nullptr; + + /* Arguments to #global_handle_add, excluding some known args: + * `data`, `wl_registry` & `interface` are known by the caller + * and don't need to be stored here. */ + uint32_t name = 0; + uint32_t version = 0; +}; + static void global_handle_add(void *data, struct wl_registry *wl_registry, const uint32_t name, @@ -4625,34 +4681,42 @@ static void global_handle_add(void *data, const uint32_t version) { /* Log last since it's useful to know if the interface was handled or not. */ - GWL_Display *display = static_cast(data); - /* The interface name that is ensured not to be freed. */ - GWL_RegisteryAdd_Params params = { - .wl_registry = wl_registry, - .name = name, - .version = version, - .interface_slot = 0, - }; - bool found = false, added = false; - for (const GWL_RegistryHandler *handler = gwl_registry_handlers; handler->interface_p != nullptr; - handler++) { - if (!STREQ(interface, *handler->interface_p)) { - continue; + const int interface_slot = gwl_registry_handler_interface_slot_from_string(interface); + bool added = false; + + if (interface_slot != -1) { + /* Defer registration until later (running on startup). */ + if (display->registry_add_deferred) { + GWL_RegistryAdd_Deferred *reg_add = new GWL_RegistryAdd_Deferred; + reg_add->name = name; + reg_add->version = version; + + /* Add to the list. */ + GWL_RegistryAdd_Deferred **reg_p = &display->registry_add_deferred[interface_slot]; + reg_add->next = *reg_p; + *reg_p = reg_add; + return; } + + const GWL_RegistryHandler *handler = &gwl_registry_handlers[interface_slot]; const GWL_RegistryEntry *registry_entry_prev = display->registry_entry; - params.interface_slot = int(handler - gwl_registry_handlers); + + /* The interface name that is ensured not to be freed. */ + GWL_RegisteryAdd_Params params = { + .wl_registry = wl_registry, + .name = name, + .version = version, + .interface_slot = interface_slot, + }; handler->add_fn(display, ¶ms); added = display->registry_entry != registry_entry_prev; - found = true; - break; } - - /* Not found. */ - if (!found) { + else { + /* Not found. */ #ifdef USE_GNOME_NEEDS_LIBDECOR_HACK if (STRPREFIX(interface, "gtk_shell")) { /* `gtk_shell1` at time of writing. */ /* Only require `libdecor` when built with X11 support, @@ -4665,7 +4729,7 @@ static void global_handle_add(void *data, CLOG_INFO(LOG, 2, "add %s(interface=%s, version=%u, name=%u)", - found ? (added ? "" : "(found but not added)") : "(skipped), ", + (interface_slot != -1) ? (added ? "" : "(found but not added)") : "(skipped), ", interface, version, name); @@ -4685,14 +4749,20 @@ static void global_handle_remove(void *data, const uint32_t name) { GWL_Display *display = static_cast(data); + + /* Deferred registration only happens on startup, ensure interfaces are never removed + * when in the process of adding, while it seems unlikely compositors would do this. + * Better check as it's unsupported (it could be supported if this assert is ever reached). */ + GHOST_ASSERT(!display->registry_add_deferred, + "Interface removal while deferred adding not supported"); + int interface_slot = 0; bool found = gwl_registry_entry_remove_by_name(display, name, &interface_slot); CLOG_INFO(LOG, 2, - "remove (name=%u, interface=%s), %s", + "remove (name=%u, interface=%s)", name, - *gwl_registry_handlers[interface_slot].interface_p, - found ? "(known)" : "(unknown)"); + found ? *gwl_registry_handlers[interface_slot].interface_p : "(unknown)"); } static const struct wl_registry_listener registry_listener = { @@ -4727,13 +4797,33 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background) display_->xdg_decor = new GWL_XDG_Decor_System; /* Register interfaces. */ - struct wl_registry *registry = wl_display_get_registry(display_->wl_display); - wl_registry_add_listener(registry, ®istry_listener, display_); - /* Call callback for registry listener. */ - wl_display_roundtrip(display_->wl_display); - /* Call callbacks for registered listeners. */ - wl_display_roundtrip(display_->wl_display); - wl_registry_destroy(registry); + { + constexpr size_t registry_add_num = ARRAY_SIZE(gwl_registry_handlers) - 1; + GWL_RegistryAdd_Deferred *registry_add_table[registry_add_num] = {nullptr}; + display_->registry_add_deferred = registry_add_table; + + struct wl_registry *registry = wl_display_get_registry(display_->wl_display); + wl_registry_add_listener(registry, ®istry_listener, display_); + /* Call callback for registry listener. */ + wl_display_roundtrip(display_->wl_display); + /* Call callbacks for registered listeners. */ + wl_display_roundtrip(display_->wl_display); + + /* Run #global_handle_add again without deferred registration (for predictable order). */ + display_->registry_add_deferred = nullptr; + + for (size_t interface_slot = 0; interface_slot < registry_add_num; interface_slot++) { + const char *interface = *gwl_registry_handlers[interface_slot].interface_p; + while (registry_add_table[interface_slot]) { + GWL_RegistryAdd_Deferred *reg_add = registry_add_table[interface_slot]; + global_handle_add(display_, registry, reg_add->name, interface, reg_add->version); + registry_add_table[interface_slot] = reg_add->next; + delete reg_add; + } + } + + wl_registry_destroy(registry); + } #ifdef WITH_GHOST_WAYLAND_LIBDECOR /* Ignore windowing requirements when running in background mode, @@ -4785,23 +4875,6 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background) throw std::runtime_error("Wayland: unable to access xdg_shell!"); } } - - /* Register data device per seat for IPC between Wayland clients. */ - if (display_->wl_data_device_manager) { - for (GWL_Seat *seat : display_->seats) { - seat->wl_data_device = wl_data_device_manager_get_data_device( - display_->wl_data_device_manager, seat->wl_seat); - wl_data_device_add_listener(seat->wl_data_device, &data_device_listener, seat); - } - } - - if (display_->wp_tablet_manager) { - for (GWL_Seat *seat : display_->seats) { - seat->wp_tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(display_->wp_tablet_manager, - seat->wl_seat); - zwp_tablet_seat_v2_add_listener(seat->wp_tablet_seat, &tablet_seat_listener, seat); - } - } } GHOST_SystemWayland::~GHOST_SystemWayland() -- cgit v1.2.3 From e844f706fbc438e0f79c2162a3eeed34b8daa62b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 26 Oct 2022 12:03:34 +1100 Subject: GHOST/Wayland: support device add/removal at runtime Keep the registry listener active at runtime, now plugging/unplugging monitors at run-time is detected and the associated data stored by Blender is added/removed as well. Previously all interfaces were detected at startup, afterwards no changes were supported. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 4e3689ddfc2..90f975ed29c 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -776,6 +776,7 @@ struct GWL_Display { /** Registry entries, kept to allow removal at run-time. */ struct GWL_RegistryEntry *registry_entry = nullptr; + struct wl_registry *wl_registry = nullptr; struct wl_display *wl_display = nullptr; struct wl_compositor *wl_compositor = nullptr; @@ -805,6 +806,9 @@ struct GWL_Display { static void gwl_display_destroy(GWL_Display *display) { + wl_registry_destroy(display->wl_registry); + display->wl_registry = nullptr; + /* Unregister items in reverse order. */ gwl_registry_entry_remove_all(display); @@ -4803,6 +4807,7 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background) display_->registry_add_deferred = registry_add_table; struct wl_registry *registry = wl_display_get_registry(display_->wl_display); + display_->wl_registry = registry; wl_registry_add_listener(registry, ®istry_listener, display_); /* Call callback for registry listener. */ wl_display_roundtrip(display_->wl_display); @@ -4821,8 +4826,6 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background) delete reg_add; } } - - wl_registry_destroy(registry); } #ifdef WITH_GHOST_WAYLAND_LIBDECOR -- cgit v1.2.3 From 4046d9a3841634ac59f3acbfda51e4e6989aca2e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 26 Oct 2022 12:18:46 +1100 Subject: Cleanup: remove GWL_RegisteryAdd_Params.wl_registry No longer needed now GWL_Display holds a reference to the registry. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 34 ++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 90f975ed29c..87e5f9bb8d5 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -853,7 +853,6 @@ static void gwl_display_destroy(GWL_Display *display) struct GWL_RegisteryAdd_Params { struct GWL_Display *display = nullptr; - struct wl_registry *wl_registry = nullptr; uint32_t name = 0; uint32_t version = 0; /** Index within `gwl_registry_handlers`. */ @@ -4153,7 +4152,7 @@ static void gwl_registry_compositor_add(GWL_Display *display, const GWL_RegisteryAdd_Params *params) { display->wl_compositor = static_cast( - wl_registry_bind(params->wl_registry, params->name, &wl_compositor_interface, 3)); + wl_registry_bind(display->wl_registry, params->name, &wl_compositor_interface, 3)); gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); } @@ -4173,7 +4172,7 @@ static void gwl_registry_xdg_wm_base_add(GWL_Display *display, { GWL_XDG_Decor_System &decor = *display->xdg_decor; decor.shell = static_cast( - wl_registry_bind(params->wl_registry, params->name, &xdg_wm_base_interface, 1)); + wl_registry_bind(display->wl_registry, params->name, &xdg_wm_base_interface, 1)); xdg_wm_base_add_listener(decor.shell, &shell_listener, nullptr); decor.shell_name = params->name; @@ -4198,7 +4197,7 @@ static void gwl_registry_xdg_decoration_manager_add(GWL_Display *display, { GWL_XDG_Decor_System &decor = *display->xdg_decor; decor.manager = static_cast(wl_registry_bind( - params->wl_registry, params->name, &zxdg_decoration_manager_v1_interface, 1)); + display->wl_registry, params->name, &zxdg_decoration_manager_v1_interface, 1)); decor.manager_name = params->name; gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); @@ -4221,7 +4220,7 @@ static void gwl_registry_xdg_output_manager_add(GWL_Display *display, const GWL_RegisteryAdd_Params *params) { display->xdg_output_manager = static_cast( - wl_registry_bind(params->wl_registry, params->name, &zxdg_output_manager_v1_interface, 2)); + wl_registry_bind(display->wl_registry, params->name, &zxdg_output_manager_v1_interface, 2)); for (GWL_Output *output : display->outputs) { output->xdg_output = zxdg_output_manager_v1_get_xdg_output(display->xdg_output_manager, output->wl_output); @@ -4250,7 +4249,7 @@ static void gwl_registry_wl_output_add(GWL_Display *display, const GWL_Registery GWL_Output *output = new GWL_Output; output->system = display->system; output->wl_output = static_cast( - wl_registry_bind(params->wl_registry, params->name, &wl_output_interface, 2)); + wl_registry_bind(display->wl_registry, params->name, &wl_output_interface, 2)); ghost_wl_output_tag(output->wl_output); wl_output_set_user_data(output->wl_output, output); @@ -4292,7 +4291,7 @@ static void gwl_registry_wl_seat_add(GWL_Display *display, const GWL_RegisteryAd seat->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); seat->data_source = new GWL_DataSource; seat->wl_seat = static_cast( - wl_registry_bind(params->wl_registry, params->name, &wl_seat_interface, 5)); + wl_registry_bind(display->wl_registry, params->name, &wl_seat_interface, 5)); display->seats.push_back(seat); wl_seat_add_listener(seat->wl_seat, &seat_listener, seat); @@ -4415,7 +4414,7 @@ static void gwl_registry_wl_seat_remove(GWL_Display *display, void *user_data, c static void gwl_registry_wl_shm_add(GWL_Display *display, const GWL_RegisteryAdd_Params *params) { display->wl_shm = static_cast( - wl_registry_bind(params->wl_registry, params->name, &wl_shm_interface, 1)); + wl_registry_bind(display->wl_registry, params->name, &wl_shm_interface, 1)); gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); } @@ -4434,7 +4433,7 @@ static void gwl_registry_wl_data_device_manager_add(GWL_Display *display, const GWL_RegisteryAdd_Params *params) { display->wl_data_device_manager = static_cast( - wl_registry_bind(params->wl_registry, params->name, &wl_data_device_manager_interface, 3)); + wl_registry_bind(display->wl_registry, params->name, &wl_data_device_manager_interface, 3)); gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); } @@ -4453,7 +4452,7 @@ static void gwl_registry_wp_tablet_manager_add(GWL_Display *display, const GWL_RegisteryAdd_Params *params) { display->wp_tablet_manager = static_cast( - wl_registry_bind(params->wl_registry, params->name, &zwp_tablet_manager_v2_interface, 1)); + wl_registry_bind(display->wl_registry, params->name, &zwp_tablet_manager_v2_interface, 1)); gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); } @@ -4473,7 +4472,7 @@ static void gwl_registry_wp_relative_pointer_manager_add(GWL_Display *display, { display->wp_relative_pointer_manager = static_cast( wl_registry_bind( - params->wl_registry, params->name, &zwp_relative_pointer_manager_v1_interface, 1)); + display->wl_registry, params->name, &zwp_relative_pointer_manager_v1_interface, 1)); gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); } @@ -4492,7 +4491,7 @@ static void gwl_registry_wp_pointer_constraints_add(GWL_Display *display, const GWL_RegisteryAdd_Params *params) { display->wp_pointer_constraints = static_cast(wl_registry_bind( - params->wl_registry, params->name, &zwp_pointer_constraints_v1_interface, 1)); + display->wl_registry, params->name, &zwp_pointer_constraints_v1_interface, 1)); gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); } @@ -4511,7 +4510,7 @@ static void gwl_registry_wp_pointer_gestures_add(GWL_Display *display, const GWL_RegisteryAdd_Params *params) { display->wp_pointer_gestures = static_cast( - wl_registry_bind(params->wl_registry, params->name, &zwp_pointer_gestures_v1_interface, 3)); + wl_registry_bind(display->wl_registry, params->name, &zwp_pointer_gestures_v1_interface, 3)); gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); } @@ -4531,7 +4530,7 @@ static void gwl_registry_wp_primary_selection_device_manager_add( { display->wp_primary_selection_device_manager = static_cast( - wl_registry_bind(params->wl_registry, + wl_registry_bind(display->wl_registry, params->name, &zwp_primary_selection_device_manager_v1_interface, 1)); @@ -4679,13 +4678,14 @@ struct GWL_RegistryAdd_Deferred { }; static void global_handle_add(void *data, - struct wl_registry *wl_registry, + [[maybe_unused]] struct wl_registry *wl_registry, const uint32_t name, const char *interface, const uint32_t version) { /* Log last since it's useful to know if the interface was handled or not. */ GWL_Display *display = static_cast(data); + GHOST_ASSERT(display->wl_registry == wl_registry, "Registry argument must match!"); const int interface_slot = gwl_registry_handler_interface_slot_from_string(interface); bool added = false; @@ -4709,7 +4709,6 @@ static void global_handle_add(void *data, /* The interface name that is ensured not to be freed. */ GWL_RegisteryAdd_Params params = { - .wl_registry = wl_registry, .name = name, .version = version, .interface_slot = interface_slot, @@ -4749,10 +4748,11 @@ static void global_handle_add(void *data, * using the bind request, the client should now destroy that object. */ static void global_handle_remove(void *data, - struct wl_registry * /*wl_registry*/, + [[maybe_unused]] struct wl_registry *wl_registry, const uint32_t name) { GWL_Display *display = static_cast(data); + GHOST_ASSERT(display->wl_registry == wl_registry, "Registry argument must match!"); /* Deferred registration only happens on startup, ensure interfaces are never removed * when in the process of adding, while it seems unlikely compositors would do this. -- cgit v1.2.3 From c03838dbc8cc4a85cfc93914493a0f1562a53366 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 26 Oct 2022 14:05:33 +1100 Subject: GHOST/Wayland: postpone reading from the clipboard until needed A copy of the clipboard was always being, changes would re-read it. Now read the clipboard on request. This avoids having to keep a copy of the clipboard in memory as well as the need to keep a thread to running to read the clipboard for each data-offer. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 227 ++++++++++++++++------------ intern/ghost/intern/GHOST_SystemWayland.h | 3 - 2 files changed, 128 insertions(+), 102 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 87e5f9bb8d5..892d15254a2 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -280,9 +280,9 @@ static void gwl_simple_buffer_free_data(GWL_SimpleBuffer *buffer) buffer->data_size = 0; } -static void gwl_simple_buffer_set_and_take_ownership(GWL_SimpleBuffer *buffer, - const char *data, - size_t data_size) +[[maybe_unused]] static void gwl_simple_buffer_set_and_take_ownership(GWL_SimpleBuffer *buffer, + const char *data, + size_t data_size) { free(const_cast(buffer->data)); buffer->data = data; @@ -298,7 +298,7 @@ static void gwl_simple_buffer_set_from_string(GWL_SimpleBuffer *buffer, const ch buffer->data = data; } -static char *gwl_simple_buffer_as_string(const GWL_SimpleBuffer *buffer) +[[maybe_unused]] static char *gwl_simple_buffer_as_string(const GWL_SimpleBuffer *buffer) { char *buffer_str = static_cast(malloc(buffer->data_size + 1)); memcpy(buffer_str, buffer->data, buffer->data_size); @@ -798,10 +798,6 @@ struct GWL_Display { struct zwp_pointer_gestures_v1 *wp_pointer_gestures = nullptr; struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_device_manager = nullptr; - - GWL_SimpleBuffer clipboard; - GWL_SimpleBuffer clipboard_primary; - std::mutex clipboard_mutex; }; static void gwl_display_destroy(GWL_Display *display) @@ -836,12 +832,6 @@ static void gwl_display_destroy(GWL_Display *display) wl_display_disconnect(display->wl_display); } - { - std::lock_guard lock{display->clipboard_mutex}; - gwl_simple_buffer_free_data(&display->clipboard); - gwl_simple_buffer_free_data(&display->clipboard_primary); - } - delete display; } @@ -1539,7 +1529,7 @@ static void dnd_events(const GWL_Seat *const seat, const GHOST_TEventType event) * Read from `fd` into a buffer which is returned. * \return the buffer or null on failure. */ -static const char *read_file_as_buffer(const int fd, size_t *r_len) +static char *read_file_as_buffer(const int fd, const bool nil_terminate, size_t *r_len) { struct ByteChunk { ByteChunk *next; @@ -1575,14 +1565,23 @@ static const char *read_file_as_buffer(const int fd, size_t *r_len) char *buf = nullptr; if (ok) { - buf = static_cast(malloc(len)); + buf = static_cast(malloc(len + (nil_terminate ? 1 : 0))); if (UNLIKELY(buf == nullptr)) { CLOG_WARN(LOG, "unable to allocate file buffer: %zu bytes", len); ok = false; } } - *r_len = ok ? len : 0; + if (ok) { + *r_len = len; + if (nil_terminate) { + buf[len] = '\0'; + } + } + else { + *r_len = 0; + } + char *buf_stride = buf; while (chunk_first) { if (ok) { @@ -1599,17 +1598,23 @@ static const char *read_file_as_buffer(const int fd, size_t *r_len) return buf; } -static const char *read_buffer_from_data_offer(GWL_DataOffer *data_offer, - const char *mime_receive, - std::mutex *mutex, - size_t *r_len) +static char *read_buffer_from_data_offer(struct wl_display *wl_display, + GWL_DataOffer *data_offer, + const char *mime_receive, + std::mutex *mutex, + const bool nil_terminate, + size_t *r_len) { int pipefd[2]; if (UNLIKELY(pipe(pipefd) != 0)) { CLOG_WARN(LOG, "error creating pipe: %s", std::strerror(errno)); + if (mutex) { + mutex->unlock(); + } return nullptr; } wl_data_offer_receive(data_offer->id, mime_receive, pipefd[1]); + wl_display_flush(wl_display); close(pipefd[1]); data_offer->in_use.store(false); @@ -1619,23 +1624,28 @@ static const char *read_buffer_from_data_offer(GWL_DataOffer *data_offer, } /* WARNING: `data_offer` may be freed from now on. */ - const char *buf = read_file_as_buffer(pipefd[0], r_len); + char *buf = read_file_as_buffer(pipefd[0], nil_terminate, r_len); close(pipefd[0]); return buf; } -static const char *read_buffer_from_primary_selection_offer( - GWL_PrimarySelection_DataOffer *data_offer, - const char *mime_receive, - std::mutex *mutex, - size_t *r_len) +static char *read_buffer_from_primary_selection_offer(struct wl_display *wl_display, + GWL_PrimarySelection_DataOffer *data_offer, + const char *mime_receive, + std::mutex *mutex, + const bool nil_terminate, + size_t *r_len) { int pipefd[2]; if (UNLIKELY(pipe(pipefd) != 0)) { CLOG_WARN(LOG, "error creating pipe: %s", std::strerror(errno)); + if (mutex) { + mutex->unlock(); + } return nullptr; } zwp_primary_selection_offer_v1_receive(data_offer->id, mime_receive, pipefd[1]); + wl_display_flush(wl_display); close(pipefd[1]); data_offer->in_use.store(false); @@ -1644,7 +1654,7 @@ static const char *read_buffer_from_primary_selection_offer( mutex->unlock(); } /* WARNING: `data_offer` may be freed from now on. */ - const char *buf = read_file_as_buffer(pipefd[0], r_len); + char *buf = read_file_as_buffer(pipefd[0], nil_terminate, r_len); close(pipefd[0]); return buf; } @@ -1899,8 +1909,12 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat const wl_fixed_t xy[2] = {UNPACK2(data_offer->dnd.xy)}; size_t data_buf_len = 0; - const char *data_buf = read_buffer_from_data_offer( - data_offer, mime_receive.c_str(), nullptr, &data_buf_len); + const char *data_buf = read_buffer_from_data_offer(seat->system->wl_display(), + data_offer, + mime_receive.c_str(), + nullptr, + false, + &data_buf_len); std::string data = data_buf ? std::string(data_buf, data_buf_len) : ""; free(const_cast(data_buf)); @@ -2004,34 +2018,6 @@ static void data_device_handle_selection(void *data, /* Get new data offer. */ data_offer = static_cast(wl_data_offer_get_user_data(id)); seat->data_offer_copy_paste = data_offer; - - auto read_selection_fn = [](GWL_Seat *seat) { - GHOST_SystemWayland *const system = seat->system; - seat->data_offer_copy_paste_mutex.lock(); - - GWL_DataOffer *data_offer = seat->data_offer_copy_paste; - std::string mime_receive; - for (const std::string type : {mime_text_utf8, mime_text_plain}) { - if (data_offer->types.count(type)) { - mime_receive = type; - break; - } - } - - size_t data_len = 0; - const char *data = read_buffer_from_data_offer( - data_offer, mime_receive.c_str(), &seat->data_offer_copy_paste_mutex, &data_len); - - { - std::mutex &clipboard_mutex = system->clipboard_mutex(); - std::lock_guard lock{clipboard_mutex}; - GWL_SimpleBuffer *buf = system->clipboard_data(false); - gwl_simple_buffer_set_and_take_ownership(buf, data, data_len); - } - }; - - std::thread read_thread(read_selection_fn, seat); - read_thread.detach(); } static const struct wl_data_device_listener data_device_listener = { @@ -3584,33 +3570,6 @@ static void primary_selection_device_handle_selection( GWL_PrimarySelection_DataOffer *data_offer = static_cast( zwp_primary_selection_offer_v1_get_user_data(id)); primary->data_offer = data_offer; - - auto read_selection_fn = [](GWL_PrimarySelection *primary) { - GHOST_SystemWayland *system = static_cast(GHOST_ISystem::getSystem()); - primary->data_offer_mutex.lock(); - - GWL_PrimarySelection_DataOffer *data_offer = primary->data_offer; - std::string mime_receive; - for (const std::string type : {mime_text_utf8, mime_text_plain}) { - if (data_offer->types.count(type)) { - mime_receive = type; - break; - } - } - size_t data_len = 0; - const char *data = read_buffer_from_primary_selection_offer( - data_offer, mime_receive.c_str(), &primary->data_offer_mutex, &data_len); - - { - std::mutex &clipboard_mutex = system->clipboard_mutex(); - std::lock_guard lock{clipboard_mutex}; - GWL_SimpleBuffer *buf = system->clipboard_data(true); - gwl_simple_buffer_set_and_take_ownership(buf, data, data_len); - } - }; - - std::thread read_thread(read_selection_fn, primary); - read_thread.detach(); } static const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener = { @@ -5012,13 +4971,90 @@ GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const return GHOST_kSuccess; } +/** + * Return a mime type which is supported by GHOST and exists in `types` + * (defined by the data offer). + */ +static const char *system_clipboard_text_mime_type( + const std::unordered_set &data_offer_types) +{ + const char *ghost_supported_types[] = {mime_text_utf8, mime_text_plain}; + for (size_t i = 0; i < ARRAY_SIZE(ghost_supported_types); i++) { + if (data_offer_types.count(ghost_supported_types[i])) { + return ghost_supported_types[i]; + } + } + return nullptr; +} + +static char *system_clipboard_get_primary_selection(GWL_Display *display) +{ + GWL_Seat *seat = display->seats[0]; + + GWL_PrimarySelection *primary = &seat->primary_selection; + std::mutex &mutex = primary->data_offer_mutex; + + mutex.lock(); + bool mutex_locked = true; + char *data = nullptr; + + GWL_PrimarySelection_DataOffer *data_offer = primary->data_offer; + if (data_offer != nullptr) { + const char *mime_receive = system_clipboard_text_mime_type(data_offer->types); + if (mime_receive) { + size_t data_len = 0; + data = read_buffer_from_primary_selection_offer( + display->wl_display, data_offer, mime_receive, &mutex, true, &data_len); + /* Reading the data offer unlocks the mutex. */ + mutex_locked = false; + } + } + if (mutex_locked) { + mutex.unlock(); + } + return data; +} + +static char *system_clipboard_get(GWL_Display *display) +{ + GWL_Seat *seat = display->seats[0]; + std::mutex &mutex = seat->data_offer_copy_paste_mutex; + + mutex.lock(); + bool mutex_locked = true; + char *data = nullptr; + + GWL_DataOffer *data_offer = seat->data_offer_copy_paste; + if (data_offer != nullptr) { + const char *mime_receive = system_clipboard_text_mime_type(data_offer->types); + if (mime_receive) { + size_t data_len = 0; + data = read_buffer_from_data_offer( + display->wl_display, data_offer, mime_receive, &mutex, true, &data_len); + /* Reading the data offer unlocks the mutex. */ + mutex_locked = false; + } + } + if (mutex_locked) { + mutex.unlock(); + } + return data; +} + char *GHOST_SystemWayland::getClipboard(bool selection) const { - const GWL_SimpleBuffer *buf = clipboard_data(selection); - if (buf->data == nullptr) { + if (UNLIKELY(display_->seats.empty())) { return nullptr; } - return gwl_simple_buffer_as_string(buf); + + char *data = nullptr; + if (selection) { + data = system_clipboard_get_primary_selection(display_); + } + else { + data = system_clipboard_get(display_); + } + return data; } static void system_clipboard_put_primary_selection(GWL_Display *display, const char *buffer) @@ -5057,6 +5093,9 @@ static void system_clipboard_put_primary_selection(GWL_Display *display, const c static void system_clipboard_put(GWL_Display *display, const char *buffer) { + if (!display->wl_data_device_manager) { + return; + } GWL_Seat *seat = display->seats[0]; std::lock_guard lock{seat->data_source_mutex}; @@ -5083,7 +5122,7 @@ static void system_clipboard_put(GWL_Display *display, const char *buffer) void GHOST_SystemWayland::putClipboard(const char *buffer, bool selection) const { - if (UNLIKELY(!display_->wl_data_device_manager || display_->seats.empty())) { + if (UNLIKELY(display_->seats.empty())) { return; } @@ -6107,16 +6146,6 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod return GHOST_kSuccess; } -struct GWL_SimpleBuffer *GHOST_SystemWayland::clipboard_data(bool selection) const -{ - return selection ? &display_->clipboard_primary : &display_->clipboard; -} - -struct std::mutex &GHOST_SystemWayland::clipboard_mutex() const -{ - return display_->clipboard_mutex; -} - #ifdef WITH_GHOST_WAYLAND_LIBDECOR bool GHOST_SystemWayland::use_libdecor_runtime() { diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index 7c5459fc461..db4fef23538 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -189,9 +189,6 @@ class GHOST_SystemWayland : public GHOST_System { wl_surface *wl_surface, int scale); - struct GWL_SimpleBuffer *clipboard_data(bool selection) const; - struct std::mutex &clipboard_mutex() const; - #ifdef WITH_GHOST_WAYLAND_LIBDECOR static bool use_libdecor_runtime(); #endif -- cgit v1.2.3 From 49cd04044ae758e35148cede3f32d842c730473b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 26 Oct 2022 15:44:31 +1100 Subject: Revert "GHOST/Wayland: postpone reading from the clipboard until needed" This reverts commit c03838dbc8cc4a85cfc93914493a0f1562a53366. Pasting from Blender's own clipboard locked the process. This needs furhter investigation. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 227 ++++++++++++---------------- intern/ghost/intern/GHOST_SystemWayland.h | 3 + 2 files changed, 102 insertions(+), 128 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 892d15254a2..87e5f9bb8d5 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -280,9 +280,9 @@ static void gwl_simple_buffer_free_data(GWL_SimpleBuffer *buffer) buffer->data_size = 0; } -[[maybe_unused]] static void gwl_simple_buffer_set_and_take_ownership(GWL_SimpleBuffer *buffer, - const char *data, - size_t data_size) +static void gwl_simple_buffer_set_and_take_ownership(GWL_SimpleBuffer *buffer, + const char *data, + size_t data_size) { free(const_cast(buffer->data)); buffer->data = data; @@ -298,7 +298,7 @@ static void gwl_simple_buffer_set_from_string(GWL_SimpleBuffer *buffer, const ch buffer->data = data; } -[[maybe_unused]] static char *gwl_simple_buffer_as_string(const GWL_SimpleBuffer *buffer) +static char *gwl_simple_buffer_as_string(const GWL_SimpleBuffer *buffer) { char *buffer_str = static_cast(malloc(buffer->data_size + 1)); memcpy(buffer_str, buffer->data, buffer->data_size); @@ -798,6 +798,10 @@ struct GWL_Display { struct zwp_pointer_gestures_v1 *wp_pointer_gestures = nullptr; struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_device_manager = nullptr; + + GWL_SimpleBuffer clipboard; + GWL_SimpleBuffer clipboard_primary; + std::mutex clipboard_mutex; }; static void gwl_display_destroy(GWL_Display *display) @@ -832,6 +836,12 @@ static void gwl_display_destroy(GWL_Display *display) wl_display_disconnect(display->wl_display); } + { + std::lock_guard lock{display->clipboard_mutex}; + gwl_simple_buffer_free_data(&display->clipboard); + gwl_simple_buffer_free_data(&display->clipboard_primary); + } + delete display; } @@ -1529,7 +1539,7 @@ static void dnd_events(const GWL_Seat *const seat, const GHOST_TEventType event) * Read from `fd` into a buffer which is returned. * \return the buffer or null on failure. */ -static char *read_file_as_buffer(const int fd, const bool nil_terminate, size_t *r_len) +static const char *read_file_as_buffer(const int fd, size_t *r_len) { struct ByteChunk { ByteChunk *next; @@ -1565,23 +1575,14 @@ static char *read_file_as_buffer(const int fd, const bool nil_terminate, size_t char *buf = nullptr; if (ok) { - buf = static_cast(malloc(len + (nil_terminate ? 1 : 0))); + buf = static_cast(malloc(len)); if (UNLIKELY(buf == nullptr)) { CLOG_WARN(LOG, "unable to allocate file buffer: %zu bytes", len); ok = false; } } - if (ok) { - *r_len = len; - if (nil_terminate) { - buf[len] = '\0'; - } - } - else { - *r_len = 0; - } - + *r_len = ok ? len : 0; char *buf_stride = buf; while (chunk_first) { if (ok) { @@ -1598,23 +1599,17 @@ static char *read_file_as_buffer(const int fd, const bool nil_terminate, size_t return buf; } -static char *read_buffer_from_data_offer(struct wl_display *wl_display, - GWL_DataOffer *data_offer, - const char *mime_receive, - std::mutex *mutex, - const bool nil_terminate, - size_t *r_len) +static const char *read_buffer_from_data_offer(GWL_DataOffer *data_offer, + const char *mime_receive, + std::mutex *mutex, + size_t *r_len) { int pipefd[2]; if (UNLIKELY(pipe(pipefd) != 0)) { CLOG_WARN(LOG, "error creating pipe: %s", std::strerror(errno)); - if (mutex) { - mutex->unlock(); - } return nullptr; } wl_data_offer_receive(data_offer->id, mime_receive, pipefd[1]); - wl_display_flush(wl_display); close(pipefd[1]); data_offer->in_use.store(false); @@ -1624,28 +1619,23 @@ static char *read_buffer_from_data_offer(struct wl_display *wl_display, } /* WARNING: `data_offer` may be freed from now on. */ - char *buf = read_file_as_buffer(pipefd[0], nil_terminate, r_len); + const char *buf = read_file_as_buffer(pipefd[0], r_len); close(pipefd[0]); return buf; } -static char *read_buffer_from_primary_selection_offer(struct wl_display *wl_display, - GWL_PrimarySelection_DataOffer *data_offer, - const char *mime_receive, - std::mutex *mutex, - const bool nil_terminate, - size_t *r_len) +static const char *read_buffer_from_primary_selection_offer( + GWL_PrimarySelection_DataOffer *data_offer, + const char *mime_receive, + std::mutex *mutex, + size_t *r_len) { int pipefd[2]; if (UNLIKELY(pipe(pipefd) != 0)) { CLOG_WARN(LOG, "error creating pipe: %s", std::strerror(errno)); - if (mutex) { - mutex->unlock(); - } return nullptr; } zwp_primary_selection_offer_v1_receive(data_offer->id, mime_receive, pipefd[1]); - wl_display_flush(wl_display); close(pipefd[1]); data_offer->in_use.store(false); @@ -1654,7 +1644,7 @@ static char *read_buffer_from_primary_selection_offer(struct wl_display *wl_disp mutex->unlock(); } /* WARNING: `data_offer` may be freed from now on. */ - char *buf = read_file_as_buffer(pipefd[0], nil_terminate, r_len); + const char *buf = read_file_as_buffer(pipefd[0], r_len); close(pipefd[0]); return buf; } @@ -1909,12 +1899,8 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat const wl_fixed_t xy[2] = {UNPACK2(data_offer->dnd.xy)}; size_t data_buf_len = 0; - const char *data_buf = read_buffer_from_data_offer(seat->system->wl_display(), - data_offer, - mime_receive.c_str(), - nullptr, - false, - &data_buf_len); + const char *data_buf = read_buffer_from_data_offer( + data_offer, mime_receive.c_str(), nullptr, &data_buf_len); std::string data = data_buf ? std::string(data_buf, data_buf_len) : ""; free(const_cast(data_buf)); @@ -2018,6 +2004,34 @@ static void data_device_handle_selection(void *data, /* Get new data offer. */ data_offer = static_cast(wl_data_offer_get_user_data(id)); seat->data_offer_copy_paste = data_offer; + + auto read_selection_fn = [](GWL_Seat *seat) { + GHOST_SystemWayland *const system = seat->system; + seat->data_offer_copy_paste_mutex.lock(); + + GWL_DataOffer *data_offer = seat->data_offer_copy_paste; + std::string mime_receive; + for (const std::string type : {mime_text_utf8, mime_text_plain}) { + if (data_offer->types.count(type)) { + mime_receive = type; + break; + } + } + + size_t data_len = 0; + const char *data = read_buffer_from_data_offer( + data_offer, mime_receive.c_str(), &seat->data_offer_copy_paste_mutex, &data_len); + + { + std::mutex &clipboard_mutex = system->clipboard_mutex(); + std::lock_guard lock{clipboard_mutex}; + GWL_SimpleBuffer *buf = system->clipboard_data(false); + gwl_simple_buffer_set_and_take_ownership(buf, data, data_len); + } + }; + + std::thread read_thread(read_selection_fn, seat); + read_thread.detach(); } static const struct wl_data_device_listener data_device_listener = { @@ -3570,6 +3584,33 @@ static void primary_selection_device_handle_selection( GWL_PrimarySelection_DataOffer *data_offer = static_cast( zwp_primary_selection_offer_v1_get_user_data(id)); primary->data_offer = data_offer; + + auto read_selection_fn = [](GWL_PrimarySelection *primary) { + GHOST_SystemWayland *system = static_cast(GHOST_ISystem::getSystem()); + primary->data_offer_mutex.lock(); + + GWL_PrimarySelection_DataOffer *data_offer = primary->data_offer; + std::string mime_receive; + for (const std::string type : {mime_text_utf8, mime_text_plain}) { + if (data_offer->types.count(type)) { + mime_receive = type; + break; + } + } + size_t data_len = 0; + const char *data = read_buffer_from_primary_selection_offer( + data_offer, mime_receive.c_str(), &primary->data_offer_mutex, &data_len); + + { + std::mutex &clipboard_mutex = system->clipboard_mutex(); + std::lock_guard lock{clipboard_mutex}; + GWL_SimpleBuffer *buf = system->clipboard_data(true); + gwl_simple_buffer_set_and_take_ownership(buf, data, data_len); + } + }; + + std::thread read_thread(read_selection_fn, primary); + read_thread.detach(); } static const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener = { @@ -4971,90 +5012,13 @@ GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const return GHOST_kSuccess; } -/** - * Return a mime type which is supported by GHOST and exists in `types` - * (defined by the data offer). - */ -static const char *system_clipboard_text_mime_type( - const std::unordered_set &data_offer_types) -{ - const char *ghost_supported_types[] = {mime_text_utf8, mime_text_plain}; - for (size_t i = 0; i < ARRAY_SIZE(ghost_supported_types); i++) { - if (data_offer_types.count(ghost_supported_types[i])) { - return ghost_supported_types[i]; - } - } - return nullptr; -} - -static char *system_clipboard_get_primary_selection(GWL_Display *display) -{ - GWL_Seat *seat = display->seats[0]; - - GWL_PrimarySelection *primary = &seat->primary_selection; - std::mutex &mutex = primary->data_offer_mutex; - - mutex.lock(); - bool mutex_locked = true; - char *data = nullptr; - - GWL_PrimarySelection_DataOffer *data_offer = primary->data_offer; - if (data_offer != nullptr) { - const char *mime_receive = system_clipboard_text_mime_type(data_offer->types); - if (mime_receive) { - size_t data_len = 0; - data = read_buffer_from_primary_selection_offer( - display->wl_display, data_offer, mime_receive, &mutex, true, &data_len); - /* Reading the data offer unlocks the mutex. */ - mutex_locked = false; - } - } - if (mutex_locked) { - mutex.unlock(); - } - return data; -} - -static char *system_clipboard_get(GWL_Display *display) -{ - GWL_Seat *seat = display->seats[0]; - std::mutex &mutex = seat->data_offer_copy_paste_mutex; - - mutex.lock(); - bool mutex_locked = true; - char *data = nullptr; - - GWL_DataOffer *data_offer = seat->data_offer_copy_paste; - if (data_offer != nullptr) { - const char *mime_receive = system_clipboard_text_mime_type(data_offer->types); - if (mime_receive) { - size_t data_len = 0; - data = read_buffer_from_data_offer( - display->wl_display, data_offer, mime_receive, &mutex, true, &data_len); - /* Reading the data offer unlocks the mutex. */ - mutex_locked = false; - } - } - if (mutex_locked) { - mutex.unlock(); - } - return data; -} - char *GHOST_SystemWayland::getClipboard(bool selection) const { - if (UNLIKELY(display_->seats.empty())) { + const GWL_SimpleBuffer *buf = clipboard_data(selection); + if (buf->data == nullptr) { return nullptr; } - - char *data = nullptr; - if (selection) { - data = system_clipboard_get_primary_selection(display_); - } - else { - data = system_clipboard_get(display_); - } - return data; + return gwl_simple_buffer_as_string(buf); } static void system_clipboard_put_primary_selection(GWL_Display *display, const char *buffer) @@ -5093,9 +5057,6 @@ static void system_clipboard_put_primary_selection(GWL_Display *display, const c static void system_clipboard_put(GWL_Display *display, const char *buffer) { - if (!display->wl_data_device_manager) { - return; - } GWL_Seat *seat = display->seats[0]; std::lock_guard lock{seat->data_source_mutex}; @@ -5122,7 +5083,7 @@ static void system_clipboard_put(GWL_Display *display, const char *buffer) void GHOST_SystemWayland::putClipboard(const char *buffer, bool selection) const { - if (UNLIKELY(display_->seats.empty())) { + if (UNLIKELY(!display_->wl_data_device_manager || display_->seats.empty())) { return; } @@ -6146,6 +6107,16 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod return GHOST_kSuccess; } +struct GWL_SimpleBuffer *GHOST_SystemWayland::clipboard_data(bool selection) const +{ + return selection ? &display_->clipboard_primary : &display_->clipboard; +} + +struct std::mutex &GHOST_SystemWayland::clipboard_mutex() const +{ + return display_->clipboard_mutex; +} + #ifdef WITH_GHOST_WAYLAND_LIBDECOR bool GHOST_SystemWayland::use_libdecor_runtime() { diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index db4fef23538..7c5459fc461 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -189,6 +189,9 @@ class GHOST_SystemWayland : public GHOST_System { wl_surface *wl_surface, int scale); + struct GWL_SimpleBuffer *clipboard_data(bool selection) const; + struct std::mutex &clipboard_mutex() const; + #ifdef WITH_GHOST_WAYLAND_LIBDECOR static bool use_libdecor_runtime(); #endif -- cgit v1.2.3 From 2186d58d1c2711f722a811e6c2885045e485efa9 Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Tue, 25 Oct 2022 11:51:04 +0200 Subject: Fix T102045: Properties Editor Attribute panels errors when pinning mesh When pinning a Mesh, we cannot rely on the context object. Instead, use the context mesh now. For vertexgroups names [which are still on the object API wise], this means name collisions cannot be checked when pinning a Mesh (so print this as a warning in that case) Maniphest Tasks: T102045 Differential Revision: https://developer.blender.org/D16333 --- release/scripts/startup/bl_ui/properties_data_mesh.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py index a775a3cfa1b..a6b97fbdc85 100644 --- a/release/scripts/startup/bl_ui/properties_data_mesh.py +++ b/release/scripts/startup/bl_ui/properties_data_mesh.py @@ -586,7 +586,7 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel): def draw_attribute_warnings(self, context, layout): ob = context.object - mesh = ob.data + mesh = context.mesh unique_names = set() colliding_names = [] @@ -595,8 +595,11 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel): {"position": None, "shade_smooth": None, "normal": None, "crease": None}, mesh.attributes, mesh.uv_layers, - ob.vertex_groups, + None if ob is None else ob.vertex_groups, ): + if collection is None: + colliding_names.append("Cannot check for object vertex groups when pinning mesh") + continue for name in collection.keys(): unique_names_len = len(unique_names) unique_names.add(name) -- cgit v1.2.3 From 16acd7e473bbfb1e92605f8e4fd4727153d008bf Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Tue, 25 Oct 2022 15:18:22 +0200 Subject: Fix: set more UI colors to PROP_COLOR_GAMMA Followup to rBfb424db2b7bb. Found some more candidates. UI colors should use PROP_COLOR_GAMMA to avoid being affected by scene color management (clarification by @brecht). Differential Revision: https://developer.blender.org/D16337 --- source/blender/makesrna/intern/rna_brush.c | 4 ++-- source/blender/makesrna/intern/rna_fcurve.c | 2 +- source/blender/makesrna/intern/rna_tracking.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 137020ce3f8..5ba31070e1d 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -3663,13 +3663,13 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Mask Texture Overlay Alpha", ""); RNA_def_property_update(prop, 0, "rna_Brush_update"); - prop = RNA_def_property(srna, "cursor_color_add", PROP_FLOAT, PROP_COLOR); + prop = RNA_def_property(srna, "cursor_color_add", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "add_col"); RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Add Color", "Color of cursor when adding"); RNA_def_property_update(prop, 0, "rna_Brush_update"); - prop = RNA_def_property(srna, "cursor_color_subtract", PROP_FLOAT, PROP_COLOR); + prop = RNA_def_property(srna, "cursor_color_subtract", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "sub_col"); RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Subtract Color", "Color of cursor when subtracting"); diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index 727d329781d..9fe7dda0e20 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -2416,7 +2416,7 @@ static void rna_def_fcurve(BlenderRNA *brna) prop, "Color Mode", "Method used to determine color of F-Curve in Graph Editor"); RNA_def_property_update(prop, NC_ANIMATION, NULL); - prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR); + prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Color", "Color of the F-Curve in the Graph Editor"); diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index c4a11d4e9e0..44df0db9ade 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -1640,7 +1640,7 @@ static void rna_def_trackingTrack(BlenderRNA *brna) RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); /* color */ - prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR); + prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text( -- cgit v1.2.3 From 633d314b75a1e84c9ed93e09047f87f34ddab802 Mon Sep 17 00:00:00 2001 From: Michael Jones Date: Tue, 25 Oct 2022 19:36:13 +0100 Subject: Fix T101790: MNEE caustic settings are not visible in the UI when using Metal This patch fixes T101790 by adding a macOS version check for deciding whether to show the caustics settings in the UI (MNEE kernels don't compile on macOS < 13.0) Reviewed By: brecht Maniphest Tasks: T101790 Differential Revision: https://developer.blender.org/D16339 --- intern/cycles/blender/addon/ui.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index f763fe0eb0b..581533db0b6 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -149,6 +149,14 @@ def get_effective_preview_denoiser(context): return 'OIDN' +def use_mnee(context): + # The MNEE kernel doesn't compile on macOS < 13. + if use_metal(context): + import platform + v, _, _ = platform.mac_ver() + if float(v) < 13.0: + return False + return True class CYCLES_RENDER_PT_sampling(CyclesButtonsPanel, Panel): bl_label = "Sampling" @@ -1235,7 +1243,7 @@ class CYCLES_OBJECT_PT_shading_caustics(CyclesButtonsPanel, Panel): @classmethod def poll(cls, context): - return CyclesButtonsPanel.poll(context) and not use_metal(context) and context.object.type != 'LIGHT' + return CyclesButtonsPanel.poll(context) and use_mnee(context) and context.object.type != 'LIGHT' def draw(self, context): layout = self.layout @@ -1449,7 +1457,7 @@ class CYCLES_LIGHT_PT_light(CyclesButtonsPanel, Panel): sub.active = not (light.type == 'AREA' and clamp.is_portal) sub.prop(clamp, "cast_shadow") sub.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance") - if not use_metal(context): + if use_mnee(context): sub.prop(clamp, "is_caustics_light", text="Shadow Caustics") if light.type == 'AREA': -- cgit v1.2.3 From 4b14b33ea887e685937b7757af0c2093093b7c7e Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Wed, 26 Oct 2022 10:35:18 +0200 Subject: Cycles: use packed float3 back for oneAPI This fixes a 15% performance regression silently introduced by 79ab76e156d4bde937335be784cdf220294600d5 that aligned the compact float3 on 16 bytes for oneAPI. Current change is minimalist, there are further cleanup opportunities such as removing packed_float3 definition for oneAPI but for some reason, it cuts the recovered speedup in half, so we're starting with this small fix for now. Reviewed by: brecht Differential Revision: https://developer.blender.org/D16340 --- intern/cycles/util/types_float3.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/intern/cycles/util/types_float3.h b/intern/cycles/util/types_float3.h index 87c6b1d3654..34430945c38 100644 --- a/intern/cycles/util/types_float3.h +++ b/intern/cycles/util/types_float3.h @@ -10,7 +10,12 @@ CCL_NAMESPACE_BEGIN #ifndef __KERNEL_NATIVE_VECTOR_TYPES__ +# ifdef __KERNEL_ONEAPI__ +/* Define float3 as packed for oneAPI. */ +struct float3 +# else struct ccl_try_align(16) float3 +# endif { # ifdef __KERNEL_GPU__ /* Compact structure for GPU. */ -- cgit v1.2.3 From ff89c1793d8c75615ed43248def25812ec13e6e3 Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Wed, 26 Oct 2022 14:13:18 +0200 Subject: Cycles: List Level-Zero in oneAPI device requirements in the UI on Linux Intel documentation for Ubuntu 22.04 does list all runtime components needed by the driver and oneAPI Cycles device but end-users getting drivers from (other) sources can easily end-up missing required Level-Zero Loader and struggle root causing what's wrong in their system. Calling this requirement out in the UI will hopefull help them. oneAPI Level-Zero incl. Loader: https://github.com/oneapi-src/level-zero Common package names: level-zero, level-zero-loader --- intern/cycles/blender/addon/properties.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 425d123e9e6..94e2d840b28 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1636,11 +1636,13 @@ class CyclesPreferences(bpy.types.AddonPreferences): col.label(text="and AMD driver version 22.10 or newer", icon='BLANK1') elif device_type == 'ONEAPI': import sys - col.label(text="Requires Intel GPU with Xe-HPG architecture", icon='BLANK1') if sys.platform.startswith("win"): + col.label(text="Requires Intel GPU with Xe-HPG architecture", icon='BLANK1') col.label(text="and Windows driver version 101.3430 or newer", icon='BLANK1') elif sys.platform.startswith("linux"): - col.label(text="and Linux driver version xx.xx.23904 or newer", icon='BLANK1') + col.label(text="Requires Intel GPU with Xe-HPG architecture and", icon='BLANK1') + col.label(text=" - Linux driver version xx.xx.23904 or newer", icon='BLANK1') + col.label(text=" - oneAPI Level-Zero Loader", icon='BLANK1') elif device_type == 'METAL': col.label(text="Requires Apple Silicon with macOS 12.2 or newer", icon='BLANK1') col.label(text="or AMD with macOS 12.3 or newer", icon='BLANK1') -- cgit v1.2.3 From 414d5429fe32587c56c423308ad0a40fad242dab Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Wed, 26 Oct 2022 18:30:48 +0200 Subject: Cycles: oneAPI: update dg2 target to acm-g10 Reverting 63aec82e8ae388c8ae0cf3717d18a1eb1e97395a since IGC dependency now supports acm-g10 target. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f2f34ca3dd2..3c5fa8a63f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -489,8 +489,8 @@ if(NOT APPLE) option(WITH_CYCLES_ONEAPI_BINARIES "Enable Ahead-Of-Time compilation for Cycles oneAPI device" OFF) # https://www.intel.com/content/www/us/en/develop/documentation/oneapi-dpcpp-cpp-compiler-dev-guide-and-reference/top/compilation/ahead-of-time-compilation.html - # acm-g10 is the architecture for the first Arc Alchemist GPUs but we'll keep using dg2 until IGC dependency is updated to support acm-g10. - set(CYCLES_ONEAPI_SPIR64_GEN_DEVICES "dg2" CACHE STRING "oneAPI Intel GPU architectures to build binaries for") + # acm-g10 is the target for the first Intel Arc Alchemist GPUs. + set(CYCLES_ONEAPI_SPIR64_GEN_DEVICES "acm-g10" CACHE STRING "oneAPI Intel GPU architectures to build binaries for") set(CYCLES_ONEAPI_SYCL_TARGETS spir64 spir64_gen CACHE STRING "oneAPI targets to build AOT binaries for") mark_as_advanced(CYCLES_ONEAPI_SPIR64_GEN_DEVICES) -- cgit v1.2.3 From bc7de854c90dd45758e7ff59c88ed0121c8cccca Mon Sep 17 00:00:00 2001 From: Joseph Eagar Date: Wed, 26 Oct 2022 19:00:55 +0200 Subject: Sculpt: fix T102067: Set material properly in new pbvh draw Note: Still need to fix PBVH_BMESH. --- source/blender/draw/intern/draw_pbvh.cc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/source/blender/draw/intern/draw_pbvh.cc b/source/blender/draw/intern/draw_pbvh.cc index 38fb6d55245..a4de9e4fa47 100644 --- a/source/blender/draw/intern/draw_pbvh.cc +++ b/source/blender/draw/intern/draw_pbvh.cc @@ -951,6 +951,13 @@ struct PBVHBatches { void create_index_faces(PBVH_GPU_Args *args) { + int *mat_index = static_cast(CustomData_get_layer_named(args->pdata, CD_PROP_INT32, "material_index")); + + if (mat_index && args->totprim) { + int poly_index = args->mlooptri[args->prim_indices[0]].poly; + material_index = mat_index[poly_index]; + } + /* Calculate number of edges*/ int edge_count = 0; for (int i = 0; i < args->totprim; i++) { @@ -959,6 +966,7 @@ struct PBVHBatches { if (args->hide_poly && args->hide_poly[lt->poly]) { continue; } + int r_edges[3]; BKE_mesh_looptri_get_real_edges(args->me, lt, r_edges); @@ -1030,6 +1038,14 @@ struct PBVHBatches { void create_index_grids(PBVH_GPU_Args *args) { + int *mat_index = static_cast( + CustomData_get_layer_named(args->pdata, CD_PROP_INT32, "material_index")); + + if (mat_index && args->totprim) { + int poly_index = BKE_subdiv_ccg_grid_to_face_index(args->subdiv_ccg, args->grid_indices[0]); + material_index = mat_index[poly_index]; + } + needs_tri_index = true; int gridsize = args->ccg_key.grid_size; int totgrid = args->totprim; -- cgit v1.2.3 From 1840f44666fee3807a8090097e0c50dd5be6401e Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 26 Oct 2022 18:58:04 +0200 Subject: Fix build error on Windows without precompiled headers Recent refactoring to use uint relied on indirect includes and precompiled headers for uint to be defined. Explicitly include BLI_sys_types where this type is used now. --- source/blender/freestyle/intern/geometry/FitCurve.cpp | 2 ++ source/blender/freestyle/intern/geometry/GeomCleaner.cpp | 2 ++ source/blender/freestyle/intern/geometry/GeomUtils.cpp | 2 ++ source/blender/freestyle/intern/geometry/HashGrid.cpp | 2 ++ source/blender/freestyle/intern/geometry/Noise.cpp | 1 + source/blender/freestyle/intern/image/ImagePyramid.cpp | 2 ++ source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp | 2 ++ source/blender/freestyle/intern/python/BPy_FrsNoise.cpp | 2 ++ source/blender/freestyle/intern/python/BPy_IntegrationType.cpp | 2 ++ source/blender/freestyle/intern/python/BPy_Operators.cpp | 2 ++ source/blender/freestyle/intern/python/BPy_SShape.cpp | 2 ++ source/blender/freestyle/intern/python/BPy_ViewShape.cpp | 2 ++ source/blender/freestyle/intern/python/Director.cpp | 2 ++ source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp | 2 ++ source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp | 2 ++ .../freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp | 2 ++ .../freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp | 2 ++ .../intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp | 2 ++ .../python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp | 2 ++ .../UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp | 2 ++ .../intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp | 2 ++ .../python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp | 2 ++ .../UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp | 2 ++ .../python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp | 2 ++ .../intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp | 2 ++ .../freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp | 2 ++ source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp | 2 ++ source/blender/freestyle/intern/scene_graph/NodeTransform.cpp | 1 + source/blender/freestyle/intern/scene_graph/SceneHash.cpp | 2 ++ source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp | 2 ++ source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp | 2 ++ source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp | 2 ++ source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp | 2 ++ source/blender/freestyle/intern/stroke/Canvas.cpp | 2 ++ source/blender/freestyle/intern/stroke/ContextFunctions.cpp | 2 ++ source/blender/freestyle/intern/stroke/Operators.cpp | 2 ++ source/blender/freestyle/intern/stroke/StrokeRenderer.cpp | 2 ++ source/blender/freestyle/intern/system/StringUtils.cpp | 2 ++ .../freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp | 2 ++ .../freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp | 2 ++ source/blender/freestyle/intern/view_map/BoxGrid.cpp | 2 ++ source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp | 2 ++ source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp | 2 ++ source/blender/freestyle/intern/view_map/Functions0D.cpp | 2 ++ .../freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp | 2 ++ source/blender/freestyle/intern/view_map/OccluderSource.cpp | 2 ++ source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp | 2 ++ source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp | 2 ++ source/blender/freestyle/intern/view_map/SphericalGrid.cpp | 2 ++ source/blender/freestyle/intern/view_map/SteerableViewMap.cpp | 4 +++- source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp | 2 ++ source/blender/freestyle/intern/view_map/ViewMap.cpp | 2 ++ source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp | 2 ++ source/blender/freestyle/intern/winged_edge/WEdge.cpp | 2 ++ source/blender/freestyle/intern/winged_edge/WXEdge.cpp | 3 +++ source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp | 2 ++ source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp | 2 ++ 57 files changed, 114 insertions(+), 1 deletion(-) diff --git a/source/blender/freestyle/intern/geometry/FitCurve.cpp b/source/blender/freestyle/intern/geometry/FitCurve.cpp index ad9b7dfa5ed..0d47665c6d3 100644 --- a/source/blender/freestyle/intern/geometry/FitCurve.cpp +++ b/source/blender/freestyle/intern/geometry/FitCurve.cpp @@ -12,6 +12,8 @@ #include "FitCurve.h" +#include "BLI_sys_types.h" + using namespace std; namespace Freestyle { diff --git a/source/blender/freestyle/intern/geometry/GeomCleaner.cpp b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp index c17fb92a58c..db6816bf045 100644 --- a/source/blender/freestyle/intern/geometry/GeomCleaner.cpp +++ b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp @@ -25,6 +25,8 @@ #include "BKE_global.h" +#include "BLI_sys_types.h" + using namespace std; namespace Freestyle { diff --git a/source/blender/freestyle/intern/geometry/GeomUtils.cpp b/source/blender/freestyle/intern/geometry/GeomUtils.cpp index f1e4297ab5e..b8beeed5880 100644 --- a/source/blender/freestyle/intern/geometry/GeomUtils.cpp +++ b/source/blender/freestyle/intern/geometry/GeomUtils.cpp @@ -7,6 +7,8 @@ #include "GeomUtils.h" +#include "BLI_sys_types.h" + namespace Freestyle::GeomUtils { // This internal procedure is defined below. diff --git a/source/blender/freestyle/intern/geometry/HashGrid.cpp b/source/blender/freestyle/intern/geometry/HashGrid.cpp index 51c87757645..46ce9184951 100644 --- a/source/blender/freestyle/intern/geometry/HashGrid.cpp +++ b/source/blender/freestyle/intern/geometry/HashGrid.cpp @@ -7,6 +7,8 @@ #include "HashGrid.h" +#include "BLI_sys_types.h" + namespace Freestyle { void HashGrid::clear() diff --git a/source/blender/freestyle/intern/geometry/Noise.cpp b/source/blender/freestyle/intern/geometry/Noise.cpp index 306913e6297..04e271f7a5b 100644 --- a/source/blender/freestyle/intern/geometry/Noise.cpp +++ b/source/blender/freestyle/intern/geometry/Noise.cpp @@ -12,6 +12,7 @@ #include "BLI_compiler_attrs.h" #include "BLI_rand.h" +#include "BLI_sys_types.h" #include "Noise.h" diff --git a/source/blender/freestyle/intern/image/ImagePyramid.cpp b/source/blender/freestyle/intern/image/ImagePyramid.cpp index 95afa4dda48..bc68d17a1f9 100644 --- a/source/blender/freestyle/intern/image/ImagePyramid.cpp +++ b/source/blender/freestyle/intern/image/ImagePyramid.cpp @@ -11,6 +11,8 @@ #include "Image.h" #include "ImagePyramid.h" +#include "BLI_sys_types.h" + using namespace std; namespace Freestyle { diff --git a/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp b/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp index 114fafea55b..d79c2f4d9b0 100644 --- a/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp +++ b/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp @@ -9,6 +9,8 @@ #include "../stroke/ContextFunctions.h" +#include "BLI_sys_types.h" + using namespace Freestyle; #ifdef __cplusplus diff --git a/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp index 097fdb6a16b..684edb26a97 100644 --- a/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp +++ b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp @@ -9,6 +9,8 @@ #include "../system/RandGen.h" +#include "BLI_sys_types.h" + #include #ifdef __cplusplus diff --git a/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp b/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp index d88d3edecc0..711cf9c6bab 100644 --- a/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp +++ b/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp @@ -12,6 +12,8 @@ #include "UnaryFunction0D/BPy_UnaryFunction0DFloat.h" #include "UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/BPy_Operators.cpp b/source/blender/freestyle/intern/python/BPy_Operators.cpp index 1c5e90474ab..860573016f2 100644 --- a/source/blender/freestyle/intern/python/BPy_Operators.cpp +++ b/source/blender/freestyle/intern/python/BPy_Operators.cpp @@ -16,6 +16,8 @@ #include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h" #include "UnaryFunction1D/BPy_UnaryFunction1DVoid.h" +#include "BLI_sys_types.h" + #include #ifdef __cplusplus diff --git a/source/blender/freestyle/intern/python/BPy_SShape.cpp b/source/blender/freestyle/intern/python/BPy_SShape.cpp index 7fb647119e6..92867e36479 100644 --- a/source/blender/freestyle/intern/python/BPy_SShape.cpp +++ b/source/blender/freestyle/intern/python/BPy_SShape.cpp @@ -12,6 +12,8 @@ #include "Interface0D/BPy_SVertex.h" #include "Interface1D/BPy_FEdge.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp index 77c3c708103..130526ac309 100644 --- a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp +++ b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp @@ -11,6 +11,8 @@ #include "Interface0D/BPy_ViewVertex.h" #include "Interface1D/BPy_ViewEdge.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/Director.cpp b/source/blender/freestyle/intern/python/Director.cpp index ad54787ad05..40df2033221 100644 --- a/source/blender/freestyle/intern/python/Director.cpp +++ b/source/blender/freestyle/intern/python/Director.cpp @@ -42,6 +42,8 @@ #include "UnaryFunction1D/BPy_UnaryFunction1DVec3f.h" #include "UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h" +#include "BLI_sys_types.h" + using namespace Freestyle; // BinaryPredicate0D: __call__ diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp index cb84b7e82ba..55faebc509c 100644 --- a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp @@ -10,6 +10,8 @@ #include "../BPy_Id.h" #include "../Interface1D/BPy_FEdge.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp index e9dcedef34e..6f90406d74d 100644 --- a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp @@ -13,6 +13,8 @@ #include "../Interface0D/CurvePoint/BPy_StrokeVertex.h" #include "../Iterator/BPy_StrokeVertexIterator.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp index 0a4d1a5d32c..aae8d5514c9 100644 --- a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp @@ -9,6 +9,8 @@ #include "../../BPy_Convert.h" #include "../../Interface0D/BPy_SVertex.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp index 51ae9334f37..6516ad8af9c 100644 --- a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp @@ -9,6 +9,8 @@ #include "../../BPy_Convert.h" #include "../../Interface0D/BPy_SVertex.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp index 29e1a1d3525..8faefd085d6 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp @@ -11,6 +11,8 @@ #include "UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp index e0aa5af2adb..7f5b98da223 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp @@ -11,6 +11,8 @@ #include "UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp index 3a2c9868014..82362704119 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp @@ -8,6 +8,8 @@ #include "../../../stroke/AdvancedFunctions0D.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp index 41bc3199271..800a5da1978 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp @@ -12,6 +12,8 @@ #include "UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp index 242f4a141bc..fa15983f0d3 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp @@ -14,6 +14,8 @@ #include "UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h" #include "UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp index b513686524e..d1479f27935 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp @@ -10,6 +10,8 @@ #include "../../BPy_Convert.h" #include "../../BPy_IntegrationType.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp index ecf95e189d8..99c688985f5 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp @@ -6,6 +6,8 @@ #include "BPy_EqualToChainingTimeStampUP1D.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp index b75e45cb132..48365507d1a 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp @@ -6,6 +6,8 @@ #include "BPy_EqualToTimeStampUP1D.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp index ad8aba9eb29..b410ee14831 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp @@ -6,6 +6,8 @@ #include "BPy_ShapeUP1D.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp index 3962ac0aa35..39dbf4b87a9 100644 --- a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp +++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp @@ -7,6 +7,8 @@ #include "IndexedFaceSet.h" +#include "BLI_sys_types.h" + namespace Freestyle { IndexedFaceSet::IndexedFaceSet() diff --git a/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp b/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp index 97fa07df4c9..0089f68ce2d 100644 --- a/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp +++ b/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp @@ -9,6 +9,7 @@ #include "NodeTransform.h" #include "BLI_math.h" +#include "BLI_sys_types.h" namespace Freestyle { diff --git a/source/blender/freestyle/intern/scene_graph/SceneHash.cpp b/source/blender/freestyle/intern/scene_graph/SceneHash.cpp index a4ef70722d0..0ab83003514 100644 --- a/source/blender/freestyle/intern/scene_graph/SceneHash.cpp +++ b/source/blender/freestyle/intern/scene_graph/SceneHash.cpp @@ -6,6 +6,8 @@ #include "SceneHash.h" +#include "BLI_sys_types.h" + #include namespace Freestyle { diff --git a/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp index cc5d8ef6ed4..4a2b6979985 100644 --- a/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp +++ b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp @@ -10,6 +10,8 @@ #include "IndexedFaceSet.h" #include "ScenePrettyPrinter.h" +#include "BLI_sys_types.h" + namespace Freestyle { #define VISIT(CLASS) \ diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp index 79825b626d5..a221e0e8bbd 100644 --- a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp +++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp @@ -10,6 +10,8 @@ #include "../view_map/SteerableViewMap.h" +#include "BLI_sys_types.h" + namespace Freestyle::Functions1D { int GetSteerableViewMapDensityF1D::operator()(Interface1D &inter) diff --git a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp index 4ff00dd0a08..6508c95f2b4 100644 --- a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp +++ b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp @@ -11,6 +11,8 @@ #include "../system/PseudoNoise.h" #include "../system/RandGen.h" +#include "BLI_sys_types.h" + namespace Freestyle { ///////////////////////////////////////// diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp index 4df0bd7b089..e77ba63f3d6 100644 --- a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp +++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp @@ -23,6 +23,8 @@ #include "BKE_global.h" +#include "BLI_sys_types.h" + #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/freestyle/intern/stroke/Canvas.cpp b/source/blender/freestyle/intern/stroke/Canvas.cpp index af79a8eb4eb..741fad592cf 100644 --- a/source/blender/freestyle/intern/stroke/Canvas.cpp +++ b/source/blender/freestyle/intern/stroke/Canvas.cpp @@ -22,6 +22,8 @@ #include "../view_map/SteerableViewMap.h" +#include "BLI_sys_types.h" + #include "BKE_global.h" // soc #include diff --git a/source/blender/freestyle/intern/stroke/ContextFunctions.cpp b/source/blender/freestyle/intern/stroke/ContextFunctions.cpp index 879ea49b43a..cd37a5f893d 100644 --- a/source/blender/freestyle/intern/stroke/ContextFunctions.cpp +++ b/source/blender/freestyle/intern/stroke/ContextFunctions.cpp @@ -12,6 +12,8 @@ #include "../system/TimeStamp.h" +#include "BLI_sys_types.h" + namespace Freestyle::ContextFunctions { uint GetTimeStampCF() diff --git a/source/blender/freestyle/intern/stroke/Operators.cpp b/source/blender/freestyle/intern/stroke/Operators.cpp index b45e3218a13..93524e6ebe5 100644 --- a/source/blender/freestyle/intern/stroke/Operators.cpp +++ b/source/blender/freestyle/intern/stroke/Operators.cpp @@ -14,6 +14,8 @@ #include "Stroke.h" #include "StrokeIterators.h" +#include "BLI_sys_types.h" + #include "BKE_global.h" namespace Freestyle { diff --git a/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp b/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp index 30dacb7f7df..095cb74d607 100644 --- a/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp +++ b/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp @@ -9,6 +9,8 @@ #include "../geometry/GeomUtils.h" +#include "BLI_sys_types.h" + using namespace std; namespace Freestyle { diff --git a/source/blender/freestyle/intern/system/StringUtils.cpp b/source/blender/freestyle/intern/system/StringUtils.cpp index 79b2cea0446..fbd85815da1 100644 --- a/source/blender/freestyle/intern/system/StringUtils.cpp +++ b/source/blender/freestyle/intern/system/StringUtils.cpp @@ -10,6 +10,8 @@ #include "StringUtils.h" #include "FreestyleConfig.h" +#include "BLI_sys_types.h" + namespace Freestyle::StringUtils { void getPathName(const string &path, const string &base, vector &pathnames) diff --git a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp index 7fa4f52506d..f4619e6e85f 100644 --- a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp +++ b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp @@ -7,6 +7,8 @@ #include "ArbitraryGridDensityProvider.h" +#include "BLI_sys_types.h" + #include "BKE_global.h" namespace Freestyle { diff --git a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp index 11ba5933ce0..b984d5dba29 100644 --- a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp +++ b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp @@ -7,6 +7,8 @@ #include "AverageAreaGridDensityProvider.h" +#include "BLI_sys_types.h" + #include "BKE_global.h" namespace Freestyle { diff --git a/source/blender/freestyle/intern/view_map/BoxGrid.cpp b/source/blender/freestyle/intern/view_map/BoxGrid.cpp index 36afb0119a2..4464aab6419 100644 --- a/source/blender/freestyle/intern/view_map/BoxGrid.cpp +++ b/source/blender/freestyle/intern/view_map/BoxGrid.cpp @@ -10,6 +10,8 @@ #include "BoxGrid.h" +#include "BLI_sys_types.h" + #include "BKE_global.h" using namespace std; diff --git a/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp b/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp index e2886370800..c1afb6de881 100644 --- a/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp +++ b/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp @@ -9,6 +9,8 @@ #include "../geometry/GridHelpers.h" +#include "BLI_sys_types.h" + #include "BKE_global.h" namespace Freestyle { diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp index e455011f187..b7e805f8767 100644 --- a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp +++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp @@ -12,6 +12,8 @@ #include "../geometry/GeomUtils.h" #include "../geometry/normal_cycle.h" +#include "BLI_sys_types.h" + #include "BKE_global.h" namespace Freestyle { diff --git a/source/blender/freestyle/intern/view_map/Functions0D.cpp b/source/blender/freestyle/intern/view_map/Functions0D.cpp index 2157c533986..aaafc5c884a 100644 --- a/source/blender/freestyle/intern/view_map/Functions0D.cpp +++ b/source/blender/freestyle/intern/view_map/Functions0D.cpp @@ -8,6 +8,8 @@ #include "Functions0D.h" #include "ViewMap.h" +#include "BLI_sys_types.h" + #include "BKE_global.h" using namespace std; diff --git a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp index 7e4f673e2fb..40fa8387637 100644 --- a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp +++ b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp @@ -7,6 +7,8 @@ #include "HeuristicGridDensityProviderFactory.h" +#include "BLI_sys_types.h" + namespace Freestyle { HeuristicGridDensityProviderFactory::HeuristicGridDensityProviderFactory(real sizeFactor, diff --git a/source/blender/freestyle/intern/view_map/OccluderSource.cpp b/source/blender/freestyle/intern/view_map/OccluderSource.cpp index 54c30661de9..7ac5de9abbc 100644 --- a/source/blender/freestyle/intern/view_map/OccluderSource.cpp +++ b/source/blender/freestyle/intern/view_map/OccluderSource.cpp @@ -9,6 +9,8 @@ #include "OccluderSource.h" +#include "BLI_sys_types.h" + #include "BKE_global.h" namespace Freestyle { diff --git a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp index 43809f83dc4..af6924eea6e 100644 --- a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp +++ b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp @@ -7,6 +7,8 @@ #include "Pow23GridDensityProvider.h" +#include "BLI_sys_types.h" + #include "BKE_global.h" namespace Freestyle { diff --git a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp index 7d9d871f586..ce4c8fcd453 100644 --- a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp +++ b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp @@ -14,6 +14,8 @@ #include "../geometry/GeomUtils.h" +#include "BLI_sys_types.h" + #include "BKE_global.h" using namespace std; diff --git a/source/blender/freestyle/intern/view_map/SphericalGrid.cpp b/source/blender/freestyle/intern/view_map/SphericalGrid.cpp index 6d800d13b3b..bb4dbd17f70 100644 --- a/source/blender/freestyle/intern/view_map/SphericalGrid.cpp +++ b/source/blender/freestyle/intern/view_map/SphericalGrid.cpp @@ -10,6 +10,8 @@ #include "SphericalGrid.h" +#include "BLI_sys_types.h" + #include "BKE_global.h" using namespace std; diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp index ba37dc434f4..20472599835 100644 --- a/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp +++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp @@ -16,8 +16,10 @@ #include "../image/Image.h" #include "../image/ImagePyramid.h" -#include "BKE_global.h" #include "BLI_math.h" +#include "BLI_sys_types.h" + +#include "BKE_global.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp index 277334d13fd..fcb157a4e60 100644 --- a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp +++ b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp @@ -13,6 +13,8 @@ #include "../winged_edge/WXEdge.h" +#include "BLI_sys_types.h" + using namespace std; namespace Freestyle { diff --git a/source/blender/freestyle/intern/view_map/ViewMap.cpp b/source/blender/freestyle/intern/view_map/ViewMap.cpp index 0ba4850eed5..09432aa4ac7 100644 --- a/source/blender/freestyle/intern/view_map/ViewMap.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMap.cpp @@ -13,6 +13,8 @@ #include "../geometry/GeomUtils.h" +#include "BLI_sys_types.h" + namespace Freestyle { /**********************************/ diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp index 4ef06c0ac96..9c2919b0ca8 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp @@ -24,6 +24,8 @@ #include "../winged_edge/WFillGrid.h" +#include "BLI_sys_types.h" + #include "BKE_global.h" namespace Freestyle { diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.cpp b/source/blender/freestyle/intern/winged_edge/WEdge.cpp index 33f72cc0c9f..3082988bd36 100644 --- a/source/blender/freestyle/intern/winged_edge/WEdge.cpp +++ b/source/blender/freestyle/intern/winged_edge/WEdge.cpp @@ -9,6 +9,8 @@ #include "WEdge.h" +#include "BLI_sys_types.h" + namespace Freestyle { /** Temporary structures */ diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp index 2c107a01d13..6838060b44e 100644 --- a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp +++ b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp @@ -6,6 +6,9 @@ */ #include "WXEdge.h" + +#include "BLI_sys_types.h" + #include "BKE_global.h" namespace Freestyle { diff --git a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp index 929e9b7e4dd..e22de505472 100644 --- a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp +++ b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp @@ -9,6 +9,8 @@ #include "WXEdgeBuilder.h" #include "WXEdge.h" +#include "BLI_sys_types.h" + namespace Freestyle { void WXEdgeBuilder::visitIndexedFaceSet(IndexedFaceSet &ifs) diff --git a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp index e8095d89ee1..ce6054830f3 100644 --- a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp +++ b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp @@ -14,6 +14,8 @@ #include "../scene_graph/NodeShape.h" +#include "BLI_sys_types.h" + using namespace std; namespace Freestyle { -- cgit v1.2.3 From 0385e4df3cc30e5ccae1ff3c2abcf718a7d7b794 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 26 Oct 2022 19:27:12 +0200 Subject: Fix slow continuous depsgraph updates in sculpt paint mode in some cases Updates for cursor could cause the paint data to be continuously refreshed, which is pretty cheap by itself, but not when it starts tagging the depsgraph. The paint slot refresh code ideally should not be doing depsgraph tags at all, but checking if there were changes at least avoids continuous updates. --- source/blender/blenkernel/intern/material.c | 63 ++++++++++++++++------------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 6c6d2298dbd..51e27f173c8 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -1512,58 +1512,65 @@ static ePaintSlotFilter material_paint_slot_filter(const struct Object *ob) void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma, const struct Object *ob) { - int count = 0; - if (!ma) { return; } const ePaintSlotFilter slot_filter = material_paint_slot_filter(ob); - /* COW needed when adding texture slot on an object with no materials. */ - DEG_id_tag_update(&ma->id, ID_RECALC_SHADING | ID_RECALC_COPY_ON_WRITE); + const TexPaintSlot *prev_texpaintslot = ma->texpaintslot; + const int prev_paint_active_slot = ma->paint_active_slot; + const int prev_paint_clone_slot = ma->paint_clone_slot; + const int prev_tot_slots = ma->tot_slots; - if (ma->texpaintslot) { - MEM_freeN(ma->texpaintslot); - ma->tot_slots = 0; - ma->texpaintslot = NULL; - } + ma->texpaintslot = NULL; + ma->tot_slots = 0; if (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_IMAGE) { ma->paint_active_slot = 0; ma->paint_clone_slot = 0; - return; } - - if (!(ma->nodetree)) { + else if (!(ma->nodetree)) { ma->paint_active_slot = 0; ma->paint_clone_slot = 0; - return; } + else { + int count = count_texture_nodes_recursive(ma->nodetree, slot_filter); - count = count_texture_nodes_recursive(ma->nodetree, slot_filter); - - if (count == 0) { - ma->paint_active_slot = 0; - ma->paint_clone_slot = 0; - return; - } + if (count == 0) { + ma->paint_active_slot = 0; + ma->paint_clone_slot = 0; + } + else { + ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots"); - ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots"); + bNode *active_node = nodeGetActivePaintCanvas(ma->nodetree); - bNode *active_node = nodeGetActivePaintCanvas(ma->nodetree); + fill_texpaint_slots_recursive(ma->nodetree, active_node, ob, ma, count, slot_filter); - fill_texpaint_slots_recursive(ma->nodetree, active_node, ob, ma, count, slot_filter); + ma->tot_slots = count; - ma->tot_slots = count; + if (ma->paint_active_slot >= count) { + ma->paint_active_slot = count - 1; + } - if (ma->paint_active_slot >= count) { - ma->paint_active_slot = count - 1; + if (ma->paint_clone_slot >= count) { + ma->paint_clone_slot = count - 1; + } + } } - if (ma->paint_clone_slot >= count) { - ma->paint_clone_slot = count - 1; + /* COW needed when adding texture slot on an object with no materials. + * But do it only when slots actually change to avoid continuous depsgrap updates. */ + if (ma->tot_slots != prev_tot_slots || ma->paint_active_slot != prev_paint_active_slot || + ma->paint_clone_slot != prev_paint_clone_slot || + (ma->texpaintslot && prev_texpaintslot && + memcmp(ma->texpaintslot, prev_texpaintslot, sizeof(*ma->texpaintslot) * ma->tot_slots) != + 0)) { + DEG_id_tag_update(&ma->id, ID_RECALC_SHADING | ID_RECALC_COPY_ON_WRITE); } + + MEM_SAFE_FREE(prev_texpaintslot); } void BKE_texpaint_slots_refresh_object(Scene *scene, struct Object *ob) -- cgit v1.2.3 From 1e7776907c004ad8c6081b4cfcdeda5ec793b174 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 26 Oct 2022 18:01:45 +0200 Subject: Fix T101925: sculpt color painting not updating with Cycles viewport render * External engines do not use the PBVH and need slower depsgraph updates. * Final depsgraph tag after stroke finishes was missing for sculpt color painting, caused missing updates for other viewports as well as any modifiers or nodes on other objects using the colors. --- source/blender/blenkernel/BKE_paint.h | 2 +- source/blender/blenkernel/intern/paint.cc | 9 +++-- source/blender/draw/engines/basic/basic_engine.c | 2 +- .../blender/draw/engines/eevee/eevee_materials.c | 2 +- .../blender/draw/engines/overlay/overlay_facing.cc | 2 +- .../blender/draw/engines/overlay/overlay_fade.cc | 2 +- .../draw/engines/overlay/overlay_mode_transfer.cc | 2 +- .../blender/draw/engines/overlay/overlay_sculpt.cc | 2 +- .../draw/engines/overlay/overlay_wireframe.cc | 2 +- .../draw/engines/workbench/workbench_engine.c | 2 +- source/blender/editors/sculpt_paint/sculpt.c | 46 +++++++++++----------- source/blender/editors/sculpt_paint/sculpt_undo.c | 6 +-- 12 files changed, 41 insertions(+), 38 deletions(-) diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 437a22e4782..9fc4aa5307d 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -886,7 +886,7 @@ void BKE_sculpt_sync_face_visibility_to_grids(struct Mesh *mesh, struct SubdivCC * Test if PBVH can be used directly for drawing, which is faster than * drawing the mesh and all updates that come with it. */ -bool BKE_sculptsession_use_pbvh_draw(const struct Object *ob, const struct View3D *v3d); +bool BKE_sculptsession_use_pbvh_draw(const struct Object *ob, const struct RegionView3D *rv3d); enum { SCULPT_MASK_LAYER_CALC_VERT = (1 << 0), diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index 408cd117e32..965cd153d00 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -2316,7 +2316,7 @@ void BKE_sculpt_bvh_update_from_ccg(PBVH *pbvh, SubdivCCG *subdiv_ccg) &key); } -bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const View3D * /*v3d*/) +bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const RegionView3D *rv3d) { SculptSession *ss = ob->sculpt; if (ss == nullptr || ss->pbvh == nullptr || ss->mode_type != OB_MODE_SCULPT) { @@ -2324,9 +2324,10 @@ bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const View3D * /*v3d*/) } if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) { - /* Regular mesh only draws from PBVH without modifiers and shape keys. */ - - return !(ss->shapekey_active || ss->deform_modifiers_active); + /* Regular mesh only draws from PBVH without modifiers and shape keys, or for + * external engines that do not have access to the PBVH like Eevee does. */ + const bool external_engine = rv3d && rv3d->render_engine != nullptr; + return !(ss->shapekey_active || ss->deform_modifiers_active || external_engine); } /* Multires and dyntopo always draw directly from the PBVH. */ diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c index eee6a5a7cb5..05e62764bb1 100644 --- a/source/blender/draw/engines/basic/basic_engine.c +++ b/source/blender/draw/engines/basic/basic_engine.c @@ -182,7 +182,7 @@ static void basic_cache_populate(void *vedata, Object *ob) } } - const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) && + const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) && !DRW_state_is_image_render(); const bool do_cull = (draw_ctx->v3d && (draw_ctx->v3d->shading.flag & V3D_SHADING_BACKFACE_CULLING)); diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 068b18f1117..b134d7f6dc6 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -810,7 +810,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, const DRWContextState *draw_ctx = DRW_context_state_get(); Scene *scene = draw_ctx->scene; - bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) && + bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) && !DRW_state_is_image_render(); if (ob->sculpt && ob->sculpt->pbvh) { diff --git a/source/blender/draw/engines/overlay/overlay_facing.cc b/source/blender/draw/engines/overlay/overlay_facing.cc index 825036ecd05..44dab0f0a42 100644 --- a/source/blender/draw/engines/overlay/overlay_facing.cc +++ b/source/blender/draw/engines/overlay/overlay_facing.cc @@ -43,7 +43,7 @@ void OVERLAY_facing_cache_populate(OVERLAY_Data *vedata, Object *ob) } const DRWContextState *draw_ctx = DRW_context_state_get(); - const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) && + const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) && !DRW_state_is_image_render(); const bool is_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0; diff --git a/source/blender/draw/engines/overlay/overlay_fade.cc b/source/blender/draw/engines/overlay/overlay_fade.cc index d6fd4f9127a..b9523a4eac9 100644 --- a/source/blender/draw/engines/overlay/overlay_fade.cc +++ b/source/blender/draw/engines/overlay/overlay_fade.cc @@ -53,7 +53,7 @@ void OVERLAY_fade_cache_populate(OVERLAY_Data *vedata, Object *ob) } const DRWContextState *draw_ctx = DRW_context_state_get(); - const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) && + const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) && !DRW_state_is_image_render(); const bool is_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0; diff --git a/source/blender/draw/engines/overlay/overlay_mode_transfer.cc b/source/blender/draw/engines/overlay/overlay_mode_transfer.cc index 5222abfc743..79ac92a187c 100644 --- a/source/blender/draw/engines/overlay/overlay_mode_transfer.cc +++ b/source/blender/draw/engines/overlay/overlay_mode_transfer.cc @@ -85,7 +85,7 @@ void OVERLAY_mode_transfer_cache_populate(OVERLAY_Data *vedata, Object *ob) } const DRWContextState *draw_ctx = DRW_context_state_get(); - const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) && + const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) && !DRW_state_is_image_render(); const bool is_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0; diff --git a/source/blender/draw/engines/overlay/overlay_sculpt.cc b/source/blender/draw/engines/overlay/overlay_sculpt.cc index 8f142d68350..3377aa5394b 100644 --- a/source/blender/draw/engines/overlay/overlay_sculpt.cc +++ b/source/blender/draw/engines/overlay/overlay_sculpt.cc @@ -37,7 +37,7 @@ void OVERLAY_sculpt_cache_populate(OVERLAY_Data *vedata, Object *ob) struct GPUBatch *sculpt_overlays; PBVH *pbvh = ob->sculpt->pbvh; - const bool use_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d); + const bool use_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d); if (!pbvh) { /* It is possible to have SculptSession without PBVH. This happens, for example, when toggling diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.cc b/source/blender/draw/engines/overlay/overlay_wireframe.cc index bff1bf46923..7ee0e89f2f9 100644 --- a/source/blender/draw/engines/overlay/overlay_wireframe.cc +++ b/source/blender/draw/engines/overlay/overlay_wireframe.cc @@ -276,7 +276,7 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, /* Don't do that in edit Mesh mode, unless there is a modifier preview. */ if (use_wire && (!is_mesh || (!is_edit_mode || has_edit_mesh_cage))) { const bool is_sculpt_mode = ((ob->mode & OB_MODE_SCULPT) != 0) && (ob->sculpt != nullptr); - const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) && + const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) && !DRW_state_is_image_render(); const bool is_instance = (ob->base_flag & BASE_FROM_DUPLI); const bool instance_parent_in_edit_mode = is_instance ? DRW_object_is_in_edit_mode( diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c index 8dbddb4265d..15a16539a26 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.c +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -267,7 +267,7 @@ static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd, const DRWContextState *draw_ctx = DRW_context_state_get(); const bool is_active = (ob == draw_ctx->obact); - const bool is_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) && + const bool is_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) && !DRW_state_is_image_render(); const bool is_render = DRW_state_is_image_render() && (draw_ctx->v3d == NULL); const bool is_texpaint_mode = is_active && (wpd->ctx_mode == CTX_MODE_PAINT_TEXTURE); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 95192114429..34d0158f187 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1121,8 +1121,8 @@ void SCULPT_tag_update_overlays(bContext *C) DEG_id_tag_update(&ob->id, ID_RECALC_SHADING); - View3D *v3d = CTX_wm_view3d(C); - if (!BKE_sculptsession_use_pbvh_draw(ob, v3d)) { + RegionView3D *rv3d = CTX_wm_region_view3d(C); + if (!BKE_sculptsession_use_pbvh_draw(ob, rv3d)) { DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); } } @@ -4813,12 +4813,12 @@ static bool sculpt_needs_connectivity_info(const Sculpt *sd, void SCULPT_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *brush) { SculptSession *ss = ob->sculpt; - View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); Sculpt *sd = CTX_data_tool_settings(C)->sculpt; bool need_pmap = sculpt_needs_connectivity_info(sd, brush, ss, 0); if (ss->shapekey_active || ss->deform_modifiers_active || - (!BKE_sculptsession_use_pbvh_draw(ob, v3d) && need_pmap)) { + (!BKE_sculptsession_use_pbvh_draw(ob, rv3d) && need_pmap)) { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); BKE_sculpt_update_object_for_edit( depsgraph, ob, need_pmap, false, SCULPT_tool_is_paint(brush->sculpt_tool)); @@ -5249,7 +5249,6 @@ void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags) SculptSession *ss = ob->sculpt; ARegion *region = CTX_wm_region(C); MultiresModifierData *mmd = ss->multires.modifier; - View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); if (rv3d) { @@ -5274,7 +5273,7 @@ void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags) /* Only current viewport matters, slower update for all viewports will * be done in sculpt_flush_update_done. */ - if (!BKE_sculptsession_use_pbvh_draw(ob, v3d)) { + if (!BKE_sculptsession_use_pbvh_draw(ob, rv3d)) { /* Slow update with full dependency graph update and all that comes with it. * Needed when there are modifiers or full shading in the 3D viewport. */ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); @@ -5316,16 +5315,15 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up /* After we are done drawing the stroke, check if we need to do a more * expensive depsgraph tag to update geometry. */ wmWindowManager *wm = CTX_wm_manager(C); - View3D *current_v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = CTX_wm_region_view3d(C); + RegionView3D *current_rv3d = CTX_wm_region_view3d(C); SculptSession *ss = ob->sculpt; Mesh *mesh = ob->data; /* Always needed for linked duplicates. */ bool need_tag = (ID_REAL_USERS(&mesh->id) > 1); - if (rv3d) { - rv3d->rflag &= ~RV3D_PAINTING; + if (current_rv3d) { + current_rv3d->rflag &= ~RV3D_PAINTING; } LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { @@ -5335,16 +5333,17 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up if (sl->spacetype != SPACE_VIEW3D) { continue; } - View3D *v3d = (View3D *)sl; - if (v3d != current_v3d) { - need_tag |= !BKE_sculptsession_use_pbvh_draw(ob, v3d); - } /* Tag all 3D viewports for redraw now that we are done. Others * viewports did not get a full redraw, and anti-aliasing for the * current viewport was deactivated. */ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { if (region->regiontype == RGN_TYPE_WINDOW) { + RegionView3D *rv3d = region->regiondata; + if (rv3d != current_rv3d) { + need_tag |= !BKE_sculptsession_use_pbvh_draw(ob, rv3d); + } + ED_region_tag_redraw(region); } } @@ -5378,15 +5377,17 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up BKE_sculpt_attributes_destroy_temporary_stroke(ob); - if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { - BKE_pbvh_bmesh_after_stroke(ss->pbvh); - } + if (update_flags & SCULPT_UPDATE_COORDS) { + if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { + BKE_pbvh_bmesh_after_stroke(ss->pbvh); + } - /* Optimization: if there is locked key and active modifiers present in */ - /* the stack, keyblock is updating at each step. otherwise we could update */ - /* keyblock only when stroke is finished. */ - if (ss->shapekey_active && !ss->deform_modifiers_active) { - sculpt_update_keyblock(ob); + /* Optimization: if there is locked key and active modifiers present in */ + /* the stack, keyblock is updating at each step. otherwise we could update */ + /* keyblock only when stroke is finished. */ + if (ss->shapekey_active && !ss->deform_modifiers_active) { + sculpt_update_keyblock(ob); + } } if (need_tag) { @@ -5625,6 +5626,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str } else { BKE_sculpt_attributes_destroy_temporary_stroke(ob); + SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COLOR); } } else { diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index 13e3dd64521..eb92c865f18 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -857,7 +857,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase { Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); BKE_view_layer_synced_ensure(scene, view_layer); Object *ob = BKE_view_layer_active_object_get(view_layer); SculptSession *ss = ob->sculpt; @@ -911,7 +911,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase } DEG_id_tag_update(&ob->id, ID_RECALC_SHADING); - if (!BKE_sculptsession_use_pbvh_draw(ob, v3d)) { + if (!BKE_sculptsession_use_pbvh_draw(ob, rv3d)) { DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); } @@ -1070,7 +1070,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase } } - tag_update |= ID_REAL_USERS(ob->data) > 1 || !BKE_sculptsession_use_pbvh_draw(ob, v3d) || + tag_update |= ID_REAL_USERS(ob->data) > 1 || !BKE_sculptsession_use_pbvh_draw(ob, rv3d) || ss->shapekey_active || ss->deform_modifiers_active; if (tag_update) { -- cgit v1.2.3 From e75be000e3e83b53e0fc18c5719f41de37bd6a75 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 27 Oct 2022 17:24:51 +1100 Subject: GHOST/Wayland: replace deferred registration with an update callback There were two issues caused by deferred registration (added by [0]), one crash on startup (T102075), another unreported issue with the GLX/EGL context failing to initialize. Unfortunately I'm unable to reproduce the errors but it seems likely deferring interface registration is not well supported so this commit uses an alternative solution to some interfaces depending on others for initialization. Instead of relying on the order of registration, a separate "update" callback has been added which is called after binding interfaces. This has the advantage that it can be called when adding/removing interfaces at run-time to avoid the dangling pointers being left in locally allocated structures. In practice adding/removing interfaces happens so rarely (only with "outputs" as far as I'm aware) that this benefit is theoretical at the moment. This should resolve T102075. [0]: 9fe9705bc0af9d881905d75957c8dd467f8c8cb3 --- intern/ghost/intern/GHOST_SystemWayland.cpp | 287 +++++++++++++++++----------- 1 file changed, 171 insertions(+), 116 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 87e5f9bb8d5..d4eabfb815d 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -763,17 +763,17 @@ static GWL_SeatStatePointer *gwl_seat_state_pointer_from_cursor_surface( * \{ */ struct GWL_RegistryEntry; -struct GWL_RegistryAdd_Deferred; struct GWL_Display { GHOST_SystemWayland *system = nullptr; /** - * An array of registration arguments aligned with `gwl_registry_handlers`. - * Only used during registration at startup. + * True when initializing registration, while updating all other entries wont cause problems, + * it will preform many redundant update calls. */ - struct GWL_RegistryAdd_Deferred **registry_add_deferred = nullptr; - /** Registry entries, kept to allow removal at run-time. */ + bool registry_skip_update_all = false; + + /** Registry entries, kept to allow updating & removal at run-time. */ struct GWL_RegistryEntry *registry_entry = nullptr; struct wl_registry *wl_registry = nullptr; @@ -852,21 +852,42 @@ static void gwl_display_destroy(GWL_Display *display) * \{ */ struct GWL_RegisteryAdd_Params { - struct GWL_Display *display = nullptr; uint32_t name = 0; - uint32_t version = 0; /** Index within `gwl_registry_handlers`. */ int interface_slot = 0; + uint32_t version = 0; }; /** * Add callback for object registry. + * \note Any operations that depend on other interfaces being registered must be performed in the + * #GWL_RegistryHandler_UpdateFn callback as the order interfaces are added is out of our control. + * * \param display: The display which holes a reference to the global object. * \param params: Various arguments needed for registration. */ using GWL_RegistryHandler_AddFn = void (*)(GWL_Display *display, const GWL_RegisteryAdd_Params *params); +struct GWL_RegisteryUpdate_Params { + uint32_t name = 0; + /** Index within `gwl_registry_handlers`. */ + int interface_slot = 0; + uint32_t version = 0; + + /** Set to #GWL_RegistryEntry.user_data. */ + void *user_data = nullptr; +}; + +/** + * Optional update callback to refresh internal data when another interface has been added/removed. + * + * \param display: The display which holes a reference to the global object. + * \param params: Various arguments needed for updating. + */ +using GWL_RegistryHandler_UpdateFn = void (*)(GWL_Display *display, + const GWL_RegisteryUpdate_Params *params); + /** * Remove callback for object registry. * \param display: The display which holes a reference to the global object. @@ -883,7 +904,11 @@ struct GWL_RegistryHandler { /** Pointer to the name (not the name it's self), needed as the values aren't set on startup. */ const char *const *interface_p = nullptr; + /** Add the interface. */ GWL_RegistryHandler_AddFn add_fn = nullptr; + /** Optional update the interface (when other interfaces have been added/removed). */ + GWL_RegistryHandler_UpdateFn update_fn = nullptr; + /** Remove the interface. */ GWL_RegistryEntry_RemoveFn remove_fn = nullptr; }; @@ -909,6 +934,10 @@ struct GWL_RegistryEntry { * A unique identifier used as a handle by `wl_registry_listener.global_remove`. */ uint32_t name = WL_NAME_UNSET; + /** + * Version passed by the add callback. + */ + uint32_t version; /** * The index in `gwl_registry_handlers`, * useful for accessing the interface name (for logging for example). @@ -917,14 +946,14 @@ struct GWL_RegistryEntry { }; static void gwl_registry_entry_add(GWL_Display *display, - const int interface_slot, - const uint32_t name, + const GWL_RegisteryAdd_Params *params, void *user_data) { GWL_RegistryEntry *reg = new GWL_RegistryEntry; - reg->interface_slot = interface_slot; - reg->name = name; + reg->interface_slot = params->interface_slot; + reg->name = params->name; + reg->version = params->version; reg->user_data = user_data; reg->next = display->registry_entry; @@ -1016,6 +1045,49 @@ static void gwl_registry_entry_remove_all(GWL_Display *display) display->registry_entry = nullptr; } +/** + * Run GWL_RegistryHandler.update_fn an all registered interface instances. + * This is needed to refresh the state of interfaces that may reference other interfaces. + * Called when interfaces are added/removed. + * + * \param interface_slot_exclude: Skip updating slots of this type. + * Note that while harmless dependencies only exist between different types, + * so there is no reason to update all other outputs that an output was removed (for e.g.). + * Pass as -1 to update all slots. + * + * NOTE(@campbellbarton): Updating all other items on a single change is typically worth avoiding. + * In practice this isn't a problem as so there are so few elements in `display->registry_entry`, + * so few use update functions and adding/removal at runtime is rarely called (plugging/unplugging) + * hardware for e.g. So while it's possible to store dependency links to avoid unnecessary + * looping over data - so it ends up being a non issue. + */ +static void gwl_registry_entry_update_all(GWL_Display *display, const int interface_slot_exclude) +{ + GHOST_ASSERT(interface_slot_exclude == -1 || (uint(interface_slot_exclude) < + uint(gwl_registry_handler_interface_slot_max())), + "Invalid exclude slot"); + + for (GWL_RegistryEntry *reg = display->registry_entry; reg; reg = reg->next) { + if (reg->interface_slot == interface_slot_exclude) { + continue; + } + const GWL_RegistryHandler *handler = gwl_registry_handler_from_interface_slot( + reg->interface_slot); + if (handler->update_fn == nullptr) { + continue; + } + + GWL_RegisteryUpdate_Params params = { + .name = reg->name, + .interface_slot = reg->interface_slot, + .version = reg->version, + + .user_data = reg->user_data, + }; + handler->update_fn(display, ¶ms); + } +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -4153,8 +4225,7 @@ static void gwl_registry_compositor_add(GWL_Display *display, { display->wl_compositor = static_cast( wl_registry_bind(display->wl_registry, params->name, &wl_compositor_interface, 3)); - - gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); + gwl_registry_entry_add(display, params, nullptr); } static void gwl_registry_compositor_remove(GWL_Display *display, void * /*user_data*/, @@ -4175,8 +4246,7 @@ static void gwl_registry_xdg_wm_base_add(GWL_Display *display, wl_registry_bind(display->wl_registry, params->name, &xdg_wm_base_interface, 1)); xdg_wm_base_add_listener(decor.shell, &shell_listener, nullptr); decor.shell_name = params->name; - - gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); + gwl_registry_entry_add(display, params, nullptr); } static void gwl_registry_xdg_wm_base_remove(GWL_Display *display, void * /*user_data*/, @@ -4199,8 +4269,7 @@ static void gwl_registry_xdg_decoration_manager_add(GWL_Display *display, decor.manager = static_cast(wl_registry_bind( display->wl_registry, params->name, &zxdg_decoration_manager_v1_interface, 1)); decor.manager_name = params->name; - - gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); + gwl_registry_entry_add(display, params, nullptr); } static void gwl_registry_xdg_decoration_manager_remove(GWL_Display *display, void * /*user_data*/, @@ -4221,13 +4290,7 @@ static void gwl_registry_xdg_output_manager_add(GWL_Display *display, { display->xdg_output_manager = static_cast( wl_registry_bind(display->wl_registry, params->name, &zxdg_output_manager_v1_interface, 2)); - for (GWL_Output *output : display->outputs) { - output->xdg_output = zxdg_output_manager_v1_get_xdg_output(display->xdg_output_manager, - output->wl_output); - zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output); - } - - gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); + gwl_registry_entry_add(display, params, nullptr); } static void gwl_registry_xdg_output_manager_remove(GWL_Display *display, void * /*user_data*/, @@ -4236,10 +4299,6 @@ static void gwl_registry_xdg_output_manager_remove(GWL_Display *display, struct zxdg_output_manager_v1 **value_p = &display->xdg_output_manager; zxdg_output_manager_v1_destroy(*value_p); *value_p = nullptr; - - for (GWL_Output *output : display->outputs) { - output->xdg_output = nullptr; - } } /* #GWL_Display.wl_output */ @@ -4255,15 +4314,22 @@ static void gwl_registry_wl_output_add(GWL_Display *display, const GWL_Registery display->outputs.push_back(output); wl_output_add_listener(output->wl_output, &output_listener, output); - + gwl_registry_entry_add(display, params, static_cast(output)); +} +static void gwl_registry_wl_output_update(GWL_Display *display, + const GWL_RegisteryUpdate_Params *params) +{ + GWL_Output *output = static_cast(params->user_data); if (display->xdg_output_manager) { - output->xdg_output = zxdg_output_manager_v1_get_xdg_output(display->xdg_output_manager, - output->wl_output); - zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output); + if (output->xdg_output == nullptr) { + output->xdg_output = zxdg_output_manager_v1_get_xdg_output(display->xdg_output_manager, + output->wl_output); + zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output); + } + } + else { + output->xdg_output = nullptr; } - - gwl_registry_entry_add( - display, params->interface_slot, params->name, static_cast(output)); } static void gwl_registry_wl_output_remove(GWL_Display *display, void *user_data, @@ -4294,18 +4360,31 @@ static void gwl_registry_wl_seat_add(GWL_Display *display, const GWL_RegisteryAd wl_registry_bind(display->wl_registry, params->name, &wl_seat_interface, 5)); display->seats.push_back(seat); wl_seat_add_listener(seat->wl_seat, &seat_listener, seat); + gwl_registry_entry_add(display, params, static_cast(seat)); +} +static void gwl_registry_wl_seat_update(GWL_Display *display, + const GWL_RegisteryUpdate_Params *params) +{ + GWL_Seat *seat = static_cast(params->user_data); - /* Register data device per seat for IPC between Wayland clients. */ + /* Register data device per seat for IPC between WAYLAND clients. */ if (display->wl_data_device_manager) { - seat->wl_data_device = wl_data_device_manager_get_data_device(display->wl_data_device_manager, - seat->wl_seat); - wl_data_device_add_listener(seat->wl_data_device, &data_device_listener, seat); + if (seat->wl_data_device == nullptr) { + seat->wl_data_device = wl_data_device_manager_get_data_device( + display->wl_data_device_manager, seat->wl_seat); + wl_data_device_add_listener(seat->wl_data_device, &data_device_listener, seat); + } + } + else { + seat->wl_data_device = nullptr; } if (display->wp_tablet_manager) { - seat->wp_tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(display->wp_tablet_manager, - seat->wl_seat); - zwp_tablet_seat_v2_add_listener(seat->wp_tablet_seat, &tablet_seat_listener, seat); + if (seat->wp_tablet_seat == nullptr) { + seat->wp_tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(display->wp_tablet_manager, + seat->wl_seat); + zwp_tablet_seat_v2_add_listener(seat->wp_tablet_seat, &tablet_seat_listener, seat); + } } if (display->wp_primary_selection_device_manager) { @@ -4318,8 +4397,9 @@ static void gwl_registry_wl_seat_add(GWL_Display *display, const GWL_RegisteryAd &seat->primary_selection); } } - - gwl_registry_entry_add(display, params->interface_slot, params->name, static_cast(seat)); + else { + seat->wp_primary_selection_device = nullptr; + } } static void gwl_registry_wl_seat_remove(GWL_Display *display, void *user_data, const bool on_exit) { @@ -4415,8 +4495,7 @@ static void gwl_registry_wl_shm_add(GWL_Display *display, const GWL_RegisteryAdd { display->wl_shm = static_cast( wl_registry_bind(display->wl_registry, params->name, &wl_shm_interface, 1)); - - gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); + gwl_registry_entry_add(display, params, nullptr); } static void gwl_registry_wl_shm_remove(GWL_Display *display, void * /*user_data*/, @@ -4434,8 +4513,7 @@ static void gwl_registry_wl_data_device_manager_add(GWL_Display *display, { display->wl_data_device_manager = static_cast( wl_registry_bind(display->wl_registry, params->name, &wl_data_device_manager_interface, 3)); - - gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); + gwl_registry_entry_add(display, params, nullptr); } static void gwl_registry_wl_data_device_manager_remove(GWL_Display *display, void * /*user_data*/, @@ -4453,8 +4531,7 @@ static void gwl_registry_wp_tablet_manager_add(GWL_Display *display, { display->wp_tablet_manager = static_cast( wl_registry_bind(display->wl_registry, params->name, &zwp_tablet_manager_v2_interface, 1)); - - gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); + gwl_registry_entry_add(display, params, nullptr); } static void gwl_registry_wp_tablet_manager_remove(GWL_Display *display, void * /*user_data*/, @@ -4473,8 +4550,7 @@ static void gwl_registry_wp_relative_pointer_manager_add(GWL_Display *display, display->wp_relative_pointer_manager = static_cast( wl_registry_bind( display->wl_registry, params->name, &zwp_relative_pointer_manager_v1_interface, 1)); - - gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); + gwl_registry_entry_add(display, params, nullptr); } static void gwl_registry_wp_relative_pointer_manager_remove(GWL_Display *display, void * /*user_data*/, @@ -4492,8 +4568,7 @@ static void gwl_registry_wp_pointer_constraints_add(GWL_Display *display, { display->wp_pointer_constraints = static_cast(wl_registry_bind( display->wl_registry, params->name, &zwp_pointer_constraints_v1_interface, 1)); - - gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); + gwl_registry_entry_add(display, params, nullptr); } static void gwl_registry_wp_pointer_constraints_remove(GWL_Display *display, void * /*user_data*/, @@ -4511,8 +4586,7 @@ static void gwl_registry_wp_pointer_gestures_add(GWL_Display *display, { display->wp_pointer_gestures = static_cast( wl_registry_bind(display->wl_registry, params->name, &zwp_pointer_gestures_v1_interface, 3)); - - gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); + gwl_registry_entry_add(display, params, nullptr); } static void gwl_registry_wp_pointer_gestures_remove(GWL_Display *display, void * /*user_data*/, @@ -4534,8 +4608,7 @@ static void gwl_registry_wp_primary_selection_device_manager_add( params->name, &zwp_primary_selection_device_manager_v1_interface, 1)); - - gwl_registry_entry_add(display, params->interface_slot, params->name, nullptr); + gwl_registry_entry_add(display, params, nullptr); } static void gwl_registry_wp_primary_selection_device_manager_remove(GWL_Display *display, void * /*user_data*/, @@ -4548,81 +4621,90 @@ static void gwl_registry_wp_primary_selection_device_manager_remove(GWL_Display } /** - * Map interfaces to to initialization functions. + * Map interfaces to initialization functions. * - * \note This list also defines the order interfaces added & removed. - * - On startup interface registration is performed from first to last. - * - On exit interface removal runs from last to first. + * \note This list also defines the order interfaces are removed. + * On exit interface removal runs from last to first to avoid potential bugs + * caused by undefined order of removal. * * In general fundamental, low level objects such as the compositor and shared memory * should be declared earlier and other interfaces that may use them should be declared later. - * - * This is useful for predictable registration, especially when one interface depends on another. - * It also helps avoid potential bugs caused by undefined order of removal. */ static const GWL_RegistryHandler gwl_registry_handlers[] = { /* Low level interfaces. */ { &wl_compositor_interface.name, gwl_registry_compositor_add, + nullptr, gwl_registry_compositor_remove, }, { &wl_shm_interface.name, gwl_registry_wl_shm_add, + nullptr, gwl_registry_wl_shm_remove, }, { &xdg_wm_base_interface.name, gwl_registry_xdg_wm_base_add, + nullptr, gwl_registry_xdg_wm_base_remove, }, /* Managers. */ { &zxdg_decoration_manager_v1_interface.name, gwl_registry_xdg_decoration_manager_add, + nullptr, gwl_registry_xdg_decoration_manager_remove, }, { &zxdg_output_manager_v1_interface.name, gwl_registry_xdg_output_manager_add, + nullptr, gwl_registry_xdg_output_manager_remove, }, { &wl_data_device_manager_interface.name, gwl_registry_wl_data_device_manager_add, + nullptr, gwl_registry_wl_data_device_manager_remove, }, { &zwp_primary_selection_device_manager_v1_interface.name, gwl_registry_wp_primary_selection_device_manager_add, + nullptr, gwl_registry_wp_primary_selection_device_manager_remove, }, { &zwp_tablet_manager_v2_interface.name, gwl_registry_wp_tablet_manager_add, + nullptr, gwl_registry_wp_tablet_manager_remove, }, { &zwp_relative_pointer_manager_v1_interface.name, gwl_registry_wp_relative_pointer_manager_add, + nullptr, gwl_registry_wp_relative_pointer_manager_remove, }, /* Higher level interfaces. */ { &zwp_pointer_constraints_v1_interface.name, gwl_registry_wp_pointer_constraints_add, + nullptr, gwl_registry_wp_pointer_constraints_remove, }, { &zwp_pointer_gestures_v1_interface.name, gwl_registry_wp_pointer_gestures_add, + nullptr, gwl_registry_wp_pointer_gestures_remove, }, /* Display outputs. */ { &wl_output_interface.name, gwl_registry_wl_output_add, + gwl_registry_wl_output_update, gwl_registry_wl_output_remove, }, /* Seats. @@ -4631,6 +4713,7 @@ static const GWL_RegistryHandler gwl_registry_handlers[] = { { &wl_seat_interface.name, gwl_registry_wl_seat_add, + gwl_registry_wl_seat_update, gwl_registry_wl_seat_remove, }, {nullptr, nullptr, nullptr}, @@ -4663,20 +4746,6 @@ static const GWL_RegistryHandler *gwl_registry_handler_from_interface_slot(int i return &gwl_registry_handlers[interface_slot]; } -/** - * Support deferred registration, needed so interface registration order on startup is predictable. - * (defined by the interface order in `gwl_registry_handlers`) - */ -struct GWL_RegistryAdd_Deferred { - GWL_RegistryAdd_Deferred *next = nullptr; - - /* Arguments to #global_handle_add, excluding some known args: - * `data`, `wl_registry` & `interface` are known by the caller - * and don't need to be stored here. */ - uint32_t name = 0; - uint32_t version = 0; -}; - static void global_handle_add(void *data, [[maybe_unused]] struct wl_registry *wl_registry, const uint32_t name, @@ -4691,27 +4760,14 @@ static void global_handle_add(void *data, bool added = false; if (interface_slot != -1) { - /* Defer registration until later (running on startup). */ - if (display->registry_add_deferred) { - GWL_RegistryAdd_Deferred *reg_add = new GWL_RegistryAdd_Deferred; - reg_add->name = name; - reg_add->version = version; - - /* Add to the list. */ - GWL_RegistryAdd_Deferred **reg_p = &display->registry_add_deferred[interface_slot]; - reg_add->next = *reg_p; - *reg_p = reg_add; - return; - } - const GWL_RegistryHandler *handler = &gwl_registry_handlers[interface_slot]; const GWL_RegistryEntry *registry_entry_prev = display->registry_entry; /* The interface name that is ensured not to be freed. */ GWL_RegisteryAdd_Params params = { .name = name, - .version = version, .interface_slot = interface_slot, + .version = version, }; handler->add_fn(display, ¶ms); @@ -4736,6 +4792,14 @@ static void global_handle_add(void *data, interface, version, name); + + /* Initialization avoids excessive calls by calling update after all have been initialized. */ + if (added) { + if (display->registry_skip_update_all == false) { + /* See doc-string for rationale on updating all on add/removal. */ + gwl_registry_entry_update_all(display, interface_slot); + } + } } /** @@ -4754,19 +4818,21 @@ static void global_handle_remove(void *data, GWL_Display *display = static_cast(data); GHOST_ASSERT(display->wl_registry == wl_registry, "Registry argument must match!"); - /* Deferred registration only happens on startup, ensure interfaces are never removed - * when in the process of adding, while it seems unlikely compositors would do this. - * Better check as it's unsupported (it could be supported if this assert is ever reached). */ - GHOST_ASSERT(!display->registry_add_deferred, - "Interface removal while deferred adding not supported"); - int interface_slot = 0; - bool found = gwl_registry_entry_remove_by_name(display, name, &interface_slot); + const bool removed = gwl_registry_entry_remove_by_name(display, name, &interface_slot); + CLOG_INFO(LOG, 2, "remove (name=%u, interface=%s)", name, - found ? *gwl_registry_handlers[interface_slot].interface_p : "(unknown)"); + removed ? *gwl_registry_handlers[interface_slot].interface_p : "(unknown)"); + + if (removed) { + if (display->registry_skip_update_all == false) { + /* See doc-string for rationale on updating all on add/removal. */ + gwl_registry_entry_update_all(display, interface_slot); + } + } } static const struct wl_registry_listener registry_listener = { @@ -4802,10 +4868,7 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background) /* Register interfaces. */ { - constexpr size_t registry_add_num = ARRAY_SIZE(gwl_registry_handlers) - 1; - GWL_RegistryAdd_Deferred *registry_add_table[registry_add_num] = {nullptr}; - display_->registry_add_deferred = registry_add_table; - + display_->registry_skip_update_all = true; struct wl_registry *registry = wl_display_get_registry(display_->wl_display); display_->wl_registry = registry; wl_registry_add_listener(registry, ®istry_listener, display_); @@ -4814,18 +4877,10 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background) /* Call callbacks for registered listeners. */ wl_display_roundtrip(display_->wl_display); - /* Run #global_handle_add again without deferred registration (for predictable order). */ - display_->registry_add_deferred = nullptr; + /* Account for dependencies between interfaces. */ + gwl_registry_entry_update_all(display_, -1); - for (size_t interface_slot = 0; interface_slot < registry_add_num; interface_slot++) { - const char *interface = *gwl_registry_handlers[interface_slot].interface_p; - while (registry_add_table[interface_slot]) { - GWL_RegistryAdd_Deferred *reg_add = registry_add_table[interface_slot]; - global_handle_add(display_, registry, reg_add->name, interface, reg_add->version); - registry_add_table[interface_slot] = reg_add->next; - delete reg_add; - } - } + display_->registry_skip_update_all = false; } #ifdef WITH_GHOST_WAYLAND_LIBDECOR -- cgit v1.2.3 From 2625c39ce77ba303e44d9ea90ee8d1bc09c0f336 Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Thu, 27 Oct 2022 16:46:51 +0200 Subject: Fix T102092: GPencil Sculpt Grab crash using Shift key There was a problem with the hash table that was not created as expected. Also fixed an unreported memory leak in Grab tool not related to this crash but detected during debug. --- .../blender/editors/gpencil/gpencil_sculpt_paint.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index 9b934876ebb..3b7336f41e8 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -1202,6 +1202,9 @@ static bool gpencil_sculpt_brush_init(bContext *C, wmOperator *op) gso->automasking_strokes = BLI_ghash_ptr_new(__func__); } else { + if (gso->automasking_strokes != NULL) { + BLI_ghash_free(gso->automasking_strokes, NULL, NULL); + } gso->automasking_strokes = NULL; } /* save mask */ @@ -1292,6 +1295,10 @@ static void gpencil_sculpt_brush_exit(bContext *C, wmOperator *op) } default: + if (gso->stroke_customdata != NULL) { + BLI_ghash_free(gso->stroke_customdata, NULL, NULL); + gso->stroke_customdata = NULL; + } break; } @@ -2075,6 +2082,20 @@ static void gpencil_sculpt_brush_apply_event(bContext *C, wmOperator *op, const if (gso->brush == NULL) { gso->brush = gso->brush_prev; } + Brush *brush = gso->brush; + if (brush->gpencil_settings->sculpt_mode_flag & + (GP_SCULPT_FLAGMODE_AUTOMASK_STROKE | GP_SCULPT_FLAGMODE_AUTOMASK_LAYER | + GP_SCULPT_FLAGMODE_AUTOMASK_MATERIAL)) { + if (gso->automasking_strokes == NULL) { + gso->automasking_strokes = BLI_ghash_ptr_new(__func__); + } + } + else { + if (gso->automasking_strokes != NULL) { + BLI_ghash_free(gso->automasking_strokes, NULL, NULL); + } + gso->automasking_strokes = NULL; + } } else { if (gso->brush_prev != NULL) { -- cgit v1.2.3 From c967bdcbb1e8496c1e0d440aebb4bab97ad4508b Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Thu, 27 Oct 2022 09:16:51 -0600 Subject: GPencil: Fix MSVC warning in lineart_cpp_bridge.cc MSVC give a rather large warning when using blender::parallel_sort without using a lambda for the comparison. Fixed by using a lambda --- .../intern/lineart/lineart_cpp_bridge.cc | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpp_bridge.cc b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpp_bridge.cc index 5e741ccbd55..85f158d42e6 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpp_bridge.cc +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpp_bridge.cc @@ -9,17 +9,15 @@ #include "MOD_lineart.h" #include "lineart_intern.h" -static bool cmp_adjacent_items(const LineartAdjacentEdge &p1, const LineartAdjacentEdge &p2) -{ - int a = p1.v1 - p2.v1; - int b = p1.v2 - p2.v2; - /* parallel_sort() requires cmp() to return true when the first element needs to appear before - * the second element in the sorted array, false otherwise (strict weak ordering), see - * https://en.cppreference.com/w/cpp/named_req/Compare. */ - return a < 0 ? true : (a == 0 ? b < 0 : false); -} - void lineart_sort_adjacent_items(LineartAdjacentEdge *ai, int length) { - blender::parallel_sort(ai, ai + length, cmp_adjacent_items); + blender::parallel_sort( + ai, ai + length, [](const LineartAdjacentEdge &p1, const LineartAdjacentEdge &p2) { + int a = p1.v1 - p2.v1; + int b = p1.v2 - p2.v2; + /* parallel_sort() requires cmp() to return true when the first element needs to appear + * before the second element in the sorted array, false otherwise (strict weak ordering), + * see https://en.cppreference.com/w/cpp/named_req/Compare. */ + return a < 0 ? true : (a == 0 ? b < 0 : false); + }); } -- cgit v1.2.3 From 7c3cd63f95f8cb54aece57b4a4788abd10a11253 Mon Sep 17 00:00:00 2001 From: Anton Raves Date: Thu, 27 Oct 2022 13:29:03 -0600 Subject: Fix T102085: X11 Startup crash wl_registry_destroy does not enjoy being fed a null pointer. Added a null check to keep it out of trouble. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index d4eabfb815d..0f609395124 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -806,8 +806,10 @@ struct GWL_Display { static void gwl_display_destroy(GWL_Display *display) { - wl_registry_destroy(display->wl_registry); - display->wl_registry = nullptr; + if (display->wl_registry) { + wl_registry_destroy(display->wl_registry); + display->wl_registry = nullptr; + } /* Unregister items in reverse order. */ gwl_registry_entry_remove_all(display); -- cgit v1.2.3 From 454dd3f7f0a30837c58cece3740754e2fdd7a6c4 Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Thu, 27 Oct 2022 23:09:14 +0200 Subject: Cycles: fix up logic in oneAPI devices filtering CYCLES_ONEAPI_ALL_DEVICES environment variable wasn't working as intended after 305b92e05f748a0fd9cb62b9829791d717ba2d57. --- intern/cycles/device/oneapi/device_impl.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/intern/cycles/device/oneapi/device_impl.cpp b/intern/cycles/device/oneapi/device_impl.cpp index 3588b75713b..d0ddd69289c 100644 --- a/intern/cycles/device/oneapi/device_impl.cpp +++ b/intern/cycles/device/oneapi/device_impl.cpp @@ -668,8 +668,9 @@ int OneapiDevice::parse_driver_build_version(const sycl::device &device) std::vector OneapiDevice::available_devices() { bool allow_all_devices = false; - if (getenv("CYCLES_ONEAPI_ALL_DEVICES") != nullptr) + if (getenv("CYCLES_ONEAPI_ALL_DEVICES") != nullptr) { allow_all_devices = true; + } const std::vector &oneapi_platforms = sycl::platform::get_platforms(); @@ -686,15 +687,16 @@ std::vector OneapiDevice::available_devices() platform.get_devices(sycl::info::device_type::gpu); for (const sycl::device &device : oneapi_devices) { + bool filter_out = false; if (!allow_all_devices) { - bool filter_out = false; - /* For now we support all Intel(R) Arc(TM) devices and likely any future GPU, * assuming they have either more than 96 Execution Units or not 7 threads per EU. * Official support can be broaden to older and smaller GPUs once ready. */ - if (device.is_gpu() && platform.get_backend() == sycl::backend::ext_oneapi_level_zero) { - /* Filtered-out defaults in-case these values aren't available through too old L0 - * runtime. */ + if (!device.is_gpu() || platform.get_backend() != sycl::backend::ext_oneapi_level_zero) { + filter_out = true; + } + else { + /* Filtered-out defaults in-case these values aren't available. */ int number_of_eus = 96; int threads_per_eu = 7; if (device.has(sycl::aspect::ext_intel_gpu_eu_count)) { @@ -718,13 +720,9 @@ std::vector OneapiDevice::available_devices() } } } - else if (!allow_all_devices) { - filter_out = true; - } - - if (!filter_out) { - available_devices.push_back(device); - } + } + if (!filter_out) { + available_devices.push_back(device); } } } -- cgit v1.2.3 From b544d989d1535705cfd77312829bf6d09394ea5f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 28 Oct 2022 09:29:00 +1100 Subject: GHOST/Wayland: unlock clipboard mutex on failure When the Wayland pipe can't be opened, don't leave the mutex locked. Also skip checking wl_data_device_manager when reading from the primary clipboard. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 0f609395124..36894807e73 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1681,6 +1681,9 @@ static const char *read_buffer_from_data_offer(GWL_DataOffer *data_offer, int pipefd[2]; if (UNLIKELY(pipe(pipefd) != 0)) { CLOG_WARN(LOG, "error creating pipe: %s", std::strerror(errno)); + if (mutex) { + mutex->unlock(); + } return nullptr; } wl_data_offer_receive(data_offer->id, mime_receive, pipefd[1]); @@ -1707,6 +1710,9 @@ static const char *read_buffer_from_primary_selection_offer( int pipefd[2]; if (UNLIKELY(pipe(pipefd) != 0)) { CLOG_WARN(LOG, "error creating pipe: %s", std::strerror(errno)); + if (mutex) { + mutex->unlock(); + } return nullptr; } zwp_primary_selection_offer_v1_receive(data_offer->id, mime_receive, pipefd[1]); @@ -5114,6 +5120,9 @@ static void system_clipboard_put_primary_selection(GWL_Display *display, const c static void system_clipboard_put(GWL_Display *display, const char *buffer) { + if (!display->wl_data_device_manager) { + return; + } GWL_Seat *seat = display->seats[0]; std::lock_guard lock{seat->data_source_mutex}; @@ -5140,7 +5149,7 @@ static void system_clipboard_put(GWL_Display *display, const char *buffer) void GHOST_SystemWayland::putClipboard(const char *buffer, bool selection) const { - if (UNLIKELY(!display_->wl_data_device_manager || display_->seats.empty())) { + if (UNLIKELY(display_->seats.empty())) { return; } -- cgit v1.2.3 From d488a87d7015cc5303e7bea46b40fad467594f1c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 28 Oct 2022 09:41:53 +1100 Subject: GHOST/Wayland: postpone reading from the clipboard until needed A copy of the clipboard was always being, changes would re-read it. Now read the clipboard on request. This avoids having to keep a copy of the clipboard in memory as well as the need to keep a thread to running to read the clipboard for each data-offer. To prevent a deadlock when pasting from Blender's own clipboard. - Sending the clipboard (using write(..)) runs in a background thread. - Reading the clipboard uses a thread that performs round-trips to the Wayland server to prevent until the read is complete. This is an update to [0] that resolves the deadlock. [0]: c03838dbc8cc4a85cfc93914493a0f1562a53366 --- intern/ghost/intern/GHOST_SystemWayland.cpp | 292 ++++++++++++++++------------ intern/ghost/intern/GHOST_SystemWayland.h | 3 - 2 files changed, 169 insertions(+), 126 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 36894807e73..49bed2f9c0e 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -280,15 +280,6 @@ static void gwl_simple_buffer_free_data(GWL_SimpleBuffer *buffer) buffer->data_size = 0; } -static void gwl_simple_buffer_set_and_take_ownership(GWL_SimpleBuffer *buffer, - const char *data, - size_t data_size) -{ - free(const_cast(buffer->data)); - buffer->data = data; - buffer->data_size = data_size; -} - static void gwl_simple_buffer_set_from_string(GWL_SimpleBuffer *buffer, const char *str) { free(const_cast(buffer->data)); @@ -298,14 +289,6 @@ static void gwl_simple_buffer_set_from_string(GWL_SimpleBuffer *buffer, const ch buffer->data = data; } -static char *gwl_simple_buffer_as_string(const GWL_SimpleBuffer *buffer) -{ - char *buffer_str = static_cast(malloc(buffer->data_size + 1)); - memcpy(buffer_str, buffer->data, buffer->data_size); - buffer_str[buffer->data_size] = '\0'; - return buffer_str; -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -798,10 +781,6 @@ struct GWL_Display { struct zwp_pointer_gestures_v1 *wp_pointer_gestures = nullptr; struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_device_manager = nullptr; - - GWL_SimpleBuffer clipboard; - GWL_SimpleBuffer clipboard_primary; - std::mutex clipboard_mutex; }; static void gwl_display_destroy(GWL_Display *display) @@ -838,12 +817,6 @@ static void gwl_display_destroy(GWL_Display *display) wl_display_disconnect(display->wl_display); } - { - std::lock_guard lock{display->clipboard_mutex}; - gwl_simple_buffer_free_data(&display->clipboard); - gwl_simple_buffer_free_data(&display->clipboard_primary); - } - delete display; } @@ -1613,7 +1586,7 @@ static void dnd_events(const GWL_Seat *const seat, const GHOST_TEventType event) * Read from `fd` into a buffer which is returned. * \return the buffer or null on failure. */ -static const char *read_file_as_buffer(const int fd, size_t *r_len) +static char *read_file_as_buffer(const int fd, const bool nil_terminate, size_t *r_len) { struct ByteChunk { ByteChunk *next; @@ -1649,14 +1622,23 @@ static const char *read_file_as_buffer(const int fd, size_t *r_len) char *buf = nullptr; if (ok) { - buf = static_cast(malloc(len)); + buf = static_cast(malloc(len + (nil_terminate ? 1 : 0))); if (UNLIKELY(buf == nullptr)) { CLOG_WARN(LOG, "unable to allocate file buffer: %zu bytes", len); ok = false; } } - *r_len = ok ? len : 0; + if (ok) { + *r_len = len; + if (nil_terminate) { + buf[len] = '\0'; + } + } + else { + *r_len = 0; + } + char *buf_stride = buf; while (chunk_first) { if (ok) { @@ -1673,10 +1655,11 @@ static const char *read_file_as_buffer(const int fd, size_t *r_len) return buf; } -static const char *read_buffer_from_data_offer(GWL_DataOffer *data_offer, - const char *mime_receive, - std::mutex *mutex, - size_t *r_len) +static char *read_buffer_from_data_offer(GWL_DataOffer *data_offer, + const char *mime_receive, + std::mutex *mutex, + const bool nil_terminate, + size_t *r_len) { int pipefd[2]; if (UNLIKELY(pipe(pipefd) != 0)) { @@ -1696,16 +1679,16 @@ static const char *read_buffer_from_data_offer(GWL_DataOffer *data_offer, } /* WARNING: `data_offer` may be freed from now on. */ - const char *buf = read_file_as_buffer(pipefd[0], r_len); + char *buf = read_file_as_buffer(pipefd[0], nil_terminate, r_len); close(pipefd[0]); return buf; } -static const char *read_buffer_from_primary_selection_offer( - GWL_PrimarySelection_DataOffer *data_offer, - const char *mime_receive, - std::mutex *mutex, - size_t *r_len) +static char *read_buffer_from_primary_selection_offer(GWL_PrimarySelection_DataOffer *data_offer, + const char *mime_receive, + std::mutex *mutex, + const bool nil_terminate, + size_t *r_len) { int pipefd[2]; if (UNLIKELY(pipe(pipefd) != 0)) { @@ -1724,7 +1707,7 @@ static const char *read_buffer_from_primary_selection_offer( mutex->unlock(); } /* WARNING: `data_offer` may be freed from now on. */ - const char *buf = read_file_as_buffer(pipefd[0], r_len); + char *buf = read_file_as_buffer(pipefd[0], nil_terminate, r_len); close(pipefd[0]); return buf; } @@ -1748,15 +1731,22 @@ static void data_source_handle_send(void *data, const int32_t fd) { GWL_Seat *seat = static_cast(data); - std::lock_guard lock{seat->data_source_mutex}; CLOG_INFO(LOG, 2, "send"); - const char *const buffer = seat->data_source->buffer_out.data; - if (UNLIKELY(write(fd, buffer, seat->data_source->buffer_out.data_size) < 0)) { - CLOG_WARN(LOG, "error writing to clipboard: %s", std::strerror(errno)); - } - close(fd); + auto write_file_fn = [](GWL_Seat *seat, const int fd) { + if (UNLIKELY(write(fd, + seat->data_source->buffer_out.data, + seat->data_source->buffer_out.data_size) < 0)) { + CLOG_WARN(LOG, "error writing to clipboard: %s", std::strerror(errno)); + } + close(fd); + seat->data_source_mutex.unlock(); + }; + + seat->data_source_mutex.lock(); + std::thread write_thread(write_file_fn, seat, fd); + write_thread.detach(); } static void data_source_handle_cancelled(void *data, struct wl_data_source *wl_data_source) @@ -1980,7 +1970,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat size_t data_buf_len = 0; const char *data_buf = read_buffer_from_data_offer( - data_offer, mime_receive.c_str(), nullptr, &data_buf_len); + data_offer, mime_receive.c_str(), nullptr, false, &data_buf_len); std::string data = data_buf ? std::string(data_buf, data_buf_len) : ""; free(const_cast(data_buf)); @@ -2084,34 +2074,6 @@ static void data_device_handle_selection(void *data, /* Get new data offer. */ data_offer = static_cast(wl_data_offer_get_user_data(id)); seat->data_offer_copy_paste = data_offer; - - auto read_selection_fn = [](GWL_Seat *seat) { - GHOST_SystemWayland *const system = seat->system; - seat->data_offer_copy_paste_mutex.lock(); - - GWL_DataOffer *data_offer = seat->data_offer_copy_paste; - std::string mime_receive; - for (const std::string type : {mime_text_utf8, mime_text_plain}) { - if (data_offer->types.count(type)) { - mime_receive = type; - break; - } - } - - size_t data_len = 0; - const char *data = read_buffer_from_data_offer( - data_offer, mime_receive.c_str(), &seat->data_offer_copy_paste_mutex, &data_len); - - { - std::mutex &clipboard_mutex = system->clipboard_mutex(); - std::lock_guard lock{clipboard_mutex}; - GWL_SimpleBuffer *buf = system->clipboard_data(false); - gwl_simple_buffer_set_and_take_ownership(buf, data, data_len); - } - }; - - std::thread read_thread(read_selection_fn, seat); - read_thread.detach(); } static const struct wl_data_device_listener data_device_listener = { @@ -3664,33 +3626,6 @@ static void primary_selection_device_handle_selection( GWL_PrimarySelection_DataOffer *data_offer = static_cast( zwp_primary_selection_offer_v1_get_user_data(id)); primary->data_offer = data_offer; - - auto read_selection_fn = [](GWL_PrimarySelection *primary) { - GHOST_SystemWayland *system = static_cast(GHOST_ISystem::getSystem()); - primary->data_offer_mutex.lock(); - - GWL_PrimarySelection_DataOffer *data_offer = primary->data_offer; - std::string mime_receive; - for (const std::string type : {mime_text_utf8, mime_text_plain}) { - if (data_offer->types.count(type)) { - mime_receive = type; - break; - } - } - size_t data_len = 0; - const char *data = read_buffer_from_primary_selection_offer( - data_offer, mime_receive.c_str(), &primary->data_offer_mutex, &data_len); - - { - std::mutex &clipboard_mutex = system->clipboard_mutex(); - std::lock_guard lock{clipboard_mutex}; - GWL_SimpleBuffer *buf = system->clipboard_data(true); - gwl_simple_buffer_set_and_take_ownership(buf, data, data_len); - } - }; - - std::thread read_thread(read_selection_fn, primary); - read_thread.detach(); } static const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener = { @@ -3718,14 +3653,19 @@ static void primary_selection_source_send(void *data, GWL_PrimarySelection *primary = static_cast(data); - std::lock_guard lock{primary->data_source_mutex}; - GWL_PrimarySelection_DataSource *data_source = primary->data_source; + auto write_file_fn = [](GWL_PrimarySelection *primary, const int fd) { + if (UNLIKELY(write(fd, + primary->data_source->buffer_out.data, + primary->data_source->buffer_out.data_size) < 0)) { + CLOG_WARN(LOG, "error writing to primary clipboard: %s", std::strerror(errno)); + } + close(fd); + primary->data_source_mutex.unlock(); + }; - const char *const buffer = data_source->buffer_out.data; - if (UNLIKELY(write(fd, buffer, data_source->buffer_out.data_size) < 0)) { - CLOG_WARN(LOG, "error writing to primary clipboard: %s", std::strerror(errno)); - } - close(fd); + primary->data_source_mutex.lock(); + std::thread write_thread(write_file_fn, primary, fd); + write_thread.detach(); } static void primary_selection_source_cancelled(void *data, @@ -5075,13 +5015,129 @@ GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const return GHOST_kSuccess; } +/** + * Return a mime type which is supported by GHOST and exists in `types` + * (defined by the data offer). + */ +static const char *system_clipboard_text_mime_type( + const std::unordered_set &data_offer_types) +{ + const char *ghost_supported_types[] = {mime_text_utf8, mime_text_plain}; + for (size_t i = 0; i < ARRAY_SIZE(ghost_supported_types); i++) { + if (data_offer_types.count(ghost_supported_types[i])) { + return ghost_supported_types[i]; + } + } + return nullptr; +} + +static char *system_clipboard_get_primary_selection(GWL_Display *display) +{ + GWL_Seat *seat = display->seats[0]; + GWL_PrimarySelection *primary = &seat->primary_selection; + std::mutex &mutex = primary->data_offer_mutex; + + mutex.lock(); + bool mutex_locked = true; + char *data = nullptr; + + GWL_PrimarySelection_DataOffer *data_offer = primary->data_offer; + if (data_offer != nullptr) { + const char *mime_receive = system_clipboard_text_mime_type(data_offer->types); + if (mime_receive) { + /* Receive the clipboard in a thread, performing round-trips while waiting. + * This is needed so pasting contents from our own `primary->data_source` doesn't hang. */ + struct ThreadResult { + char *data = nullptr; + std::atomic done = false; + } thread_result; + auto read_clipboard_fn = [](GWL_PrimarySelection_DataOffer *data_offer, + const char *mime_receive, + std::mutex *mutex, + struct ThreadResult *thread_result) { + size_t data_len = 0; + thread_result->data = read_buffer_from_primary_selection_offer( + data_offer, mime_receive, mutex, true, &data_len); + thread_result->done = true; + }; + std::thread read_thread(read_clipboard_fn, data_offer, mime_receive, &mutex, &thread_result); + read_thread.detach(); + + while (!thread_result.done) { + wl_display_roundtrip(display->wl_display); + } + data = thread_result.data; + + /* Reading the data offer unlocks the mutex. */ + mutex_locked = false; + } + } + if (mutex_locked) { + mutex.unlock(); + } + return data; +} + +static char *system_clipboard_get(GWL_Display *display) +{ + GWL_Seat *seat = display->seats[0]; + std::mutex &mutex = seat->data_offer_copy_paste_mutex; + + mutex.lock(); + bool mutex_locked = true; + char *data = nullptr; + + GWL_DataOffer *data_offer = seat->data_offer_copy_paste; + if (data_offer != nullptr) { + const char *mime_receive = system_clipboard_text_mime_type(data_offer->types); + if (mime_receive) { + /* Receive the clipboard in a thread, performing round-trips while waiting. + * This is needed so pasting contents from our own `seat->data_source` doesn't hang. */ + struct ThreadResult { + char *data = nullptr; + std::atomic done = false; + } thread_result; + auto read_clipboard_fn = [](GWL_DataOffer *data_offer, + const char *mime_receive, + std::mutex *mutex, + struct ThreadResult *thread_result) { + size_t data_len = 0; + thread_result->data = read_buffer_from_data_offer( + data_offer, mime_receive, mutex, true, &data_len); + thread_result->done = true; + }; + std::thread read_thread(read_clipboard_fn, data_offer, mime_receive, &mutex, &thread_result); + read_thread.detach(); + + while (!thread_result.done) { + wl_display_roundtrip(display->wl_display); + } + data = thread_result.data; + + /* Reading the data offer unlocks the mutex. */ + mutex_locked = false; + } + } + if (mutex_locked) { + mutex.unlock(); + } + return data; +} + char *GHOST_SystemWayland::getClipboard(bool selection) const { - const GWL_SimpleBuffer *buf = clipboard_data(selection); - if (buf->data == nullptr) { + if (UNLIKELY(display_->seats.empty())) { return nullptr; } - return gwl_simple_buffer_as_string(buf); + + char *data = nullptr; + if (selection) { + data = system_clipboard_get_primary_selection(display_); + } + else { + data = system_clipboard_get(display_); + } + return data; } static void system_clipboard_put_primary_selection(GWL_Display *display, const char *buffer) @@ -6173,16 +6229,6 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod return GHOST_kSuccess; } -struct GWL_SimpleBuffer *GHOST_SystemWayland::clipboard_data(bool selection) const -{ - return selection ? &display_->clipboard_primary : &display_->clipboard; -} - -struct std::mutex &GHOST_SystemWayland::clipboard_mutex() const -{ - return display_->clipboard_mutex; -} - #ifdef WITH_GHOST_WAYLAND_LIBDECOR bool GHOST_SystemWayland::use_libdecor_runtime() { diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index 7c5459fc461..db4fef23538 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -189,9 +189,6 @@ class GHOST_SystemWayland : public GHOST_System { wl_surface *wl_surface, int scale); - struct GWL_SimpleBuffer *clipboard_data(bool selection) const; - struct std::mutex &clipboard_mutex() const; - #ifdef WITH_GHOST_WAYLAND_LIBDECOR static bool use_libdecor_runtime(); #endif -- cgit v1.2.3 From 00533de7d53d389931b1e310027bb329f342d2ca Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 28 Oct 2022 10:46:39 +1100 Subject: Cleanup: move GWL_DataOffer in_use to the 'dnd' struct It wasn't clear that this is only used for drag & drop, also don't use an atomic type as all access is guarded by the drag & drop mutex. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 49bed2f9c0e..9151cfa008d 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -360,9 +360,13 @@ struct GWL_TabletTool { struct GWL_DataOffer { struct wl_data_offer *id = nullptr; std::unordered_set types; - std::atomic in_use = false; struct { + /** + * Prevents freeing after #wl_data_device_listener.leave, + * before #wl_data_device_listener.drop. + */ + bool in_use = false; /** * Bit-mask with available drop options. * #WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY, #WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE.. etc. @@ -564,7 +568,6 @@ static void gwl_xdg_decor_system_destroy(struct GWL_Display *display, GWL_XDG_De struct GWL_PrimarySelection_DataOffer { struct zwp_primary_selection_offer_v1 *id = nullptr; - std::atomic in_use = false; std::unordered_set types; }; @@ -1672,7 +1675,8 @@ static char *read_buffer_from_data_offer(GWL_DataOffer *data_offer, wl_data_offer_receive(data_offer->id, mime_receive, pipefd[1]); close(pipefd[1]); - data_offer->in_use.store(false); + /* Only for DND (A no-op to disable for clipboard data-offer). */ + data_offer->dnd.in_use = false; if (mutex) { mutex->unlock(); @@ -1701,8 +1705,6 @@ static char *read_buffer_from_primary_selection_offer(GWL_PrimarySelection_DataO zwp_primary_selection_offer_v1_receive(data_offer->id, mime_receive, pipefd[1]); close(pipefd[1]); - data_offer->in_use.store(false); - if (mutex) { mutex->unlock(); } @@ -1897,7 +1899,7 @@ static void data_device_handle_enter(void *data, seat->data_offer_dnd = static_cast(wl_data_offer_get_user_data(id)); GWL_DataOffer *data_offer = seat->data_offer_dnd; - data_offer->in_use.store(true); + data_offer->dnd.in_use = true; data_offer->dnd.xy[0] = x; data_offer->dnd.xy[1] = y; @@ -1924,7 +1926,7 @@ static void data_device_handle_leave(void *data, struct wl_data_device * /*wl_da dnd_events(seat, GHOST_kEventDraggingExited); seat->wl_surface_focus_dnd = nullptr; - if (seat->data_offer_dnd && !seat->data_offer_dnd->in_use.load()) { + if (seat->data_offer_dnd && !seat->data_offer_dnd->dnd.in_use) { wl_data_offer_destroy(seat->data_offer_dnd->id); delete seat->data_offer_dnd; seat->data_offer_dnd = nullptr; -- cgit v1.2.3 From d447cf9704ae016d543a28977db6cc6066ed1fb1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 28 Oct 2022 12:08:54 +1100 Subject: Cleanup: use plain 'char *' for mime types in GHOST/Wayland There wasn't much advantage in using C++ native types as all Wayland API's deal with C strings. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 62 +++++++++++++++++------------ 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 9151cfa008d..c4a98b672a4 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1307,19 +1307,19 @@ static constexpr const char *mime_text_plain = "text/plain"; static constexpr const char *mime_text_utf8 = "text/plain;charset=utf-8"; static constexpr const char *mime_text_uri = "text/uri-list"; -static const std::unordered_map mime_dnd = { - {mime_text_plain, GHOST_kDragnDropTypeString}, - {mime_text_utf8, GHOST_kDragnDropTypeString}, - {mime_text_uri, GHOST_kDragnDropTypeFilenames}, -}; - -static const std::vector mime_preference_order = { +static const char *mime_preference_order[] = { mime_text_uri, mime_text_utf8, mime_text_plain, }; +/* Aligned to `mime_preference_order`. */ +static const GHOST_TDragnDropTypes mime_preference_order_ghost[] = { + GHOST_kDragnDropTypeString, + GHOST_kDragnDropTypeString, + GHOST_kDragnDropTypeFilenames, +}; -static const std::vector mime_send = { +static const char *mime_send[] = { "UTF8_STRING", "COMPOUND_TEXT", "TEXT", @@ -1578,9 +1578,10 @@ static void dnd_events(const GWL_Seat *const seat, const GHOST_TEventType event) }; const uint64_t time = seat->system->getMilliSeconds(); - for (const std::string &type : mime_preference_order) { - seat->system->pushEvent(new GHOST_EventDragnDrop( - time, event, mime_dnd.at(type), win, UNPACK2(event_xy), nullptr)); + for (size_t i = 0; i < ARRAY_SIZE(mime_preference_order_ghost); i++) { + const GHOST_TDragnDropTypes type = mime_preference_order_ghost[i]; + seat->system->pushEvent( + new GHOST_EventDragnDrop(time, event, type, win, UNPACK2(event_xy), nullptr)); } } } @@ -1908,8 +1909,9 @@ static void data_device_handle_enter(void *data, WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY); - for (const std::string &type : mime_preference_order) { - wl_data_offer_accept(id, serial, type.c_str()); + for (size_t i = 0; i < ARRAY_SIZE(mime_preference_order); i++) { + const char *type = mime_preference_order[i]; + wl_data_offer_accept(id, serial, type); } seat->wl_surface_focus_dnd = wl_surface; @@ -1957,27 +1959,35 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat GWL_DataOffer *data_offer = seat->data_offer_dnd; - const std::string mime_receive = *std::find_first_of(mime_preference_order.begin(), - mime_preference_order.end(), - data_offer->types.begin(), - data_offer->types.end()); + /* Use a blank string for `mime_receive` to prevent crashes, although could also be `nullptr`. + * Failure to set this to a known type just means the file won't have any special handling. + * GHOST still generates a dropped file event. + * NOTE: this string can be compared with `mime_text_plain`, `mime_text_uri` etc... + * as the this always points to the same values. */ + const char *mime_receive = ""; + for (size_t i = 0; i < ARRAY_SIZE(mime_preference_order); i++) { + const char *type = mime_preference_order[i]; + if (data_offer->types.count(type)) { + mime_receive = type; + break; + } + } - CLOG_INFO(LOG, 2, "drop mime_recieve=%s", mime_receive.c_str()); + CLOG_INFO(LOG, 2, "drop mime_recieve=%s", mime_receive); auto read_uris_fn = [](GWL_Seat *const seat, GWL_DataOffer *data_offer, wl_surface *wl_surface, - const std::string mime_receive) { + const char *mime_receive) { const wl_fixed_t xy[2] = {UNPACK2(data_offer->dnd.xy)}; size_t data_buf_len = 0; const char *data_buf = read_buffer_from_data_offer( - data_offer, mime_receive.c_str(), nullptr, false, &data_buf_len); + data_offer, mime_receive, nullptr, false, &data_buf_len); std::string data = data_buf ? std::string(data_buf, data_buf_len) : ""; free(const_cast(data_buf)); - CLOG_INFO( - LOG, 2, "drop_read_uris mime_receive=%s, data=%s", mime_receive.c_str(), data.c_str()); + CLOG_INFO(LOG, 2, "drop_read_uris mime_receive=%s, data=%s", mime_receive, data.c_str()); wl_data_offer_finish(data_offer->id); wl_data_offer_destroy(data_offer->id); @@ -5166,8 +5176,8 @@ static void system_clipboard_put_primary_selection(GWL_Display *display, const c zwp_primary_selection_source_v1_add_listener( data_source->wp_source, &primary_selection_source_listener, primary); - for (const std::string &type : mime_send) { - zwp_primary_selection_source_v1_offer(data_source->wp_source, type.c_str()); + for (size_t i = 0; i < ARRAY_SIZE(mime_send); i++) { + zwp_primary_selection_source_v1_offer(data_source->wp_source, mime_send[i]); } if (seat->wp_primary_selection_device) { @@ -5195,8 +5205,8 @@ static void system_clipboard_put(GWL_Display *display, const char *buffer) wl_data_source_add_listener(data_source->wl_source, &data_source_listener, seat); - for (const std::string &type : mime_send) { - wl_data_source_offer(data_source->wl_source, type.c_str()); + for (size_t i = 0; i < ARRAY_SIZE(mime_send); i++) { + wl_data_source_offer(data_source->wl_source, mime_send[i]); } if (seat->wl_data_device) { -- cgit v1.2.3 From 18e0f741c8194e4c87c58d874029c77c9a9f5ced Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 28 Oct 2022 12:16:25 +1100 Subject: GHOST/Wayland: improve code-comments --- intern/ghost/intern/GHOST_SystemWayland.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index c4a98b672a4..eaf42bee683 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -786,8 +786,14 @@ struct GWL_Display { struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_device_manager = nullptr; }; +/** + * Free the #GWL_Display and it's related members. + * \note This may run on a partially initialized struct, so it can't be assumed all mebers are set. + */ static void gwl_display_destroy(GWL_Display *display) { + /* For typical WAYLAND use this will always be set. + * However when WAYLAND isn't running, this will early-exit and be null. */ if (display->wl_registry) { wl_registry_destroy(display->wl_registry); display->wl_registry = nullptr; @@ -1037,7 +1043,7 @@ static void gwl_registry_entry_remove_all(GWL_Display *display) * In practice this isn't a problem as so there are so few elements in `display->registry_entry`, * so few use update functions and adding/removal at runtime is rarely called (plugging/unplugging) * hardware for e.g. So while it's possible to store dependency links to avoid unnecessary - * looping over data - so it ends up being a non issue. + * looping over data - it ends up being a non issue. */ static void gwl_registry_entry_update_all(GWL_Display *display, const int interface_slot_exclude) { -- cgit v1.2.3 From 586d9214b75b070bc37d06860be62404974dba91 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 28 Oct 2022 12:21:42 +1100 Subject: Cleanup: use common prefix for static ghost/wayland variables File level static variable names weren't well distinguished from others. Use `ghost_wl_` prefix for static variables. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 58 ++++++++++++++--------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index eaf42bee683..72a9b5beef1 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1268,7 +1268,7 @@ static GHOST_TTabletMode tablet_tool_map_type(enum zwp_tablet_tool_v2_type wp_ta static const int default_cursor_size = 24; -static const std::unordered_map cursors = { +static const std::unordered_map ghost_wl_cursors = { {GHOST_kStandardCursorDefault, "left_ptr"}, {GHOST_kStandardCursorRightArrow, "right_ptr"}, {GHOST_kStandardCursorLeftArrow, "left_ptr"}, @@ -1309,23 +1309,23 @@ static const std::unordered_map cursors = { {GHOST_kStandardCursorCopy, "copy"}, }; -static constexpr const char *mime_text_plain = "text/plain"; -static constexpr const char *mime_text_utf8 = "text/plain;charset=utf-8"; -static constexpr const char *mime_text_uri = "text/uri-list"; +static constexpr const char *ghost_wl_mime_text_plain = "text/plain"; +static constexpr const char *ghost_wl_mime_text_utf8 = "text/plain;charset=utf-8"; +static constexpr const char *ghost_wl_mime_text_uri = "text/uri-list"; -static const char *mime_preference_order[] = { - mime_text_uri, - mime_text_utf8, - mime_text_plain, +static const char *ghost_wl_mime_preference_order[] = { + ghost_wl_mime_text_uri, + ghost_wl_mime_text_utf8, + ghost_wl_mime_text_plain, }; -/* Aligned to `mime_preference_order`. */ -static const GHOST_TDragnDropTypes mime_preference_order_ghost[] = { +/* Aligned to `ghost_wl_mime_preference_order`. */ +static const GHOST_TDragnDropTypes ghost_wl_mime_preference_order_type[] = { GHOST_kDragnDropTypeString, GHOST_kDragnDropTypeString, GHOST_kDragnDropTypeFilenames, }; -static const char *mime_send[] = { +static const char *ghost_wl_mime_send[] = { "UTF8_STRING", "COMPOUND_TEXT", "TEXT", @@ -1584,8 +1584,8 @@ static void dnd_events(const GWL_Seat *const seat, const GHOST_TEventType event) }; const uint64_t time = seat->system->getMilliSeconds(); - for (size_t i = 0; i < ARRAY_SIZE(mime_preference_order_ghost); i++) { - const GHOST_TDragnDropTypes type = mime_preference_order_ghost[i]; + for (size_t i = 0; i < ARRAY_SIZE(ghost_wl_mime_preference_order_type); i++) { + const GHOST_TDragnDropTypes type = ghost_wl_mime_preference_order_type[i]; seat->system->pushEvent( new GHOST_EventDragnDrop(time, event, type, win, UNPACK2(event_xy), nullptr)); } @@ -1915,8 +1915,8 @@ static void data_device_handle_enter(void *data, WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY); - for (size_t i = 0; i < ARRAY_SIZE(mime_preference_order); i++) { - const char *type = mime_preference_order[i]; + for (size_t i = 0; i < ARRAY_SIZE(ghost_wl_mime_preference_order); i++) { + const char *type = ghost_wl_mime_preference_order[i]; wl_data_offer_accept(id, serial, type); } @@ -1971,8 +1971,8 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat * NOTE: this string can be compared with `mime_text_plain`, `mime_text_uri` etc... * as the this always points to the same values. */ const char *mime_receive = ""; - for (size_t i = 0; i < ARRAY_SIZE(mime_preference_order); i++) { - const char *type = mime_preference_order[i]; + for (size_t i = 0; i < ARRAY_SIZE(ghost_wl_mime_preference_order); i++) { + const char *type = ghost_wl_mime_preference_order[i]; if (data_offer->types.count(type)) { mime_receive = type; break; @@ -2006,7 +2006,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat GHOST_SystemWayland *const system = seat->system; - if (mime_receive == mime_text_uri) { + if (mime_receive == ghost_wl_mime_text_uri) { static constexpr const char *file_proto = "file://"; /* NOTE: some applications CRLF (`\r\n`) GTK3 for e.g. & others don't `pcmanfm-qt`. * So support both, once `\n` is found, strip the preceding `\r` if found. */ @@ -2051,7 +2051,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat wl_fixed_to_int(scale * xy[1]), flist)); } - else if (ELEM(mime_receive, mime_text_plain, mime_text_utf8)) { + else if (ELEM(mime_receive, ghost_wl_mime_text_plain, ghost_wl_mime_text_utf8)) { /* TODO: enable use of internal functions 'txt_insert_buf' and * 'text_update_edited' to behave like dropped text was pasted. */ CLOG_INFO(LOG, 2, "drop_read_uris_fn (text_plain, text_utf8), unhandled!"); @@ -5040,7 +5040,7 @@ GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const static const char *system_clipboard_text_mime_type( const std::unordered_set &data_offer_types) { - const char *ghost_supported_types[] = {mime_text_utf8, mime_text_plain}; + const char *ghost_supported_types[] = {ghost_wl_mime_text_utf8, ghost_wl_mime_text_plain}; for (size_t i = 0; i < ARRAY_SIZE(ghost_supported_types); i++) { if (data_offer_types.count(ghost_supported_types[i])) { return ghost_supported_types[i]; @@ -5182,8 +5182,8 @@ static void system_clipboard_put_primary_selection(GWL_Display *display, const c zwp_primary_selection_source_v1_add_listener( data_source->wp_source, &primary_selection_source_listener, primary); - for (size_t i = 0; i < ARRAY_SIZE(mime_send); i++) { - zwp_primary_selection_source_v1_offer(data_source->wp_source, mime_send[i]); + for (size_t i = 0; i < ARRAY_SIZE(ghost_wl_mime_send); i++) { + zwp_primary_selection_source_v1_offer(data_source->wp_source, ghost_wl_mime_send[i]); } if (seat->wp_primary_selection_device) { @@ -5211,8 +5211,8 @@ static void system_clipboard_put(GWL_Display *display, const char *buffer) wl_data_source_add_listener(data_source->wl_source, &data_source_listener, seat); - for (size_t i = 0; i < ARRAY_SIZE(mime_send); i++) { - wl_data_source_offer(data_source->wl_source, mime_send[i]); + for (size_t i = 0; i < ARRAY_SIZE(ghost_wl_mime_send); i++) { + wl_data_source_offer(data_source->wl_source, ghost_wl_mime_send[i]); } if (seat->wl_data_device) { @@ -5680,9 +5680,9 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor s if (UNLIKELY(display_->seats.empty())) { return GHOST_kFailure; } - auto cursor_find = cursors.find(shape); - const char *cursor_name = (cursor_find == cursors.end()) ? - cursors.at(GHOST_kStandardCursorDefault) : + auto cursor_find = ghost_wl_cursors.find(shape); + const char *cursor_name = (cursor_find == ghost_wl_cursors.end()) ? + ghost_wl_cursors.at(GHOST_kStandardCursorDefault) : (*cursor_find).second; GWL_Seat *seat = display_->seats[0]; @@ -5719,8 +5719,8 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor s GHOST_TSuccess GHOST_SystemWayland::hasCursorShape(const GHOST_TStandardCursor cursorShape) { - auto cursor_find = cursors.find(cursorShape); - if (cursor_find == cursors.end()) { + auto cursor_find = ghost_wl_cursors.find(cursorShape); + if (cursor_find == ghost_wl_cursors.end()) { return GHOST_kFailure; } const char *value = (*cursor_find).second; -- cgit v1.2.3 From 48d8aa74847231700db8154320d058e82fe7df4a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 28 Oct 2022 12:34:26 +1100 Subject: Fix failure to clear DND in_use in rare cases under Wayland If opening a pipe failed, 'data_offer->dnd.in_use' wasn't cleared. Avoid early return where it duplicates logic in an error prone way. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 41 ++++++++++++++++------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 72a9b5beef1..86b7a0f25f6 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1672,15 +1672,14 @@ static char *read_buffer_from_data_offer(GWL_DataOffer *data_offer, size_t *r_len) { int pipefd[2]; - if (UNLIKELY(pipe(pipefd) != 0)) { + const bool pipefd_ok = pipe(pipefd) == 0; + if (pipefd_ok) { + wl_data_offer_receive(data_offer->id, mime_receive, pipefd[1]); + close(pipefd[1]); + } + else { CLOG_WARN(LOG, "error creating pipe: %s", std::strerror(errno)); - if (mutex) { - mutex->unlock(); - } - return nullptr; } - wl_data_offer_receive(data_offer->id, mime_receive, pipefd[1]); - close(pipefd[1]); /* Only for DND (A no-op to disable for clipboard data-offer). */ data_offer->dnd.in_use = false; @@ -1689,9 +1688,11 @@ static char *read_buffer_from_data_offer(GWL_DataOffer *data_offer, mutex->unlock(); } /* WARNING: `data_offer` may be freed from now on. */ - - char *buf = read_file_as_buffer(pipefd[0], nil_terminate, r_len); - close(pipefd[0]); + char *buf = nullptr; + if (pipefd_ok) { + buf = read_file_as_buffer(pipefd[0], nil_terminate, r_len); + close(pipefd[0]); + } return buf; } @@ -1702,22 +1703,24 @@ static char *read_buffer_from_primary_selection_offer(GWL_PrimarySelection_DataO size_t *r_len) { int pipefd[2]; - if (UNLIKELY(pipe(pipefd) != 0)) { + const bool pipefd_ok = pipe(pipefd) == 0; + if (pipefd_ok) { + zwp_primary_selection_offer_v1_receive(data_offer->id, mime_receive, pipefd[1]); + close(pipefd[1]); + } + else { CLOG_WARN(LOG, "error creating pipe: %s", std::strerror(errno)); - if (mutex) { - mutex->unlock(); - } - return nullptr; } - zwp_primary_selection_offer_v1_receive(data_offer->id, mime_receive, pipefd[1]); - close(pipefd[1]); if (mutex) { mutex->unlock(); } /* WARNING: `data_offer` may be freed from now on. */ - char *buf = read_file_as_buffer(pipefd[0], nil_terminate, r_len); - close(pipefd[0]); + char *buf = nullptr; + if (pipefd_ok) { + buf = read_file_as_buffer(pipefd[0], nil_terminate, r_len); + close(pipefd[0]); + } return buf; } -- cgit v1.2.3 From af761021a3437574fe43ce8e5136eabf9a4fd38e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 28 Oct 2022 13:08:41 +1100 Subject: GHOST/Wayland: code-comments Note issues with track-pad event handling, add some other notes too. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 86b7a0f25f6..c15307da0b8 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -2429,10 +2429,11 @@ static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/) wl_fixed_to_int(scale * seat->pointer.xy[0]), wl_fixed_to_int(scale * seat->pointer.xy[1]), /* NOTE: scaling the delta doesn't seem necessary. - * NOTE: inverting delta gives correct results, see: QTBUG-85767. */ + * NOTE: inverting delta gives correct results, see: QTBUG-85767. + * NOTE: the preference to invert scrolling (in GNOME at least) + * has already been applied so there is no need to read this preference. */ -wl_fixed_to_int(seat->pointer_scroll.smooth_xy[0]), -wl_fixed_to_int(seat->pointer_scroll.smooth_xy[1]), - /* TODO: investigate a way to request this configuration from the system. */ false)); } @@ -2552,6 +2553,18 @@ static void gesture_pinch_handle_begin(void *data, if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { win = ghost_wl_surface_user_data(wl_surface_focus); } + /* NOTE(@campbellbarton): Blender's use of track-pad coordinates is inconsistent and needs work. + * This isn't specific to WAYLAND, in practice they tend to work well enough in most cases. + * Some operators scale by the UI scale, some don't. + * Even this window scale is not correct because it doesn't account for: + * 1) Fractional window scale. + * 2) Blender's UI scale preference (which GHOST doesn't know about). + * + * If support for this were all that was needed it could be handled in GHOST, + * however as the operators are not even using coordinates compatible with each other, + * it would be better to resolve this by passing rotation & zoom levels directly, + * instead of attempting to handle them as cursor coordinates. + */ const wl_fixed_t win_scale = win ? win->scale() : 1; /* NOTE(@campbellbarton): Scale factors match Blender's operators & default preferences. @@ -4304,6 +4317,8 @@ static void gwl_registry_wl_output_remove(GWL_Display *display, void *user_data, const bool /*on_exit*/) { + /* While windows & cursors hold references to outputs, there is no need to manually remove + * these references as the compositor will remove references via #wl_surface_listener.leave. */ GWL_Output *output = static_cast(user_data); wl_output_destroy(output->wl_output); std::vector::iterator iter = std::find( @@ -4841,9 +4856,9 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background) struct wl_registry *registry = wl_display_get_registry(display_->wl_display); display_->wl_registry = registry; wl_registry_add_listener(registry, ®istry_listener, display_); - /* Call callback for registry listener. */ + /* First round-trip to receive all registry objects. */ wl_display_roundtrip(display_->wl_display); - /* Call callbacks for registered listeners. */ + /* Second round-trip to receive all output events. */ wl_display_roundtrip(display_->wl_display); /* Account for dependencies between interfaces. */ -- cgit v1.2.3 From bb16a3af7f8eb7a686d316237c5a74f72ce5be21 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 28 Oct 2022 17:03:39 +1100 Subject: Fix error in leaving the tablet pointer set under Wayland Missed clearing the tablet pointer after updating removing the tablet manager. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index c15307da0b8..88540dc4260 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -4370,6 +4370,9 @@ static void gwl_registry_wl_seat_update(GWL_Display *display, zwp_tablet_seat_v2_add_listener(seat->wp_tablet_seat, &tablet_seat_listener, seat); } } + else { + seat->wp_tablet_seat = nullptr; + } if (display->wp_primary_selection_device_manager) { if (seat->wp_primary_selection_device == nullptr) { -- cgit v1.2.3 From d799388b021fe9a0163b6f970c836b858a137449 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 28 Oct 2022 17:05:13 +1100 Subject: Cleanup: quiet unused argument warnings and minor changes in GHOST --- intern/ghost/CMakeLists.txt | 4 ++-- intern/ghost/intern/GHOST_System.h | 2 +- intern/ghost/intern/GHOST_SystemWayland.cpp | 5 +++-- intern/ghost/intern/GHOST_Window.h | 8 +++++--- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index fb10530bfae..ea21d831b0c 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -385,9 +385,9 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND) "${WAYLAND_PROTOCOLS_DIR}/unstable/primary-selection/primary-selection-unstable-v1.xml" ) - add_definitions(-DWITH_GHOST_WAYLAND) - unset(INC_DST) + + add_definitions(-DWITH_GHOST_WAYLAND) endif() if(WITH_INPUT_NDOF) diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index 810f828a8a1..924a4bff790 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -76,7 +76,7 @@ class GHOST_System : public GHOST_ISystem { GHOST_ITimerTask *installTimer(uint64_t delay, uint64_t interval, GHOST_TimerProcPtr timerProc, - GHOST_TUserDataPtr userData = NULL); + GHOST_TUserDataPtr userData = nullptr); /** * Removes a timer. diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 88540dc4260..f3dc1609e69 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -777,13 +777,14 @@ struct GWL_Display { std::vector outputs; std::vector seats; + /* Managers. */ struct wl_data_device_manager *wl_data_device_manager = nullptr; struct zwp_tablet_manager_v2 *wp_tablet_manager = nullptr; struct zwp_relative_pointer_manager_v1 *wp_relative_pointer_manager = nullptr; + struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_device_manager = nullptr; + struct zwp_pointer_constraints_v1 *wp_pointer_constraints = nullptr; struct zwp_pointer_gestures_v1 *wp_pointer_gestures = nullptr; - - struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_device_manager = nullptr; }; /** diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index 1c0991bba30..396691fa161 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -74,7 +74,7 @@ class GHOST_Window : public GHOST_IWindow { */ virtual bool getValid() const override { - return m_context != NULL; + return m_context != nullptr; } /** @@ -283,8 +283,9 @@ class GHOST_Window : public GHOST_IWindow { float getNativePixelSize(void) override { - if (m_nativePixelSize > 0.0f) + if (m_nativePixelSize > 0.0f) { return m_nativePixelSize; + } return 1.0f; } @@ -298,7 +299,8 @@ class GHOST_Window : public GHOST_IWindow { } #ifdef WITH_INPUT_IME - virtual void beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed) override + virtual void beginIME( + int32_t /*x*/, int32_t /*y*/, int32_t /*w*/, int32_t /*h*/, bool /*completed*/) override { /* do nothing temporarily if not in windows */ } -- cgit v1.2.3 From 105c8d59cd07ee401722cd0a29a2fb059f2d7743 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 28 Oct 2022 17:06:21 +1100 Subject: Cleanup: format --- intern/cycles/blender/addon/ui.py | 2 ++ source/blender/draw/intern/draw_pbvh.cc | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 581533db0b6..305accc8f1a 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -149,6 +149,7 @@ def get_effective_preview_denoiser(context): return 'OIDN' + def use_mnee(context): # The MNEE kernel doesn't compile on macOS < 13. if use_metal(context): @@ -158,6 +159,7 @@ def use_mnee(context): return False return True + class CYCLES_RENDER_PT_sampling(CyclesButtonsPanel, Panel): bl_label = "Sampling" diff --git a/source/blender/draw/intern/draw_pbvh.cc b/source/blender/draw/intern/draw_pbvh.cc index a4de9e4fa47..b25bb42a8a5 100644 --- a/source/blender/draw/intern/draw_pbvh.cc +++ b/source/blender/draw/intern/draw_pbvh.cc @@ -951,7 +951,8 @@ struct PBVHBatches { void create_index_faces(PBVH_GPU_Args *args) { - int *mat_index = static_cast(CustomData_get_layer_named(args->pdata, CD_PROP_INT32, "material_index")); + int *mat_index = static_cast( + CustomData_get_layer_named(args->pdata, CD_PROP_INT32, "material_index")); if (mat_index && args->totprim) { int poly_index = args->mlooptri[args->prim_indices[0]].poly; -- cgit v1.2.3 From f9113b7eb6ee0e7a6222bd6fbc7e39cb9c6fc395 Mon Sep 17 00:00:00 2001 From: Damian Trebilco Date: Fri, 28 Oct 2022 14:30:18 +0200 Subject: Cycles: add Equiangular Cubemap Face camera projection This can be used for example for VR video formats that use this projection instead of perspective projection for cubemap faces. Differential Revision: https://developer.blender.org/D13525 --- intern/cycles/blender/addon/properties.py | 11 ++++++----- intern/cycles/kernel/camera/projection.h | 26 ++++++++++++++++++++++++++ intern/cycles/kernel/types.h | 1 + intern/cycles/scene/camera.cpp | 1 + 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 94e2d840b28..f5cd88f6b6a 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -60,13 +60,14 @@ enum_filter_types = ( ) enum_panorama_types = ( - ('EQUIRECTANGULAR', "Equirectangular", "Render the scene with a spherical camera, also known as Lat Long panorama"), - ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ideal for fulldomes, ignore the sensor dimensions"), + ('EQUIRECTANGULAR', "Equirectangular", "Spherical camera for environment maps, also known as Lat Long panorama", 0), + ('EQUIANGULAR_CUBEMAP_FACE', "Equiangular Cubemap Face", "Single face of an equiangular cubemap", 5), + ('MIRRORBALL', "Mirror Ball", "Mirror ball mapping for environment maps", 3), + ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ideal for fulldomes, ignore the sensor dimensions", 1), ('FISHEYE_EQUISOLID', "Fisheye Equisolid", - "Similar to most fisheye modern lens, takes sensor dimensions into consideration"), - ('MIRRORBALL', "Mirror Ball", "Uses the mirror ball mapping"), + "Similar to most fisheye modern lens, takes sensor dimensions into consideration", 2), ('FISHEYE_LENS_POLYNOMIAL', "Fisheye Lens Polynomial", - "Defines the lens projection as polynomial to allow real world camera lenses to be mimicked"), + "Defines the lens projection as polynomial to allow real world camera lenses to be mimicked", 4), ) enum_curve_shape = ( diff --git a/intern/cycles/kernel/camera/projection.h b/intern/cycles/kernel/camera/projection.h index c9fe3a6c7fb..1d16aa35abe 100644 --- a/intern/cycles/kernel/camera/projection.h +++ b/intern/cycles/kernel/camera/projection.h @@ -201,11 +201,35 @@ ccl_device float2 direction_to_mirrorball(float3 dir) return make_float2(u, v); } +/* Single face of a equiangular cube map projection as described in + https://blog.google/products/google-ar-vr/bringing-pixels-front-and-center-vr-video/ */ +ccl_device float3 equiangular_cubemap_face_to_direction(float u, float v) +{ + u = (1.0f - u); + + u = tanf(u * M_PI_2_F - M_PI_4_F); + v = tanf(v * M_PI_2_F - M_PI_4_F); + + return make_float3(1.0f, u, v); +} + +ccl_device float2 direction_to_equiangular_cubemap_face(float3 dir) +{ + float u = atan2f(dir.y, dir.x) * 2.0f / M_PI_F + 0.5f; + float v = atan2f(dir.z, dir.x) * 2.0f / M_PI_F + 0.5f; + + u = 1.0f - u; + + return make_float2(u, v); +} + ccl_device_inline float3 panorama_to_direction(ccl_constant KernelCamera *cam, float u, float v) { switch (cam->panorama_type) { case PANORAMA_EQUIRECTANGULAR: return equirectangular_range_to_direction(u, v, cam->equirectangular_range); + case PANORAMA_EQUIANGULAR_CUBEMAP_FACE: + return equiangular_cubemap_face_to_direction(u, v); case PANORAMA_MIRRORBALL: return mirrorball_to_direction(u, v); case PANORAMA_FISHEYE_EQUIDISTANT: @@ -230,6 +254,8 @@ ccl_device_inline float2 direction_to_panorama(ccl_constant KernelCamera *cam, f switch (cam->panorama_type) { case PANORAMA_EQUIRECTANGULAR: return direction_to_equirectangular_range(dir, cam->equirectangular_range); + case PANORAMA_EQUIANGULAR_CUBEMAP_FACE: + return direction_to_equiangular_cubemap_face(dir); case PANORAMA_MIRRORBALL: return direction_to_mirrorball(dir); case PANORAMA_FISHEYE_EQUIDISTANT: diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h index 8f7cfd19169..24c5a6a4540 100644 --- a/intern/cycles/kernel/types.h +++ b/intern/cycles/kernel/types.h @@ -490,6 +490,7 @@ enum PanoramaType { PANORAMA_FISHEYE_EQUISOLID = 2, PANORAMA_MIRRORBALL = 3, PANORAMA_FISHEYE_LENS_POLYNOMIAL = 4, + PANORAMA_EQUIANGULAR_CUBEMAP_FACE = 5, PANORAMA_NUM_TYPES, }; diff --git a/intern/cycles/scene/camera.cpp b/intern/cycles/scene/camera.cpp index 240e5d9c128..255dd320ec7 100644 --- a/intern/cycles/scene/camera.cpp +++ b/intern/cycles/scene/camera.cpp @@ -84,6 +84,7 @@ NODE_DEFINE(Camera) static NodeEnum panorama_type_enum; panorama_type_enum.insert("equirectangular", PANORAMA_EQUIRECTANGULAR); + panorama_type_enum.insert("equiangular_cubemap_face", PANORAMA_EQUIANGULAR_CUBEMAP_FACE); panorama_type_enum.insert("mirrorball", PANORAMA_MIRRORBALL); panorama_type_enum.insert("fisheye_equidistant", PANORAMA_FISHEYE_EQUIDISTANT); panorama_type_enum.insert("fisheye_equisolid", PANORAMA_FISHEYE_EQUISOLID); -- cgit v1.2.3 From 2c9fe719e68a81801fa490e980df1f3c09eb1db0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 29 Oct 2022 12:05:16 +1100 Subject: Cleanup: use STREQ macro --- source/blender/blenkernel/intern/writeffmpeg.c | 6 +++--- source/blender/editors/interface/interface_handlers.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 0d3a790ba00..0842125932b 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -492,7 +492,7 @@ static const AVCodec *get_av1_encoder( /* Apply AV1 encoder specific settings. */ if (codec) { - if (strcmp(codec->name, "librav1e") == 0) { + if (STREQ(codec->name, "librav1e")) { /* Set "tiles" to 8 to enable multi-threaded encoding. */ if (rd->threads > 8) { ffmpeg_dict_set_int(opts, "tiles", rd->threads); @@ -530,7 +530,7 @@ static const AVCodec *get_av1_encoder( BLI_snprintf(buffer, sizeof(buffer), "keyint=%d", context->ffmpeg_gop_size); av_dict_set(opts, "rav1e-params", buffer, 0); } - else if (strcmp(codec->name, "libsvtav1") == 0) { + else if (STREQ(codec->name, "libsvtav1")) { /* Set preset value based on ffmpeg_preset. * Must check context->ffmpeg_preset again in case this encoder was selected due to the * absence of another. */ @@ -552,7 +552,7 @@ static const AVCodec *get_av1_encoder( ffmpeg_dict_set_int(opts, "qp", context->ffmpeg_crf); } } - else if (strcmp(codec->name, "libaom-av1") == 0) { + else if (STREQ(codec->name, "libaom-av1")) { /* Speed up libaom-av1 encoding by enabling multithreading and setting tiles. */ ffmpeg_dict_set_int(opts, "row-mt", 1); const char *tiles_string = NULL; diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 34f33b71fb8..7b6a623f53e 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -3894,7 +3894,7 @@ static void ui_do_but_textedit( } if (event->type == WM_IME_COMPOSITE_EVENT && ime_data->result_len) { if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) && - strcmp(ime_data->str_result, "\xE3\x80\x82") == 0) { + STREQ(ime_data->str_result, "\xE3\x80\x82")) { /* Convert Ideographic Full Stop (U+3002) to decimal point when entering numbers. */ ui_textedit_insert_ascii(but, data, '.'); } -- cgit v1.2.3 From 78fe6d7ab1952503d1eef66c18e36dc7e07147bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Sat, 29 Oct 2022 17:08:12 +0200 Subject: NLA: Push down Action names the Track after the Action When pushing down an Action to a new NLA track, the track is now named after the Action. --- source/blender/blenkernel/intern/nla.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 24663d6db05..326f239a95a 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -464,6 +464,7 @@ NlaStrip *BKE_nlastack_add_strip(AnimData *adt, bAction *act, const bool is_libo */ nlt = BKE_nlatrack_add(adt, NULL, is_liboverride); BKE_nlatrack_add_strip(nlt, strip, is_liboverride); + BLI_strncpy(nlt->name, act->id.name + 2, sizeof(nlt->name)); } /* automatically name it too */ -- cgit v1.2.3 From d1d2f002c7caaf4ab457ec27bbc44666d7aac624 Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Sat, 29 Oct 2022 11:25:33 -0600 Subject: make.bat: skip SVN update when running make code_update regression from rB116d7b0042bba7d6cabd8e04c7d020ac3816caf3 --- build_files/windows/parse_arguments.cmd | 2 ++ build_files/windows/reset_variables.cmd | 1 + make.bat | 12 +++++++----- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/build_files/windows/parse_arguments.cmd b/build_files/windows/parse_arguments.cmd index eaf4a85f7ac..a2ff4c1ff95 100644 --- a/build_files/windows/parse_arguments.cmd +++ b/build_files/windows/parse_arguments.cmd @@ -80,9 +80,11 @@ if NOT "%1" == "" ( REM Non-Build Commands ) else if "%1" == "update" ( SET BUILD_UPDATE=1 + SET BUILD_UPDATE_SVN=1 set BUILD_UPDATE_ARGS= ) else if "%1" == "code_update" ( SET BUILD_UPDATE=1 + SET BUILD_UPDATE_SVN=0 set BUILD_UPDATE_ARGS="--no-libraries" ) else if "%1" == "ninja" ( SET BUILD_WITH_NINJA=1 diff --git a/build_files/windows/reset_variables.cmd b/build_files/windows/reset_variables.cmd index 8ba7b4d3307..37c5d1034ea 100644 --- a/build_files/windows/reset_variables.cmd +++ b/build_files/windows/reset_variables.cmd @@ -34,3 +34,4 @@ set BUILD_WITH_SCCACHE= set ICONS= set ICONS_GEOM= set DOC_PY= +SET BUILD_UPDATE_SVN= \ No newline at end of file diff --git a/make.bat b/make.bat index 0be70053ce1..394b2d0dad5 100644 --- a/make.bat +++ b/make.bat @@ -65,11 +65,13 @@ if "%BUILD_UPDATE%" == "1" ( REM First see if the SVN libs are there and check them out if they are not. call "%BLENDER_DIR%\build_files\windows\check_libraries.cmd" if errorlevel 1 goto EOF - REM Then update SVN platform libraries, since updating python while python is - REM running tends to be problematic. The python script that update_sources - REM calls later on may still try to switch branches and run into trouble, - REM but for *most* people this will side step the problem. - call "%BLENDER_DIR%\build_files\windows\svn_update.cmd" + if "%BUILD_UPDATE_SVN%" == "1" ( + REM Then update SVN platform libraries, since updating python while python is + REM running tends to be problematic. The python script that update_sources + REM calls later on may still try to switch branches and run into trouble, + REM but for *most* people this will side step the problem. + call "%BLENDER_DIR%\build_files\windows\svn_update.cmd" + ) REM Finally call the python script shared between all platforms that updates git REM and does any other SVN work like update the tests or branch switches REM if required. -- cgit v1.2.3 From 5d77c3a6a5a27094342d942c5eb4db3c8ded1cd1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 30 Oct 2022 15:24:41 +1100 Subject: Fix T102132: Directory selection fails to add trailing slash Regression in [0], accessing the path from the file selector relied on BLI_join_dirfile adding a trailing "/" when the filename was empty. [0]: 9f6a045e23cf4ab132ef78eeaf070bd53d0c509f --- source/blender/editors/space_file/file_ops.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index a4d4bf98474..20025b0bac9 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -1564,7 +1564,13 @@ void file_sfile_to_operator_ex( PropertyRNA *prop; /* XXX, not real length */ - BLI_path_join(filepath, FILE_MAX, params->dir, params->file); + if (params->file[0]) { + BLI_path_join(filepath, FILE_MAX, params->dir, params->file); + } + else { + BLI_strncpy(filepath, params->dir, FILE_MAX - 1); + BLI_path_slash_ensure(filepath); + } if ((prop = RNA_struct_find_property(op->ptr, "relative_path"))) { if (RNA_property_boolean_get(op->ptr, prop)) { -- cgit v1.2.3 From d66f24cfe30d26e03863a78de9fd58bb3b65ed43 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 30 Oct 2022 15:34:02 +1100 Subject: Fix potential buffer overflow with BLI_path_slash_ensure use BLI_path_slash_ensure was appending to fixed sized buffers without a size check. --- source/blender/blenkernel/intern/appdir.c | 22 ++++++++++---------- .../blenkernel/intern/asset_library_service.cc | 2 +- .../intern/asset_library_service_test.cc | 2 +- source/blender/blenkernel/intern/pointcache.c | 6 +++--- source/blender/blenlib/BLI_path_util.h | 4 ++-- source/blender/blenlib/intern/fileops.c | 2 +- source/blender/blenlib/intern/path_util.c | 18 +++++++++------- source/blender/editors/space_buttons/buttons_ops.c | 2 +- source/blender/editors/space_file/file_ops.c | 24 +++++++++++----------- source/blender/editors/space_file/filelist.cc | 12 +++++------ source/blender/editors/space_file/filesel.c | 4 ++-- source/blender/makesrna/intern/rna_userdef.c | 2 +- source/blender/sequencer/intern/disk_cache.c | 4 ++-- 13 files changed, 54 insertions(+), 50 deletions(-) diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 965f48d1e51..b3990b2b7fc 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -237,7 +237,7 @@ bool BKE_appdir_font_folder_default(char *dir) } #elif defined(__APPLE__) STRNCPY(test_dir, BLI_expand_tilde("~/Library/Fonts/")); - BLI_path_slash_ensure(test_dir); + BLI_path_slash_ensure(test_dir, sizeof(test_dir)); #else STRNCPY(test_dir, "/usr/share/fonts"); #endif @@ -1093,13 +1093,13 @@ void BKE_appdir_app_templates(ListBase *templates) * \param userdir: Directory specified in user preferences (may be NULL). * note that by default this is an empty string, only use when non-empty. */ -static void where_is_temp(char *tempdir, const size_t tempdir_len, const char *userdir) +static void where_is_temp(char *tempdir, const size_t tempdir_maxlen, const char *userdir) { tempdir[0] = '\0'; if (userdir && BLI_is_dir(userdir)) { - BLI_strncpy(tempdir, userdir, tempdir_len); + BLI_strncpy(tempdir, userdir, tempdir_maxlen); } if (tempdir[0] == '\0') { @@ -1116,23 +1116,23 @@ static void where_is_temp(char *tempdir, const size_t tempdir_len, const char *u for (int i = 0; i < ARRAY_SIZE(env_vars); i++) { const char *tmp = BLI_getenv(env_vars[i]); if (tmp && (tmp[0] != '\0') && BLI_is_dir(tmp)) { - BLI_strncpy(tempdir, tmp, tempdir_len); + BLI_strncpy(tempdir, tmp, tempdir_maxlen); break; } } } if (tempdir[0] == '\0') { - BLI_strncpy(tempdir, "/tmp/", tempdir_len); + BLI_strncpy(tempdir, "/tmp/", tempdir_maxlen); } else { /* add a trailing slash if needed */ - BLI_path_slash_ensure(tempdir); + BLI_path_slash_ensure(tempdir, tempdir_maxlen); } } static void tempdir_session_create(char *tempdir_session, - const size_t tempdir_session_len, + const size_t tempdir_session_maxlen, const char *tempdir) { tempdir_session[0] = '\0'; @@ -1146,9 +1146,9 @@ static void tempdir_session_create(char *tempdir_session, * #_mktemp_s also requires the last null character is included. */ const int tempdir_session_len_required = tempdir_len + session_name_len + 1; - if (tempdir_session_len_required <= tempdir_session_len) { + if (tempdir_session_len_required <= tempdir_session_maxlen) { /* No need to use path joining utility as we know the last character of #tempdir is a slash. */ - BLI_string_join(tempdir_session, tempdir_session_len, tempdir, session_name); + BLI_string_join(tempdir_session, tempdir_session_maxlen, tempdir, session_name); #ifdef WIN32 const bool needs_create = (_mktemp_s(tempdir_session, tempdir_session_len_required) == 0); #else @@ -1158,7 +1158,7 @@ static void tempdir_session_create(char *tempdir_session, BLI_dir_create_recursive(tempdir_session); } if (BLI_is_dir(tempdir_session)) { - BLI_path_slash_ensure(tempdir_session); + BLI_path_slash_ensure(tempdir_session, tempdir_session_maxlen); /* Success. */ return; } @@ -1168,7 +1168,7 @@ static void tempdir_session_create(char *tempdir_session, "Could not generate a temp file name for '%s', falling back to '%s'", tempdir_session, tempdir); - BLI_strncpy(tempdir_session, tempdir, tempdir_session_len); + BLI_strncpy(tempdir_session, tempdir, tempdir_session_maxlen); } void BKE_tempdir_init(const char *userdir) diff --git a/source/blender/blenkernel/intern/asset_library_service.cc b/source/blender/blenkernel/intern/asset_library_service.cc index a6b2b7548a2..a4f97234042 100644 --- a/source/blender/blenkernel/intern/asset_library_service.cc +++ b/source/blender/blenkernel/intern/asset_library_service.cc @@ -44,7 +44,7 @@ std::string normalize_directory_path(StringRefNull directory) char dir_normalized[PATH_MAX]; STRNCPY(dir_normalized, directory.c_str()); - BLI_path_normalize_dir(nullptr, dir_normalized); + BLI_path_normalize_dir(nullptr, dir_normalized, sizeof(dir_normalized)); return std::string(dir_normalized); } } // namespace diff --git a/source/blender/blenkernel/intern/asset_library_service_test.cc b/source/blender/blenkernel/intern/asset_library_service_test.cc index d105c5644de..7952e7ea3b0 100644 --- a/source/blender/blenkernel/intern/asset_library_service_test.cc +++ b/source/blender/blenkernel/intern/asset_library_service_test.cc @@ -118,7 +118,7 @@ TEST_F(AssetLibraryServiceTest, library_path_trailing_slashes) asset_lib_no_slash[strlen(asset_lib_no_slash) - 1] = '\0'; } - BLI_path_slash_ensure(asset_lib_with_slash); + BLI_path_slash_ensure(asset_lib_with_slash, PATH_MAX); AssetLibrary *const lib_no_slash = service->get_asset_library_on_disk(asset_lib_no_slash); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index ac98bed2cf0..bb9a0f458b9 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -1317,7 +1317,7 @@ static int ptcache_path(PTCacheID *pid, char *dirname) BLI_path_abs(dirname, blendfilename); } - return BLI_path_slash_ensure(dirname); /* new strlen() */ + return BLI_path_slash_ensure(dirname, MAX_PTCACHE_FILE); /* new strlen() */ } if ((blendfile_path[0] != '\0') || lib) { char file[MAX_PTCACHE_PATH]; /* we don't want the dir, only the file */ @@ -1334,14 +1334,14 @@ static int ptcache_path(PTCacheID *pid, char *dirname) BLI_snprintf(dirname, MAX_PTCACHE_PATH, "//" PTCACHE_PATH "%s", file); BLI_path_abs(dirname, blendfilename); - return BLI_path_slash_ensure(dirname); /* new strlen() */ + return BLI_path_slash_ensure(dirname, MAX_PTCACHE_FILE); /* new strlen() */ } /* use the temp path. this is weak but better than not using point cache at all */ /* temporary directory is assumed to exist and ALWAYS has a trailing slash */ BLI_snprintf(dirname, MAX_PTCACHE_PATH, "%s" PTCACHE_PATH, BKE_tempdir_session()); - return BLI_path_slash_ensure(dirname); /* new strlen() */ + return BLI_path_slash_ensure(dirname, MAX_PTCACHE_FILE); /* new strlen() */ } static size_t ptcache_filepath_ext_append(PTCacheID *pid, diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index d4d2ddead71..9c661178322 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -218,7 +218,7 @@ const char *BLI_path_slash_rfind(const char *string) ATTR_NONNULL() ATTR_WARN_UN * Appends a slash to string if there isn't one there already. * Returns the new length of the string. */ -int BLI_path_slash_ensure(char *string) ATTR_NONNULL(); +int BLI_path_slash_ensure(char *string, size_t string_maxlen) ATTR_NONNULL(1); /** * Removes the last slash and everything after it to the end of string, if there is one. */ @@ -314,7 +314,7 @@ void BLI_path_normalize(const char *relabase, char *path) ATTR_NONNULL(2); * * \note Same as #BLI_path_normalize but adds a trailing slash. */ -void BLI_path_normalize_dir(const char *relabase, char *dir) ATTR_NONNULL(2); +void BLI_path_normalize_dir(const char *relabase, char *dir, size_t dir_maxlen) ATTR_NONNULL(2); /** * Make given name safe to be used in paths. diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index a157302e51e..005de1f85b4 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -401,7 +401,7 @@ static bool delete_recursive(const char *dir) /* dir listing produces dir path without trailing slash... */ BLI_strncpy(path, fl->path, sizeof(path)); - BLI_path_slash_ensure(path); + BLI_path_slash_ensure(path, sizeof(path)); if (delete_recursive(path)) { err = true; diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index afe8c3cc033..759a1bf0dc7 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -218,7 +218,7 @@ void BLI_path_normalize(const char *relabase, char *path) #endif } -void BLI_path_normalize_dir(const char *relabase, char *dir) +void BLI_path_normalize_dir(const char *relabase, char *dir, size_t dir_maxlen) { /* Would just create an unexpected "/" path, just early exit entirely. */ if (dir[0] == '\0') { @@ -226,7 +226,7 @@ void BLI_path_normalize_dir(const char *relabase, char *dir) } BLI_path_normalize(relabase, dir); - BLI_path_slash_ensure(dir); + BLI_path_slash_ensure(dir, dir_maxlen); } bool BLI_filename_make_safe_ex(char *fname, bool allow_tokens) @@ -1624,7 +1624,7 @@ bool BLI_path_contains(const char *container_path, const char *containee_path) /* Add a trailing slash to prevent same-prefix directories from matching. * e.g. "/some/path" doesn't contain "/some/path_lib". */ - BLI_path_slash_ensure(container_native); + BLI_path_slash_ensure(container_native, sizeof(container_native)); return BLI_str_startswith(containee_native, container_native); } @@ -1659,13 +1659,17 @@ const char *BLI_path_slash_rfind(const char *string) return (lfslash > lbslash) ? lfslash : lbslash; } -int BLI_path_slash_ensure(char *string) +int BLI_path_slash_ensure(char *string, size_t string_maxlen) { int len = strlen(string); + BLI_assert(len < string_maxlen); if (len == 0 || string[len - 1] != SEP) { - string[len] = SEP; - string[len + 1] = '\0'; - return len + 1; + /* Avoid unlikely buffer overflow. */ + if (len + 1 < string_maxlen) { + string[len] = SEP; + string[len + 1] = '\0'; + return len + 1; + } } return len; } diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index a9ce9a3d723..4013288b13b 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -205,7 +205,7 @@ static int file_browse_exec(bContext *C, wmOperator *op) if (BLI_is_dir(path)) { /* Do this first so '//' isn't converted to '//\' on windows. */ - BLI_path_slash_ensure(path); + BLI_path_slash_ensure(path, sizeof(path)); if (is_relative) { BLI_path_rel(path, BKE_main_blendfile_path(bmain)); str_len = strlen(path); diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 20025b0bac9..c9c4704d16c 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -197,13 +197,13 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen) } else if (file->redirection_path) { BLI_strncpy(params->dir, file->redirection_path, sizeof(params->dir)); - BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir); - BLI_path_slash_ensure(params->dir); + BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir, sizeof(params->dir)); + BLI_path_slash_ensure(params->dir, sizeof(params->dir)); } else { - BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir); + BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir, sizeof(params->dir)); strcat(params->dir, file->relpath); - BLI_path_slash_ensure(params->dir); + BLI_path_slash_ensure(params->dir, sizeof(params->dir)); } ED_file_change_dir(C); @@ -1095,7 +1095,7 @@ static int bookmark_select_exec(bContext *C, wmOperator *op) RNA_property_string_get(op->ptr, prop, entry); BLI_strncpy(params->dir, entry, sizeof(params->dir)); - BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir); + BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir, sizeof(params->dir)); ED_file_change_dir(C); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); @@ -1568,8 +1568,8 @@ void file_sfile_to_operator_ex( BLI_path_join(filepath, FILE_MAX, params->dir, params->file); } else { - BLI_strncpy(filepath, params->dir, FILE_MAX - 1); - BLI_path_slash_ensure(filepath); + BLI_strncpy(filepath, params->dir, FILE_MAX); + BLI_path_slash_ensure(filepath, FILE_MAX); } if ((prop = RNA_struct_find_property(op->ptr, "relative_path"))) { @@ -1797,8 +1797,8 @@ static bool file_execute(bContext *C, SpaceFile *sfile) } else { BLI_path_normalize(BKE_main_blendfile_path(bmain), params->dir); - BLI_path_append(params->dir, sizeof(params->dir) - 1, file->relpath); - BLI_path_slash_ensure(params->dir); + BLI_path_append(params->dir, sizeof(params->dir), file->relpath); + BLI_path_slash_ensure(params->dir, sizeof(params->dir)); } ED_file_change_dir(C); } @@ -1961,7 +1961,7 @@ static int file_parent_exec(bContext *C, wmOperator *UNUSED(unused)) if (params) { if (BLI_path_parent_dir(params->dir)) { - BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir); + BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir, sizeof(params->dir)); ED_file_change_dir(C); if (params->recursion_level > 1) { /* Disable 'dirtree' recursion when going up in tree. */ @@ -2544,7 +2544,7 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN } } - BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir); + BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir, sizeof(params->dir)); if (filelist_is_dir(sfile->files, params->dir)) { if (!STREQ(params->dir, old_dir)) { /* Avoids flickering when nothing's changed. */ @@ -2631,7 +2631,7 @@ void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg /* if directory, open it and empty filename field */ if (filelist_is_dir(sfile->files, filepath)) { - BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), filepath); + BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), filepath, sizeof(filepath)); BLI_strncpy(params->dir, filepath, sizeof(params->dir)); params->file[0] = '\0'; ED_file_change_dir(C); diff --git a/source/blender/editors/space_file/filelist.cc b/source/blender/editors/space_file/filelist.cc index f177eebf6f2..3257534f94d 100644 --- a/source/blender/editors/space_file/filelist.cc +++ b/source/blender/editors/space_file/filelist.cc @@ -1208,7 +1208,7 @@ static int filelist_geticon_ex(const FileDirEntry *file, } else if (root) { BLI_path_join(fullpath, sizeof(fullpath), root, file->relpath); - BLI_path_slash_ensure(fullpath); + BLI_path_slash_ensure(fullpath, sizeof(fullpath)); } for (; tfsm; tfsm = tfsm->next) { if (STREQ(tfsm->path, target)) { @@ -1952,7 +1952,7 @@ void filelist_setdir(struct FileList *filelist, char *r_dir) const bool allow_invalid = filelist->asset_library_ref != nullptr; BLI_assert(strlen(r_dir) < FILE_MAX_LIBEXTRA); - BLI_path_normalize_dir(BKE_main_blendfile_path_from_global(), r_dir); + BLI_path_normalize_dir(BKE_main_blendfile_path_from_global(), r_dir, FILE_MAX_LIBEXTRA); const bool is_valid_path = filelist->check_dir_fn(filelist, r_dir, !allow_invalid); BLI_assert(is_valid_path || allow_invalid); UNUSED_VARS_NDEBUG(is_valid_path); @@ -2920,7 +2920,7 @@ static int filelist_readjob_list_dir(const char *root, if (BLI_file_alias_target(full_path, entry->redirection_path)) { if (BLI_is_dir(entry->redirection_path)) { entry->typeflag = FILE_TYPE_DIR; - BLI_path_slash_ensure(entry->redirection_path); + BLI_path_slash_ensure(entry->redirection_path, FILE_MAXDIR); } else { entry->typeflag = (eFileSel_File_Types)ED_path_extension_type(entry->redirection_path); @@ -3476,7 +3476,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib, BLI_strncpy(dir, filelist->filelist.root, sizeof(dir)); BLI_strncpy(filter_glob, filelist->filter_data.filter_glob, sizeof(filter_glob)); - BLI_path_normalize_dir(job_params->main_name, dir); + BLI_path_normalize_dir(job_params->main_name, dir, sizeof(dir)); td_dir->dir = BLI_strdup(dir); /* Init the file indexer. */ @@ -3507,7 +3507,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib, * Note that in the end, this means we 'cache' valid relative subdir once here, * this is actually better. */ BLI_strncpy(rel_subdir, subdir, sizeof(rel_subdir)); - BLI_path_normalize_dir(root, rel_subdir); + BLI_path_normalize_dir(root, rel_subdir, sizeof(rel_subdir)); BLI_path_rel(rel_subdir, root); bool is_lib = false; @@ -3555,7 +3555,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib, max_recursion, is_lib, recursion_level, entry)) { /* We have a directory we want to list, add it to todo list! */ BLI_path_join(dir, sizeof(dir), root, entry->relpath); - BLI_path_normalize_dir(job_params->main_name, dir); + BLI_path_normalize_dir(job_params->main_name, dir, sizeof(dir)); td_dir = static_cast(BLI_stack_push_r(todo_dirs)); td_dir->level = recursion_level + 1; td_dir->dir = BLI_strdup(dir); diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index df7e9702e85..af2c9d4e757 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -197,7 +197,7 @@ static FileSelectParams *fileselect_ensure_updated_file_params(SpaceFile *sfile) } if (params->dir[0]) { - BLI_path_normalize_dir(blendfile_path, params->dir); + BLI_path_normalize_dir(blendfile_path, params->dir, sizeof(params->dir)); BLI_path_abs(params->dir, blendfile_path); } @@ -1187,7 +1187,7 @@ int autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v)) match = UI_autocomplete_end(autocpl, str); if (match == AUTOCOMPLETE_FULL_MATCH) { - BLI_path_slash_ensure(str); + BLI_path_slash_ensure(str, FILE_MAX); } } } diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index e22ae205b0a..58189ab2478 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -574,7 +574,7 @@ static void rna_Userdef_disk_cache_dir_update(Main *UNUSED(bmain), { if (U.sequencer_disk_cache_dir[0] != '\0') { BLI_path_abs(U.sequencer_disk_cache_dir, BKE_main_blendfile_path_from_global()); - BLI_path_slash_ensure(U.sequencer_disk_cache_dir); + BLI_path_slash_ensure(U.sequencer_disk_cache_dir, sizeof(U.sequencer_disk_cache_dir)); BLI_path_make_safe(U.sequencer_disk_cache_dir); } diff --git a/source/blender/sequencer/intern/disk_cache.c b/source/blender/sequencer/intern/disk_cache.c index 1f52d2ea41b..8c0ae4e055c 100644 --- a/source/blender/sequencer/intern/disk_cache.c +++ b/source/blender/sequencer/intern/disk_cache.c @@ -182,7 +182,7 @@ static void seq_disk_cache_get_files(SeqDiskCache *disk_cache, char *path) if (is_dir && !FILENAME_IS_CURRPAR(file)) { char subpath[FILE_MAX]; BLI_strncpy(subpath, fl->path, sizeof(subpath)); - BLI_path_slash_ensure(subpath); + BLI_path_slash_ensure(subpath, sizeof(sizeof(subpath))); seq_disk_cache_get_files(disk_cache, subpath); } @@ -384,7 +384,7 @@ static void seq_disk_cache_delete_invalid_files(SeqDiskCache *disk_cache, DiskCacheFile *next_file, *cache_file = disk_cache->files.first; char cache_dir[FILE_MAX]; seq_disk_cache_get_dir(disk_cache, scene, seq, cache_dir, sizeof(cache_dir)); - BLI_path_slash_ensure(cache_dir); + BLI_path_slash_ensure(cache_dir, sizeof(cache_dir)); while (cache_file) { next_file = cache_file->next; -- cgit v1.2.3 From 5392f220f024b59d199dfc40ef4817401f22ee2b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 30 Oct 2022 15:44:17 +1100 Subject: BLI_path: add BLI_path_append_dir (appends and ensures trailing slash) Avoid copying the string then calling BLI_path_slash_ensure afterwards. --- source/blender/blenlib/BLI_path_util.h | 9 ++++++++- source/blender/blenlib/intern/path_util.c | 21 +++++++++++++++++---- source/blender/editors/space_file/file_ops.c | 6 ++---- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 9c661178322..6d411b51f85 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -68,8 +68,15 @@ const char *BLI_path_extension(const char *filepath) ATTR_NONNULL(); /** * Append a filename to a dir, ensuring slash separates. + * \return The new length of `dst`. */ -void BLI_path_append(char *__restrict dst, size_t maxlen, const char *__restrict file) +size_t BLI_path_append(char *__restrict dst, size_t maxlen, const char *__restrict file) + ATTR_NONNULL(); +/** + * A version of #BLI_path_append that ensures a trailing slash if there is space in `dst`. + * \return The new length of `dst`. + */ +size_t BLI_path_append_dir(char *__restrict dst, size_t maxlen, const char *__restrict dir) ATTR_NONNULL(); /** diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 759a1bf0dc7..bb87a26dada 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1431,21 +1431,34 @@ const char *BLI_path_extension(const char *filepath) return extension; } -void BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__restrict file) +size_t BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__restrict file) { size_t dirlen = BLI_strnlen(dst, maxlen); - /* inline BLI_path_slash_ensure */ + /* Inline #BLI_path_slash_ensure. */ if ((dirlen > 0) && (dst[dirlen - 1] != SEP)) { dst[dirlen++] = SEP; dst[dirlen] = '\0'; } if (dirlen >= maxlen) { - return; /* fills the path */ + return dirlen; /* fills the path */ } - BLI_strncpy(dst + dirlen, file, maxlen - dirlen); + return dirlen + BLI_strncpy_rlen(dst + dirlen, file, maxlen - dirlen); +} + +size_t BLI_path_append_dir(char *__restrict dst, const size_t maxlen, const char *__restrict dir) +{ + size_t dirlen = BLI_path_append(dst, maxlen, dir); + if (dirlen + 1 < maxlen) { + /* Inline #BLI_path_slash_ensure. */ + if ((dirlen > 0) && (dst[dirlen - 1] != SEP)) { + dst[dirlen++] = SEP; + dst[dirlen] = '\0'; + } + } + return dirlen; } size_t BLI_path_join_array(char *__restrict dst, diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index c9c4704d16c..f68d329329f 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -202,8 +202,7 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen) } else { BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir, sizeof(params->dir)); - strcat(params->dir, file->relpath); - BLI_path_slash_ensure(params->dir, sizeof(params->dir)); + BLI_path_append_dir(params->dir, sizeof(params->dir), file->relpath); } ED_file_change_dir(C); @@ -1797,8 +1796,7 @@ static bool file_execute(bContext *C, SpaceFile *sfile) } else { BLI_path_normalize(BKE_main_blendfile_path(bmain), params->dir); - BLI_path_append(params->dir, sizeof(params->dir), file->relpath); - BLI_path_slash_ensure(params->dir, sizeof(params->dir)); + BLI_path_append_dir(params->dir, sizeof(params->dir), file->relpath); } ED_file_change_dir(C); } -- cgit v1.2.3 From 9bd38750b39637f5b52ac64944af5b6113c30c03 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 30 Oct 2022 15:56:28 +1100 Subject: Cleanup: replace BLI string copy & append with BLI_path_join(..) Copying and appending is unnecessarily verbose with each call having to pass in the buffer size. --- source/blender/editors/interface/interface_ops.cc | 3 +-- source/blender/imbuf/intern/indexer.c | 6 +++--- source/blender/sequencer/intern/disk_cache.c | 12 +++++------- source/blender/sequencer/intern/proxy.c | 3 +-- 4 files changed, 10 insertions(+), 14 deletions(-) diff --git a/source/blender/editors/interface/interface_ops.cc b/source/blender/editors/interface/interface_ops.cc index e089642963d..2d06dd2c465 100644 --- a/source/blender/editors/interface/interface_ops.cc +++ b/source/blender/editors/interface/interface_ops.cc @@ -1859,8 +1859,7 @@ static void edittranslation_find_po_file(const char *root, /* First, full lang code. */ BLI_snprintf(tstr, sizeof(tstr), "%s.po", uilng); - BLI_path_join(path, maxlen, root, uilng); - BLI_path_append(path, maxlen, tstr); + BLI_path_join(path, maxlen, root, uilng, tstr); if (BLI_is_file(path)) { return; } diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index eaa72441fb6..63836690ee4 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -377,9 +377,9 @@ static void get_index_dir(struct anim *anim, char *index_dir, size_t index_dir_l { if (!anim->index_dir[0]) { char filename[FILE_MAXFILE]; - BLI_split_dirfile(anim->name, index_dir, filename, index_dir_len, sizeof(filename)); - BLI_path_append(index_dir, index_dir_len, "BL_proxy"); - BLI_path_append(index_dir, index_dir_len, filename); + char dirname[FILE_MAXDIR]; + BLI_split_dirfile(anim->name, dirname, filename, index_dir_len, sizeof(filename)); + BLI_path_join(index_dir, index_dir_len, dirname, "BL_proxy", filename); } else { BLI_strncpy(index_dir, anim->index_dir, index_dir_len); diff --git a/source/blender/sequencer/intern/disk_cache.c b/source/blender/sequencer/intern/disk_cache.c index 8c0ae4e055c..596a28201cc 100644 --- a/source/blender/sequencer/intern/disk_cache.c +++ b/source/blender/sequencer/intern/disk_cache.c @@ -291,8 +291,8 @@ static void seq_disk_cache_get_project_dir(SeqDiskCache *disk_cache, char *path, /* Use suffix, so that the cache directory name does not conflict with the bmain's blend file. */ const char *suffix = "_seq_cache"; strncat(cache_dir, suffix, sizeof(cache_dir) - strlen(cache_dir) - 1); - BLI_strncpy(path, seq_disk_cache_base_dir(), path_len); - BLI_path_append(path, path_len, cache_dir); + + BLI_path_join(path, path_len, seq_disk_cache_base_dir(), cache_dir); } static void seq_disk_cache_get_dir( @@ -307,9 +307,8 @@ static void seq_disk_cache_get_dir( BLI_strncpy(seq_name, seq->name, sizeof(seq_name)); BLI_filename_make_safe(scene_name); BLI_filename_make_safe(seq_name); - BLI_strncpy(path, project_dir, path_len); - BLI_path_append(path, path_len, scene_name); - BLI_path_append(path, path_len, seq_name); + + BLI_path_join(path, path_len, project_dir, scene_name, seq_name); } static void seq_disk_cache_get_file_path(SeqDiskCache *disk_cache, @@ -350,8 +349,7 @@ static void seq_disk_cache_handle_versioning(SeqDiskCache *disk_cache) int version = 0; seq_disk_cache_get_project_dir(disk_cache, filepath, sizeof(filepath)); - BLI_strncpy(path_version_file, filepath, sizeof(path_version_file)); - BLI_path_append(path_version_file, sizeof(path_version_file), "cache_version"); + BLI_path_join(path_version_file, sizeof(path_version_file), filepath, "cache_version"); if (BLI_exists(filepath) && BLI_is_dir(filepath)) { FILE *file = BLI_fopen(path_version_file, "r"); diff --git a/source/blender/sequencer/intern/proxy.c b/source/blender/sequencer/intern/proxy.c index 9f08db2aa45..fc1df4dc3ac 100644 --- a/source/blender/sequencer/intern/proxy.c +++ b/source/blender/sequencer/intern/proxy.c @@ -585,8 +585,7 @@ void seq_proxy_index_dir_set(struct anim *anim, const char *base_dir) char fname[FILE_MAXFILE]; IMB_anim_get_fname(anim, fname, FILE_MAXFILE); - BLI_strncpy(dir, base_dir, sizeof(dir)); - BLI_path_append(dir, sizeof(dir), fname); + BLI_path_join(dir, sizeof(dir), base_dir, fname); IMB_anim_set_index_dir(anim, dir); } -- cgit v1.2.3 From 117e17fb2259c60c4d744ae364004177de244b6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Wed, 26 Oct 2022 13:02:21 +0200 Subject: DRW: Manager: Allow custom draw command in PassMain This allows using drawcalls with non default vertex range. These calls will be culled like any other instance by the GPU culling pipeline. But they will not be batched together since the vertex range is part of the group. --- source/blender/draw/intern/draw_command.hh | 26 +++++++++++++++----------- source/blender/draw/tests/draw_pass_test.cc | 7 +++++++ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/source/blender/draw/intern/draw_command.hh b/source/blender/draw/intern/draw_command.hh index 5307a242e39..145ec0fe231 100644 --- a/source/blender/draw/intern/draw_command.hh +++ b/source/blender/draw/intern/draw_command.hh @@ -473,10 +473,8 @@ class DrawMultiBuf { uint vertex_first, ResourceHandle handle) { - /* Unsupported for now. Use PassSimple. */ - BLI_assert(vertex_first == 0 || vertex_first == -1); - BLI_assert(vertex_len == -1); - UNUSED_VARS_NDEBUG(vertex_len, vertex_first); + /* Custom draw-calls cannot be batched and will produce one group per draw. */ + const bool custom_group = (vertex_first != 0 || vertex_first != -1 || vertex_len != -1); instance_len = instance_len != -1 ? instance_len : 1; @@ -493,8 +491,14 @@ class DrawMultiBuf { bool inverted = handle.has_inverted_handedness(); - if (group_id == uint(-1)) { + DrawPrototype &draw = prototype_buf_.get_or_resize(prototype_count_++); + draw.resource_handle = handle.raw; + draw.instance_len = instance_len; + draw.group_id = group_id; + + if (group_id == uint(-1) || custom_group) { uint new_group_id = group_count_++; + draw.group_id = new_group_id; DrawGroup &group = group_buf_.get_or_resize(new_group_id); group.next = cmd.group_first; @@ -503,11 +507,16 @@ class DrawMultiBuf { group.gpu_batch = batch; group.front_proto_len = 0; group.back_proto_len = 0; + group.vertex_len = vertex_len; + group.vertex_first = vertex_first; + /* Custom group are not to be registered in the group_ids_. */ + if (!custom_group) { + group_id = new_group_id; + } /* For serialization only. */ (inverted ? group.back_proto_len : group.front_proto_len)++; /* Append to list. */ cmd.group_first = new_group_id; - group_id = new_group_id; } else { DrawGroup &group = group_buf_[group_id]; @@ -516,11 +525,6 @@ class DrawMultiBuf { /* For serialization only. */ (inverted ? group.back_proto_len : group.front_proto_len)++; } - - DrawPrototype &draw = prototype_buf_.get_or_resize(prototype_count_++); - draw.group_id = group_id; - draw.resource_handle = handle.raw; - draw.instance_len = instance_len; } void bind(RecordingState &state, diff --git a/source/blender/draw/tests/draw_pass_test.cc b/source/blender/draw/tests/draw_pass_test.cc index 394ca8bd3cf..95ab8fa2ef1 100644 --- a/source/blender/draw/tests/draw_pass_test.cc +++ b/source/blender/draw/tests/draw_pass_test.cc @@ -181,12 +181,19 @@ static void test_draw_pass_multi_draw() pass.draw_procedural(GPU_PRIM_LINES, 1, -1, -1, {5}); pass.draw_procedural(GPU_PRIM_POINTS, 6, -1, -1, {5}); pass.draw_procedural(GPU_PRIM_TRIS, 3, -1, -1, {6}); + /* Custom calls should use their own group and never be batched. */ + pass.draw_procedural(GPU_PRIM_TRIS, 2, 2, 2, {7}); + pass.draw_procedural(GPU_PRIM_TRIS, 2, 2, 2, {8}); std::string result = pass.serialize(); std::stringstream expected; expected << ".test.multi_draw" << std::endl; expected << " .shader_bind(gpu_shader_3D_image_color)" << std::endl; expected << " .draw_multi(3)" << std::endl; + expected << " .group(id=4, len=2)" << std::endl; + expected << " .proto(instance_len=2, resource_id=8, front_face)" << std::endl; + expected << " .group(id=3, len=2)" << std::endl; + expected << " .proto(instance_len=2, resource_id=7, front_face)" << std::endl; expected << " .group(id=2, len=1)" << std::endl; expected << " .proto(instance_len=1, resource_id=5, front_face)" << std::endl; expected << " .group(id=1, len=15)" << std::endl; -- cgit v1.2.3 From 486e2816442a9ec129c5737f05a4f4f816b0723c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Sun, 30 Oct 2022 13:00:38 +0100 Subject: Fix T102160: Regression: GPencil gradient fill not working Was caused by uvs not being sourced from the correct buffer. --- source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl index 9b1db09ab3c..6fd94336558 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl @@ -85,7 +85,7 @@ void main() } else { int stroke_point_id = gpencil_stroke_point_id(); - vec4 uv1 = texelFetch(gp_col_tx, stroke_point_id * 2 + 2); + vec4 uv1 = texelFetch(gp_pos_tx, stroke_point_id * 3 + 2); vec4 fcol1 = texelFetch(gp_col_tx, stroke_point_id * 2 + 1); vec4 fill_col = gp_mat.fill_color; -- cgit v1.2.3 From 77749eff876209c33ba9236c8b7fb1503af5cbb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Sun, 30 Oct 2022 14:56:54 +0100 Subject: DRW: Manager: Add possibility to record a framebuffer change inside a pass This is a convenience when one needs to often change the current framebuffer and avoid the overhead of creating many Main/Simple passes. --- source/blender/draw/intern/draw_command.cc | 10 ++++++++++ source/blender/draw/intern/draw_command.hh | 8 ++++++++ source/blender/draw/intern/draw_pass.hh | 14 ++++++++++++-- source/blender/gpu/GPU_framebuffer.h | 3 +++ source/blender/gpu/intern/gpu_framebuffer.cc | 5 +++++ source/blender/gpu/intern/gpu_framebuffer_private.hh | 5 +++++ 6 files changed, 43 insertions(+), 2 deletions(-) diff --git a/source/blender/draw/intern/draw_command.cc b/source/blender/draw/intern/draw_command.cc index 882eda9b31d..10dd63e05dc 100644 --- a/source/blender/draw/intern/draw_command.cc +++ b/source/blender/draw/intern/draw_command.cc @@ -30,6 +30,11 @@ void ShaderBind::execute(RecordingState &state) const } } +void FramebufferBind::execute() const +{ + GPU_framebuffer_bind(framebuffer); +} + void ResourceBind::execute() const { if (slot == -1) { @@ -229,6 +234,11 @@ std::string ShaderBind::serialize() const return std::string(".shader_bind(") + GPU_shader_get_name(shader) + ")"; } +std::string FramebufferBind::serialize() const +{ + return std::string(".framebuffer_bind(") + GPU_framebuffer_get_name(framebuffer) + ")"; +} + std::string ResourceBind::serialize() const { switch (type) { diff --git a/source/blender/draw/intern/draw_command.hh b/source/blender/draw/intern/draw_command.hh index 145ec0fe231..ab180cc60b1 100644 --- a/source/blender/draw/intern/draw_command.hh +++ b/source/blender/draw/intern/draw_command.hh @@ -88,6 +88,7 @@ enum class Type : uint8_t { DispatchIndirect, Draw, DrawIndirect, + FramebufferBind, PushConstant, ResourceBind, ShaderBind, @@ -118,6 +119,13 @@ struct ShaderBind { std::string serialize() const; }; +struct FramebufferBind { + GPUFrameBuffer *framebuffer; + + void execute() const; + std::string serialize() const; +}; + struct ResourceBind { eGPUSamplerState sampler; int slot; diff --git a/source/blender/draw/intern/draw_pass.hh b/source/blender/draw/intern/draw_pass.hh index 24dfdd1b97b..892dfdddfcf 100644 --- a/source/blender/draw/intern/draw_pass.hh +++ b/source/blender/draw/intern/draw_pass.hh @@ -14,8 +14,7 @@ * #Pass. Use many #PassSub along with a main #Pass to reduce the overhead and allow groupings of * commands. \note The draw call order inside a batch of multiple draw with the exact same state is * not guaranteed and is not even deterministic. Use a #PassSimple or #PassSortable if ordering is - * needed. \note As of now, it is also quite limited in the type of draw command it can record - * (no custom vertex count, no custom first vertex). + * needed. Custom vertex count and custom first vertex will effectively disable batching. * * `PassSimple`: * Does not have the overhead of #PassMain but does not have the culling and batching optimization. @@ -191,6 +190,12 @@ class PassBase { */ void shader_set(GPUShader *shader); + /** + * Bind a framebuffer. This is equivalent to a deferred GPU_framebuffer_bind() call. + * \note Changes the global GPU state (outside of DRW). + */ + void framebuffer_set(GPUFrameBuffer *framebuffer); + /** * Bind a material shader along with its associated resources. Any following bind() or * push_constant() call will use its interface. @@ -743,6 +748,11 @@ template inline void PassBase::shader_set(GPUShader *shader) create_command(Type::ShaderBind).shader_bind = {shader}; } +template inline void PassBase::framebuffer_set(GPUFrameBuffer *framebuffer) +{ + create_command(Type::FramebufferBind).framebuffer_bind = {framebuffer}; +} + template inline void PassBase::material_set(Manager &manager, GPUMaterial *material) { GPUPass *gpupass = GPU_material_get_pass(material); diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h index bdb384c16f1..917407eece3 100644 --- a/source/blender/gpu/GPU_framebuffer.h +++ b/source/blender/gpu/GPU_framebuffer.h @@ -47,6 +47,9 @@ typedef struct GPUOffScreen GPUOffScreen; GPUFrameBuffer *GPU_framebuffer_create(const char *name); void GPU_framebuffer_free(GPUFrameBuffer *fb); void GPU_framebuffer_bind(GPUFrameBuffer *fb); + +const char *GPU_framebuffer_get_name(GPUFrameBuffer *fb); + /** * Workaround for binding a SRGB frame-buffer without doing the SRGB transform. */ diff --git a/source/blender/gpu/intern/gpu_framebuffer.cc b/source/blender/gpu/intern/gpu_framebuffer.cc index 6528f39d4ec..5b50fd66196 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.cc +++ b/source/blender/gpu/intern/gpu_framebuffer.cc @@ -238,6 +238,11 @@ void GPU_framebuffer_free(GPUFrameBuffer *gpu_fb) delete unwrap(gpu_fb); } +const char *GPU_framebuffer_get_name(GPUFrameBuffer *gpu_fb) +{ + return unwrap(gpu_fb)->name_get(); +} + /* ---------- Binding ----------- */ void GPU_framebuffer_bind(GPUFrameBuffer *gpu_fb) diff --git a/source/blender/gpu/intern/gpu_framebuffer_private.hh b/source/blender/gpu/intern/gpu_framebuffer_private.hh index 5afcc102e44..cb7fd62445c 100644 --- a/source/blender/gpu/intern/gpu_framebuffer_private.hh +++ b/source/blender/gpu/intern/gpu_framebuffer_private.hh @@ -204,6 +204,11 @@ class FrameBuffer { { return attachments_[GPU_FB_COLOR_ATTACHMENT0 + slot].tex; }; + + inline const char *const name_get() const + { + return name_; + }; }; /* Syntactic sugar. */ -- cgit v1.2.3 From da365bc2adbf1c89c53136f832df9dfe7b998504 Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Sun, 30 Oct 2022 16:15:11 +0100 Subject: Fix T102163: GPencil:Set start point Operator make stroke deleted There were two problems: * The stroke was deleted if the last point was selected. Now the stroke is flipped because is faster. * If the second point was selected, the first point was removed because the internal api, removed one point strokes by default. This was done becaus ethe tools that used this API did not need one point strokes as result. Now this optional and keep one point strokes. --- source/blender/blenkernel/BKE_gpencil_geom.h | 6 +++++- source/blender/blenkernel/intern/gpencil_geom.cc | 17 ++++++++++------- source/blender/editors/gpencil/gpencil_edit.c | 7 ++++++- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h index b9219814c08..976961f27ae 100644 --- a/source/blender/blenkernel/BKE_gpencil_geom.h +++ b/source/blender/blenkernel/BKE_gpencil_geom.h @@ -332,8 +332,12 @@ bool BKE_gpencil_stroke_stretch(struct bGPDstroke *gps, * \param gps: Target stroke. * \param index_from: the index of the first point to be used in the trimmed result. * \param index_to: the index of the last point to be used in the trimmed result. + * \param keep_point: Keep strokes with one point. False remove the single points strokes */ -bool BKE_gpencil_stroke_trim_points(struct bGPDstroke *gps, int index_from, int index_to); +bool BKE_gpencil_stroke_trim_points(struct bGPDstroke *gps, + int index_from, + int index_to, + const bool keep_point); /** * Split the given stroke into several new strokes, partitioning * it based on whether the stroke points have a particular flag diff --git a/source/blender/blenkernel/intern/gpencil_geom.cc b/source/blender/blenkernel/intern/gpencil_geom.cc index 52fcdef8a43..9297663b157 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.cc +++ b/source/blender/blenkernel/intern/gpencil_geom.cc @@ -789,7 +789,10 @@ bool BKE_gpencil_stroke_stretch(bGPDstroke *gps, /** \name Stroke Trim * \{ */ -bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const int index_to) +bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, + const int index_from, + const int index_to, + const bool keep_point) { bGPDspoint *pt = gps->points, *new_pt; MDeformVert *dv, *new_dv; @@ -800,7 +803,7 @@ bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const return false; } - if (new_count == 1) { + if ((!keep_point) && (new_count == 1)) { if (gps->dvert) { BKE_gpencil_free_stroke_weights(gps); MEM_freeN(gps->dvert); @@ -894,7 +897,7 @@ bool BKE_gpencil_stroke_split(bGPdata *gpd, /* Trim the original stroke into a shorter one. * Keep the end point. */ - BKE_gpencil_stroke_trim_points(gps, 0, old_count); + BKE_gpencil_stroke_trim_points(gps, 0, old_count, false); BKE_gpencil_stroke_geometry_update(gpd, gps); return true; } @@ -917,7 +920,7 @@ bool BKE_gpencil_stroke_shrink(bGPDstroke *gps, const float dist, const short mo if (gps->totpoints == 1) { second_last = &pt[1]; if (len_v3v3(&second_last->x, &pt->x) < dist) { - BKE_gpencil_stroke_trim_points(gps, 0, 0); + BKE_gpencil_stroke_trim_points(gps, 0, 0, false); return true; } } @@ -969,7 +972,7 @@ bool BKE_gpencil_stroke_shrink(bGPDstroke *gps, const float dist, const short mo index_start = index_end = 0; /* no length left to cut */ } - BKE_gpencil_stroke_trim_points(gps, index_start, index_end); + BKE_gpencil_stroke_trim_points(gps, index_start, index_end, false); if (gps->totpoints == 0) { return false; @@ -3562,8 +3565,8 @@ void BKE_gpencil_stroke_start_set(bGPDstroke *gps, int start_idx) } bGPDstroke *gps_b = BKE_gpencil_stroke_duplicate(gps, true, false); - BKE_gpencil_stroke_trim_points(gps_b, 0, start_idx - 1); - BKE_gpencil_stroke_trim_points(gps, start_idx, gps->totpoints - 1); + BKE_gpencil_stroke_trim_points(gps_b, 0, start_idx - 1, true); + BKE_gpencil_stroke_trim_points(gps, start_idx, gps->totpoints - 1, true); /* Join both strokes. */ BKE_gpencil_stroke_join(gps, gps_b, false, false, false, false); diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 6181b9810e3..66f86a3e0c1 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -3848,7 +3848,12 @@ static int gpencil_stroke_start_set_exec(bContext *C, wmOperator *op) for (int i = 0; i < gps->totpoints; i++) { pt = &gps->points[i]; if (pt->flag & GP_SPOINT_SELECT) { - BKE_gpencil_stroke_start_set(gps, i); + if (i == gps->totpoints - 1) { + BKE_gpencil_stroke_flip(gps); + } + else { + BKE_gpencil_stroke_start_set(gps, i); + } BKE_gpencil_stroke_geometry_update(gpd, gps); changed = true; break; -- cgit v1.2.3 From 8c6d4aa1036fe8984725c5b664a263bc194526ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Sun, 30 Oct 2022 17:30:54 +0100 Subject: Fix T102126 Regression: Grease Pencil: Broken 2D Layering This was because `stroke_id` was not using `vertex_start`. But since `vertex_start` is not 1 based like it used to be, we need to add 1 to it to avoid a fragment depth of `0.0` which would be equal to the background and not render. --- source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl | 6 +++--- source/blender/draw/intern/draw_cache_impl_gpencil.cc | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl index 6fd94336558..2e7544cea29 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl @@ -71,7 +71,7 @@ void main() /* Use the index of the point as depth. * This means the stroke can overlap itself. */ float point_index = float(ma1.z); - gp_interp.depth = (point_index + gpStrokeIndexOffset + 1.0) * 0.0000002; + gp_interp.depth = (point_index + gpStrokeIndexOffset + 2.0) * 0.0000002; } else { /* Use the index of first point of the stroke as depth. @@ -80,7 +80,7 @@ void main() * We offset by one so that the fill can be overlapped by its stroke. * The offset is ok since we pad the strokes data because of adjacency infos. */ float stroke_index = float(ma1.y); - gp_interp.depth = (stroke_index + gpStrokeIndexOffset + 1.0) * 0.0000002; + gp_interp.depth = (stroke_index + gpStrokeIndexOffset + 2.0) * 0.0000002; } } else { @@ -128,7 +128,7 @@ void main() else { /* Use the index of first point of the stroke as depth. */ float stroke_index = float(ma1.y); - gp_interp.depth = (stroke_index + gpStrokeIndexOffset) * 0.0000002; + gp_interp.depth = (stroke_index + gpStrokeIndexOffset + 1.0) * 0.0000002; } } } diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.cc b/source/blender/draw/intern/draw_cache_impl_gpencil.cc index 6c38b23f44f..3d6d2631186 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.cc +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.cc @@ -319,7 +319,7 @@ static void gpencil_buffer_add_point(GPUIndexBufBuilder *ibo, vert->strength = (round_cap0) ? pt->strength : -pt->strength; vert->u_stroke = pt->uv_fac; - vert->stroke_id = gps->runtime.stroke_start; + vert->stroke_id = gps->runtime.vertex_start; vert->point_id = v; vert->thickness = max_ff(0.0f, gps->thickness * pt->pressure) * (round_cap1 ? 1.0f : -1.0f); /* Tag endpoint material to -1 so they get discarded by vertex shader. */ -- cgit v1.2.3 From 06abc9509dea9d5cd1cd49121bec9872d47e0ae4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 31 Oct 2022 11:15:38 +1100 Subject: Cleanup: quiet warning building with MSVC (_CONCAT redefined) This is defined by a system header (xatomic.h) with MSVC. --- source/blender/blenlib/intern/kdtree_impl.h | 6 ++-- source/blender/blenlib/intern/list_sort_impl.h | 49 ++++++++++++++------------ 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/source/blender/blenlib/intern/kdtree_impl.h b/source/blender/blenlib/intern/kdtree_impl.h index 6614f1bf964..f7993eb5adc 100644 --- a/source/blender/blenlib/intern/kdtree_impl.h +++ b/source/blender/blenlib/intern/kdtree_impl.h @@ -11,9 +11,9 @@ #include "BLI_strict_flags.h" #include "BLI_utildefines.h" -#define _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2 -#define _CONCAT(MACRO_ARG1, MACRO_ARG2) _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) -#define BLI_kdtree_nd_(id) _CONCAT(KDTREE_PREFIX_ID, _##id) +#define _BLI_KDTREE_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2 +#define _BLI_KDTREE_CONCAT(MACRO_ARG1, MACRO_ARG2) _BLI_KDTREE_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) +#define BLI_kdtree_nd_(id) _BLI_KDTREE_CONCAT(KDTREE_PREFIX_ID, _##id) typedef struct KDTreeNode_head { uint left, right; diff --git a/source/blender/blenlib/intern/list_sort_impl.h b/source/blender/blenlib/intern/list_sort_impl.h index e1b93986f4a..7c38fc60b29 100644 --- a/source/blender/blenlib/intern/list_sort_impl.h +++ b/source/blender/blenlib/intern/list_sort_impl.h @@ -47,24 +47,25 @@ #endif #ifdef SORT_IMPL_USE_THUNK -# define THUNK_APPEND1(a, thunk) a, thunk -# define THUNK_PREPEND2(thunk, a, b) thunk, a, b +# define BLI_LIST_THUNK_APPEND1(a, thunk) a, thunk +# define BLI_LIST_THUNK_PREPEND2(thunk, a, b) thunk, a, b #else -# define THUNK_APPEND1(a, thunk) a -# define THUNK_PREPEND2(thunk, a, b) a, b +# define BLI_LIST_THUNK_APPEND1(a, thunk) a +# define BLI_LIST_THUNK_PREPEND2(thunk, a, b) a, b #endif -#define _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2 -#define _CONCAT(MACRO_ARG1, MACRO_ARG2) _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) -#define _SORT_PREFIX(id) _CONCAT(SORT_IMPL_FUNC, _##id) +#define _BLI_LIST_SORT_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2 +#define _BLI_LIST_SORT_CONCAT(MACRO_ARG1, MACRO_ARG2) \ + _BLI_LIST_SORT_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) +#define _BLI_LIST_SORT_PREFIX(id) _BLI_LIST_SORT_CONCAT(SORT_IMPL_FUNC, _##id) /* local identifiers */ -#define SortInfo _SORT_PREFIX(SortInfo) -#define CompareFn _SORT_PREFIX(CompareFn) -#define init_sort_info _SORT_PREFIX(init_sort_info) -#define merge_lists _SORT_PREFIX(merge_lists) -#define sweep_up _SORT_PREFIX(sweep_up) -#define insert_list _SORT_PREFIX(insert_list) +#define SortInfo _BLI_LIST_SORT_PREFIX(SortInfo) +#define CompareFn _BLI_LIST_SORT_PREFIX(CompareFn) +#define init_sort_info _BLI_LIST_SORT_PREFIX(init_sort_info) +#define merge_lists _BLI_LIST_SORT_PREFIX(merge_lists) +#define sweep_up _BLI_LIST_SORT_PREFIX(sweep_up) +#define insert_list _BLI_LIST_SORT_PREFIX(insert_list) typedef int (*CompareFn)( #ifdef SORT_IMPL_USE_THUNK @@ -159,7 +160,7 @@ BLI_INLINE list_node *merge_lists(list_node *first, list_node *list = NULL; list_node **pos = &list; while (first && second) { - if (func(THUNK_PREPEND2(thunk, SORT_ARG(first), SORT_ARG(second))) > 0) { + if (func(BLI_LIST_THUNK_PREPEND2(thunk, SORT_ARG(first), SORT_ARG(second))) > 0) { *pos = second; second = second->next; } @@ -181,7 +182,7 @@ BLI_INLINE list_node *sweep_up(struct SortInfo *si, list_node *list, unsigned in { unsigned int i; for (i = si->min_rank; i < upto; i++) { - list = merge_lists(si->ranks[i], list, THUNK_APPEND1(si->func, si->thunk)); + list = merge_lists(si->ranks[i], list, BLI_LIST_THUNK_APPEND1(si->func, si->thunk)); si->ranks[i] = NULL; } return list; @@ -225,17 +226,19 @@ BLI_INLINE void insert_list(struct SortInfo *si, list_node *list, unsigned int r // printf("Rank '%d' should not exceed " STRINGIFY(MAX_RANKS), rank); rank = MAX_RANKS; } - list = merge_lists(sweep_up(si, NULL, si->n_ranks), list, THUNK_APPEND1(si->func, si->thunk)); + list = merge_lists( + sweep_up(si, NULL, si->n_ranks), list, BLI_LIST_THUNK_APPEND1(si->func, si->thunk)); for (i = si->n_ranks; i < rank; i++) { si->ranks[i] = NULL; } } else { if (rank) { - list = merge_lists(sweep_up(si, NULL, rank), list, THUNK_APPEND1(si->func, si->thunk)); + list = merge_lists( + sweep_up(si, NULL, rank), list, BLI_LIST_THUNK_APPEND1(si->func, si->thunk)); } for (i = rank; i < si->n_ranks && si->ranks[i]; i++) { - list = merge_lists(si->ranks[i], list, THUNK_APPEND1(si->func, si->thunk)); + list = merge_lists(si->ranks[i], list, BLI_LIST_THUNK_APPEND1(si->func, si->thunk)); si->ranks[i] = NULL; } } @@ -281,7 +284,7 @@ BLI_INLINE list_node *list_sort_do(list_node *list, list_node *next = list->next; list_node *tail = next->next; - if (func(THUNK_PREPEND2(thunk, SORT_ARG(list), SORT_ARG(next))) > 0) { + if (func(BLI_LIST_THUNK_PREPEND2(thunk, SORT_ARG(list), SORT_ARG(next))) > 0) { next->next = list; next = list; list = list->next; @@ -296,8 +299,8 @@ BLI_INLINE list_node *list_sort_do(list_node *list, return sweep_up(&si, list, si.n_ranks); } -#undef _CONCAT_AUX -#undef _CONCAT +#undef _BLI_LIST_SORT_CONCAT_AUX +#undef _BLI_LIST_SORT_CONCAT #undef _SORT_PREFIX #undef SortInfo @@ -310,6 +313,6 @@ BLI_INLINE list_node *list_sort_do(list_node *list, #undef list_node #undef list_sort_do -#undef THUNK_APPEND1 -#undef THUNK_PREPEND2 +#undef BLI_LIST_THUNK_APPEND1 +#undef BLI_LIST_THUNK_PREPEND2 #undef SORT_ARG -- cgit v1.2.3 From 5042f895ceeee0c7f54a0823d250a39aa68ea651 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 31 Oct 2022 12:54:36 +1100 Subject: make_update: add type hints --- build_files/utils/make_update.py | 26 ++++++++++++++++++-------- build_files/utils/make_utils.py | 2 +- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/build_files/utils/make_update.py b/build_files/utils/make_update.py index 254cccda301..e7d28aeb75b 100755 --- a/build_files/utils/make_update.py +++ b/build_files/utils/make_update.py @@ -18,8 +18,13 @@ import sys import make_utils from make_utils import call, check_output +from typing import ( + List, + Optional, +) -def print_stage(text): + +def print_stage(text: str) -> None: print("") print(text) print("") @@ -27,7 +32,7 @@ def print_stage(text): # Parse arguments -def parse_arguments(): +def parse_arguments() -> argparse.Namespace: parser = argparse.ArgumentParser() parser.add_argument("--no-libraries", action="store_true") parser.add_argument("--no-blender", action="store_true") @@ -40,13 +45,13 @@ def parse_arguments(): return parser.parse_args() -def get_blender_git_root(): +def get_blender_git_root() -> str: return check_output([args.git_command, "rev-parse", "--show-toplevel"]) # Setup for precompiled libraries and tests from svn. -def svn_update(args, release_version): +def svn_update(args: argparse.Namespace, release_version: Optional[str]) -> None: svn_non_interactive = [args.svn_command, '--non-interactive'] lib_dirpath = os.path.join(get_blender_git_root(), '..', 'lib') @@ -134,7 +139,7 @@ def svn_update(args, release_version): # Test if git repo can be updated. -def git_update_skip(args, check_remote_exists=True): +def git_update_skip(args: argparse.Namespace, check_remote_exists: bool = True) -> str: if make_utils.command_missing(args.git_command): sys.stderr.write("git not found, can't update code\n") sys.exit(1) @@ -166,13 +171,17 @@ def git_update_skip(args, check_remote_exists=True): # Update blender repository. -def blender_update(args): +def blender_update(args: argparse.Namespace) -> None: print_stage("Updating Blender Git Repository") call([args.git_command, "pull", "--rebase"]) # Update submodules. -def submodules_update(args, release_version, branch): +def submodules_update( + args: argparse.Namespace, + release_version: Optional[str], + branch: Optional[str], +) -> str: print_stage("Updating Submodules") if make_utils.command_missing(args.git_command): sys.stderr.write("git not found, can't update code\n") @@ -214,7 +223,8 @@ def submodules_update(args, release_version, branch): elif make_utils.git_branch_exists(args.git_command, submodule_branch_fallback): submodule_branch = submodule_branch_fallback else: - submodule_branch = None + # Skip. + submodule_branch = "" # Switch to branch and pull. if submodule_branch: diff --git a/build_files/utils/make_utils.py b/build_files/utils/make_utils.py index 564930617ff..9b15eb363bc 100755 --- a/build_files/utils/make_utils.py +++ b/build_files/utils/make_utils.py @@ -80,7 +80,7 @@ def git_tag(git_command: str) -> Optional[str]: return tag.strip().decode('utf8') -def git_branch_release_version(branch: str, tag: str) -> Optional[str]: +def git_branch_release_version(branch: str, tag: Optional[str]) -> Optional[str]: re_match = re.search("^blender-v(.*)-release$", branch) release_version = None if re_match: -- cgit v1.2.3 From fe5cbd5eea4ad56e889be1f6b18eb2ca96225754 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 31 Oct 2022 12:54:38 +1100 Subject: make_update: support updating "lib" as a single repository With a full SVN checkout of "../lib", updating all paths is slower than running an update on the whole repository at once. Also collect paths and run the update in separate passes, this avoids some duplicate checks such as checking the svn command exists. --- build_files/utils/make_update.py | 60 ++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/build_files/utils/make_update.py b/build_files/utils/make_update.py index e7d28aeb75b..a0b61b18e60 100755 --- a/build_files/utils/make_update.py +++ b/build_files/utils/make_update.py @@ -104,37 +104,37 @@ def svn_update(args: argparse.Namespace, release_version: Optional[str]) -> None call(svn_non_interactive + ["checkout", svn_url_tests, lib_tests_dirpath]) # Update precompiled libraries and tests - print_stage("Updating Precompiled Libraries and Tests") - - if os.path.isdir(lib_dirpath): - for dirname in os.listdir(lib_dirpath): - dirpath = os.path.join(lib_dirpath, dirname) - - if dirname == ".svn": - # Cleanup must be run from svn root directory if it exists. - if not make_utils.command_missing(args.svn_command): - call(svn_non_interactive + ["cleanup", lib_dirpath]) - continue - elif dirname.startswith("."): - # Temporary paths such as ".mypy_cache" will report a warning, skip hidden directories. - continue - - svn_dirpath = os.path.join(dirpath, ".svn") - svn_root_dirpath = os.path.join(lib_dirpath, ".svn") - - if ( - os.path.isdir(dirpath) and - (os.path.exists(svn_dirpath) or os.path.exists(svn_root_dirpath)) - ): - if make_utils.command_missing(args.svn_command): - sys.stderr.write("svn not found, can't update libraries\n") - sys.exit(1) - - # Cleanup to continue with interrupted downloads. - if os.path.exists(svn_dirpath): - call(svn_non_interactive + ["cleanup", dirpath]) + + if not os.path.isdir(lib_dirpath): + print("Library path: %r, not found, skipping" % lib_dirpath) + else: + paths_local_and_remote = [] + if os.path.exists(os.path.join(lib_dirpath, ".svn")): + print_stage("Updating Precompiled Libraries and Tests (one repository)") + paths_local_and_remote.append((lib_dirpath, svn_url)) + else: + print_stage("Updating Precompiled Libraries and Tests (multiple repositories)") + # Separate paths checked out. + for dirname in os.listdir(lib_dirpath): + if dirname.startswith("."): + # Temporary paths such as ".mypy_cache" will report a warning, skip hidden directories. + continue + + dirpath = os.path.join(lib_dirpath, dirname) + if not (os.path.isdir(dirpath) and os.path.exists(os.path.join(dirpath, ".svn"))): + continue + + paths_local_and_remote.append((dirpath, svn_url + dirname)) + + if paths_local_and_remote: + if make_utils.command_missing(args.svn_command): + sys.stderr.write("svn not found, can't update libraries\n") + sys.exit(1) + + for dirpath, svn_url_full in paths_local_and_remote: + call(svn_non_interactive + ["cleanup", dirpath]) # Switch to appropriate branch and update. - call(svn_non_interactive + ["switch", svn_url + dirname, dirpath], exit_on_error=False) + call(svn_non_interactive + ["switch", svn_url_full, dirpath], exit_on_error=False) call(svn_non_interactive + ["update", dirpath]) -- cgit v1.2.3 From 8f7ab1bf46d5e8610b167180b7631ff62e718a08 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 31 Oct 2022 13:04:30 +1100 Subject: BLI_path: only operate on native path slashes for BLI_path_join Previously both slashes were considered when joining paths, meaning slashes that were part of the path name could be stripped before joining the path. Prefer using the native path separator for low level path functions, callers can always convert slashes into the expected direction if they need. This also matches BLI_path_append behavior. --- source/blender/blenlib/intern/path_util.c | 11 ++--- source/blender/blenlib/tests/BLI_path_util_test.cc | 47 +++++++++++++++++++--- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index bb87a26dada..4e3d9be6186 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1487,9 +1487,10 @@ size_t BLI_path_join_array(char *__restrict dst, bool has_trailing_slash = false; if (ofs != 0) { size_t len = ofs; - while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) { + while ((len != 0) && (path[len - 1] == SEP)) { len -= 1; } + if (len != 0) { ofs = len; } @@ -1500,18 +1501,18 @@ size_t BLI_path_join_array(char *__restrict dst, path = path_array[path_index]; has_trailing_slash = false; const char *path_init = path; - while (ELEM(path[0], SEP, ALTSEP)) { + while (path[0] == SEP) { path++; } size_t len = strlen(path); if (len != 0) { - while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) { + while ((len != 0) && (path[len - 1] == SEP)) { len -= 1; } if (len != 0) { /* the very first path may have a slash at the end */ - if (ofs && !ELEM(dst[ofs - 1], SEP, ALTSEP)) { + if (ofs && (dst[ofs - 1] != SEP)) { dst[ofs++] = SEP; if (ofs == dst_last) { break; @@ -1534,7 +1535,7 @@ size_t BLI_path_join_array(char *__restrict dst, } if (has_trailing_slash) { - if ((ofs != dst_last) && (ofs != 0) && (ELEM(dst[ofs - 1], SEP, ALTSEP) == 0)) { + if ((ofs != dst_last) && (ofs != 0) && (dst[ofs - 1] != SEP)) { dst[ofs++] = SEP; } } diff --git a/source/blender/blenlib/tests/BLI_path_util_test.cc b/source/blender/blenlib/tests/BLI_path_util_test.cc index 89e537235db..1120e85c959 100644 --- a/source/blender/blenlib/tests/BLI_path_util_test.cc +++ b/source/blender/blenlib/tests/BLI_path_util_test.cc @@ -201,20 +201,53 @@ TEST(path_util, NameAtIndex_NoneComplexNeg) #undef AT_INDEX -#define JOIN(str_expect, out_size, ...) \ +/* For systems with `/` path separator (non WIN32). */ +#define JOIN_FORWARD_SLASH(str_expect, out_size, ...) \ { \ const char *expect = str_expect; \ char result[(out_size) + 1024]; \ - /* check we don't write past the last byte */ \ + /* Check we don't write past the last byte. */ \ result[out_size] = '\0'; \ BLI_path_join(result, out_size, __VA_ARGS__); \ - /* simplify expected string */ \ + EXPECT_STREQ(result, expect); \ + EXPECT_EQ(result[out_size], '\0'); \ + } \ + ((void)0) + +/* For systems with `\` path separator (WIN32). + * Perform additional manipulation to behave as if input arguments used `\` separators. + * Needed since #BLI_path_join uses native slashes. */ +#define JOIN_BACK_SLASH(str_expect, out_size, ...) \ + { \ + const char *expect = str_expect; \ + char result[(out_size) + 1024]; \ + const char *input_forward_slash[] = {__VA_ARGS__}; \ + char *input_back_slash[ARRAY_SIZE(input_forward_slash)] = {nullptr}; \ + for (int i = 0; i < ARRAY_SIZE(input_forward_slash); i++) { \ + input_back_slash[i] = strdup(input_forward_slash[i]); \ + BLI_str_replace_char(input_back_slash[i], '/', '\\'); \ + } \ + /* Check we don't write past the last byte. */ \ + result[out_size] = '\0'; \ + BLI_path_join_array(result, \ + out_size, \ + const_cast(input_back_slash), \ + ARRAY_SIZE(input_back_slash)); \ BLI_str_replace_char(result, '\\', '/'); \ EXPECT_STREQ(result, expect); \ EXPECT_EQ(result[out_size], '\0'); \ + for (int i = 0; i < ARRAY_SIZE(input_forward_slash); i++) { \ + free(input_back_slash[i]); \ + } \ } \ ((void)0) +#ifdef WIN32 +# define JOIN JOIN_BACK_SLASH +#else +# define JOIN JOIN_FORWARD_SLASH +#endif + /* BLI_path_join */ TEST(path_util, JoinNop) { @@ -293,9 +326,9 @@ TEST(path_util, JoinTruncateLong) TEST(path_util, JoinComplex) { - JOIN("/a/b/c/d/e/f/g/", 100, "/", "\\a/b", "//////c/d", "", "e\\\\", "f", "g//"); - JOIN("/aa/bb/cc/dd/ee/ff/gg/", 100, "/", "\\aa/bb", "//////cc/dd", "", "ee\\\\", "ff", "gg//"); - JOIN("1/2/3/", 100, "1", "////////", "", "2", "3\\"); + JOIN("/a/b/c/d/e/f/g/", 100, "/", "a/b", "//////c/d", "", "e", "f", "g//"); + JOIN("/aa/bb/cc/dd/ee/ff/gg/", 100, "/", "aa/bb", "//////cc/dd", "", "ee", "ff", "gg//"); + JOIN("1/2/3/", 100, "1", "////////", "", "2", "3///"); } TEST(path_util, JoinRelativePrefix) @@ -306,6 +339,8 @@ TEST(path_util, JoinRelativePrefix) } #undef JOIN +#undef JOIN_BACK_SLASH +#undef JOIN_FORWARD_SLASH /* BLI_path_frame */ TEST(path_util, Frame) -- cgit v1.2.3 From 511ae2226473df57e47b439392da387cd355abef Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 31 Oct 2022 13:21:24 +1100 Subject: BLI_path: only operate on native path slashes for BLI_path_name_at_index Prefer using the native path separator for low level path functions. --- source/blender/blenlib/intern/path_util.c | 4 ++-- source/blender/blenlib/tests/BLI_path_util_test.cc | 24 +++++++++++++--------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 4e3d9be6186..b16cf8ea161 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1563,7 +1563,7 @@ bool BLI_path_name_at_index(const char *__restrict path, int i = 0; while (true) { const char c = path[i]; - if (ELEM(c, SEP, ALTSEP, '\0')) { + if (ELEM(c, SEP, '\0')) { if (prev + 1 != i) { prev += 1; if (index_step == index) { @@ -1590,7 +1590,7 @@ bool BLI_path_name_at_index(const char *__restrict path, int i = prev - 1; while (true) { const char c = i >= 0 ? path[i] : '\0'; - if (ELEM(c, SEP, ALTSEP, '\0')) { + if (ELEM(c, SEP, '\0')) { if (prev - 1 != i) { i += 1; if (index_step == index) { diff --git a/source/blender/blenlib/tests/BLI_path_util_test.cc b/source/blender/blenlib/tests/BLI_path_util_test.cc index 1120e85c959..1241c71cf94 100644 --- a/source/blender/blenlib/tests/BLI_path_util_test.cc +++ b/source/blender/blenlib/tests/BLI_path_util_test.cc @@ -72,6 +72,10 @@ TEST(path_util, Clean) #define AT_INDEX(str_input, index_input, str_expect) \ { \ char path[] = str_input; \ + /* Test input assumes forward slash, support back-slash on WIN32. */ \ + if (SEP == '\\') { \ + BLI_str_replace_char(path, '/', '\\'); \ + } \ const char *expect = str_expect; \ int index_output, len_output; \ const bool ret = BLI_path_name_at_index(path, index_input, &index_output, &len_output); \ @@ -166,21 +170,21 @@ TEST(path_util, NameAtIndex_MiscNeg) TEST(path_util, NameAtIndex_MiscComplex) { AT_INDEX("how//now/brown/cow", 0, "how"); - AT_INDEX("//how///now\\/brown/cow", 1, "now"); - AT_INDEX("/how/now\\//brown\\/cow", 2, "brown"); - AT_INDEX("/how/now/brown/cow//\\", 3, "cow"); - AT_INDEX("/how/now/brown/\\cow", 4, nullptr); - AT_INDEX("how/now/brown/\\cow\\", 4, nullptr); + AT_INDEX("//how///now//brown/cow", 1, "now"); + AT_INDEX("/how/now///brown//cow", 2, "brown"); + AT_INDEX("/how/now/brown/cow///", 3, "cow"); + AT_INDEX("/how/now/brown//cow", 4, nullptr); + AT_INDEX("how/now/brown//cow/", 4, nullptr); } TEST(path_util, NameAtIndex_MiscComplexNeg) { AT_INDEX("how//now/brown/cow", -4, "how"); - AT_INDEX("//how///now\\/brown/cow", -3, "now"); - AT_INDEX("/how/now\\//brown\\/cow", -2, "brown"); - AT_INDEX("/how/now/brown/cow//\\", -1, "cow"); - AT_INDEX("/how/now/brown/\\cow", -5, nullptr); - AT_INDEX("how/now/brown/\\cow\\", -5, nullptr); + AT_INDEX("//how///now//brown/cow", -3, "now"); + AT_INDEX("/how/now///brown//cow", -2, "brown"); + AT_INDEX("/how/now/brown/cow///", -1, "cow"); + AT_INDEX("/how/now/brown//cow", -5, nullptr); + AT_INDEX("how/now/brown//cow/", -5, nullptr); } TEST(path_util, NameAtIndex_NoneComplex) -- cgit v1.2.3 From c2e36c09b993fc0678eaf6a65b2cbd8ea9132cdb Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Mon, 31 Oct 2022 06:54:17 -0300 Subject: Fix variable value assigned twice in succession Error introduced in rBa7aa0f1a0c24 Mentioned in https://pvs-studio.com/en/blog/posts/cpp/1004/ It could cause the absolute snap to the y direction to fail in some editor. --- source/blender/editors/transform/transform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 5b194ae7237..ad6ab625438 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1725,7 +1725,7 @@ static void initSnapSpatial(TransInfo *t, float r_snap[3], float *r_snap_precisi { /* Default values. */ r_snap[0] = r_snap[1] = 1.0f; - r_snap[1] = 0.0f; + r_snap[2] = 0.0f; *r_snap_precision = 0.1f; if (t->spacetype == SPACE_VIEW3D) { -- cgit v1.2.3 From 0e6f2d9fe0f49de658414bf16a9babab61f1895a Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 31 Oct 2022 16:01:02 +0100 Subject: GPU: Add placeholder for Vulkan backend. This patch adds a placeholder for the vulkan backend. When activated (`WITH_VULKAN_BACKEND=On` and `--gpu-backend vulkan`) it might open a blender screen, but nothing should be visible as none of the functions are implemented or otherwise crash on a nullptr. This is expected as this is just a placeholder. The goal is to add shader compilation +validation to this backend as one of the next steps so we can validate changes to existing shaders on OpenGL, Metal and Vulkan at the same time. Reviewed By: fclem Differential Revision: https://developer.blender.org/D16338 --- CMakeLists.txt | 13 +++ source/blender/gpu/CMakeLists.txt | 33 ++++++++ source/blender/gpu/GPU_platform.h | 1 + source/blender/gpu/intern/gpu_context.cc | 14 ++++ source/blender/gpu/vulkan/vk_backend.cc | 107 ++++++++++++++++++++++++ source/blender/gpu/vulkan/vk_backend.hh | 42 ++++++++++ source/blender/gpu/vulkan/vk_batch.cc | 27 ++++++ source/blender/gpu/vulkan/vk_batch.hh | 24 ++++++ source/blender/gpu/vulkan/vk_context.cc | 48 +++++++++++ source/blender/gpu/vulkan/vk_context.hh | 34 ++++++++ source/blender/gpu/vulkan/vk_drawlist.cc | 20 +++++ source/blender/gpu/vulkan/vk_drawlist.hh | 20 +++++ source/blender/gpu/vulkan/vk_framebuffer.cc | 62 ++++++++++++++ source/blender/gpu/vulkan/vk_framebuffer.hh | 50 +++++++++++ source/blender/gpu/vulkan/vk_index_buffer.cc | 33 ++++++++ source/blender/gpu/vulkan/vk_index_buffer.hh | 28 +++++++ source/blender/gpu/vulkan/vk_query.cc | 28 +++++++ source/blender/gpu/vulkan/vk_query.hh | 22 +++++ source/blender/gpu/vulkan/vk_shader.cc | 101 ++++++++++++++++++++++ source/blender/gpu/vulkan/vk_shader.hh | 47 +++++++++++ source/blender/gpu/vulkan/vk_storage_buffer.cc | 42 ++++++++++ source/blender/gpu/vulkan/vk_storage_buffer.hh | 30 +++++++ source/blender/gpu/vulkan/vk_texture.cc | 70 ++++++++++++++++ source/blender/gpu/vulkan/vk_texture.hh | 39 +++++++++ source/blender/gpu/vulkan/vk_uniform_buffer.cc | 24 ++++++ source/blender/gpu/vulkan/vk_uniform_buffer.hh | 25 ++++++ source/blender/gpu/vulkan/vk_vertex_buffer.cc | 58 +++++++++++++ source/blender/gpu/vulkan/vk_vertex_buffer.hh | 32 +++++++ source/blender/python/gpu/gpu_py_platform.c | 4 +- source/blender/windowmanager/intern/wm_window.c | 3 + source/creator/creator_args.c | 8 ++ 31 files changed, 1088 insertions(+), 1 deletion(-) create mode 100644 source/blender/gpu/vulkan/vk_backend.cc create mode 100644 source/blender/gpu/vulkan/vk_backend.hh create mode 100644 source/blender/gpu/vulkan/vk_batch.cc create mode 100644 source/blender/gpu/vulkan/vk_batch.hh create mode 100644 source/blender/gpu/vulkan/vk_context.cc create mode 100644 source/blender/gpu/vulkan/vk_context.hh create mode 100644 source/blender/gpu/vulkan/vk_drawlist.cc create mode 100644 source/blender/gpu/vulkan/vk_drawlist.hh create mode 100644 source/blender/gpu/vulkan/vk_framebuffer.cc create mode 100644 source/blender/gpu/vulkan/vk_framebuffer.hh create mode 100644 source/blender/gpu/vulkan/vk_index_buffer.cc create mode 100644 source/blender/gpu/vulkan/vk_index_buffer.hh create mode 100644 source/blender/gpu/vulkan/vk_query.cc create mode 100644 source/blender/gpu/vulkan/vk_query.hh create mode 100644 source/blender/gpu/vulkan/vk_shader.cc create mode 100644 source/blender/gpu/vulkan/vk_shader.hh create mode 100644 source/blender/gpu/vulkan/vk_storage_buffer.cc create mode 100644 source/blender/gpu/vulkan/vk_storage_buffer.hh create mode 100644 source/blender/gpu/vulkan/vk_texture.cc create mode 100644 source/blender/gpu/vulkan/vk_texture.hh create mode 100644 source/blender/gpu/vulkan/vk_uniform_buffer.cc create mode 100644 source/blender/gpu/vulkan/vk_uniform_buffer.hh create mode 100644 source/blender/gpu/vulkan/vk_vertex_buffer.cc create mode 100644 source/blender/gpu/vulkan/vk_vertex_buffer.hh diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c5fa8a63f6..7e89943714a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -569,6 +569,12 @@ mark_as_advanced( WITH_GPU_BUILDTIME_SHADER_BUILDER ) +# Vulkan +option(WITH_VULKAN_BACKEND "Enable Vulkan as graphics backend (only for development)" OFF) +mark_as_advanced( + WITH_VULKAN_BACKEND +) + # Metal if(APPLE) @@ -1222,6 +1228,13 @@ if(WITH_OPENGL) endif() +# ----------------------------------------------------------------------------- +# Configure Vulkan. + +if(WITH_VULKAN_BACKEND) + add_definitions(-DWITH_VULKAN_BACKEND) +endif() + # ----------------------------------------------------------------------------- # Configure Metal diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 58b1cd0a50b..bfbbf1be225 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -12,6 +12,7 @@ endif() set(INC . intern + vulkan metal opengl ../blenkernel @@ -184,6 +185,34 @@ set(OPENGL_SRC opengl/gl_vertex_buffer.hh ) +set(VULKAN_SRC + vulkan/vk_backend.cc + vulkan/vk_batch.cc + vulkan/vk_context.cc + vulkan/vk_drawlist.cc + vulkan/vk_framebuffer.cc + vulkan/vk_index_buffer.cc + vulkan/vk_query.cc + vulkan/vk_shader.cc + vulkan/vk_storage_buffer.cc + vulkan/vk_texture.cc + vulkan/vk_uniform_buffer.cc + vulkan/vk_vertex_buffer.cc + + vulkan/vk_backend.hh + vulkan/vk_batch.hh + vulkan/vk_context.hh + vulkan/vk_drawlist.hh + vulkan/vk_framebuffer.hh + vulkan/vk_index_buffer.hh + vulkan/vk_query.hh + vulkan/vk_shader.hh + vulkan/vk_storage_buffer.hh + vulkan/vk_texture.hh + vulkan/vk_uniform_buffer.hh + vulkan/vk_vertex_buffer.hh +) + set(METAL_SRC metal/mtl_backend.mm metal/mtl_batch.mm @@ -235,6 +264,10 @@ if(WITH_OPENGL) list(APPEND SRC ${OPENGL_SRC}) endif() +if(WITH_VULKAN_BACKEND) + list(APPEND SRC ${VULKAN_SRC}) +endif() + if(WITH_METAL_BACKEND) list(APPEND SRC ${METAL_SRC}) endif() diff --git a/source/blender/gpu/GPU_platform.h b/source/blender/gpu/GPU_platform.h index b63fe4c0580..657b45df1a5 100644 --- a/source/blender/gpu/GPU_platform.h +++ b/source/blender/gpu/GPU_platform.h @@ -16,6 +16,7 @@ typedef enum eGPUBackendType { GPU_BACKEND_NONE = 0, GPU_BACKEND_OPENGL = 1 << 0, GPU_BACKEND_METAL = 1 << 1, + GPU_BACKEND_VULKAN = 1 << 3, GPU_BACKEND_ANY = 0xFFFFFFFFu } eGPUBackendType; diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc index f6b88c4231c..7e94538892a 100644 --- a/source/blender/gpu/intern/gpu_context.cc +++ b/source/blender/gpu/intern/gpu_context.cc @@ -33,6 +33,9 @@ # include "gl_backend.hh" # include "gl_context.hh" #endif +#ifdef WITH_VULKAN_BACKEND +# include "vk_backend.hh" +#endif #ifdef WITH_METAL_BACKEND # include "mtl_backend.hh" #endif @@ -244,6 +247,12 @@ bool GPU_backend_supported(void) return true; #else return false; +#endif + case GPU_BACKEND_VULKAN: +#ifdef WITH_VULKAN_BACKEND + return true; +#else + return false; #endif case GPU_BACKEND_METAL: #ifdef WITH_METAL_BACKEND @@ -268,6 +277,11 @@ static void gpu_backend_create() g_backend = new GLBackend; break; #endif +#ifdef WITH_VULKAN_BACKEND + case GPU_BACKEND_VULKAN: + g_backend = new VKBackend; + break; +#endif #ifdef WITH_METAL_BACKEND case GPU_BACKEND_METAL: g_backend = new MTLBackend; diff --git a/source/blender/gpu/vulkan/vk_backend.cc b/source/blender/gpu/vulkan/vk_backend.cc new file mode 100644 index 00000000000..00bc43333d6 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_backend.cc @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#include "vk_backend.hh" + +#include "vk_batch.hh" +#include "vk_context.hh" +#include "vk_drawlist.hh" +#include "vk_framebuffer.hh" +#include "vk_index_buffer.hh" +#include "vk_query.hh" +#include "vk_shader.hh" +#include "vk_storage_buffer.hh" +#include "vk_texture.hh" +#include "vk_uniform_buffer.hh" +#include "vk_vertex_buffer.hh" + +namespace blender::gpu { + +void VKBackend::delete_resources() +{ +} + +void VKBackend::samplers_update() +{ +} + +void VKBackend::compute_dispatch(int /*groups_x_len*/, int /*groups_y_len*/, int /*groups_z_len*/) +{ +} + +void VKBackend::compute_dispatch_indirect(StorageBuf * /*indirect_buf*/) +{ +} + +Context *VKBackend::context_alloc(void * /*ghost_window*/, void * /*ghost_context*/) +{ + return new VKContext(); +} + +Batch *VKBackend::batch_alloc() +{ + return new VKBatch(); +} + +DrawList *VKBackend::drawlist_alloc(int /*list_length*/) +{ + return new VKDrawList(); +} + +FrameBuffer *VKBackend::framebuffer_alloc(const char *name) +{ + return new VKFrameBuffer(name); +} + +IndexBuf *VKBackend::indexbuf_alloc() +{ + return new VKIndexBuffer(); +} + +QueryPool *VKBackend::querypool_alloc() +{ + return new VKQueryPool(); +} + +Shader *VKBackend::shader_alloc(const char *name) +{ + return new VKShader(name); +} + +Texture *VKBackend::texture_alloc(const char *name) +{ + return new VKTexture(name); +} + +UniformBuf *VKBackend::uniformbuf_alloc(int size, const char *name) +{ + return new VKUniformBuffer(size, name); +} + +StorageBuf *VKBackend::storagebuf_alloc(int size, GPUUsageType /*usage*/, const char *name) +{ + return new VKStorageBuffer(size, name); +} + +VertBuf *VKBackend::vertbuf_alloc() +{ + return new VKVertexBuffer(); +} + +void VKBackend::render_begin() +{ +} + +void VKBackend::render_end() +{ +} + +void VKBackend::render_step() +{ +} + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_backend.hh b/source/blender/gpu/vulkan/vk_backend.hh new file mode 100644 index 00000000000..549478586e8 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_backend.hh @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "gpu_backend.hh" + +namespace blender::gpu { + +class VKBackend : public GPUBackend { + public: + void delete_resources() override; + + void samplers_update() override; + void compute_dispatch(int groups_x_len, int groups_y_len, int groups_z_len) override; + void compute_dispatch_indirect(StorageBuf *indirect_buf) override; + + Context *context_alloc(void *ghost_window, void *ghost_context) override; + + Batch *batch_alloc() override; + DrawList *drawlist_alloc(int list_length) override; + FrameBuffer *framebuffer_alloc(const char *name) override; + IndexBuf *indexbuf_alloc() override; + QueryPool *querypool_alloc() override; + Shader *shader_alloc(const char *name) override; + Texture *texture_alloc(const char *name) override; + UniformBuf *uniformbuf_alloc(int size, const char *name) override; + StorageBuf *storagebuf_alloc(int size, GPUUsageType usage, const char *name) override; + VertBuf *vertbuf_alloc() override; + + /* Render Frame Coordination -- + * Used for performing per-frame actions globally */ + void render_begin() override; + void render_end() override; + void render_step() override; +}; + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_batch.cc b/source/blender/gpu/vulkan/vk_batch.cc new file mode 100644 index 00000000000..a25f98a2e24 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_batch.cc @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#include "vk_batch.hh" + +namespace blender::gpu { + +void VKBatch::draw(int /*v_first*/, int /*v_count*/, int /*i_first*/, int /*i_count*/) +{ +} + +void VKBatch::draw_indirect(GPUStorageBuf * /*indirect_buf*/, intptr_t /*offset*/) +{ +} + +void VKBatch::multi_draw_indirect(GPUStorageBuf * /*indirect_buf*/, + int /*count*/, + intptr_t /*offset*/, + intptr_t /*stride*/) +{ +} + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_batch.hh b/source/blender/gpu/vulkan/vk_batch.hh new file mode 100644 index 00000000000..0f6df41606d --- /dev/null +++ b/source/blender/gpu/vulkan/vk_batch.hh @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "gpu_batch_private.hh" + +namespace blender::gpu { + +class VKBatch : public Batch { + public: + void draw(int v_first, int v_count, int i_first, int i_count) override; + void draw_indirect(GPUStorageBuf *indirect_buf, intptr_t offset) override; + void multi_draw_indirect(GPUStorageBuf *indirect_buf, + int count, + intptr_t offset, + intptr_t stride) override; +}; + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_context.cc b/source/blender/gpu/vulkan/vk_context.cc new file mode 100644 index 00000000000..55b29ea4e2f --- /dev/null +++ b/source/blender/gpu/vulkan/vk_context.cc @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#include "vk_context.hh" + +namespace blender::gpu { + +void VKContext::activate() +{ +} + +void VKContext::deactivate() +{ +} + +void VKContext::begin_frame() +{ +} + +void VKContext::end_frame() +{ +} + +void VKContext::flush() +{ +} + +void VKContext::finish() +{ +} + +void VKContext::memory_statistics_get(int * /*total_mem*/, int * /*free_mem*/) +{ +} + +void VKContext::debug_group_begin(const char *, int) +{ +} + +void VKContext::debug_group_end() +{ +} + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_context.hh b/source/blender/gpu/vulkan/vk_context.hh new file mode 100644 index 00000000000..17292b891b6 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_context.hh @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "gpu_context_private.hh" + +namespace blender::gpu { + +class VKContext : public Context { + public: + VKContext() + { + } + + void activate() override; + void deactivate() override; + void begin_frame() override; + void end_frame() override; + + void flush() override; + void finish() override; + + void memory_statistics_get(int *total_mem, int *free_mem) override; + + void debug_group_begin(const char *, int) override; + void debug_group_end() override; +}; + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_drawlist.cc b/source/blender/gpu/vulkan/vk_drawlist.cc new file mode 100644 index 00000000000..c8f3c736bb8 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_drawlist.cc @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#include "vk_drawlist.hh" + +namespace blender::gpu { + +void VKDrawList::append(GPUBatch * /*batch*/, int /*i_first*/, int /*i_count*/) +{ +} + +void VKDrawList::submit() +{ +} + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_drawlist.hh b/source/blender/gpu/vulkan/vk_drawlist.hh new file mode 100644 index 00000000000..4707bf4bb26 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_drawlist.hh @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "gpu_drawlist_private.hh" + +namespace blender::gpu { + +class VKDrawList : public DrawList { + public: + void append(GPUBatch *batch, int i_first, int i_count) override; + void submit() override; +}; + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_framebuffer.cc b/source/blender/gpu/vulkan/vk_framebuffer.cc new file mode 100644 index 00000000000..01a5f7c0f81 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_framebuffer.cc @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#include "vk_framebuffer.hh" + +namespace blender::gpu { + +void VKFrameBuffer::bind(bool /*enabled_srgb*/) +{ +} + +bool VKFrameBuffer::check(char /*err_out*/[256]) +{ + return false; +} + +void VKFrameBuffer::clear(eGPUFrameBufferBits /*buffers*/, + const float /*clear_col*/[4], + float /*clear_depth*/, + uint /*clear_stencil*/) +{ +} + +void VKFrameBuffer::clear_multi(const float (* /*clear_col*/)[4]) +{ +} + +void VKFrameBuffer::clear_attachment(GPUAttachmentType /*type*/, + eGPUDataFormat /*data_format*/, + const void * /*clear_value*/) +{ +} + +void VKFrameBuffer::attachment_set_loadstore_op(GPUAttachmentType /*type*/, + eGPULoadOp /*load_action*/, + eGPUStoreOp /*store_action*/) +{ +} + +void VKFrameBuffer::read(eGPUFrameBufferBits /*planes*/, + eGPUDataFormat /*format*/, + const int /*area*/[4], + int /*channel_len*/, + int /*slot*/, + void * /*r_data*/) +{ +} + +void VKFrameBuffer::blit_to(eGPUFrameBufferBits /*planes*/, + int /*src_slot*/, + FrameBuffer * /*dst*/, + int /*dst_slot*/, + int /*dst_offset_x*/, + int /*dst_offset_y*/) +{ +} + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_framebuffer.hh b/source/blender/gpu/vulkan/vk_framebuffer.hh new file mode 100644 index 00000000000..632d45ce709 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_framebuffer.hh @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "gpu_framebuffer_private.hh" + +namespace blender::gpu { + +class VKFrameBuffer : public FrameBuffer { + public: + VKFrameBuffer(const char *name) : FrameBuffer(name) + { + } + + void bind(bool enabled_srgb) override; + bool check(char err_out[256]) override; + void clear(eGPUFrameBufferBits buffers, + const float clear_col[4], + float clear_depth, + uint clear_stencil) override; + void clear_multi(const float (*clear_col)[4]) override; + void clear_attachment(GPUAttachmentType type, + eGPUDataFormat data_format, + const void *clear_value) override; + + void attachment_set_loadstore_op(GPUAttachmentType type, + eGPULoadOp load_action, + eGPUStoreOp store_action) override; + + void read(eGPUFrameBufferBits planes, + eGPUDataFormat format, + const int area[4], + int channel_len, + int slot, + void *r_data) override; + + void blit_to(eGPUFrameBufferBits planes, + int src_slot, + FrameBuffer *dst, + int dst_slot, + int dst_offset_x, + int dst_offset_y) override; +}; + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_index_buffer.cc b/source/blender/gpu/vulkan/vk_index_buffer.cc new file mode 100644 index 00000000000..119a617a159 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_index_buffer.cc @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#include "vk_index_buffer.hh" + +namespace blender::gpu { + +void VKIndexBuffer::upload_data() +{ +} + +void VKIndexBuffer::bind_as_ssbo(uint /*binding*/) +{ +} + +const uint32_t *VKIndexBuffer::read() const +{ + return 0; +} + +void VKIndexBuffer::update_sub(uint /*start*/, uint /*len*/, const void * /*data*/) +{ +} + +void VKIndexBuffer::strip_restart_indices() +{ +} + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_index_buffer.hh b/source/blender/gpu/vulkan/vk_index_buffer.hh new file mode 100644 index 00000000000..f002d5581c7 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_index_buffer.hh @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "gpu_index_buffer_private.hh" + +namespace blender::gpu { + +class VKIndexBuffer : public IndexBuf { + public: + void upload_data() override; + + void bind_as_ssbo(uint binding) override; + + const uint32_t *read() const override; + + void update_sub(uint start, uint len, const void *data) override; + + private: + void strip_restart_indices() override; +}; + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_query.cc b/source/blender/gpu/vulkan/vk_query.cc new file mode 100644 index 00000000000..e24fe54e5d0 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_query.cc @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#include "vk_query.hh" + +namespace blender::gpu { + +void VKQueryPool::init(GPUQueryType /*type*/) +{ +} + +void VKQueryPool::begin_query() +{ +} + +void VKQueryPool::end_query() +{ +} + +void VKQueryPool::get_occlusion_result(MutableSpan /*r_values*/) +{ +} + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_query.hh b/source/blender/gpu/vulkan/vk_query.hh new file mode 100644 index 00000000000..7f8f81e2b95 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_query.hh @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "gpu_query.hh" + +namespace blender::gpu { + +class VKQueryPool : public QueryPool { + public: + void init(GPUQueryType type) override; + void begin_query() override; + void end_query() override; + void get_occlusion_result(MutableSpan r_values) override; +}; + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_shader.cc b/source/blender/gpu/vulkan/vk_shader.cc new file mode 100644 index 00000000000..e85d571711a --- /dev/null +++ b/source/blender/gpu/vulkan/vk_shader.cc @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#include "vk_shader.hh" + +namespace blender::gpu { +void VKShader::vertex_shader_from_glsl(MutableSpan /*sources*/) +{ +} + +void VKShader::geometry_shader_from_glsl(MutableSpan /*sources*/) +{ +} + +void VKShader::fragment_shader_from_glsl(MutableSpan /*sources*/) +{ +} + +void VKShader::compute_shader_from_glsl(MutableSpan /*sources*/) +{ +} + +bool VKShader::finalize(const shader::ShaderCreateInfo * /*info*/) +{ +} + +void VKShader::transform_feedback_names_set(Span /*name_list*/, + eGPUShaderTFBType /*geom_type*/) +{ +} + +bool VKShader::transform_feedback_enable(GPUVertBuf *) +{ + return false; +} + +void VKShader::transform_feedback_disable() +{ +} + +void VKShader::bind() +{ +} + +void VKShader::unbind() +{ +} + +void VKShader::uniform_float(int /*location*/, + int /*comp_len*/, + int /*array_size*/, + const float * /*data*/) +{ +} +void VKShader::uniform_int(int /*location*/, + int /*comp_len*/, + int /*array_size*/, + const int * /*data*/) +{ +} + +std::string VKShader::resources_declare(const shader::ShaderCreateInfo & /*info*/) const +{ + return std::string(); +} + +std::string VKShader::vertex_interface_declare(const shader::ShaderCreateInfo & /*info*/) const +{ + return std::string(); +} + +std::string VKShader::fragment_interface_declare(const shader::ShaderCreateInfo & /*info*/) const +{ + return std::string(); +} + +std::string VKShader::geometry_interface_declare(const shader::ShaderCreateInfo & /*info*/) const +{ + return std::string(); +} + +std::string VKShader::geometry_layout_declare(const shader::ShaderCreateInfo & /*info*/) const +{ + return std::string(); +} + +std::string VKShader::compute_layout_declare(const shader::ShaderCreateInfo & /*info*/) const +{ + return std::string(); +} + +int VKShader::program_handle_get() const +{ + return -1; +} + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_shader.hh b/source/blender/gpu/vulkan/vk_shader.hh new file mode 100644 index 00000000000..1c09ef407ad --- /dev/null +++ b/source/blender/gpu/vulkan/vk_shader.hh @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "gpu_shader_private.hh" + +namespace blender::gpu { + +class VKShader : public Shader { + public: + VKShader(const char *name) : Shader(name) + { + } + + void vertex_shader_from_glsl(MutableSpan sources)override; + void geometry_shader_from_glsl(MutableSpan sources)override; + void fragment_shader_from_glsl(MutableSpan sources)override; + void compute_shader_from_glsl(MutableSpan sources)override; + bool finalize(const shader::ShaderCreateInfo *info = nullptr)override; + + void transform_feedback_names_set(Span name_list, eGPUShaderTFBType geom_type)override; + bool transform_feedback_enable(GPUVertBuf *)override; + void transform_feedback_disable()override; + + void bind()override; + void unbind()override; + + void uniform_float(int location, int comp_len, int array_size, const float *data)override; + void uniform_int(int location, int comp_len, int array_size, const int *data)override; + + std::string resources_declare(const shader::ShaderCreateInfo &info) const override; + std::string vertex_interface_declare(const shader::ShaderCreateInfo &info) const override; + std::string fragment_interface_declare(const shader::ShaderCreateInfo &info) const override; + std::string geometry_interface_declare(const shader::ShaderCreateInfo &info) const override; + std::string geometry_layout_declare(const shader::ShaderCreateInfo &info) const override; + std::string compute_layout_declare(const shader::ShaderCreateInfo &info) const override; + + /* DEPRECATED: Kept only because of BGL API. */ + int program_handle_get() const override; +}; + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_storage_buffer.cc b/source/blender/gpu/vulkan/vk_storage_buffer.cc new file mode 100644 index 00000000000..2b6fda0547d --- /dev/null +++ b/source/blender/gpu/vulkan/vk_storage_buffer.cc @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#include "vk_vertex_buffer.hh" + +#include "vk_storage_buffer.hh" + +namespace blender::gpu { + +void VKStorageBuffer::update(const void * /*data*/) +{ +} + +void VKStorageBuffer::bind(int /*slot*/) +{ +} + +void VKStorageBuffer::unbind() +{ +} + +void VKStorageBuffer::clear(eGPUTextureFormat /* internal_format*/, + eGPUDataFormat /*data_format*/, + void * /*data*/) +{ +} +void VKStorageBuffer::copy_sub(VertBuf * /*src*/, + uint /*dst_offset*/, + uint /*src_offset*/, + uint /*copy_size*/) +{ +} + +void VKStorageBuffer::read(void * /*data*/) +{ +} + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_storage_buffer.hh b/source/blender/gpu/vulkan/vk_storage_buffer.hh new file mode 100644 index 00000000000..a51f89f627a --- /dev/null +++ b/source/blender/gpu/vulkan/vk_storage_buffer.hh @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "GPU_texture.h" + +#include "gpu_storage_buffer_private.hh" + +namespace blender::gpu { + +class VKStorageBuffer : public StorageBuf { + public: + VKStorageBuffer(int size, const char *name) : StorageBuf(size, name) + { + } + + void update(const void *data) override; + void bind(int slot) override; + void unbind() override; + void clear(eGPUTextureFormat internal_format, eGPUDataFormat data_format, void *data) override; + void copy_sub(VertBuf *src, uint dst_offset, uint src_offset, uint copy_size) override; + void read(void *data) override; +}; + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_texture.cc b/source/blender/gpu/vulkan/vk_texture.cc new file mode 100644 index 00000000000..ea5379e6572 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_texture.cc @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#include "vk_texture.hh" + +namespace blender::gpu { + +void VKTexture::generate_mipmap() +{ +} + +void VKTexture::copy_to(Texture * /*tex*/) +{ +} + +void VKTexture::clear(eGPUDataFormat /*format*/, const void * /*data*/) +{ +} + +void VKTexture::swizzle_set(const char /*swizzle_mask*/[4]) +{ +} + +void VKTexture::stencil_texture_mode_set(bool /*use_stencil*/) +{ +} + +void VKTexture::mip_range_set(int /*min*/, int /*max*/) +{ +} + +void *VKTexture::read(int /*mip*/, eGPUDataFormat /*format*/) +{ + return nullptr; +} + +void VKTexture::update_sub(int /*mip*/, + int /*offset*/[3], + int /*extent*/[3], + eGPUDataFormat /*format*/, + const void * /*data*/) +{ +} + +/* TODO(fclem): Legacy. Should be removed at some point. */ +uint VKTexture::gl_bindcode_get() const +{ + return 0; +} + +bool VKTexture::init_internal() +{ + return false; +} + +bool VKTexture::init_internal(GPUVertBuf * /*vbo*/) +{ + return false; +} + +bool VKTexture::init_internal(const GPUTexture * /*src*/, int /*mip_offset*/, int /*layer_offset*/) +{ + return false; +} + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_texture.hh b/source/blender/gpu/vulkan/vk_texture.hh new file mode 100644 index 00000000000..93094b7e540 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_texture.hh @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "gpu_texture_private.hh" + +namespace blender::gpu { + +class VKTexture : public Texture { + public: + VKTexture(const char *name) : Texture(name) + { + } + + void generate_mipmap() override; + void copy_to(Texture *tex) override; + void clear(eGPUDataFormat format, const void *data) override; + void swizzle_set(const char swizzle_mask[4]) override; + void stencil_texture_mode_set(bool use_stencil) override; + void mip_range_set(int min, int max) override; + void *read(int mip, eGPUDataFormat format) override; + void update_sub( + int mip, int offset[3], int extent[3], eGPUDataFormat format, const void *data) override; + + /* TODO(fclem): Legacy. Should be removed at some point. */ + uint gl_bindcode_get() const override; + + protected: + bool init_internal() override; + bool init_internal(GPUVertBuf *vbo) override; + bool init_internal(const GPUTexture *src, int mip_offset, int layer_offset) override; +}; + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_uniform_buffer.cc b/source/blender/gpu/vulkan/vk_uniform_buffer.cc new file mode 100644 index 00000000000..8ef5b19273a --- /dev/null +++ b/source/blender/gpu/vulkan/vk_uniform_buffer.cc @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#include "vk_uniform_buffer.hh" + +namespace blender::gpu { + +void VKUniformBuffer::update(const void * /*data*/) +{ +} + +void VKUniformBuffer::bind(int /*slot*/) +{ +} + +void VKUniformBuffer::unbind() +{ +} + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_uniform_buffer.hh b/source/blender/gpu/vulkan/vk_uniform_buffer.hh new file mode 100644 index 00000000000..f086a7aa391 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_uniform_buffer.hh @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "gpu_uniform_buffer_private.hh" + +namespace blender::gpu { + +class VKUniformBuffer : public UniformBuf { + public: + VKUniformBuffer(int size, const char *name) : UniformBuf(size, name) + { + } + + void update(const void *data) override; + void bind(int slot) override; + void unbind() override; +}; + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_vertex_buffer.cc b/source/blender/gpu/vulkan/vk_vertex_buffer.cc new file mode 100644 index 00000000000..5791e20fb30 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_vertex_buffer.cc @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#include "vk_vertex_buffer.hh" + +namespace blender::gpu { + +void VKVertexBuffer::bind_as_ssbo(uint /*binding*/) +{ +} + +void VKVertexBuffer::bind_as_texture(uint /*binding*/) +{ +} + +void VKVertexBuffer::wrap_handle(uint64_t /*handle*/) +{ +} + +void VKVertexBuffer::update_sub(uint /*start*/, uint /*len*/, const void * /*data*/) +{ +} + +const void *VKVertexBuffer::read() const +{ + return nullptr; +} + +void *VKVertexBuffer::unmap(const void * /*mapped_data*/) const +{ + return nullptr; +} + +void VKVertexBuffer::acquire_data() +{ +} + +void VKVertexBuffer::resize_data() +{ +} + +void VKVertexBuffer::release_data() +{ +} + +void VKVertexBuffer::upload_data() +{ +} + +void VKVertexBuffer::duplicate_data(VertBuf * /*dst*/) +{ +} + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_vertex_buffer.hh b/source/blender/gpu/vulkan/vk_vertex_buffer.hh new file mode 100644 index 00000000000..84ccc65bcdf --- /dev/null +++ b/source/blender/gpu/vulkan/vk_vertex_buffer.hh @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "gpu_vertex_buffer_private.hh" + +namespace blender::gpu { + +class VKVertexBuffer : public VertBuf { + public: + void bind_as_ssbo(uint binding) override; + void bind_as_texture(uint binding) override; + void wrap_handle(uint64_t handle) override; + + void update_sub(uint start, uint len, const void *data) override; + const void *read() const override; + void *unmap(const void *mapped_data) const override; + + protected: + void acquire_data() override; + void resize_data() override; + void release_data() override; + void upload_data() override; + void duplicate_data(VertBuf *dst) override; +}; + +} // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/python/gpu/gpu_py_platform.c b/source/blender/python/gpu/gpu_py_platform.c index 51366d199b0..c6e964405fa 100644 --- a/source/blender/python/gpu/gpu_py_platform.c +++ b/source/blender/python/gpu/gpu_py_platform.c @@ -89,11 +89,13 @@ PyDoc_STRVAR(pygpu_platform_backend_type_get_doc, "\n" " Get actuve GPU backend.\n" "\n" - " :return: Backend type ('OPENGL', 'METAL', 'NONE', 'UNKNOWN').\n" + " :return: Backend type ('OPENGL', 'VULKAN', 'METAL', 'NONE', 'UNKNOWN').\n" " :rtype: str\n"); static PyObject *pygpu_platform_backend_type_get(PyObject *UNUSED(self)) { switch (GPU_backend_get_type()) { + case GPU_BACKEND_VULKAN: + return PyUnicode_FromString("VULKAN"); case GPU_BACKEND_METAL: return PyUnicode_FromString("METAL"); case GPU_BACKEND_NONE: diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 2ca7b5f470d..265aa08a6b1 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1625,6 +1625,9 @@ GHOST_TDrawingContextType wm_ghost_drawing_context_type(const eGPUBackendType gp case GPU_BACKEND_ANY: case GPU_BACKEND_OPENGL: return GHOST_kDrawingContextTypeOpenGL; + case GPU_BACKEND_VULKAN: + BLI_assert_unreachable(); + return GHOST_kDrawingContextTypeNone; case GPU_BACKEND_METAL: #ifdef WITH_METAL_BACKEND return GHOST_kDrawingContextTypeMetal; diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index 4144603555b..ba905f91f97 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -1116,6 +1116,9 @@ static int arg_handle_debug_gpu_set(int UNUSED(argc), static const char arg_handle_gpu_backend_set_doc[] = "\n" "\tForce to use a specific GPU backend. Valid options: " +# ifdef WITH_VULKAN_BACKEND + "'vulkan', " +# endif # ifdef WITH_METAL_BACKEND "'metal', " # endif @@ -1132,6 +1135,11 @@ static int arg_handle_gpu_backend_set(int argc, const char **argv, void *UNUSED( if (STREQ(argv[1], "opengl")) { gpu_backend = GPU_BACKEND_OPENGL; } +# ifdef WITH_VULKAN_BACKEND + else if (STREQ(argv[1], "vulkan")) { + gpu_backend = GPU_BACKEND_VULKAN; + } +# endif # ifdef WITH_METAL_BACKEND else if (STREQ(argv[1], "metal")) { gpu_backend = GPU_BACKEND_METAL; -- cgit v1.2.3 From c39eb09ae587e1d9365b14d7c28b98b4a85f297f Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 31 Oct 2022 16:31:36 +0100 Subject: Nodes: Improve socket node lookup performance Use the newly added node topology cache to find the node that contains a socket rather than looping through all nodes every time. The change improves performance of drawing a some large node trees by 2-3x. --- source/blender/blenkernel/intern/node.cc | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 3e3a8355f98..8f8cd02e119 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -2022,21 +2022,29 @@ bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name) bool nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r_sockindex) { *r_node = nullptr; + if (!ntree->runtime->topology_cache_is_dirty) { + bNode *node = &sock->owner_node(); + *r_node = node; + if (r_sockindex) { + ListBase *sockets = (sock->in_out == SOCK_IN) ? &node->inputs : &node->outputs; + *r_sockindex = BLI_findindex(sockets, sock); + } + return true; + } LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { ListBase *sockets = (sock->in_out == SOCK_IN) ? &node->inputs : &node->outputs; - int index = 0; - LISTBASE_FOREACH (bNodeSocket *, tsock, sockets) { + int i; + LISTBASE_FOREACH_INDEX (bNodeSocket *, tsock, sockets, i) { if (sock == tsock) { if (r_node != nullptr) { *r_node = node; } if (r_sockindex != nullptr) { - *r_sockindex = index; + *r_sockindex = i; } return true; } - index++; } } return false; -- cgit v1.2.3 From 6a3af76fbe92c9b0a4687b020131e1a03c50d117 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 31 Oct 2022 19:09:25 +0100 Subject: Geometry Nodes: Use attribute API in deform curves on surface node Retrieve the surface UV coordinates with the attribute API instead of the helper function. This allows more flexibility of data types (and domains), which is helpful especially because geometry nodes can't write 2D vectors yet. --- .../nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc index 0932624bdc3..dabd2a1a9f2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc @@ -310,7 +310,8 @@ static void node_geo_exec(GeoNodeExecParams params) ATTR_DOMAIN_CORNER); const VArraySpan rest_positions = mesh_attributes_eval.lookup(rest_position_name, ATTR_DOMAIN_POINT); - const Span surface_uv_coords = curves.surface_uv_coords(); + const VArraySpan surface_uv_coords = curves.attributes().lookup_or_default( + "surface_uv_coordinate", ATTR_DOMAIN_CURVE, float2(0)); const Span looptris_orig = surface_mesh_orig->looptris(); const Span looptris_eval = surface_mesh_eval->looptris(); @@ -379,7 +380,8 @@ static void node_geo_exec(GeoNodeExecParams params) invalid_uv_count); /* Then also deform edit curve information for use in sculpt mode. */ const CurvesGeometry &curves_orig = CurvesGeometry::wrap(edit_hints->curves_id_orig.geometry); - const Span surface_uv_coords_orig = curves_orig.surface_uv_coords(); + const VArraySpan surface_uv_coords_orig = curves_orig.attributes().lookup_or_default( + "surface_uv_coordinate", ATTR_DOMAIN_CURVE, float2(0)); if (!surface_uv_coords_orig.is_empty()) { deform_curves(curves_orig, *surface_mesh_orig, -- cgit v1.2.3 From 8bddbc9a944965c431bbef4c0158f5581575791e Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 31 Oct 2022 19:31:58 +0100 Subject: Fix bpy wheel build error on Windows, where there are no abi flags --- build_files/utils/make_bpy_wheel.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/build_files/utils/make_bpy_wheel.py b/build_files/utils/make_bpy_wheel.py index ba1d0f21937..81d267c6e10 100755 --- a/build_files/utils/make_bpy_wheel.py +++ b/build_files/utils/make_bpy_wheel.py @@ -208,12 +208,15 @@ def main() -> None: dist_dir = os.path.join(install_dir, "dist") for f in os.listdir(dist_dir): if f.endswith(".whl"): - # No apparent way to override this ABI version with setuptools, so rename. - sys_py = "cp%d%d" % (sys.version_info.major, sys.version_info.minor) - sys_py_abi = sys_py + sys.abiflags blender_py = "cp%d%d" % (python_version_number[0], python_version_number[1]) - renamed_f = f.replace(sys_py_abi, blender_py).replace(sys_py, blender_py) + # No apparent way to override this ABI version with setuptools, so rename. + sys_py = "cp%d%d" % (sys.version_info.major, sys.version_info.minor) + if hasattr(sys, "abiflags"): + sys_py_abi = sys_py + sys.abiflags + renamed_f = f.replace(sys_py_abi, blender_py).replace(sys_py, blender_py) + else: + renamed_f = f.replace(sys_py, blender_py) os.rename(os.path.join(dist_dir, f), os.path.join(output_dir, renamed_f)) -- cgit v1.2.3 From c082b088ab966db78af47a5e831c77412fbeba85 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 31 Oct 2022 19:53:02 +0100 Subject: Fix bpy wheel on buildbot being incomplete on Windows Need to explicitly install __init__.pyd for the case where the install folder is different than the build folder. --- source/creator/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index caaffa283ba..bb9e73c0895 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -1077,6 +1077,13 @@ elseif(WIN32) ) endif() + if(WITH_PYTHON_MODULE AND TARGETDIR_BPY) + install( + TARGETS blender + LIBRARY DESTINATION ${TARGETDIR_BPY} + ) + endif() + if(PLATFORM_BUNDLED_LIBRARIES) install( FILES ${PLATFORM_BUNDLED_LIBRARIES} -- cgit v1.2.3 From a8ce926eaa6bd28f174eba85c164518e01ac6ad7 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 31 Oct 2022 20:05:11 +0100 Subject: Build: ignore more CVEs from tiff command line tools that we don't use --- build_files/build_environment/cmake/cve_check.csv.in | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build_files/build_environment/cmake/cve_check.csv.in b/build_files/build_environment/cmake/cve_check.csv.in index 734a24f8c77..946dda5ab17 100644 --- a/build_files/build_environment/cmake/cve_check.csv.in +++ b/build_files/build_environment/cmake/cve_check.csv.in @@ -17,6 +17,12 @@ vendor,product,version,cve_number,remarks,comment @TIFF_ID@,CVE-2022-2521,Ignored,issue in tiff command line tool not used by blender @TIFF_ID@,CVE-2022-2953,Ignored,issue in tiff command line tool not used by blender @TIFF_ID@,CVE-2022-34526,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-3570,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-3597,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-3598,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-3599,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-3626,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-3627,Ignored,issue in tiff command line tool not used by blender @XML2_ID@,CVE-2016-3709,Ignored,not affecting blender and not considered a security issue upstream @GMP_ID@,CVE-2021-43618,Mitigated,patched using upstream commit 561a9c25298e @SQLITE_ID@,CVE-2022-35737,Ignored,only affects SQLITE_ENABLE_STAT4 compile option not used by blender or python -- cgit v1.2.3 From 5016a8687c118dd4c74b06b49f7b56424bc84995 Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Mon, 31 Oct 2022 16:37:09 -0600 Subject: deps: openPGL 0.4.1-beta --- build_files/build_environment/cmake/versions.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake index 06a923e5c22..89b0a8d72de 100644 --- a/build_files/build_environment/cmake/versions.cmake +++ b/build_files/build_environment/cmake/versions.cmake @@ -558,10 +558,10 @@ set(BROTLI_HASH_TYPE SHA256) set(BROTLI_FILE brotli-v${BROTLI_VERSION}.tar.gz) set(BROTLI_CPE "cpe:2.3:a:google:brotli:${BROTLI_VERSION}:*:*:*:*:*:*:*") -set(OPENPGL_VERSION v0.4.0-beta) -set(OPENPGL_SHORT_VERSION 0.4.0) +set(OPENPGL_VERSION v0.4.1-beta) +set(OPENPGL_SHORT_VERSION 0.4.1) set(OPENPGL_URI https://github.com/OpenPathGuidingLibrary/openpgl/archive/refs/tags/${OPENPGL_VERSION}.tar.gz) -set(OPENPGL_HASH 1f090f88ab2bad028e8b3619aa926f4f97cf7b2c175b904704d2fec8593dd3cd) +set(OPENPGL_HASH db63f5dac5cfa8c110ede241f0c413f00db0c4748697381c4fa23e0f9e82a754) set(OPENPGL_HASH_TYPE SHA256) set(OPENPGL_FILE openpgl-${OPENPGL_VERSION}.tar.gz) -- cgit v1.2.3 From c3e4fa74044a5a2a38ec28cf66be45c98f982501 Mon Sep 17 00:00:00 2001 From: Chris Blackbourn Date: Tue, 1 Nov 2022 12:50:16 +1300 Subject: Cleanup: fix translation for rare UV unwrapping with unit scale Fixes very rare cases where the UV Cylinder Project, UV Sphere Project and UV From View might not set the translation correctly if the scale is exactly 1.0. Mainly fixed because this code might later be reused elsewhere. --- source/blender/editors/uvedit/uvedit_unwrap_ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index ecaba3234a7..92efaf79de7 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -1774,8 +1774,8 @@ static void uv_map_clip_correct(const Scene *scene, dy = 1.0f / dy; } - if (dx == 1.0f && dy == 1.0f) { - /* Scaling by 1.0 has no effect. */ + if (dx == 1.0f && dy == 1.0f && min[0] == 0.0f && min[1] == 0.0f) { + /* Scaling by 1.0, without translating, has no effect. */ return; } -- cgit v1.2.3 From 409070e0d480df99948e36bf2e48f123d9285aa0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 1 Nov 2022 10:41:06 +1100 Subject: GHOST/Wayland: support for multiple seats (one active seat at a time) This isn't full multi-seat support, instead set the active seat using pointer/tablet & keyboard enter handlers. This means that seats beside the first aren't prevented from having their events handled. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 146 ++++++++++++++++++++-------- intern/ghost/intern/GHOST_SystemWayland.h | 3 + 2 files changed, 109 insertions(+), 40 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index f3dc1609e69..f713ddced27 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -776,6 +776,18 @@ struct GWL_Display { struct wl_shm *wl_shm = nullptr; std::vector outputs; std::vector seats; + /** + * Support a single active seat at once, this isn't an exact or correct mapping from WAYLAND. + * Only allow input from different seats, not full concurrent multi-seat support. + * + * The main purpose of having an active seat is an alternative from always using the first + * seat which prevents events from any other seat. + * + * NOTE(@campbellbarton): This could be extended and developed further extended to support + * an active seat per window (for e.g.), basic support is sufficient for now as currently isn't + * a widely used feature. + */ + int seats_active_index = 0; /* Managers. */ struct wl_data_device_manager *wl_data_device_manager = nullptr; @@ -830,6 +842,37 @@ static void gwl_display_destroy(GWL_Display *display) delete display; } +static int gwl_display_seat_index(GWL_Display *display, const GWL_Seat *seat) +{ + std::vector::iterator iter = std::find( + display->seats.begin(), display->seats.end(), seat); + const int index = (iter != display->seats.cend()) ? std::distance(display->seats.begin(), iter) : + -1; + GHOST_ASSERT(index != -1, "invalid internal state"); + return index; +} + +static GWL_Seat *gwl_display_seat_active_get(const GWL_Display *display) +{ + if (UNLIKELY(display->seats.empty())) { + return nullptr; + } + return display->seats[display->seats_active_index]; +} + +static bool gwl_display_seat_active_set(GWL_Display *display, const GWL_Seat *seat) +{ + if (UNLIKELY(display->seats.empty())) { + return false; + } + const int index = gwl_display_seat_index(display, seat); + if (index == display->seats_active_index) { + return false; + } + display->seats_active_index = index; + return true; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -1925,6 +1968,9 @@ static void data_device_handle_enter(void *data, } seat->wl_surface_focus_dnd = wl_surface; + + seat->system->seat_active_set(seat); + dnd_events(seat, GHOST_kEventDraggingEntered); } @@ -2256,6 +2302,8 @@ static void pointer_handle_enter(void *data, seat->pointer.wl_surface = wl_surface; + seat->system->seat_active_set(seat); + win->setCursorShape(win->getCursorShape()); const wl_fixed_t scale = win->scale(); @@ -2900,6 +2948,8 @@ static void tablet_tool_handle_proximity_in(void *data, seat->data_source_serial = serial; + seat->system->seat_active_set(seat); + /* Update #GHOST_TabletData. */ GHOST_TabletData &td = tablet_tool->data; /* Reset, to avoid using stale tilt/pressure. */ @@ -3286,6 +3336,8 @@ static void keyboard_handle_enter(void *data, seat->keyboard.serial = serial; seat->keyboard.wl_surface = wl_surface; + seat->system->seat_active_set(seat); + /* If there are any keys held when activating the window, * modifiers will be compared against the seat state, * only enabling modifiers that were previously disabled. */ @@ -4472,6 +4524,9 @@ static void gwl_registry_wl_seat_remove(GWL_Display *display, void *user_data, c GHOST_ASSERT(index != -1, "invalid internal state"); if (!on_exit) { + if (display->seats_active_index >= index) { + display->seats_active_index -= 1; + } display->seats.erase(display->seats.begin() + index); } delete seat; @@ -4980,12 +5035,11 @@ bool GHOST_SystemWayland::setConsoleWindowState(GHOST_TConsoleWindowState /*acti GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) const { - if (UNLIKELY(display_->seats.empty())) { + GWL_Seat *seat = gwl_display_seat_active_get(display_); + if (UNLIKELY(!seat)) { return GHOST_kFailure; } - GWL_Seat *seat = display_->seats[0]; - const xkb_mod_mask_t state = xkb_state_serialize_mods(seat->xkb_state, XKB_STATE_MODS_DEPRESSED); bool show_warning = true; @@ -5042,10 +5096,10 @@ GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) co GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const { - if (UNLIKELY(display_->seats.empty())) { + GWL_Seat *seat = gwl_display_seat_active_get(display_); + if (UNLIKELY(!seat)) { return GHOST_kFailure; } - GWL_Seat *seat = display_->seats[0]; GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_active(seat); if (!seat_state_pointer) { return GHOST_kFailure; @@ -5073,7 +5127,10 @@ static const char *system_clipboard_text_mime_type( static char *system_clipboard_get_primary_selection(GWL_Display *display) { - GWL_Seat *seat = display->seats[0]; + GWL_Seat *seat = gwl_display_seat_active_get(display); + if (UNLIKELY(!seat)) { + return nullptr; + } GWL_PrimarySelection *primary = &seat->primary_selection; std::mutex &mutex = primary->data_offer_mutex; @@ -5120,7 +5177,10 @@ static char *system_clipboard_get_primary_selection(GWL_Display *display) static char *system_clipboard_get(GWL_Display *display) { - GWL_Seat *seat = display->seats[0]; + GWL_Seat *seat = gwl_display_seat_active_get(display); + if (UNLIKELY(!seat)) { + return nullptr; + } std::mutex &mutex = seat->data_offer_copy_paste_mutex; mutex.lock(); @@ -5166,10 +5226,6 @@ static char *system_clipboard_get(GWL_Display *display) char *GHOST_SystemWayland::getClipboard(bool selection) const { - if (UNLIKELY(display_->seats.empty())) { - return nullptr; - } - char *data = nullptr; if (selection) { data = system_clipboard_get_primary_selection(display_); @@ -5185,7 +5241,10 @@ static void system_clipboard_put_primary_selection(GWL_Display *display, const c if (!display->wp_primary_selection_device_manager) { return; } - GWL_Seat *seat = display->seats[0]; + GWL_Seat *seat = gwl_display_seat_active_get(display); + if (UNLIKELY(!seat)) { + return; + } GWL_PrimarySelection *primary = &seat->primary_selection; std::lock_guard lock{primary->data_source_mutex}; @@ -5219,8 +5278,10 @@ static void system_clipboard_put(GWL_Display *display, const char *buffer) if (!display->wl_data_device_manager) { return; } - GWL_Seat *seat = display->seats[0]; - + GWL_Seat *seat = gwl_display_seat_active_get(display); + if (UNLIKELY(!seat)) { + return; + } std::lock_guard lock{seat->data_source_mutex}; GWL_DataSource *data_source = seat->data_source; @@ -5245,10 +5306,6 @@ static void system_clipboard_put(GWL_Display *display, const char *buffer) void GHOST_SystemWayland::putClipboard(const char *buffer, bool selection) const { - if (UNLIKELY(display_->seats.empty())) { - return; - } - if (selection) { system_clipboard_put_primary_selection(display_, buffer); } @@ -5301,10 +5358,10 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorPositionClientRelative(const GHOST_ int32_t &x, int32_t &y) const { - if (UNLIKELY(display_->seats.empty())) { + GWL_Seat *seat = gwl_display_seat_active_get(display_); + if (UNLIKELY(!seat)) { return GHOST_kFailure; } - GWL_Seat *seat = display_->seats[0]; GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_active(seat); if (!seat_state_pointer || !seat_state_pointer->wl_surface) { return GHOST_kFailure; @@ -5317,20 +5374,20 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorPositionClientRelative(GHOST_IWindo const int32_t x, const int32_t y) { - if (UNLIKELY(display_->seats.empty())) { + GWL_Seat *seat = gwl_display_seat_active_get(display_); + if (UNLIKELY(!seat)) { return GHOST_kFailure; } - GWL_Seat *seat = display_->seats[0]; GHOST_WindowWayland *win = static_cast(window); return setCursorPositionClientRelative_impl(seat, win, x, y); } GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(int32_t &x, int32_t &y) const { - if (UNLIKELY(display_->seats.empty())) { + GWL_Seat *seat = gwl_display_seat_active_get(display_); + if (UNLIKELY(!seat)) { return GHOST_kFailure; } - GWL_Seat *seat = display_->seats[0]; GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_active(seat); if (!seat_state_pointer) { return GHOST_kFailure; @@ -5345,10 +5402,10 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(int32_t &x, int32_t &y) co GHOST_TSuccess GHOST_SystemWayland::setCursorPosition(const int32_t x, const int32_t y) { - if (UNLIKELY(display_->seats.empty())) { + GWL_Seat *seat = gwl_display_seat_active_get(display_); + if (UNLIKELY(!seat)) { return GHOST_kFailure; } - GWL_Seat *seat = display_->seats[0]; /* Intentionally different from `getCursorPosition` which supports both tablet & pointer. * In the case of setting the cursor location, tablets don't support this. */ @@ -5699,7 +5756,8 @@ static bool cursor_is_software(const GHOST_TGrabCursorMode mode, const bool use_ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor shape) { - if (UNLIKELY(display_->seats.empty())) { + GWL_Seat *seat = gwl_display_seat_active_get(display_); + if (UNLIKELY(!seat)) { return GHOST_kFailure; } auto cursor_find = ghost_wl_cursors.find(shape); @@ -5707,7 +5765,6 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor s ghost_wl_cursors.at(GHOST_kStandardCursorDefault) : (*cursor_find).second; - GWL_Seat *seat = display_->seats[0]; GWL_Cursor *cursor = &seat->cursor; if (!cursor->wl_theme) { @@ -5760,12 +5817,12 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap, const int hotY, const bool /*canInvertColor*/) { - if (UNLIKELY(display_->seats.empty())) { + GWL_Seat *seat = gwl_display_seat_active_get(display_); + if (UNLIKELY(!seat)) { return GHOST_kFailure; } - GWL_Cursor *cursor = &display_->seats[0]->cursor; - + GWL_Cursor *cursor = &seat->cursor; if (cursor->custom_data) { munmap(cursor->custom_data, cursor->custom_data_size); cursor->custom_data = nullptr; @@ -5823,14 +5880,19 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap, cursor->wl_image.hotspot_x = uint32_t(hotX); cursor->wl_image.hotspot_y = uint32_t(hotY); - cursor_buffer_set(display_->seats[0], buffer); + cursor_buffer_set(seat, buffer); return GHOST_kSuccess; } GHOST_TSuccess GHOST_SystemWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitmap) { - GWL_Cursor *cursor = &display_->seats[0]->cursor; + GWL_Seat *seat = gwl_display_seat_active_get(display_); + if (UNLIKELY(!seat)) { + return GHOST_kFailure; + } + + GWL_Cursor *cursor = &seat->cursor; if (cursor->custom_data == nullptr) { return GHOST_kFailure; } @@ -5851,11 +5913,11 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitma GHOST_TSuccess GHOST_SystemWayland::setCursorVisibility(const bool visible) { - if (UNLIKELY(display_->seats.empty())) { + GWL_Seat *seat = gwl_display_seat_active_get(display_); + if (UNLIKELY(!seat)) { return GHOST_kFailure; } - GWL_Seat *seat = display_->seats[0]; cursor_visible_set(seat, visible, seat->cursor.is_hardware, CURSOR_VISIBLE_ALWAYS_SET); return GHOST_kSuccess; } @@ -5875,12 +5937,12 @@ bool GHOST_SystemWayland::supportsWindowPosition() bool GHOST_SystemWayland::getCursorGrabUseSoftwareDisplay(const GHOST_TGrabCursorMode mode) { - if (UNLIKELY(display_->seats.empty())) { + GWL_Seat *seat = gwl_display_seat_active_get(display_); + if (UNLIKELY(!seat)) { return false; } #ifdef USE_GNOME_CONFINE_HACK - GWL_Seat *seat = display_->seats[0]; const bool use_software_confine = seat->use_pointer_software_confine; #else const bool use_software_confine = false; @@ -6068,6 +6130,11 @@ GHOST_WindowWayland *ghost_wl_surface_user_data(struct wl_surface *wl_surface) * Functionality only used for the WAYLAND implementation. * \{ */ +void GHOST_SystemWayland::seat_active_set(const struct GWL_Seat *seat) +{ + gwl_display_seat_active_set(display_, seat); +} + void GHOST_SystemWayland::window_surface_unref(const wl_surface *wl_surface) { #define SURFACE_CLEAR_PTR(surface_test) \ @@ -6099,7 +6166,8 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod return GHOST_kFailure; } - if (UNLIKELY(display_->seats.empty())) { + GWL_Seat *seat = gwl_display_seat_active_get(display_); + if (UNLIKELY(!seat)) { return GHOST_kFailure; } /* No change, success. */ @@ -6107,8 +6175,6 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod return GHOST_kSuccess; } - GWL_Seat *seat = display_->seats[0]; - #ifdef USE_GNOME_CONFINE_HACK const bool was_software_confine = seat->use_pointer_software_confine; const bool use_software_confine = setCursorGrab_use_software_confine(mode, wl_surface); diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index db4fef23538..a8e8d8ddc45 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -178,6 +178,9 @@ class GHOST_SystemWayland : public GHOST_System { /* WAYLAND utility functions. */ + /** Set this seat to be active. */ + void seat_active_set(const struct GWL_Seat *seat); + /** Clear all references to this surface to prevent accessing NULL pointers. */ void window_surface_unref(const wl_surface *wl_surface); -- cgit v1.2.3 From 4d782110701ec0585bf5a928dc62df27e6260814 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 1 Nov 2022 11:10:25 +1100 Subject: Cleanup: disambiguate naming for Wayland surfaces Name surfaces for their use. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 104 ++++++++++++++-------------- intern/ghost/intern/GHOST_WindowWayland.cpp | 5 +- 2 files changed, 56 insertions(+), 53 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index f713ddced27..3073a8fe80d 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -312,7 +312,7 @@ struct GWL_Cursor { bool is_hardware = true; /** When true, a custom image is used to display the cursor (stored in `wl_image`). */ bool is_custom = false; - struct wl_surface *wl_surface = nullptr; + struct wl_surface *wl_surface_cursor = nullptr; struct wl_buffer *wl_buffer = nullptr; struct wl_cursor_image wl_image = {0}; struct wl_cursor_theme *wl_theme = nullptr; @@ -456,7 +456,7 @@ struct GWL_SeatStatePointer { * The wl_surface last used with this pointing device * (events with this pointing device will be sent here). */ - struct wl_surface *wl_surface = nullptr; + struct wl_surface *wl_surface_window = nullptr; GHOST_Buttons buttons = GHOST_Buttons(); }; @@ -518,7 +518,7 @@ struct GWL_SeatStateKeyboard { * The wl_surface last used with this pointing device * (events with this pointing device will be sent here). */ - struct wl_surface *wl_surface = nullptr; + struct wl_surface *wl_surface_window = nullptr; }; /** @@ -697,7 +697,7 @@ struct GWL_Seat { GHOST_ITimerTask *timer = nullptr; } key_repeat; - struct wl_surface *wl_surface_focus_dnd = nullptr; + struct wl_surface *wl_surface_window_focus_dnd = nullptr; struct wl_data_device *wl_data_device = nullptr; /** Drag & Drop. */ @@ -1499,7 +1499,7 @@ static void keyboard_depressed_state_key_event(GWL_Seat *seat, static void keyboard_depressed_state_push_events_from_change( GWL_Seat *seat, const GWL_KeyboardDepressedState &key_depressed_prev) { - GHOST_IWindow *win = ghost_wl_surface_user_data(seat->keyboard.wl_surface); + GHOST_IWindow *win = ghost_wl_surface_user_data(seat->keyboard.wl_surface_window); GHOST_SystemWayland *system = seat->system; /* Separate key up and down into separate passes so key down events always come after key up. @@ -1586,7 +1586,7 @@ static void relative_pointer_handle_relative_motion( const wl_fixed_t /*dy_unaccel*/) { GWL_Seat *seat = static_cast(data); - if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { + if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) { CLOG_INFO(LOG, 2, "relative_motion"); GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); const wl_fixed_t scale = win->scale(); @@ -1619,7 +1619,7 @@ static CLG_LogRef LOG_WL_DATA_SOURCE = {"ghost.wl.handle.data_source"}; static void dnd_events(const GWL_Seat *const seat, const GHOST_TEventType event) { /* NOTE: `seat->data_offer_dnd_mutex` must already be locked. */ - if (wl_surface *wl_surface_focus = seat->wl_surface_focus_dnd) { + if (wl_surface *wl_surface_focus = seat->wl_surface_window_focus_dnd) { GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); const wl_fixed_t scale = win->scale(); const int event_xy[2] = { @@ -1967,7 +1967,7 @@ static void data_device_handle_enter(void *data, wl_data_offer_accept(id, serial, type); } - seat->wl_surface_focus_dnd = wl_surface; + seat->wl_surface_window_focus_dnd = wl_surface; seat->system->seat_active_set(seat); @@ -1982,7 +1982,7 @@ static void data_device_handle_leave(void *data, struct wl_data_device * /*wl_da CLOG_INFO(LOG, 2, "leave"); dnd_events(seat, GHOST_kEventDraggingExited); - seat->wl_surface_focus_dnd = nullptr; + seat->wl_surface_window_focus_dnd = nullptr; if (seat->data_offer_dnd && !seat->data_offer_dnd->dnd.in_use) { wl_data_offer_destroy(seat->data_offer_dnd->id); @@ -2033,7 +2033,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat auto read_uris_fn = [](GWL_Seat *const seat, GWL_DataOffer *data_offer, - wl_surface *wl_surface, + wl_surface *wl_surface_window, const char *mime_receive) { const wl_fixed_t xy[2] = {UNPACK2(data_offer->dnd.xy)}; @@ -2062,7 +2062,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat * So support both, once `\n` is found, strip the preceding `\r` if found. */ static constexpr const char *lf = "\n"; - GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface); + GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_window); std::vector uris; size_t pos = 0; @@ -2109,10 +2109,10 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat wl_display_roundtrip(system->wl_display()); }; - /* Pass in `seat->wl_surface_focus_dnd` instead of accessing it from `seat` since the leave - * callback (#data_device_handle_leave) will clear the value once this function starts. */ + /* Pass in `seat->wl_surface_window_focus_dnd` instead of accessing it from `seat` since the + * leave callback (#data_device_handle_leave) will clear the value once this function starts. */ std::thread read_thread( - read_uris_fn, seat, data_offer, seat->wl_surface_focus_dnd, mime_receive); + read_uris_fn, seat, data_offer, seat->wl_surface_window_focus_dnd, mime_receive); read_thread.detach(); } @@ -2195,7 +2195,7 @@ static CLG_LogRef LOG_WL_CURSOR_SURFACE = {"ghost.wl.handle.cursor_surface"}; static bool update_cursor_scale(GWL_Cursor &cursor, wl_shm *shm, GWL_SeatStatePointer *seat_state_pointer, - wl_surface *wl_cursor_surface) + wl_surface *wl_surface_cursor) { int scale = 0; for (const GWL_Output *output : seat_state_pointer->outputs) { @@ -2207,7 +2207,7 @@ static bool update_cursor_scale(GWL_Cursor &cursor, if (scale > 0 && seat_state_pointer->theme_scale != scale) { seat_state_pointer->theme_scale = scale; if (!cursor.is_custom) { - wl_surface_set_buffer_scale(wl_cursor_surface, scale); + wl_surface_set_buffer_scale(wl_surface_cursor, scale); } wl_cursor_theme_destroy(cursor.wl_theme); cursor.wl_theme = wl_cursor_theme_load( @@ -2300,7 +2300,7 @@ static void pointer_handle_enter(void *data, seat->pointer_scroll.discrete_xy[1] = 0; seat->pointer_scroll.axis_source = WL_POINTER_AXIS_SOURCE_WHEEL; - seat->pointer.wl_surface = wl_surface; + seat->pointer.wl_surface_window = wl_surface; seat->system->seat_active_set(seat); @@ -2321,7 +2321,7 @@ static void pointer_handle_leave(void *data, struct wl_surface *wl_surface) { /* First clear the `pointer.wl_surface`, since the window won't exist when closing the window. */ - static_cast(data)->pointer.wl_surface = nullptr; + static_cast(data)->pointer.wl_surface_window = nullptr; if (wl_surface && ghost_wl_surface_own(wl_surface)) { CLOG_INFO(LOG, 2, "leave"); GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface); @@ -2342,7 +2342,7 @@ static void pointer_handle_motion(void *data, seat->pointer.xy[0] = surface_x; seat->pointer.xy[1] = surface_y; - if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { + if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) { CLOG_INFO(LOG, 2, "motion"); GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); const wl_fixed_t scale = win->scale(); @@ -2406,7 +2406,7 @@ static void pointer_handle_button(void *data, seat->data_source_serial = serial; seat->pointer.buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED); - if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { + if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) { GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); seat->system->pushEvent(new GHOST_EventButton( seat->system->getMilliSeconds(), etype, win, ebutton, GHOST_TABLET_DATA_NONE)); @@ -2457,7 +2457,7 @@ static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/) /* Discrete X axis currently unsupported. */ if (seat->pointer_scroll.discrete_xy[1]) { - if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { + if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) { GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); const int32_t discrete = seat->pointer_scroll.discrete_xy[1]; seat->system->pushEvent(new GHOST_EventWheel( @@ -2468,7 +2468,7 @@ static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/) } if (seat->pointer_scroll.smooth_xy[0] || seat->pointer_scroll.smooth_xy[1]) { - if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { + if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) { GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); const wl_fixed_t scale = win->scale(); seat->system->pushEvent(new GHOST_EventTrackpad( @@ -2599,7 +2599,7 @@ static void gesture_pinch_handle_begin(void *data, seat->pointer_gesture_pinch = GWL_SeatStatePointerGesture_Pinch{}; GHOST_WindowWayland *win = nullptr; - if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { + if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) { win = ghost_wl_surface_user_data(wl_surface_focus); } /* NOTE(@campbellbarton): Blender's use of track-pad coordinates is inconsistent and needs work. @@ -2655,7 +2655,7 @@ static void gesture_pinch_handle_update(void *data, GHOST_WindowWayland *win = nullptr; - if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { + if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) { win = ghost_wl_surface_user_data(wl_surface_focus); } @@ -2943,7 +2943,7 @@ static void tablet_tool_handle_proximity_in(void *data, GWL_Seat *seat = tablet_tool->seat; seat->cursor_source_serial = serial; - seat->tablet.wl_surface = wl_surface; + seat->tablet.wl_surface_window = wl_surface; seat->tablet.serial = serial; seat->data_source_serial = serial; @@ -2958,7 +2958,7 @@ static void tablet_tool_handle_proximity_in(void *data, /* In case pressure isn't supported. */ td.Pressure = 1.0f; - GHOST_WindowWayland *win = ghost_wl_surface_user_data(seat->tablet.wl_surface); + GHOST_WindowWayland *win = ghost_wl_surface_user_data(seat->tablet.wl_surface_window); win->activate(); @@ -2988,7 +2988,7 @@ static void tablet_tool_handle_down(void *data, seat->data_source_serial = serial; seat->tablet.buttons.set(ebutton, true); - if (wl_surface *wl_surface_focus = seat->tablet.wl_surface) { + if (wl_surface *wl_surface_focus = seat->tablet.wl_surface_window) { GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); seat->system->pushEvent(new GHOST_EventButton( seat->system->getMilliSeconds(), etype, win, ebutton, tablet_tool->data)); @@ -3006,7 +3006,7 @@ static void tablet_tool_handle_up(void *data, struct zwp_tablet_tool_v2 * /*zwp_ seat->tablet.buttons.set(ebutton, false); - if (wl_surface *wl_surface_focus = seat->tablet.wl_surface) { + if (wl_surface *wl_surface_focus = seat->tablet.wl_surface_window) { GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); seat->system->pushEvent(new GHOST_EventButton( seat->system->getMilliSeconds(), etype, win, ebutton, tablet_tool->data)); @@ -3091,7 +3091,7 @@ static void tablet_tool_handle_wheel(void *data, GWL_TabletTool *tablet_tool = static_cast(data); GWL_Seat *seat = tablet_tool->seat; - if (wl_surface *wl_surface_focus = seat->tablet.wl_surface) { + if (wl_surface *wl_surface_focus = seat->tablet.wl_surface_window) { GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); seat->system->pushEvent(new GHOST_EventWheel(seat->system->getMilliSeconds(), win, clicks)); } @@ -3133,7 +3133,7 @@ static void tablet_tool_handle_button(void *data, seat->data_source_serial = serial; seat->tablet.buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED); - if (wl_surface *wl_surface_focus = seat->tablet.wl_surface) { + if (wl_surface *wl_surface_focus = seat->tablet.wl_surface_window) { GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); seat->system->pushEvent(new GHOST_EventButton( seat->system->getMilliSeconds(), etype, win, ebutton, tablet_tool->data)); @@ -3149,7 +3149,7 @@ static void tablet_tool_handle_frame(void *data, GWL_Seat *seat = tablet_tool->seat; /* No need to check the surfaces origin, it's already known to be owned by GHOST. */ - if (wl_surface *wl_surface_focus = seat->tablet.wl_surface) { + if (wl_surface *wl_surface_focus = seat->tablet.wl_surface_window) { GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); const wl_fixed_t scale = win->scale(); seat->system->pushEvent(new GHOST_EventCursor(seat->system->getMilliSeconds(), @@ -3164,7 +3164,7 @@ static void tablet_tool_handle_frame(void *data, } if (tablet_tool->proximity == false) { - seat->tablet.wl_surface = nullptr; + seat->tablet.wl_surface_window = nullptr; } } @@ -3334,7 +3334,7 @@ static void keyboard_handle_enter(void *data, GWL_Seat *seat = static_cast(data); seat->keyboard.serial = serial; - seat->keyboard.wl_surface = wl_surface; + seat->keyboard.wl_surface_window = wl_surface; seat->system->seat_active_set(seat); @@ -3379,7 +3379,7 @@ static void keyboard_handle_leave(void *data, CLOG_INFO(LOG, 2, "leave"); GWL_Seat *seat = static_cast(data); - seat->keyboard.wl_surface = nullptr; + seat->keyboard.wl_surface_window = nullptr; /* Losing focus must stop repeating text. */ if (seat->key_repeat.timer) { @@ -3540,7 +3540,7 @@ static void keyboard_handle_key(void *data, keyboard_depressed_state_key_event(seat, gkey, etype); - if (wl_surface *wl_surface_focus = seat->keyboard.wl_surface) { + if (wl_surface *wl_surface_focus = seat->keyboard.wl_surface_window) { GHOST_IWindow *win = ghost_wl_surface_user_data(wl_surface_focus); seat->system->pushEvent( new GHOST_EventKey(seat->system->getMilliSeconds(), etype, win, gkey, false, utf8_buf)); @@ -3564,7 +3564,7 @@ static void keyboard_handle_key(void *data, task->getUserData()); GWL_Seat *seat = payload->seat; - if (wl_surface *wl_surface_focus = seat->keyboard.wl_surface) { + if (wl_surface *wl_surface_focus = seat->keyboard.wl_surface_window) { GHOST_IWindow *win = ghost_wl_surface_user_data(wl_surface_focus); GHOST_SystemWayland *system = seat->system; /* Calculate this value every time in case modifier keys are pressed. */ @@ -3789,7 +3789,7 @@ static void gwl_seat_capability_pointer_enable(GWL_Seat *seat) return; } seat->wl_pointer = wl_seat_get_pointer(seat->wl_seat); - seat->cursor.wl_surface = wl_compositor_create_surface(seat->system->wl_compositor()); + seat->cursor.wl_surface_cursor = wl_compositor_create_surface(seat->system->wl_compositor()); seat->cursor.visible = true; seat->cursor.wl_buffer = nullptr; if (!get_cursor_settings(seat->cursor.theme_name, seat->cursor.theme_size)) { @@ -3798,8 +3798,8 @@ static void gwl_seat_capability_pointer_enable(GWL_Seat *seat) } wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat); - wl_surface_add_listener(seat->cursor.wl_surface, &cursor_surface_listener, seat); - ghost_wl_surface_tag_cursor_pointer(seat->cursor.wl_surface); + wl_surface_add_listener(seat->cursor.wl_surface_cursor, &cursor_surface_listener, seat); + ghost_wl_surface_tag_cursor_pointer(seat->cursor.wl_surface_cursor); zwp_pointer_gestures_v1 *pointer_gestures = seat->system->wp_pointer_gestures(); if (pointer_gestures) { @@ -3870,9 +3870,9 @@ static void gwl_seat_capability_pointer_disable(GWL_Seat *seat) #endif } - if (seat->cursor.wl_surface) { - wl_surface_destroy(seat->cursor.wl_surface); - seat->cursor.wl_surface = nullptr; + if (seat->cursor.wl_surface_cursor) { + wl_surface_destroy(seat->cursor.wl_surface_cursor); + seat->cursor.wl_surface_cursor = nullptr; } if (seat->cursor.wl_theme) { wl_cursor_theme_destroy(seat->cursor.wl_theme); @@ -5363,7 +5363,7 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorPositionClientRelative(const GHOST_ return GHOST_kFailure; } GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_active(seat); - if (!seat_state_pointer || !seat_state_pointer->wl_surface) { + if (!seat_state_pointer || !seat_state_pointer->wl_surface_window) { return GHOST_kFailure; } const GHOST_WindowWayland *win = static_cast(window); @@ -5393,7 +5393,7 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(int32_t &x, int32_t &y) co return GHOST_kFailure; } - if (wl_surface *wl_surface_focus = seat_state_pointer->wl_surface) { + if (wl_surface *wl_surface_focus = seat_state_pointer->wl_surface_window) { GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); return getCursorPositionClientRelative_impl(seat_state_pointer, win, x, y); } @@ -5409,7 +5409,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorPosition(const int32_t x, const int /* Intentionally different from `getCursorPosition` which supports both tablet & pointer. * In the case of setting the cursor location, tablets don't support this. */ - if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { + if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) { GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); return setCursorPositionClientRelative_impl(seat, win, x, y); } @@ -5583,7 +5583,7 @@ static void cursor_buffer_show(const GWL_Seat *seat) const int32_t hotspot_y = int32_t(cursor->wl_image.hotspot_y) / scale; if (seat->wl_pointer) { wl_pointer_set_cursor( - seat->wl_pointer, seat->pointer.serial, cursor->wl_surface, hotspot_x, hotspot_y); + seat->wl_pointer, seat->pointer.serial, cursor->wl_surface_cursor, hotspot_x, hotspot_y); } } @@ -5667,10 +5667,10 @@ static void cursor_buffer_set(const GWL_Seat *seat, wl_buffer *buffer) wl_image, cursor->is_custom ? cursor->custom_scale : seat->pointer.theme_scale); const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale; const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale; - cursor_buffer_set_surface_impl(seat, buffer, cursor->wl_surface, scale); + cursor_buffer_set_surface_impl(seat, buffer, cursor->wl_surface_cursor, scale); wl_pointer_set_cursor(seat->wl_pointer, seat->pointer.serial, - visible ? cursor->wl_surface : nullptr, + visible ? cursor->wl_surface_cursor : nullptr, hotspot_x, hotspot_y); } @@ -6145,10 +6145,10 @@ void GHOST_SystemWayland::window_surface_unref(const wl_surface *wl_surface) /* Only clear window surfaces (not cursors, off-screen surfaces etc). */ for (GWL_Seat *seat : display_->seats) { - SURFACE_CLEAR_PTR(seat->pointer.wl_surface); - SURFACE_CLEAR_PTR(seat->tablet.wl_surface); - SURFACE_CLEAR_PTR(seat->keyboard.wl_surface); - SURFACE_CLEAR_PTR(seat->wl_surface_focus_dnd); + SURFACE_CLEAR_PTR(seat->pointer.wl_surface_window); + SURFACE_CLEAR_PTR(seat->tablet.wl_surface_window); + SURFACE_CLEAR_PTR(seat->keyboard.wl_surface_window); + SURFACE_CLEAR_PTR(seat->wl_surface_window_focus_dnd); } #undef SURFACE_CLEAR_PTR } diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp index 6ee1fb8b27f..ad94a02b514 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.cpp +++ b/intern/ghost/intern/GHOST_WindowWayland.cpp @@ -90,7 +90,10 @@ struct GWL_Window { /** The scale value written to #wl_surface_set_buffer_scale. */ int scale = 0; - /** The fractional scale used to calculate the DPI. */ + /** + * The fractional scale used to calculate the DPI. + * (always set, even when scaling is rounded to whole units). + */ wl_fixed_t scale_fractional = 0; #ifdef WITH_GHOST_WAYLAND_LIBDECOR -- cgit v1.2.3 From ef76a67153c9670b42f3f8091bbf41388c5bbd73 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 1 Nov 2022 12:24:04 +1100 Subject: Cleanup: doxy comment formatting --- source/blender/blenkernel/BKE_bpath.h | 33 ++++++++++++++-------- source/blender/blenkernel/BKE_duplilist.h | 12 +++++--- source/blender/blenkernel/BKE_nla.h | 8 +++--- source/blender/editors/space_buttons/buttons_ops.c | 2 +- .../editors/transform/transform_convert_nla.c | 6 ++-- source/blender/imbuf/intern/webp.c | 2 +- 6 files changed, 38 insertions(+), 25 deletions(-) diff --git a/source/blender/blenkernel/BKE_bpath.h b/source/blender/blenkernel/BKE_bpath.h index bc60b6f050e..5b1dea0833a 100644 --- a/source/blender/blenkernel/BKE_bpath.h +++ b/source/blender/blenkernel/BKE_bpath.h @@ -55,15 +55,18 @@ typedef enum eBPathForeachFlag { * This is needed for directory manipulation callbacks which might otherwise modify the same * directory multiple times. */ BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE = (1 << 8), - /** Reload data (when the path is edited). - * \note Only used by Image IDType currently. */ + /** + * Reload data (when the path is edited). + * \note Only used by Image #IDType currently. + */ BKE_BPATH_FOREACH_PATH_RELOAD_EDITED = (1 << 9), } eBPathForeachFlag; ENUM_OPERATORS(eBPathForeachFlag, BKE_BPATH_FOREACH_PATH_RELOAD_EDITED) struct BPathForeachPathData; -/** Callback used to iterate over an ID's file paths. +/** + * Callback used to iterate over an ID's file paths. * * \note `path`s parameters should be considered as having a maximal `FILE_MAX` string length. * @@ -145,8 +148,9 @@ bool BKE_bpath_foreach_path_allocated_process(struct BPathForeachPathData *bpath /** Check for missing files. */ void BKE_bpath_missing_files_check(struct Main *bmain, struct ReportList *reports); -/** Recursively search into given search directory, for all file paths of all IDs in given \a - * bmain, and replace existing paths as needed. +/** + * Recursively search into given search directory, for all file paths of all IDs in given + * \a bmain, and replace existing paths as needed. * * \note The search will happen into the whole search directory tree recursively (with a limit of * MAX_DIR_RECURSE), if several files are found matching a searched filename, the biggest one will @@ -156,7 +160,7 @@ void BKE_bpath_missing_files_check(struct Main *bmain, struct ReportList *report * \param searchpath: The root directory in which the new filepaths should be searched for. * \param find_all: If `true`, also search for files which current path is still valid, if `false` * skip those still valid paths. - * */ + */ void BKE_bpath_missing_files_find(struct Main *bmain, const char *searchpath, struct ReportList *reports, @@ -178,23 +182,28 @@ void BKE_bpath_absolute_convert(struct Main *bmain, const char *basedir, struct ReportList *reports); -/** Temp backup of paths from all IDs in given \a bmain. +/** + * Temp backup of paths from all IDs in given \a bmain. * - * \return An opaque handle to pass to #BKE_bpath_list_restore and #BKE_bpath_list_free. + * \return An opaque handle to pass to #BKE_bpath_list_restore and #BKE_bpath_list_free. */ void *BKE_bpath_list_backup(struct Main *bmain, eBPathForeachFlag flag); -/** Restore the temp backup of paths from \a path_list_handle into all IDs in given \a bmain. +/** + * Restore the temp backup of paths from \a path_list_handle into all IDs in given \a bmain. * * \note This function assumes that the data in given Main did not change (no * addition/deletion/re-ordering of IDs, or their file paths) since the call to - * #BKE_bpath_list_backup that generated the given \a path_list_handle. */ + * #BKE_bpath_list_backup that generated the given \a path_list_handle. + */ void BKE_bpath_list_restore(struct Main *bmain, eBPathForeachFlag flag, void *path_list_handle); -/** Free the temp backup of paths in \a path_list_handle. +/** + * Free the temp backup of paths in \a path_list_handle. * * \note This function assumes that the path list has already been restored with a call to - * #BKE_bpath_list_restore, and is therefore empty. */ + * #BKE_bpath_list_restore, and is therefore empty. + */ void BKE_bpath_list_free(void *path_list_handle); /** \} */ diff --git a/source/blender/blenkernel/BKE_duplilist.h b/source/blender/blenkernel/BKE_duplilist.h index 44c4df1fc2e..a0732bf39cf 100644 --- a/source/blender/blenkernel/BKE_duplilist.h +++ b/source/blender/blenkernel/BKE_duplilist.h @@ -76,16 +76,20 @@ typedef struct DupliObject { unsigned int random_id; } DupliObject; -/** Look up the RGBA value of a uniform shader attribute. - * \return true if the attribute was found; if not, r_value is also set to zero. */ +/** + * Look up the RGBA value of a uniform shader attribute. + * \return true if the attribute was found; if not, r_value is also set to zero. + */ bool BKE_object_dupli_find_rgba_attribute(struct Object *ob, struct DupliObject *dupli, struct Object *dupli_parent, const char *name, float r_value[4]); -/** Look up the RGBA value of a view layer/scene/world shader attribute. - * \return true if the attribute was found; if not, r_value is also set to zero. */ +/** + * Look up the RGBA value of a view layer/scene/world shader attribute. + * \return true if the attribute was found; if not, r_value is also set to zero. + */ bool BKE_view_layer_find_rgba_attribute(struct Scene *scene, struct ViewLayer *layer, const char *name, diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index efadd5c11d6..2913beee759 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -249,8 +249,8 @@ float BKE_nlastrip_compute_frame_to_next_strip(struct NlaStrip *strip); /** * Returns the next strip in this strip's NLA track, or a null pointer. * - * \param strip The strip to find the next trip from. - * \param check_transitions Whether or not to skip transitions. + * \param strip: The strip to find the next trip from. + * \param check_transitions: Whether or not to skip transitions. * \return The next strip in the track, or NULL if none are present. */ struct NlaStrip *BKE_nlastrip_next_in_track(struct NlaStrip *strip, bool skip_transitions); @@ -258,8 +258,8 @@ struct NlaStrip *BKE_nlastrip_next_in_track(struct NlaStrip *strip, bool skip_tr /** * Returns the previous strip in this strip's NLA track, or a null pointer. * - * \param strip The strip to find the previous trip from. - * \param check_transitions Whether or not to skip transitions. + * \param strip: The strip to find the previous trip from. + * \param check_transitions: Whether or not to skip transitions. * \return The previous strip in the track, or NULL if none are present. */ struct NlaStrip *BKE_nlastrip_prev_in_track(struct NlaStrip *strip, bool skip_transitions); diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index 4013288b13b..9c8d46a41f9 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -41,7 +41,7 @@ /* -------------------------------------------------------------------- */ /** \name Start / Clear Search Filter Operators * - * \note Almost a duplicate of the file browser operator #FILE_OT_start_filter. + * \note Almost a duplicate of the file browser operator #FILE_OT_start_filter. * \{ */ static int buttons_start_filter_exec(bContext *C, wmOperator *UNUSED(op)) diff --git a/source/blender/editors/transform/transform_convert_nla.c b/source/blender/editors/transform/transform_convert_nla.c index af5a51cbff6..830094ebe83 100644 --- a/source/blender/editors/transform/transform_convert_nla.c +++ b/source/blender/editors/transform/transform_convert_nla.c @@ -60,9 +60,9 @@ typedef struct TransDataNla { * \{ */ /** - * \brief Applies a translation to the given NlaStrip. - * \param strip_rna_ptr The RNA pointer of the NLA strip to modify. - * \param transdata The transformation info structure. + * \brief Applies a translation to the given #NlaStrip. + * \param strip_rna_ptr: The RNA pointer of the NLA strip to modify. + * \param transdata: The transformation info structure. */ static void applyTransformNLA_translation(PointerRNA *strip_rna_ptr, const TransDataNla *transdata) { diff --git a/source/blender/imbuf/intern/webp.c b/source/blender/imbuf/intern/webp.c index 27c26fb19c1..3031b8c3e33 100644 --- a/source/blender/imbuf/intern/webp.c +++ b/source/blender/imbuf/intern/webp.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /** \file - * \ingroup imbuf + * \ingroup imbuf */ #ifdef _WIN32 -- cgit v1.2.3 From afc091c3c4bc86d4bb6165cbcdc9f17129d743e8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 1 Nov 2022 12:24:06 +1100 Subject: Cleanup: spelling in comments --- intern/cycles/blender/session.cpp | 6 +- intern/cycles/integrator/path_trace_work_gpu.cpp | 4 +- intern/ghost/intern/GHOST_SystemWayland.cpp | 4 +- source/blender/blenkernel/BKE_armature.h | 4 +- source/blender/blenkernel/BKE_key.h | 4 +- source/blender/blenkernel/BKE_pointcache.h | 1 + source/blender/blenkernel/BKE_undo_system.h | 2 +- source/blender/blenkernel/intern/blendfile.c | 2 +- source/blender/blenkernel/intern/layer.c | 2 +- source/blender/blenkernel/intern/lib_id_delete.c | 4 +- source/blender/blenkernel/intern/mask_rasterize.c | 4 +- source/blender/blenkernel/intern/material.c | 4 +- source/blender/blenkernel/intern/pointcache.c | 4 +- source/blender/blenkernel/intern/screen.c | 2 +- source/blender/blenkernel/intern/softbody.c | 6 +- source/blender/blenkernel/intern/writeffmpeg.c | 2 +- source/blender/blenloader/intern/readfile.cc | 2 +- source/blender/bmesh/tools/bmesh_bevel.c | 2 +- source/blender/bmesh/tools/bmesh_wireframe.c | 2 +- .../compositor/operations/COM_ConvertOperation.h | 4 +- source/blender/editors/armature/armature_utils.c | 8 +-- source/blender/editors/armature/pose_transform.c | 10 ++-- .../blender/editors/interface/interface_handlers.c | 4 +- source/blender/editors/mesh/mesh_data.cc | 4 +- source/blender/editors/space_action/action_draw.c | 2 +- source/blender/editors/space_graph/graph_draw.c | 2 +- source/blender/editors/space_nla/nla_draw.c | 2 +- .../editors/transform/transform_convert_armature.c | 5 +- .../freestyle/intern/stroke/AdvancedFunctions1D.h | 2 +- .../freestyle/intern/view_map/ViewMapTesselator.h | 4 +- source/blender/gpu/metal/mtl_shader_generator.hh | 2 +- source/blender/gpu/metal/mtl_texture_util.mm | 2 +- source/blender/makesdna/DNA_customdata_types.h | 4 +- source/blender/makesdna/DNA_layer_types.h | 6 +- source/blender/makesdna/DNA_meta_types.h | 4 +- source/blender/makesdna/DNA_modifier_types.h | 70 +++++++++++----------- source/blender/makesdna/DNA_node_types.h | 4 +- source/blender/makesdna/DNA_particle_types.h | 2 +- source/blender/makesdna/DNA_space_types.h | 2 +- source/blender/makesdna/DNA_windowmanager_types.h | 6 +- source/blender/makesdna/DNA_workspace_types.h | 6 +- source/blender/makesrna/intern/rna_armature.c | 2 +- source/blender/makesrna/intern/rna_object.c | 2 +- source/blender/nodes/intern/node_exec.cc | 2 +- source/blender/nodes/intern/node_exec.h | 4 +- source/blender/nodes/shader/node_shader_tree.cc | 3 +- source/blender/nodes/texture/node_texture_tree.c | 3 +- source/blender/python/intern/bpy_rna.c | 4 +- source/blender/python/mathutils/mathutils_noise.c | 4 +- source/blender/render/intern/render_result.cc | 2 +- source/blender/windowmanager/WM_types.h | 2 +- source/blender/windowmanager/wm.h | 4 +- 52 files changed, 128 insertions(+), 120 deletions(-) diff --git a/intern/cycles/blender/session.cpp b/intern/cycles/blender/session.cpp index f9a83b2dc4b..6641e2b8ac5 100644 --- a/intern/cycles/blender/session.cpp +++ b/intern/cycles/blender/session.cpp @@ -497,9 +497,9 @@ void BlenderSession::render_frame_finish() session->full_buffer_written_cb = function_null; /* The display driver is the source of drawing context for both drawing and possible graphics - * interop objects in the path trace. Once the frame is finished the OpenGL context might be - * freed form Blender side. Need to ensure that all GPU resources are freed prior to that - * point. + * interoperability objects in the path trace. Once the frame is finished the OpenGL context + * might be freed form Blender side. Need to ensure that all GPU resources are freed prior to + * that point. * Ideally would only do this when OpenGL context is actually destroyed, but there is no way to * know when this happens (at least in the code at the time when this comment was written). * The penalty of re-creating resources on every frame is unlikely to be noticed. */ diff --git a/intern/cycles/integrator/path_trace_work_gpu.cpp b/intern/cycles/integrator/path_trace_work_gpu.cpp index 48f6cf3c903..547e8d50a22 100644 --- a/intern/cycles/integrator/path_trace_work_gpu.cpp +++ b/intern/cycles/integrator/path_trace_work_gpu.cpp @@ -100,8 +100,8 @@ void PathTraceWorkGPU::alloc_integrator_soa() integrator_state_soa_volume_stack_size_ = max(integrator_state_soa_volume_stack_size_, requested_volume_stack_size); - /* Deterine the number of path states. Deferring this for as long as possible allows the backend - * to make better decisions about memory availability. */ + /* Determine the number of path states. Deferring this for as long as possible allows the + * back-end to make better decisions about memory availability. */ if (max_num_paths_ == 0) { size_t single_state_size = estimate_single_state_size(kernel_features); diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 3073a8fe80d..5af9f5a0231 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -801,7 +801,9 @@ struct GWL_Display { /** * Free the #GWL_Display and it's related members. - * \note This may run on a partially initialized struct, so it can't be assumed all mebers are set. + * + * \note This may run on a partially initialized struct, + * so it can't be assumed all members are set. */ static void gwl_display_destroy(GWL_Display *display) { diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index ee0f41937e2..eff05e471aa 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -34,9 +34,9 @@ typedef struct EditBone { /** User-Defined Properties on this Bone */ struct IDProperty *prop; /** - * Editbones have a one-way link (i.e. children refer + * Edit-bones have a one-way link (i.e. children refer * to parents. This is converted to a two-way link for - * normal bones when leaving editmode. + * normal bones when leaving edit-mode. */ struct EditBone *parent; /** (64 == MAXBONENAME) */ diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index 0fe351c0aa4..6cae56b775f 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -167,9 +167,9 @@ void BKE_keyblock_update_from_offset(const struct Object *ob, * Move shape key from org_index to new_index. Safe, clamps index to valid range, * updates reference keys, the object's active shape index, * the 'frame' value in case of absolute keys, etc. - * Note indices are expected in real values (not 'fake' shapenr +1 ones). + * Note indices are expected in real values (not *fake* `shapenr +1` ones). * - * \param org_index: if < 0, current object's active shape will be used as skey to move. + * \param org_index: if < 0, current object's active shape will be used as shape-key to move. * \return true if something was done, else false. */ bool BKE_keyblock_move(struct Object *ob, int org_index, int new_index); diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index efb8c2a9bb1..4331a25c112 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -293,6 +293,7 @@ void BKE_ptcache_ids_from_object(struct ListBase *lb, bool BKE_ptcache_object_has(struct Scene *scene, struct Object *ob, int duplis); /************ ID specific functions ************************/ + void BKE_ptcache_id_clear(PTCacheID *id, int mode, unsigned int cfra); bool BKE_ptcache_id_exist(PTCacheID *id, int cfra); int BKE_ptcache_id_reset(struct Scene *scene, PTCacheID *id, int mode); diff --git a/source/blender/blenkernel/BKE_undo_system.h b/source/blender/blenkernel/BKE_undo_system.h index f3a929dc5b9..5d1a27f8ba0 100644 --- a/source/blender/blenkernel/BKE_undo_system.h +++ b/source/blender/blenkernel/BKE_undo_system.h @@ -75,7 +75,7 @@ typedef struct UndoStep { /** Some situations require the global state to be stored, edge cases when exiting modes. */ bool use_memfile_step; /** When this is true, undo/memfile read code is allowed to re-use old data-blocks for unchanged - * IDs, and existing depsgraphes. This has to be forbidden in some cases (like renamed IDs). */ + * IDs, and existing depsgraphs. This has to be forbidden in some cases (like renamed IDs). */ bool use_old_bmain_data; /** For use by undo systems that accumulate changes (mesh-sculpt & image-painting). */ bool is_applied; diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index 85a43b7c479..8b0d3f2e92e 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -186,7 +186,7 @@ static void setup_app_data(bContext *C, clean_paths(bfd->main); } - /* XXX here the complex windowmanager matching */ + /* The following code blocks performs complex window-manager matching. */ /* no load screens? */ if (mode != LOAD_UI) { diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index 06d69b6ff61..5b54f16661c 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -614,7 +614,7 @@ static bool layer_collection_hidden(ViewLayer *view_layer, LayerCollection *lc) return true; } - /* Check visiblilty restriction flags */ + /* Check visibility restriction flags */ if (lc->flag & LAYER_COLLECTION_HIDE || lc->collection->flag & COLLECTION_HIDE_VIEWPORT) { return true; } diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index 1a80376f482..c7643c56212 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -293,14 +293,14 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) * is never affected). */ for (ID *id = tagged_deleted_ids.first; id; id = id->next) { id->tag |= LIB_TAG_NO_MAIN; - /* Usercount needs to be reset artificially, since some usages may not be cleared in batch + /* User-count needs to be reset artificially, since some usages may not be cleared in batch * deletion (typically, if one deleted ID uses another deleted ID, this may not be cleared by * remapping code, depending on order in which these are handled). */ id->us = ID_FAKE_USERS(id); } } else { - /* First tag all datablocks directly from target lib. + /* First tag all data-blocks directly from target lib. * Note that we go forward here, since we want to check dependencies before users * (e.g. meshes before objects). * Avoids to have to loop twice. */ diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 55834d5cf4e..adc0eb5f78c 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -521,7 +521,7 @@ static void layer_bucket_init(MaskRasterLayer *layer, const float pixel_size) } if (1) { - /* now convert linknodes into arrays for faster per pixel access */ + /* Now convert link-nodes into arrays for faster per pixel access. */ uint **buckets_face = MEM_mallocN(bucket_tot * sizeof(*buckets_face), __func__); uint bucket_index; @@ -1186,7 +1186,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, // printf("tris %d, feather tris %d\n", sf_tri_tot, tot_feather_quads); } - /* add trianges */ + /* Add triangles. */ BLI_scanfill_end_arena(&sf_ctx, sf_arena); } diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 51e27f173c8..59530a6d6a6 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -1450,7 +1450,7 @@ static bool fill_texpaint_slots_cb(bNode *node, void *userdata) NodeTexImage *storage = (NodeTexImage *)node->storage; slot->interp = storage->interpolation; slot->image_user = &storage->iuser; - /* for new renderer, we need to traverse the treeback in search of a UV node */ + /* For new renderer, we need to traverse the tree back in search of a UV node. */ bNode *uvnode = nodetree_uv_node_recursive(node); if (uvnode) { @@ -1561,7 +1561,7 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma, const struct Ob } /* COW needed when adding texture slot on an object with no materials. - * But do it only when slots actually change to avoid continuous depsgrap updates. */ + * But do it only when slots actually change to avoid continuous depsgraph updates. */ if (ma->tot_slots != prev_tot_slots || ma->paint_active_slot != prev_paint_active_slot || ma->paint_clone_slot != prev_paint_clone_slot || (ma->texpaintslot && prev_texpaintslot && diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index bb9a0f458b9..868cdde6d01 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -2611,7 +2611,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, uint cfra) } #endif - /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */ + /* Clear all files in the temp dir with the prefix of the ID and the `.bphys` suffix. */ switch (mode) { case PTCACHE_CLEAR_ALL: case PTCACHE_CLEAR_BEFORE: @@ -2775,7 +2775,7 @@ void BKE_ptcache_id_time( /* time handling for point cache: * - simulation time is scaled by result of bsystem_time * - for offsetting time only time offset is taken into account, since - * that's always the same and can't be animated. a timeoffset which + * that's always the same and can't be animated. a time-offset which * varies over time is not simple to support. * - field and motion blur offsets are currently ignored, proper solution * is probably to interpolate results from two frames for that .. diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 3e5dbc47c40..2c896788b20 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -304,7 +304,7 @@ IDTypeInfo IDType_ID_SCR = { /* ************ Space-type/region-type handling ************** */ -/* keep global; this has to be accessible outside of windowmanager */ +/** Keep global; this has to be accessible outside of window-manager. */ static ListBase spacetypes = {NULL, NULL}; /* not SpaceType itself */ diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 14a7d26a354..b35031b9a88 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -133,9 +133,9 @@ typedef struct SB_thread_context { #define BSF_INTERSECT 1 /* edge intersects collider face */ -/* private definitions for bodypoint states */ -#define SBF_DOFUZZY 1 /* Bodypoint do fuzzy. */ -#define SBF_OUTOFCOLLISION 2 /* Bodypoint does not collide. */ +/* private definitions for body-point states */ +#define SBF_DOFUZZY 1 /* Body-point do fuzzy. */ +#define SBF_OUTOFCOLLISION 2 /* Body-point does not collide. */ #define BFF_INTERSECT 1 /* collider edge intrudes face. */ #define BFF_CLOSEVERT 2 /* collider vertex repulses face. */ diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 0842125932b..ee827cd8cd4 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -1017,7 +1017,7 @@ static AVStream *alloc_audio_stream(FFMpegContext *context, return NULL; } - /* need to prevent floating point exception when using vorbis audio codec, + /* Need to prevent floating point exception when using VORBIS audio codec, * initialize this value in the same way as it's done in FFmpeg itself (sergey) */ c->time_base.num = 1; c->time_base.den = c->sample_rate; diff --git a/source/blender/blenloader/intern/readfile.cc b/source/blender/blenloader/intern/readfile.cc index ec1768232c8..569798048f6 100644 --- a/source/blender/blenloader/intern/readfile.cc +++ b/source/blender/blenloader/intern/readfile.cc @@ -2143,7 +2143,7 @@ static void direct_link_id_common( BlendDataReader *reader, Library *current_library, ID *id, ID *id_old, const int tag) { if (!BLO_read_data_is_undo(reader)) { - /* When actually reading a file, we do want to reset/re-generate session uuids. + /* When actually reading a file, we do want to reset/re-generate session UUIDS. * In undo case, we want to re-use existing ones. */ id->session_uuid = MAIN_ID_SESSION_UUID_UNSET; } diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 8da28af3ca7..c45f9dbe49c 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -2058,7 +2058,7 @@ static void get_profile_point(BevelParams *bp, const Profile *pro, int i, int ns } else { BLI_assert(is_power_of_2_i(nseg) && nseg <= bp->pro_spacing.seg_2); - /* Find spacing between subsamples in prof_co_2. */ + /* Find spacing between sub-samples in `prof_co_2`. */ int subsample_spacing = bp->pro_spacing.seg_2 / nseg; copy_v3_v3(r_co, pro->prof_co_2 + 3 * i * subsample_spacing); } diff --git a/source/blender/bmesh/tools/bmesh_wireframe.c b/source/blender/bmesh/tools/bmesh_wireframe.c index 14ec45f14b0..bdc36559e05 100644 --- a/source/blender/bmesh/tools/bmesh_wireframe.c +++ b/source/blender/bmesh/tools/bmesh_wireframe.c @@ -175,7 +175,7 @@ void BM_mesh_wireframe(BMesh *bm, BMVert **verts_neg = MEM_mallocN(sizeof(BMVert *) * totvert_orig, __func__); BMVert **verts_pos = MEM_mallocN(sizeof(BMVert *) * totvert_orig, __func__); - /* Will over-alloc, but makes for easy lookups by index to keep aligned. */ + /* Will over-allocate, but makes for easy lookups by index to keep aligned. */ BMVert **verts_boundary = use_boundary ? MEM_mallocN(sizeof(BMVert *) * totvert_orig, __func__) : NULL; diff --git a/source/blender/compositor/operations/COM_ConvertOperation.h b/source/blender/compositor/operations/COM_ConvertOperation.h index 16d1e2e6bb5..ffd02ed5a2f 100644 --- a/source/blender/compositor/operations/COM_ConvertOperation.h +++ b/source/blender/compositor/operations/COM_ConvertOperation.h @@ -98,7 +98,7 @@ class ConvertVectorToValueOperation : public ConvertBaseOperation { class ConvertRGBToYCCOperation : public ConvertBaseOperation { private: - /** YCbCr mode (Jpeg, ITU601, ITU709) */ + /** YCbCr mode (JPEG, ITU601, ITU709) */ int mode_; public: @@ -116,7 +116,7 @@ class ConvertRGBToYCCOperation : public ConvertBaseOperation { class ConvertYCCToRGBOperation : public ConvertBaseOperation { private: - /** YCbCr mode (Jpeg, ITU601, ITU709) */ + /** YCbCr mode (JPEG, ITU601, ITU709) */ int mode_; public: diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index 09174aa5e47..0465606e694 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -703,11 +703,11 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm) newBone->inherit_scale_mode = eBone->inherit_scale_mode; if (eBone == arm->act_edbone) { - /* don't change active selection, this messes up separate which uses - * editmode toggle and can separate active bone which is de-selected originally */ + /* Don't change active selection, this messes up separate which uses + * edit-mode toggle and can separate active bone which is de-selected originally. */ - /* important, editbones can be active with only 1 point selected */ - /* newBone->flag |= BONE_SELECTED; */ + /* important, edit-bones can be active with only 1 point selected */ + /* `newBone->flag |= BONE_SELECTED;` */ arm->act_bone = newBone; } newBone->roll = 0.0f; diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index 9ed963f0c66..f92b72bbb66 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -361,7 +361,7 @@ static void applyarmature_reset_constraints(bPose *pose, const bool use_selected } } -/* set the current pose as the restpose */ +/* Set the current pose as the rest-pose. */ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -404,10 +404,10 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op) } } - /* Get editbones of active armature to alter */ + /* Get edit-bones of active armature to alter. */ ED_armature_to_edit(arm); - /* get pose of active object and move it out of posemode */ + /* Get pose of active object and move it out of pose-mode. */ pose = ob->pose; if (use_selected) { @@ -429,11 +429,11 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op) } } - /* convert editbones back to bones, and then free the edit-data */ + /* Convert edit-bones back to bones, and then free the edit-data. */ ED_armature_from_edit(bmain, arm); ED_armature_edit_free(arm); - /* flush positions of posebones */ + /* Flush positions of pose-bones. */ BKE_pose_where_is(depsgraph, scene, ob); /* fix parenting of objects which are bone-parented */ diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 7b6a623f53e..ac16d41dabe 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -3519,7 +3519,7 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data) static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonData *data) { - /* label and roundbox can overlap real buttons (backdrops...) */ + /* Label and round-box can overlap real buttons (backdrops...). */ if (ELEM(actbut->type, UI_BTYPE_LABEL, UI_BTYPE_SEPR, @@ -3551,7 +3551,7 @@ static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonData *data) { - /* label and roundbox can overlap real buttons (backdrops...) */ + /* Label and round-box can overlap real buttons (backdrops...). */ if (ELEM(actbut->type, UI_BTYPE_LABEL, UI_BTYPE_SEPR, diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc index 122b8fa7d89..b468360ff9b 100644 --- a/source/blender/editors/mesh/mesh_data.cc +++ b/source/blender/editors/mesh/mesh_data.cc @@ -787,7 +787,7 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator if (me->edit_mesh) { /* Tag edges as sharp according to smooth threshold if needed, - * to preserve autosmooth shading. */ + * to preserve auto-smooth shading. */ if (me->flag & ME_AUTOSMOOTH) { BM_edges_sharp_from_angle_set(me->edit_mesh->bm, me->smoothresh); } @@ -796,7 +796,7 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator } else { /* Tag edges as sharp according to smooth threshold if needed, - * to preserve autosmooth shading. */ + * to preserve auto-smooth shading. */ if (me->flag & ME_AUTOSMOOTH) { const Span verts = me->verts(); MutableSpan edges = me->edges_for_write(); diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index eb56c6c4b54..343975919e2 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -104,7 +104,7 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region) UI_block_draw(C, block); } - /* free tempolary channels */ + /* Free temporary channels. */ ANIM_animdata_freelist(&anim_data); } diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index 41a8368152d..f8a0dff3a41 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -1446,7 +1446,7 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region) GPU_blend(GPU_BLEND_NONE); } - /* free tempolary channels */ + /* Free temporary channels. */ ANIM_animdata_freelist(&anim_data); } diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index f57c9fead56..45bbe50eedd 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -905,7 +905,7 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *region) } } - /* free tempolary channels */ + /* Free temporary channels. */ ANIM_animdata_freelist(&anim_data); } diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index 4b79625fa66..6fd25d26c31 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -306,8 +306,9 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan) * just make things obey standard rotation locks too */ if (data->rootbone == 0) { for (bPoseChannel *pchan_iter = pchan; pchan_iter; pchan_iter = pchan_iter->parent) { - /* here, we set ik-settings for bone from pchan->protectflag */ - /* XXX: careful with quats/axis-angle rotations where we're locking 4d components. */ + /* Here, we set IK-settings for bone from `pchan->protectflag`. */ + /* XXX: careful with quaternion/axis-angle rotations + * where we're locking 4d components. */ if (pchan_iter->protectflag & OB_LOCK_ROTX) { pchan_iter->ikflag |= BONE_IK_NO_XDOF_TEMP; } diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h index c19ac31ae4a..e5009f2b4f8 100644 --- a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h +++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h @@ -33,7 +33,7 @@ class DensityF1D : public UnaryFunction1D { public: /** Builds the functor. * \param sigma: - * Thesigma used in DensityF0D and determining the window size used in each density query. + * The sigma used in DensityF0D and determining the window size used in each density query. * \param iType: * The integration method used to compute a single value from a set of values. * \param sampling: diff --git a/source/blender/freestyle/intern/view_map/ViewMapTesselator.h b/source/blender/freestyle/intern/view_map/ViewMapTesselator.h index 2da95d47912..c666e548884 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapTesselator.h +++ b/source/blender/freestyle/intern/view_map/ViewMapTesselator.h @@ -89,7 +89,7 @@ class ViewMapTesselator { #endif }; -/** Class to tesselate the 2D projected silhouette */ +/** Class to tessellate the 2D projected silhouette */ class ViewMapTesselator2D : public ViewMapTesselator { public: inline ViewMapTesselator2D() : ViewMapTesselator() @@ -110,7 +110,7 @@ class ViewMapTesselator2D : public ViewMapTesselator { #endif }; -/** Class to tesselate the 3D silhouette */ +/** Class to tessellate the 3D silhouette */ class ViewMapTesselator3D : public ViewMapTesselator { public: inline ViewMapTesselator3D() : ViewMapTesselator() diff --git a/source/blender/gpu/metal/mtl_shader_generator.hh b/source/blender/gpu/metal/mtl_shader_generator.hh index 43890ca0170..63e2e6d5924 100644 --- a/source/blender/gpu/metal/mtl_shader_generator.hh +++ b/source/blender/gpu/metal/mtl_shader_generator.hh @@ -497,7 +497,7 @@ inline std::string get_stage_class_name(ShaderStage stage) inline bool is_builtin_type(std::string type) { /* Add Types as needed. */ - /* TODO(Metal): Consider replacing this with a switch and constexpr hash and switch. + /* TODO(Metal): Consider replacing this with a switch and `constexpr` hash and switch. * Though most efficient and maintainable approach to be determined. */ static std::map glsl_builtin_types = { {"float", MTL_DATATYPE_FLOAT}, diff --git a/source/blender/gpu/metal/mtl_texture_util.mm b/source/blender/gpu/metal/mtl_texture_util.mm index 5ed7659f260..33a62e2e3ef 100644 --- a/source/blender/gpu/metal/mtl_texture_util.mm +++ b/source/blender/gpu/metal/mtl_texture_util.mm @@ -34,7 +34,7 @@ MTLPixelFormat gpu_texture_format_to_metal(eGPUTextureFormat tex_format) { switch (tex_format) { - /* Formats texture & renderbuffer. */ + /* Formats texture & render-buffer. */ case GPU_RGBA8UI: return MTLPixelFormatRGBA8Uint; case GPU_RGBA8I: diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 287a9e2f3b9..0355ed3febe 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -116,7 +116,7 @@ typedef enum eCustomDataType { CD_PROP_BYTE_COLOR = 17, CD_TANGENT = 18, CD_MDISPS = 19, - CD_PREVIEW_MCOL = 20, /* for displaying weightpaint colors */ + CD_PREVIEW_MCOL = 20, /* For displaying weight-paint colors. */ /* CD_ID_MCOL = 21, */ /* CD_TEXTURE_MLOOPCOL = 22, */ /* UNUSED */ CD_CLOTH_ORCO = 23, @@ -209,7 +209,7 @@ typedef enum eCustomDataType { #define CD_MASK_HAIRLENGTH (1ULL << CD_HAIRLENGTH) -/** Multires loop data. */ +/** Multi-resolution loop data. */ #define CD_MASK_MULTIRES_GRIDS (CD_MASK_MDISPS | CD_GRID_PAINT_MASK) /* All data layers. */ diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h index 827e07725a1..6ea35dfb770 100644 --- a/source/blender/makesdna/DNA_layer_types.h +++ b/source/blender/makesdna/DNA_layer_types.h @@ -134,13 +134,13 @@ typedef struct ViewLayerAOV { typedef struct ViewLayerLightgroup { struct ViewLayerLightgroup *next, *prev; - /* Name of the Lightgroup */ + /* Name of the Light-group. */ char name[64]; } ViewLayerLightgroup; -/* Lightgroup membership information. */ +/* Light-group membership information. */ typedef struct LightgroupMembership { - /* Name of the Lightgroup */ + /* Name of the Light-group. */ char name[64]; } LightgroupMembership; diff --git a/source/blender/makesdna/DNA_meta_types.h b/source/blender/makesdna/DNA_meta_types.h index d0c09a0d6ab..b4a66a46efe 100644 --- a/source/blender/makesdna/DNA_meta_types.h +++ b/source/blender/makesdna/DNA_meta_types.h @@ -42,7 +42,7 @@ typedef struct MetaElem { float rad2; /** Stiffness, how much of the element to fill. */ float s; - /** Old, only used for backwards compat. use dimensions now. */ + /** Old, only used for backwards compatibility. use dimensions now. */ float len; /** Matrix and inverted matrix. */ @@ -63,7 +63,7 @@ typedef struct MetaBall { /* material of the mother ball will define the material used of all others */ struct Material **mat; - /** Flag is enum for updates, flag2 is bitflags for settings. */ + /** Flag is enum for updates, flag2 is bit-flags for settings. */ char flag, flag2; short totcol; /** Used to store MB_AUTOSPACE. */ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 7625f04fefa..c4180071352 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -195,7 +195,7 @@ typedef struct LatticeModifierData { ModifierData modifier; struct Object *object; - /** Optional vertexgroup name, MAX_VGROUP_NAME. */ + /** Optional vertex-group name, #MAX_VGROUP_NAME. */ char name[64]; float strength; short flag; @@ -212,7 +212,7 @@ typedef struct CurveModifierData { ModifierData modifier; struct Object *object; - /** Optional vertexgroup name, MAX_VGROUP_NAME. */ + /** Optional vertex-group name, #MAX_VGROUP_NAME. */ char name[64]; /** Axis along which curve deforms. */ short defaxis; @@ -262,7 +262,7 @@ typedef struct MaskModifierData { /** Armature to use to in place of hardcoded vgroup. */ struct Object *ob_arm; - /** Name of vertex group to use to mask, MAX_VGROUP_NAME. */ + /** Name of vertex group to use to mask, #MAX_VGROUP_NAME. */ char vgroup[64]; /** Using armature or hardcoded vgroup. */ @@ -447,7 +447,7 @@ typedef struct BevelModifierData { float bevel_angle; float spread; /** if the MOD_BEVEL_VWEIGHT option is set, - * this will be the name of the vert group, MAX_VGROUP_NAME */ + * this will be the name of the vert group, #MAX_VGROUP_NAME */ char defgrp_name[64]; char _pad1[4]; @@ -565,7 +565,7 @@ typedef struct DisplaceModifierData { float strength; int direction; - /** MAX_VGROUP_NAME. */ + /** #MAX_VGROUP_NAME. */ char defgrp_name[64]; float midlevel; int space; @@ -635,7 +635,7 @@ typedef struct DecimateModifierData { /** (mode == MOD_DECIM_MODE_DISSOLVE). */ float angle; - /** MAX_VGROUP_NAME. */ + /** #MAX_VGROUP_NAME. */ char defgrp_name[64]; float defgrp_factor; short flag, mode; @@ -663,7 +663,7 @@ enum { typedef struct SmoothModifierData { ModifierData modifier; float fac; - /** MAX_VGROUP_NAME. */ + /** #MAX_VGROUP_NAME. */ char defgrp_name[64]; short flag, repeat; @@ -684,7 +684,7 @@ typedef struct CastModifierData { float fac; float radius; float size; - /** MAX_VGROUP_NAME. */ + /** #MAX_VGROUP_NAME. */ char defgrp_name[64]; short flag; /** Cast modifier projection type. */ @@ -725,7 +725,7 @@ typedef struct WaveModifierData { /* End MappingInfoModifierData. */ struct Object *objectcenter; - /** MAX_VGROUP_NAME. */ + /** #MAX_VGROUP_NAME. */ char defgrp_name[64]; short flag; @@ -760,7 +760,7 @@ typedef struct ArmatureModifierData { struct Object *object; /** Stored input of previous modifier, for vertex-group blending. */ float (*vert_coords_prev)[3]; - /** MAX_VGROUP_NAME. */ + /** #MAX_VGROUP_NAME. */ char defgrp_name[64]; } ArmatureModifierData; @@ -803,11 +803,11 @@ typedef struct HookModifierData { struct CurveMapping *curfalloff; - /** If NULL, it's using vertexgroup. */ + /** If NULL, it's using vertex-group. */ int *indexar; int indexar_num; float force; - /** Optional vertexgroup name, MAX_VGROUP_NAME. */ + /** Optional vertex-group name, #MAX_VGROUP_NAME. */ char name[64]; void *_pad1; } HookModifierData; @@ -946,7 +946,7 @@ typedef struct MeshDeformModifierData { /** Mesh object. */ struct Object *object; - /** Optional vertexgroup name, MAX_VGROUP_NAME. */ + /** Optional vertex-group name, #MAX_VGROUP_NAME. */ char defgrp_name[64]; short gridsize, flag; @@ -1124,7 +1124,7 @@ typedef struct ShrinkwrapModifierData { struct Object *target; /** Additional shrink target. */ struct Object *auxTarget; - /** Optional vertexgroup name, MAX_VGROUP_NAME. */ + /** Optional vertex-group name, #MAX_VGROUP_NAME. */ char vgroup_name[64]; /** Distance offset to keep from mesh/projection point. */ float keepDist; @@ -1171,9 +1171,9 @@ enum { /** #ShrinkwrapModifierData.shrinkOpts */ enum { - /** allow shrinkwrap to move the vertex in the positive direction of axis */ + /** Allow shrink-wrap to move the vertex in the positive direction of axis. */ MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR = (1 << 0), - /** allow shrinkwrap to move the vertex in the negative direction of axis */ + /** Allow shrink-wrap to move the vertex in the negative direction of axis. */ MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR = (1 << 1), /** ignore vertex moves if a vertex ends projected on a front face of the target */ @@ -1207,7 +1207,7 @@ typedef struct SimpleDeformModifierData { /** Object to control the origin of modifier space coordinates. */ struct Object *origin; - /** Optional vertexgroup name, MAX_VGROUP_NAME. */ + /** Optional vertex-group name, #MAX_VGROUP_NAME. */ char vgroup_name[64]; /** Factors to control simple deforms. */ float factor; @@ -1250,7 +1250,7 @@ typedef struct ShapeKeyModifierData { typedef struct SolidifyModifierData { ModifierData modifier; - /** Name of vertex group to use, MAX_VGROUP_NAME. */ + /** Name of vertex group to use, #MAX_VGROUP_NAME. */ char defgrp_name[64]; char shell_defgrp_name[64]; char rim_defgrp_name[64]; @@ -1451,7 +1451,7 @@ typedef struct WarpModifierData { char bone_to[64]; struct CurveMapping *curfalloff; - /** Optional vertexgroup name, MAX_VGROUP_NAME. */ + /** Optional vertex-group name, #MAX_VGROUP_NAME. */ char defgrp_name[64]; float strength; float falloff_radius; @@ -1484,7 +1484,7 @@ typedef enum { typedef struct WeightVGEditModifierData { ModifierData modifier; - /** Name of vertex group to edit. MAX_VGROUP_NAME. */ + /** Name of vertex group to edit. #MAX_VGROUP_NAME. */ char defgrp_name[64]; /** Using MOD_WVG_EDIT_* flags. */ @@ -1504,7 +1504,7 @@ typedef struct WeightVGEditModifierData { /* Masking options. */ /** The global "influence", if no vgroup nor tex is used as mask. */ float mask_constant; - /** Name of mask vertex group from which to get weight factors. MAX_VGROUP_NAME. */ + /** Name of mask vertex group from which to get weight factors. #MAX_VGROUP_NAME. */ char mask_defgrp_name[64]; /* Texture masking. */ @@ -1540,9 +1540,9 @@ enum { typedef struct WeightVGMixModifierData { ModifierData modifier; - /** Name of vertex group to modify/weight. MAX_VGROUP_NAME. */ + /** Name of vertex group to modify/weight. #MAX_VGROUP_NAME. */ char defgrp_name_a[64]; - /** Name of other vertex group to mix in. MAX_VGROUP_NAME. */ + /** Name of other vertex group to mix in. #MAX_VGROUP_NAME. */ char defgrp_name_b[64]; /** Default weight value for first vgroup. */ float default_weight_a; @@ -1558,7 +1558,7 @@ typedef struct WeightVGMixModifierData { /* Masking options. */ /** The global "influence", if no vgroup nor tex is used as mask. */ float mask_constant; - /** Name of mask vertex group from which to get weight factors. MAX_VGROUP_NAME. */ + /** Name of mask vertex group from which to get weight factors. #MAX_VGROUP_NAME. */ char mask_defgrp_name[64]; /* Texture masking. */ @@ -1628,7 +1628,7 @@ enum { typedef struct WeightVGProximityModifierData { ModifierData modifier; - /** Name of vertex group to modify/weight. MAX_VGROUP_NAME. */ + /** Name of vertex group to modify/weight. #MAX_VGROUP_NAME. */ char defgrp_name[64]; /* Mapping stuff. */ @@ -1646,7 +1646,7 @@ typedef struct WeightVGProximityModifierData { /* Masking options. */ /** The global "influence", if no vgroup nor tex is used as mask. */ float mask_constant; - /** Name of mask vertex group from which to get weight factors. MAX_VGROUP_NAME. */ + /** Name of mask vertex group from which to get weight factors. #MAX_VGROUP_NAME. */ char mask_defgrp_name[64]; /* Texture masking. */ @@ -1840,7 +1840,7 @@ typedef struct LaplacianSmoothModifierData { float lambda, lambda_border; char _pad1[4]; - /** MAX_VGROUP_NAME. */ + /** #MAX_VGROUP_NAME. */ char defgrp_name[64]; short flag, repeat; } LaplacianSmoothModifierData; @@ -1887,7 +1887,7 @@ typedef struct CorrectiveSmoothModifierData { char smooth_type, rest_source; char _pad[6]; - /** MAX_VGROUP_NAME. */ + /** #MAX_VGROUP_NAME. */ char defgrp_name[64]; /* runtime-only cache */ @@ -1932,7 +1932,7 @@ typedef struct UVWarpModifierData { /** Optional name of bone target, MAX_ID_NAME-2. */ char bone_dst[64]; - /** Optional vertexgroup name, MAX_VGROUP_NAME. */ + /** Optional vertex-group name, #MAX_VGROUP_NAME. */ char vgroup_name[64]; /** MAX_CUSTOMDATA_LAYER_NAME. */ char uvlayer_name[64]; @@ -2013,7 +2013,7 @@ enum { typedef struct LaplacianDeformModifierData { ModifierData modifier; - /** MAX_VGROUP_NAME. */ + /** #MAX_VGROUP_NAME. */ char anchor_grp_name[64]; int verts_num, repeat; float *vertexco; @@ -2035,7 +2035,7 @@ enum { */ typedef struct WireframeModifierData { ModifierData modifier; - /** MAX_VGROUP_NAME. */ + /** #MAX_VGROUP_NAME. */ char defgrp_name[64]; float offset; float offset_fac; @@ -2059,7 +2059,7 @@ typedef struct WeldModifierData { /* The limit below which to merge vertices. */ float merge_dist; - /* Name of vertex group to use to mask, MAX_VGROUP_NAME. */ + /** Name of vertex group to use to mask, #MAX_VGROUP_NAME. */ char defgrp_name[64]; char mode; @@ -2107,7 +2107,7 @@ typedef struct DataTransferModifierData { /** See CDT_MIX_ enum in BKE_customdata.h. */ int mix_mode; float mix_factor; - /** MAX_VGROUP_NAME. */ + /** #MAX_VGROUP_NAME. */ char defgrp_name[64]; int flags; @@ -2130,7 +2130,7 @@ enum { /** Set Split Normals modifier. */ typedef struct NormalEditModifierData { ModifierData modifier; - /** MAX_VGROUP_NAME. */ + /** #MAX_VGROUP_NAME. */ char defgrp_name[64]; /** Source of normals, or center of ellipsoid. */ struct Object *target; @@ -2253,7 +2253,7 @@ enum { typedef struct WeightedNormalModifierData { ModifierData modifier; - /** MAX_VGROUP_NAME. */ + /** #MAX_VGROUP_NAME. */ char defgrp_name[64]; char mode, flag; short weight; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index c7962db8198..74714cf7e41 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -931,7 +931,7 @@ typedef struct NodeImageMultiFileSocket { char path[1024]; ImageFormatData format; - /* multilayer output */ + /* Multi-layer output. */ /** EXR_TOT_MAXNAME-2 ('.' and channel char are appended). */ char layer[30]; char _pad2[2]; @@ -1273,7 +1273,7 @@ typedef struct CryptomatteLayer { typedef struct NodeCryptomatte_Runtime { /* Contains `CryptomatteLayer`. */ ListBase layers; - /* Temp storage for the cryptomatte picker. */ + /* Temp storage for the crypto-matte picker. */ float add[3]; float remove[3]; } NodeCryptomatte_Runtime; diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 44f1d3479b1..c4f11905e10 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -465,7 +465,7 @@ enum { #define PART_REACT_MULTIPLE 2 //#define PART_LOOP 4 /* not used anymore */ -/* for dopesheet */ +/* For dope-sheet. */ #define PART_DS_EXPAND 8 #define PART_HAIR_REGROW 16 /* regrow hair for each frame */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index d2d20bcde78..4bb92e6fcc5 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -667,7 +667,7 @@ typedef struct SpaceSeq { struct SequencerPreviewOverlay preview_overlay; struct SequencerTimelineOverlay timeline_overlay; - /** Multiview current eye - for internal use. */ + /** Multi-view current eye - for internal use. */ char multiview_eye; char _pad2[7]; diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 9b235fac049..7231a995f10 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -89,13 +89,13 @@ typedef struct Report { } Report; /** - * \note Saved in the wm, don't remove. + * \note Saved in the #wmWindowManager, don't remove. */ typedef struct ReportList { ListBase list; - /** eReportType. */ + /** #eReportType. */ int printlevel; - /** eReportType. */ + /** #eReportType. */ int storelevel; int flag; char _pad[4]; diff --git a/source/blender/makesdna/DNA_workspace_types.h b/source/blender/makesdna/DNA_workspace_types.h index e99f317f057..0cd1144b30d 100644 --- a/source/blender/makesdna/DNA_workspace_types.h +++ b/source/blender/makesdna/DNA_workspace_types.h @@ -199,8 +199,10 @@ typedef struct WorkSpaceInstanceHook { WorkSpace *active; struct WorkSpaceLayout *act_layout; - /** Needed because we can't change workspaces/layouts in running handler loop, - * it would break context. */ + /** + * Needed because we can't change work-spaces/layouts in running handler loop, + * it would break context. + */ WorkSpace *temp_workspace_store; struct WorkSpaceLayout *temp_layout_store; } WorkSpaceInstanceHook; diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index e6b1ea1321c..a2386205013 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -1129,7 +1129,7 @@ static void rna_def_bone_common(StructRNA *srna, int editbone) RNA_define_lib_overridable(false); } -/* err... bones should not be directly edited (only editbones should be...) */ +/* Err... bones should not be directly edited (only edit-bones should be...). */ static void rna_def_bone(BlenderRNA *brna) { StructRNA *srna; diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 46a89d3a6e0..7f4ed39c001 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -407,7 +407,7 @@ static void rna_Object_matrix_local_set(PointerRNA *ptr, const float values[16]) Object *ob = (Object *)ptr->owner_id; float local_mat[4][4]; - /* Localspace matrix is truly relative to the parent, + /* Local-space matrix is truly relative to the parent, * but parameters stored in object are relative to parentinv matrix. * Undo the parent inverse part before applying it as local matrix. */ if (ob->parent) { diff --git a/source/blender/nodes/intern/node_exec.cc b/source/blender/nodes/intern/node_exec.cc index 724d6f1a1e1..af783ca391f 100644 --- a/source/blender/nodes/intern/node_exec.cc +++ b/source/blender/nodes/intern/node_exec.cc @@ -162,7 +162,7 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context, /* XXX could let callbacks do this for specialized data */ exec = MEM_cnew("node tree execution data"); - /* backpointer to node tree */ + /* Back-pointer to node tree. */ exec->nodetree = ntree; /* set stack indices */ diff --git a/source/blender/nodes/intern/node_exec.h b/source/blender/nodes/intern/node_exec.h index dc07f52e23f..55bf409444e 100644 --- a/source/blender/nodes/intern/node_exec.h +++ b/source/blender/nodes/intern/node_exec.h @@ -27,7 +27,7 @@ struct bNodeTree; /* Node execution data */ typedef struct bNodeExec { - /** Backpointer to node. */ + /** Back-pointer to node. */ struct bNode *node; bNodeExecData data; @@ -37,7 +37,7 @@ typedef struct bNodeExec { /* Execution Data for each instance of node tree execution */ typedef struct bNodeTreeExec { - struct bNodeTree *nodetree; /* backpointer to node tree */ + struct bNodeTree *nodetree; /* Back-pointer to node tree. */ int totnodes; /* total node count */ struct bNodeExec *nodeexec; /* per-node execution data */ diff --git a/source/blender/nodes/shader/node_shader_tree.cc b/source/blender/nodes/shader/node_shader_tree.cc index 52edf68b3ff..f177fc95ef8 100644 --- a/source/blender/nodes/shader/node_shader_tree.cc +++ b/source/blender/nodes/shader/node_shader_tree.cc @@ -1126,7 +1126,8 @@ void ntreeShaderEndExecTree(bNodeTreeExec *exec) bNodeTree *ntree = exec->nodetree; ntreeShaderEndExecTree_internal(exec); - /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */ + /* XXX: clear node-tree back-pointer to exec data, + * same problem as noted in #ntreeBeginExecTree. */ ntree->execdata = nullptr; } } diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c index 81d0b0fbc84..99146f1a25c 100644 --- a/source/blender/nodes/texture/node_texture_tree.c +++ b/source/blender/nodes/texture/node_texture_tree.c @@ -308,7 +308,8 @@ void ntreeTexEndExecTree(bNodeTreeExec *exec) bNodeTree *ntree = exec->nodetree; ntreeTexEndExecTree_internal(exec); - /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */ + /* XXX: clear node-tree back-pointer to exec data, + * same problem as noted in #ntreeBeginExecTree. */ ntree->execdata = NULL; } } diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 0eaa5d6b6c7..02f7e16e805 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -380,10 +380,10 @@ static short pyrna_rotation_euler_order_get(PointerRNA *ptr, const short order_fallback, PropertyRNA **r_prop_eul_order); -/* bpyrna vector/euler/quat callbacks. */ +/* `bpyrna` vector/euler/quaternion callbacks. */ static uchar mathutils_rna_array_cb_index = -1; /* Index for our callbacks. */ -/* Subtype not used much yet. */ +/* Sub-type not used much yet. */ # define MATHUTILS_CB_SUBTYPE_EUL 0 # define MATHUTILS_CB_SUBTYPE_VEC 1 # define MATHUTILS_CB_SUBTYPE_QUAT 2 diff --git a/source/blender/python/mathutils/mathutils_noise.c b/source/blender/python/mathutils/mathutils_noise.c index 3a3297f27f7..3c564142160 100644 --- a/source/blender/python/mathutils/mathutils_noise.c +++ b/source/blender/python/mathutils/mathutils_noise.c @@ -40,7 +40,7 @@ * * Any feedback is very welcome. * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html - * email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space). */ + * email: `m-mat @ math.sci.hiroshima-u.ac.jp` (remove space). */ /* Period parameters */ #define N 624 @@ -120,7 +120,7 @@ static void setRndSeed(int seed) } } -/* float number in range [0, 1) using the mersenne twister rng */ +/* Float number in range [0, 1) using the mersenne twister random number generator. */ static float frand(void) { ulong y; diff --git a/source/blender/render/intern/render_result.cc b/source/blender/render/intern/render_result.cc index f9524fdbf05..94f6e2f1509 100644 --- a/source/blender/render/intern/render_result.cc +++ b/source/blender/render/intern/render_result.cc @@ -262,7 +262,7 @@ RenderResult *render_result_new(Render *re, render_result_views_new(rr, &re->r); - /* check renderdata for amount of layers */ + /* Check render-data for amount of layers. */ FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer) { if (layername && layername[0]) { if (!STREQ(view_layer->name, layername)) { diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index e25169109e7..e4050397aaa 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -359,7 +359,7 @@ typedef struct wmNotifier { /* data type, 256 entries is enough, it can overlap */ #define NOTE_DATA 0x00FF0000 -/* NC_WM windowmanager */ +/* NC_WM (window-manager). */ #define ND_FILEREAD (1 << 16) #define ND_FILESAVE (2 << 16) #define ND_DATACHANGED (3 << 16) diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h index 0b54560c56a..0a27b9c1cfd 100644 --- a/source/blender/windowmanager/wm.h +++ b/source/blender/windowmanager/wm.h @@ -45,12 +45,12 @@ extern void wm_close_and_free_all(bContext *C, ListBase *); extern void wm_add_default(struct Main *bmain, bContext *C); extern void wm_clear_default_size(bContext *C); -/* register to windowmanager for redo or macro */ +/* Register to window-manager for redo or macro. */ /** * Called on event handling by `event_system.c`. * - * All operations get registered in the windowmanager here. + * All operations get registered in the window-manager here. */ void wm_operator_register(bContext *C, wmOperator *op); -- cgit v1.2.3 From 4d139601baec7b1195394fc03bfde98d93060c2c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 1 Nov 2022 12:48:57 +1100 Subject: CMake: mark Wayland variables advanced --- build_files/cmake/platform/platform_unix.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake index 424926afe39..343ed6d8ef4 100644 --- a/build_files/cmake/platform/platform_unix.cmake +++ b/build_files/cmake/platform/platform_unix.cmake @@ -660,6 +660,7 @@ if(WITH_GHOST_WAYLAND) set(wayland-scanner_FOUND ON) set(wayland-cursor_FOUND ON) endif() + mark_as_advanced(WAYLAND_PROTOCOLS_DIR) set_and_warn_library_found("wayland-client" wayland-client_FOUND WITH_GHOST_WAYLAND) set_and_warn_library_found("wayland-egl" wayland-egl_FOUND WITH_GHOST_WAYLAND) @@ -694,6 +695,7 @@ if(WITH_GHOST_WAYLAND) else() pkg_get_variable(WAYLAND_SCANNER wayland-scanner wayland_scanner) endif() + mark_as_advanced(WAYLAND_SCANNER) # When using dynamic loading, headers generated # from older versions of `wayland-scanner` aren't compatible. -- cgit v1.2.3 From fe863b59db40315866d70b78662fc059cc04c59e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 1 Nov 2022 14:23:02 +1100 Subject: Fix T102194: unhandled number keys on AZERTY layout under Wayland Support layouts such as AZERTY where the shift key is held for number keys. Text entry remains unchanged but these keys now activate shortcuts as expected. This matches a fix in X11 for the same problem: T47228. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 112 +++++++++++++++++++++++++--- 1 file changed, 100 insertions(+), 12 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 5af9f5a0231..5afbf5b0b5f 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -101,9 +101,7 @@ static const struct GWL_RegistryHandler *gwl_registry_handler_from_interface_slo int interface_slot); /* -------------------------------------------------------------------- */ -/** \name Local Defines - * - * Control local functionality, compositors specific workarounds. +/** \name Workaround Compositor Sprsific Bugs * \{ */ /** @@ -156,6 +154,18 @@ static bool use_gnome_confine_hack = false; # define USE_GNOME_NEEDS_LIBDECOR_HACK #endif +/* -------------------------------------------------------------------- */ +/** \name Local Defines + * + * Control local functionality, compositors specific workarounds. + * \{ */ + +/** + * Fix short-cut part of keyboard reading code not properly handling some keys, see: T102194. + * \note This is similar to X11 workaround by the same name, see: T47228. + */ +#define USE_NON_LATIN_KB_WORKAROUND + #define WL_NAME_UNSET uint32_t(-1) /** \} */ @@ -198,6 +208,19 @@ static bool use_gnome_confine_hack = false; */ #define KEY_GRAVE 41 +#ifdef USE_NON_LATIN_KB_WORKAROUND +# define KEY_1 2 +# define KEY_2 3 +# define KEY_3 4 +# define KEY_4 5 +# define KEY_5 6 +# define KEY_6 7 +# define KEY_7 8 +# define KEY_8 9 +# define KEY_9 10 +# define KEY_0 11 +#endif + /** \} */ /* -------------------------------------------------------------------- */ @@ -665,12 +688,22 @@ struct GWL_Seat { * Keep a state with no modifiers active, use for symbol lookups. */ struct xkb_state *xkb_state_empty = nullptr; + + /** + * Keep a state with shift enabled, use to access predictable number access for AZERTY keymaps. + * If shift is not supported by the key-map, this is set to NULL. + */ + struct xkb_state *xkb_state_empty_with_shift = nullptr; /** * Keep a state with number-lock enabled, use to access predictable key-pad symbols. * If number-lock is not supported by the key-map, this is set to NULL. */ struct xkb_state *xkb_state_empty_with_numlock = nullptr; +#ifdef USE_NON_LATIN_KB_WORKAROUND + bool xkb_use_non_latin_workaround = false; +#endif + /** Keys held matching `xkb_state`. */ struct GWL_KeyboardDepressedState key_depressed; @@ -3294,9 +3327,23 @@ static void keyboard_handle_keymap(void *data, xkb_state_unref(seat->xkb_state_empty); seat->xkb_state_empty = xkb_state_new(keymap); + for (int i = 0; i < MOD_INDEX_NUM; i++) { + const GWL_ModifierInfo &mod_info = g_modifier_info_table[i]; + seat->xkb_keymap_mod_index[i] = xkb_keymap_mod_get_index(keymap, mod_info.xkb_id); + } + + xkb_state_unref(seat->xkb_state_empty_with_shift); + seat->xkb_state_empty_with_shift = nullptr; + { + const xkb_mod_index_t mod_shift = seat->xkb_keymap_mod_index[MOD_INDEX_SHIFT]; + if (mod_shift != XKB_MOD_INVALID) { + seat->xkb_state_empty_with_shift = xkb_state_new(keymap); + xkb_state_update_mask(seat->xkb_state_empty_with_shift, (1 << mod_shift), 0, 0, 0, 0, 0); + } + } + xkb_state_unref(seat->xkb_state_empty_with_numlock); seat->xkb_state_empty_with_numlock = nullptr; - { const xkb_mod_index_t mod2 = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_NUM); const xkb_mod_index_t num = xkb_keymap_mod_get_index(keymap, "NumLock"); @@ -3307,10 +3354,21 @@ static void keyboard_handle_keymap(void *data, } } - for (int i = 0; i < MOD_INDEX_NUM; i++) { - const GWL_ModifierInfo &mod_info = g_modifier_info_table[i]; - seat->xkb_keymap_mod_index[i] = xkb_keymap_mod_get_index(keymap, mod_info.xkb_id); +#ifdef USE_NON_LATIN_KB_WORKAROUND + seat->xkb_use_non_latin_workaround = false; + if (seat->xkb_state_empty_with_shift) { + seat->xkb_use_non_latin_workaround = true; + for (xkb_keycode_t key_code = KEY_1 + EVDEV_OFFSET; key_code <= KEY_0 + EVDEV_OFFSET; + key_code++) { + const xkb_keysym_t sym_test = xkb_state_key_get_one_sym(seat->xkb_state_empty_with_shift, + key_code); + if (!(sym_test >= XKB_KEY_0 && sym_test <= XKB_KEY_9)) { + seat->xkb_use_non_latin_workaround = false; + break; + } + } } +#endif keyboard_depressed_state_reset(seat); @@ -3401,6 +3459,8 @@ static void keyboard_handle_leave(void *data, static xkb_keysym_t xkb_state_key_get_one_sym_without_modifiers( struct xkb_state *xkb_state_empty, struct xkb_state *xkb_state_empty_with_numlock, + struct xkb_state *xkb_state_empty_with_shift, + const bool xkb_use_non_latin_workaround, const xkb_keycode_t key) { /* Use an empty keyboard state to access key symbol without modifiers. */ @@ -3414,12 +3474,31 @@ static xkb_keysym_t xkb_state_key_get_one_sym_without_modifiers( /* Accounts for key-pad keys typically swapped for numbers when number-lock is enabled: * `Home Left Up Right Down Prior Page_Up Next Page_Dow End Begin Insert Delete`. */ - if (xkb_state_empty_with_numlock && (sym >= XKB_KEY_KP_Home && sym <= XKB_KEY_KP_Delete)) { - const xkb_keysym_t sym_test = xkb_state_key_get_one_sym(xkb_state_empty_with_numlock, key); - if (sym_test != XKB_KEY_NoSymbol) { - sym = sym_test; + if (sym >= XKB_KEY_KP_Home && sym <= XKB_KEY_KP_Delete) { + if (xkb_state_empty_with_numlock) { + const xkb_keysym_t sym_test = xkb_state_key_get_one_sym(xkb_state_empty_with_numlock, key); + if (sym_test != XKB_KEY_NoSymbol) { + sym = sym_test; + } } } + else { +#ifdef USE_NON_LATIN_KB_WORKAROUND + if (key >= (KEY_1 + EVDEV_OFFSET) && key <= (KEY_0 + EVDEV_OFFSET)) { + if (xkb_state_empty_with_shift && xkb_use_non_latin_workaround) { + const xkb_keysym_t sym_test = xkb_state_key_get_one_sym(xkb_state_empty_with_shift, key); + if (sym_test != XKB_KEY_NoSymbol) { + /* Should never happen as enabling `xkb_use_non_latin_workaround` checks this. */ + GHOST_ASSERT(sym_test >= XKB_KEY_0 && sym_test <= XKB_KEY_9, "Unexpected key"); + sym = sym_test; + } + } + } +#else + (void)xkb_state_empty_with_shift; + (void)xkb_use_non_latin_workaround; +#endif + } return sym; } @@ -3461,7 +3540,15 @@ static void keyboard_handle_key(void *data, const xkb_keycode_t key_code = key + EVDEV_OFFSET; const xkb_keysym_t sym = xkb_state_key_get_one_sym_without_modifiers( - seat->xkb_state_empty, seat->xkb_state_empty_with_numlock, key_code); + seat->xkb_state_empty, + seat->xkb_state_empty_with_numlock, + seat->xkb_state_empty_with_shift, +#ifdef USE_NON_LATIN_KB_WORKAROUND + seat->xkb_use_non_latin_workaround, +#else + false, +#endif + key_code); if (sym == XKB_KEY_NoSymbol) { CLOG_INFO(LOG, 2, "key (code=%d, state=%u, no symbol, skipped)", int(key_code), state); return; @@ -4512,6 +4599,7 @@ static void gwl_registry_wl_seat_remove(GWL_Display *display, void *user_data, c /* Un-referencing checks for NULL case. */ xkb_state_unref(seat->xkb_state); xkb_state_unref(seat->xkb_state_empty); + xkb_state_unref(seat->xkb_state_empty_with_shift); xkb_state_unref(seat->xkb_state_empty_with_numlock); xkb_context_unref(seat->xkb_context); -- cgit v1.2.3 From 8b2b5b0b8384c95d92da41297b1a950e729cd782 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 1 Nov 2022 09:20:42 +0100 Subject: Fix compilation error on Windows. Missing return statement in recent commit. Code is disabled by default, so might not have been noticed. --- source/blender/gpu/vulkan/vk_shader.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/gpu/vulkan/vk_shader.cc b/source/blender/gpu/vulkan/vk_shader.cc index e85d571711a..d628f3eb851 100644 --- a/source/blender/gpu/vulkan/vk_shader.cc +++ b/source/blender/gpu/vulkan/vk_shader.cc @@ -26,6 +26,7 @@ void VKShader::compute_shader_from_glsl(MutableSpan /*sources*/) bool VKShader::finalize(const shader::ShaderCreateInfo * /*info*/) { + return false; } void VKShader::transform_feedback_names_set(Span /*name_list*/, -- cgit v1.2.3 From f17fbf80653dc0e1561b30fe03f46e354deb12bf Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 24 Oct 2022 14:16:37 +0200 Subject: Refactor: Rename Object->obmat to Object->object_to_world Motivation is to disambiguate on the naming level what the matrix actually means. It is very easy to understand the meaning backwards, especially since in Python the name goes the opposite way (it is called `world_matrix` in the Python API). It is important to disambiguate the naming without making developers to look into the comment in the header file (which is also not super clear either). Additionally, more clear naming facilitates the unit verification (or, in this case, space validation) when reading an expression. This patch calls the matrix `object_to_world` which makes it clear from the local code what is it exactly going on. This is only done on DNA level, and a lot of local variables still follow the old naming. A DNA rename is setup in a way that there is no change on the file level, so there should be no regressions at all. The possibility is to add `_matrix` or `_mat` suffix to the name to make it explicit that it is a matrix. Although, not sure if it really helps the readability, or is it something redundant. Differential Revision: https://developer.blender.org/D16328 --- source/blender/blenkernel/BKE_object.h | 2 +- source/blender/blenkernel/intern/action.c | 2 +- source/blender/blenkernel/intern/armature.c | 10 +-- source/blender/blenkernel/intern/armature_deform.c | 4 +- source/blender/blenkernel/intern/armature_update.c | 4 +- source/blender/blenkernel/intern/boids.c | 2 +- source/blender/blenkernel/intern/camera.c | 20 ++--- source/blender/blenkernel/intern/cloth.c | 10 +-- source/blender/blenkernel/intern/constraint.c | 89 ++++++++++---------- source/blender/blenkernel/intern/curve_deform.c | 4 +- source/blender/blenkernel/intern/curves.cc | 4 +- source/blender/blenkernel/intern/dynamicpaint.c | 22 ++--- source/blender/blenkernel/intern/effect.c | 20 ++--- source/blender/blenkernel/intern/fcurve_driver.c | 14 ++-- source/blender/blenkernel/intern/fluid.c | 28 +++---- .../blenkernel/intern/geometry_set_instances.cc | 4 +- source/blender/blenkernel/intern/gpencil.c | 18 ++-- source/blender/blenkernel/intern/lattice.c | 6 +- source/blender/blenkernel/intern/lattice_deform.c | 6 +- .../blender/blenkernel/intern/mball_tessellate.cc | 11 +-- source/blender/blenkernel/intern/mesh_mirror.c | 10 +-- source/blender/blenkernel/intern/object.cc | 95 +++++++++++----------- source/blender/blenkernel/intern/object_dupli.cc | 47 +++++------ source/blender/blenkernel/intern/object_update.cc | 14 ++-- source/blender/blenkernel/intern/paint.cc | 2 +- source/blender/blenkernel/intern/particle.c | 22 ++--- source/blender/blenkernel/intern/particle_child.c | 4 +- source/blender/blenkernel/intern/particle_system.c | 32 ++++---- source/blender/blenkernel/intern/rigidbody.c | 18 ++-- source/blender/blenkernel/intern/scene.cc | 8 +- source/blender/blenkernel/intern/softbody.c | 12 +-- source/blender/blenkernel/intern/sound.c | 8 +- source/blender/blenkernel/intern/vfont.c | 4 +- source/blender/blenlib/BLI_math_matrix.h | 2 +- source/blender/blenlib/BLI_uvproject.h | 2 +- source/blender/blenlib/intern/uvproject.c | 2 +- .../depsgraph/intern/depsgraph_query_iter.cc | 4 +- .../depsgraph/intern/eval/deg_eval_flush.cc | 2 +- .../blender/draw/engines/eevee/eevee_lightprobes.c | 40 ++++----- source/blender/draw/engines/eevee/eevee_lights.c | 4 +- .../blender/draw/engines/eevee/eevee_motion_blur.c | 4 +- source/blender/draw/engines/eevee/eevee_shadows.c | 2 +- source/blender/draw/engines/eevee/eevee_volumes.c | 2 +- .../blender/draw/engines/eevee_next/eevee_light.cc | 2 +- .../draw/engines/eevee_next/eevee_pipeline.cc | 4 +- .../draw/engines/eevee_next/eevee_velocity.cc | 6 +- .../draw/engines/gpencil/gpencil_cache_utils.c | 10 +-- .../draw/engines/gpencil/gpencil_draw_data.c | 6 +- .../draw/engines/gpencil/gpencil_shader_fx.c | 30 +++---- .../draw/engines/overlay/overlay_armature.cc | 55 +++++++------ .../draw/engines/overlay/overlay_edit_text.cc | 6 +- .../blender/draw/engines/overlay/overlay_extra.cc | 84 ++++++++++--------- .../draw/engines/overlay/overlay_gpencil.cc | 6 +- .../blender/draw/engines/overlay/overlay_image.cc | 2 +- .../draw/engines/overlay/overlay_lattice.cc | 2 +- .../draw/engines/overlay/overlay_metaball.cc | 8 +- .../draw/engines/overlay/overlay_outline.cc | 4 +- .../engines/overlay/overlay_viewer_attribute.cc | 4 +- .../draw/engines/overlay/overlay_wireframe.cc | 18 ++-- source/blender/draw/engines/select/select_engine.c | 10 +-- .../draw/engines/workbench/workbench_shadow.c | 2 +- .../draw/engines/workbench/workbench_volume.c | 4 +- source/blender/draw/intern/draw_cache_impl_mesh.cc | 8 +- source/blender/draw/intern/draw_curves.cc | 2 +- source/blender/draw/intern/draw_hair.cc | 6 +- source/blender/draw/intern/draw_manager.c | 6 +- source/blender/draw/intern/draw_manager_data.cc | 22 ++--- source/blender/draw/intern/draw_manager_text.cc | 30 +++---- source/blender/draw/intern/draw_resource.hh | 2 +- source/blender/draw/intern/draw_volume.cc | 2 +- .../blender/editors/animation/anim_motion_paths.c | 4 +- source/blender/editors/animation/keyframing.c | 4 +- source/blender/editors/armature/armature_add.c | 8 +- source/blender/editors/armature/armature_edit.c | 12 +-- .../blender/editors/armature/armature_relations.c | 4 +- source/blender/editors/armature/armature_select.c | 8 +- .../blender/editors/armature/armature_skinning.c | 8 +- source/blender/editors/armature/meshlaplacian.c | 4 +- source/blender/editors/armature/pose_transform.c | 4 +- source/blender/editors/curve/editcurve.c | 18 ++-- source/blender/editors/curve/editcurve_paint.c | 14 ++-- source/blender/editors/curve/editcurve_pen.c | 10 +-- source/blender/editors/curve/editcurve_select.c | 4 +- source/blender/editors/curves/intern/curves_ops.cc | 4 +- .../editors/gizmo_library/gizmo_library_presets.c | 2 +- source/blender/editors/gpencil/gpencil_armature.c | 6 +- .../editors/gpencil/gpencil_bake_animation.cc | 4 +- source/blender/editors/gpencil/gpencil_data.c | 4 +- source/blender/editors/gpencil/gpencil_edit.c | 4 +- source/blender/editors/gpencil/gpencil_fill.c | 2 +- source/blender/editors/gpencil/gpencil_mesh.cc | 2 +- source/blender/editors/gpencil/gpencil_paint.c | 2 +- .../blender/editors/gpencil/gpencil_sculpt_paint.c | 8 +- source/blender/editors/gpencil/gpencil_utils.c | 16 ++-- source/blender/editors/gpencil/gpencil_uv.c | 4 +- .../interface/eyedroppers/eyedropper_depth.c | 2 +- source/blender/editors/mesh/editface.cc | 4 +- source/blender/editors/mesh/editmesh_add_gizmo.c | 2 +- source/blender/editors/mesh/editmesh_bevel.c | 2 +- source/blender/editors/mesh/editmesh_bisect.c | 4 +- source/blender/editors/mesh/editmesh_extrude.c | 12 +-- .../blender/editors/mesh/editmesh_extrude_screw.c | 8 +- .../blender/editors/mesh/editmesh_extrude_spin.c | 2 +- .../editors/mesh/editmesh_extrude_spin_gizmo.c | 2 +- source/blender/editors/mesh/editmesh_inset.c | 2 +- source/blender/editors/mesh/editmesh_knife.c | 18 ++-- source/blender/editors/mesh/editmesh_loopcut.c | 2 +- source/blender/editors/mesh/editmesh_polybuild.c | 18 ++-- .../blender/editors/mesh/editmesh_preselect_elem.c | 4 +- source/blender/editors/mesh/editmesh_select.cc | 18 ++-- .../blender/editors/mesh/editmesh_select_similar.c | 22 ++--- source/blender/editors/mesh/editmesh_tools.c | 6 +- source/blender/editors/mesh/editmesh_utils.c | 2 +- source/blender/editors/mesh/meshtools.cc | 6 +- source/blender/editors/object/object_add.cc | 22 ++--- source/blender/editors/object/object_bake_api.c | 33 ++++---- source/blender/editors/object/object_constraint.c | 6 +- source/blender/editors/object/object_hook.c | 18 ++-- source/blender/editors/object/object_relations.c | 22 ++--- source/blender/editors/object/object_remesh.cc | 10 +-- source/blender/editors/object/object_transform.cc | 44 +++++----- source/blender/editors/object/object_utils.c | 24 +++--- source/blender/editors/object/object_warp.c | 2 +- source/blender/editors/physics/particle_edit.c | 14 ++-- source/blender/editors/physics/particle_object.c | 14 ++-- source/blender/editors/render/render_preview.cc | 2 +- .../editors/sculpt_paint/curves_sculpt_brush.cc | 4 +- .../editors/sculpt_paint/curves_sculpt_ops.cc | 2 +- source/blender/editors/sculpt_paint/paint_cursor.c | 20 ++--- .../editors/sculpt_paint/paint_image_proj.c | 6 +- source/blender/editors/sculpt_paint/paint_mask.c | 12 +-- source/blender/editors/sculpt_paint/paint_stroke.c | 12 +-- source/blender/editors/sculpt_paint/paint_utils.c | 6 +- .../blender/editors/sculpt_paint/paint_vertex.cc | 10 +-- source/blender/editors/sculpt_paint/sculpt.c | 33 ++++---- source/blender/editors/sculpt_paint/sculpt_cloth.c | 8 +- .../blender/editors/sculpt_paint/sculpt_detail.c | 14 ++-- .../editors/sculpt_paint/sculpt_face_set.cc | 2 +- .../editors/sculpt_paint/sculpt_filter_mesh.c | 8 +- source/blender/editors/sculpt_paint/sculpt_ops.c | 2 +- .../blender/editors/space_view3d/space_view3d.cc | 10 +-- .../blender/editors/space_view3d/view3d_buttons.c | 6 +- .../editors/space_view3d/view3d_camera_control.c | 4 +- source/blender/editors/space_view3d/view3d_draw.cc | 2 +- .../editors/space_view3d/view3d_gizmo_armature.c | 2 +- .../editors/space_view3d/view3d_gizmo_camera.c | 18 ++-- .../editors/space_view3d/view3d_gizmo_empty.c | 2 +- .../editors/space_view3d/view3d_gizmo_forcefield.c | 4 +- .../editors/space_view3d/view3d_gizmo_light.c | 8 +- .../space_view3d/view3d_gizmo_preselect_type.cc | 6 +- .../editors/space_view3d/view3d_iterators.cc | 16 ++-- .../blender/editors/space_view3d/view3d_navigate.c | 14 ++-- .../space_view3d/view3d_navigate_smoothview.c | 5 +- .../blender/editors/space_view3d/view3d_project.c | 4 +- .../blender/editors/space_view3d/view3d_select.cc | 9 +- source/blender/editors/space_view3d/view3d_snap.c | 47 ++++++----- source/blender/editors/space_view3d/view3d_utils.c | 17 ++-- source/blender/editors/space_view3d/view3d_view.c | 6 +- source/blender/editors/transform/transform.h | 3 +- .../blender/editors/transform/transform_convert.c | 6 +- .../editors/transform/transform_convert_armature.c | 4 +- .../editors/transform/transform_convert_curve.c | 2 +- .../editors/transform/transform_convert_lattice.c | 2 +- .../editors/transform/transform_convert_mball.c | 2 +- .../editors/transform/transform_convert_mesh.c | 2 +- .../transform/transform_convert_mesh_edge.c | 2 +- .../transform/transform_convert_mesh_skin.c | 2 +- .../transform/transform_convert_mesh_vert_cdata.c | 2 +- .../editors/transform/transform_convert_object.c | 14 ++-- .../transform/transform_convert_object_texspace.c | 4 +- .../editors/transform/transform_convert_particle.c | 2 +- .../editors/transform/transform_convert_sculpt.c | 12 +-- .../blender/editors/transform/transform_generics.c | 6 +- .../blender/editors/transform/transform_gizmo_3d.c | 50 ++++++------ source/blender/editors/transform/transform_mode.c | 2 +- .../editors/transform/transform_mode_edge_slide.c | 2 +- .../editors/transform/transform_mode_vert_slide.c | 11 +-- .../editors/transform/transform_orientations.c | 16 ++-- source/blender/editors/transform/transform_snap.c | 4 +- .../editors/transform/transform_snap_object.cc | 8 +- source/blender/editors/uvedit/uvedit_select.c | 16 ++-- source/blender/editors/uvedit/uvedit_unwrap_ops.c | 14 ++-- .../intern/blender_interface/BlenderFileLoader.cpp | 2 +- .../blender/geometry/intern/realize_instances.cc | 2 +- .../gpencil_modifiers/intern/MOD_gpencilarray.c | 4 +- .../gpencil_modifiers/intern/MOD_gpencilbuild.c | 4 +- .../gpencil_modifiers/intern/MOD_gpencilhook.c | 6 +- .../gpencil_modifiers/intern/MOD_gpencilmirror.c | 4 +- .../gpencil_modifiers/intern/MOD_gpencilmultiply.c | 2 +- .../gpencil_modifiers/intern/MOD_gpenciloutline.c | 6 +- .../gpencil_modifiers/intern/MOD_gpenciltint.c | 2 +- .../intern/MOD_gpencilweight_angle.c | 6 +- .../intern/MOD_gpencilweight_proximity.c | 4 +- .../gpencil_modifiers/intern/lineart/lineart_cpu.c | 14 ++-- .../intern/lineart/lineart_shadow.c | 2 +- source/blender/ikplugin/intern/iksolver_plugin.c | 4 +- source/blender/ikplugin/intern/itasc_plugin.cpp | 16 ++-- .../blender/io/alembic/exporter/abc_writer_hair.cc | 4 +- .../io/alembic/intern/abc_axis_conversion.cc | 8 +- .../blender/io/alembic/intern/abc_reader_object.cc | 2 +- source/blender/io/collada/AnimationImporter.cpp | 6 +- source/blender/io/collada/ArmatureImporter.cpp | 4 +- source/blender/io/collada/ControllerExporter.cpp | 4 +- source/blender/io/collada/DocumentImporter.cpp | 4 +- source/blender/io/collada/SkinInfo.cpp | 6 +- source/blender/io/collada/collada_utils.cpp | 8 +- .../common/intern/abstract_hierarchy_iterator.cc | 2 +- .../blender/io/gpencil/intern/gpencil_io_base.cc | 8 +- .../io/gpencil/intern/gpencil_io_export_pdf.cc | 2 +- .../io/gpencil/intern/gpencil_io_export_svg.cc | 2 +- .../io/wavefront_obj/exporter/obj_export_mesh.cc | 7 +- .../io/wavefront_obj/exporter/obj_export_nurbs.cc | 8 +- source/blender/makesdna/DNA_object_defaults.h | 2 +- source/blender/makesdna/DNA_object_types.h | 4 +- source/blender/makesdna/intern/dna_rename_defs.h | 1 + source/blender/makesrna/intern/rna_depsgraph.c | 2 +- source/blender/makesrna/intern/rna_gpencil.c | 8 +- source/blender/makesrna/intern/rna_object.c | 5 +- source/blender/makesrna/intern/rna_particle.c | 2 +- source/blender/modifiers/intern/MOD_array.c | 6 +- source/blender/modifiers/intern/MOD_boolean.cc | 34 ++++---- source/blender/modifiers/intern/MOD_cast.c | 16 ++-- source/blender/modifiers/intern/MOD_collision.c | 4 +- source/blender/modifiers/intern/MOD_displace.c | 2 +- source/blender/modifiers/intern/MOD_explode.c | 4 +- source/blender/modifiers/intern/MOD_hook.c | 6 +- .../blender/modifiers/intern/MOD_mesh_to_volume.cc | 2 +- source/blender/modifiers/intern/MOD_meshdeform.c | 4 +- source/blender/modifiers/intern/MOD_normal_edit.cc | 8 +- .../modifiers/intern/MOD_particleinstance.c | 2 +- source/blender/modifiers/intern/MOD_screw.c | 4 +- source/blender/modifiers/intern/MOD_surface.c | 2 +- .../blender/modifiers/intern/MOD_surfacedeform.c | 4 +- source/blender/modifiers/intern/MOD_util.cc | 10 +-- source/blender/modifiers/intern/MOD_uvproject.cc | 6 +- source/blender/modifiers/intern/MOD_uvwarp.cc | 4 +- .../modifiers/intern/MOD_volume_displace.cc | 4 +- .../blender/modifiers/intern/MOD_volume_to_mesh.cc | 2 +- source/blender/modifiers/intern/MOD_warp.c | 6 +- source/blender/modifiers/intern/MOD_wave.cc | 4 +- .../modifiers/intern/MOD_weightvgproximity.cc | 6 +- .../geometry/nodes/node_geo_collection_info.cc | 2 +- .../nodes/geometry/nodes/node_geo_object_info.cc | 2 +- source/blender/render/intern/bake.c | 2 +- .../blender/render/intern/texture_pointdensity.c | 8 +- .../windowmanager/xr/intern/wm_xr_session.c | 2 +- 246 files changed, 1175 insertions(+), 1133 deletions(-) diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 60dfc0af25f..5cbd7937f3f 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -323,7 +323,7 @@ struct Base **BKE_object_pose_base_array_get(const struct Scene *scene, void BKE_object_get_parent_matrix(struct Object *ob, struct Object *par, float r_parentmat[4][4]); /** - * Compute object world transform and store it in `ob->obmat`. + * Compute object world transform and store it in `ob->object_to_world`. */ void BKE_object_where_is_calc(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); void BKE_object_where_is_calc_ex(struct Depsgraph *depsgraph, diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 10aa4ec7906..8f6bd812d8e 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -1738,7 +1738,7 @@ void what_does_obaction(Object *ob, BKE_object_workob_clear(workob); /* init workob */ - copy_m4_m4(workob->obmat, ob->obmat); + copy_m4_m4(workob->object_to_world, ob->object_to_world); copy_m4_m4(workob->parentinv, ob->parentinv); copy_m4_m4(workob->constinv, ob->constinv); workob->parent = ob->parent; diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 2e73cac99b5..0f8bf0e9928 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1596,7 +1596,7 @@ void BKE_armature_mat_world_to_pose(Object *ob, const float inmat[4][4], float o } /* Get inverse of (armature) object's matrix. */ - invert_m4_m4(obmat, ob->obmat); + invert_m4_m4(obmat, ob->object_to_world); /* multiply given matrix by object's-inverse to find pose-space matrix */ mul_m4_m4m4(outmat, inmat, obmat); @@ -2569,7 +2569,7 @@ void BKE_pose_where_is(struct Depsgraph *depsgraph, Scene *scene, Object *ob) } } else { - invert_m4_m4(ob->imat, ob->obmat); /* imat is needed */ + invert_m4_m4(ob->imat, ob->object_to_world); /* imat is needed */ /* 1. clear flags */ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { @@ -2696,14 +2696,14 @@ void BKE_pchan_minmax(const Object *ob, pchan->custom_translation[0], pchan->custom_translation[1], pchan->custom_translation[2]); - mul_m4_series(mat, ob->obmat, tmp, rmat, smat); + mul_m4_series(mat, ob->object_to_world, tmp, rmat, smat); BKE_boundbox_minmax(bb_custom, mat, r_min, r_max); } else { float vec[3]; - mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_head); + mul_v3_m4v3(vec, ob->object_to_world, pchan_tx->pose_head); minmax_v3v3_v3(r_min, r_max, vec); - mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_tail); + mul_v3_m4v3(vec, ob->object_to_world, pchan_tx->pose_tail); minmax_v3v3_v3(r_min, r_max, vec); } } diff --git a/source/blender/blenkernel/intern/armature_deform.c b/source/blender/blenkernel/intern/armature_deform.c index 89afb886fc2..64a3937c191 100644 --- a/source/blender/blenkernel/intern/armature_deform.c +++ b/source/blender/blenkernel/intern/armature_deform.c @@ -582,9 +582,9 @@ static void armature_deform_coords_impl(const Object *ob_arm, }; float obinv[4][4]; - invert_m4_m4(obinv, ob_target->obmat); + invert_m4_m4(obinv, ob_target->object_to_world); - mul_m4_m4m4(data.postmat, obinv, ob_arm->obmat); + mul_m4_m4m4(data.postmat, obinv, ob_arm->object_to_world); invert_m4_m4(data.premat, data.postmat); if (em_target != NULL) { diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index 6d7aed239e7..b9f46118c0d 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -249,7 +249,7 @@ static void apply_curve_transform( * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root). */ if ((ik_data->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0) { - mul_m4_v3(ik_data->tar->obmat, r_vec); + mul_m4_v3(ik_data->tar->object_to_world, r_vec); } /* Convert the position to pose-space. */ @@ -819,7 +819,7 @@ void BKE_pose_eval_init(struct Depsgraph *depsgraph, Scene *UNUSED(scene), Objec BLI_assert((object->pose->flag & POSE_RECALC) == 0); /* imat is needed for solvers. */ - invert_m4_m4(object->imat, object->obmat); + invert_m4_m4(object->imat, object->object_to_world); /* clear flags */ for (bPoseChannel *pchan = pose->chanbase.first; pchan != NULL; pchan = pchan->next) { diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index 2e07b52c7bf..a0458f0f8d8 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -959,7 +959,7 @@ void boids_precalc_rules(ParticleSettings *part, float cfra) if (flbr->ob && flbr->cfra != cfra) { /* save object locations for velocity calculations */ copy_v3_v3(flbr->oloc, flbr->loc); - copy_v3_v3(flbr->loc, flbr->ob->obmat[3]); + copy_v3_v3(flbr->loc, flbr->ob->object_to_world[3]); flbr->cfra = cfra; } } diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 8608ce97397..7c1193d80ab 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -221,16 +221,16 @@ float BKE_camera_object_dof_distance(const Object *ob) } if (cam->dof.focus_object) { float view_dir[3], dof_dir[3]; - normalize_v3_v3(view_dir, ob->obmat[2]); + normalize_v3_v3(view_dir, ob->object_to_world[2]); bPoseChannel *pchan = BKE_pose_channel_find_name(cam->dof.focus_object->pose, cam->dof.focus_subtarget); if (pchan) { float posemat[4][4]; - mul_m4_m4m4(posemat, cam->dof.focus_object->obmat, pchan->pose_mat); - sub_v3_v3v3(dof_dir, ob->obmat[3], posemat[3]); + mul_m4_m4m4(posemat, cam->dof.focus_object->object_to_world, pchan->pose_mat); + sub_v3_v3v3(dof_dir, ob->object_to_world[3], posemat[3]); } else { - sub_v3_v3v3(dof_dir, ob->obmat[3], cam->dof.focus_object->obmat[3]); + sub_v3_v3v3(dof_dir, ob->object_to_world[3], cam->dof.focus_object->object_to_world[3]); } return fabsf(dot_v3v3(view_dir, dof_dir)); } @@ -628,7 +628,7 @@ static void camera_frame_fit_data_init(const Scene *scene, BKE_camera_params_compute_matrix(params); /* initialize callback data */ - copy_m3_m4(data->camera_rotmat, (float(*)[4])ob->obmat); + copy_m3_m4(data->camera_rotmat, (float(*)[4])ob->object_to_world); normalize_m3(data->camera_rotmat); /* To transform a plane which is in its homogeneous representation (4d vector), * we need the inverse of the transpose of the transform matrix... */ @@ -828,7 +828,7 @@ bool BKE_camera_view_frame_fit_to_coords(const Depsgraph *depsgraph, static void camera_model_matrix(const Object *camera, float r_modelmat[4][4]) { - copy_m4_m4(r_modelmat, camera->obmat); + copy_m4_m4(r_modelmat, camera->object_to_world); } static void camera_stereo3d_model_matrix(const Object *camera, @@ -854,7 +854,7 @@ static void camera_stereo3d_model_matrix(const Object *camera, } float size[3]; - mat4_to_size(size, camera->obmat); + mat4_to_size(size, camera->object_to_world); size_to_mat4(sizemat, size); if (pivot == CAM_S3D_PIVOT_CENTER) { @@ -894,7 +894,7 @@ static void camera_stereo3d_model_matrix(const Object *camera, toeinmat[3][0] = interocular_distance * fac_signed; /* transform */ - normalize_m4_m4(r_modelmat, camera->obmat); + normalize_m4_m4(r_modelmat, camera->object_to_world); mul_m4_m4m4(r_modelmat, r_modelmat, toeinmat); /* scale back to the original size */ @@ -902,7 +902,7 @@ static void camera_stereo3d_model_matrix(const Object *camera, } else { /* CAM_S3D_PIVOT_LEFT, CAM_S3D_PIVOT_RIGHT */ /* rotate perpendicular to the interocular line */ - normalize_m4_m4(r_modelmat, camera->obmat); + normalize_m4_m4(r_modelmat, camera->object_to_world); mul_m4_m4m4(r_modelmat, r_modelmat, rotmat); /* translate along the interocular line */ @@ -918,7 +918,7 @@ static void camera_stereo3d_model_matrix(const Object *camera, } } else { - normalize_m4_m4(r_modelmat, camera->obmat); + normalize_m4_m4(r_modelmat, camera->object_to_world); /* translate - no rotation in CAM_S3D_OFFAXIS, CAM_S3D_PARALLEL */ translate_m4(r_modelmat, -interocular_distance * fac_signed, 0.0f, 0.0f); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 89983eb8f62..910869bbc72 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -269,7 +269,7 @@ static int do_step_cloth( /* Get the current position. */ copy_v3_v3(verts->xconst, mvert[i].co); - mul_m4_v3(ob->obmat, verts->xconst); + mul_m4_v3(ob->object_to_world, verts->xconst); if (vert_mass_changed) { verts->mass = clmd->sim_parms->mass; @@ -581,7 +581,7 @@ static void cloth_to_object(Object *ob, ClothModifierData *clmd, float (*vertexC if (clmd->clothObject) { /* Inverse matrix is not up to date. */ - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); for (i = 0; i < cloth->mvert_num; i++) { copy_v3_v3(vertexCos[i], cloth->verts[i].x); @@ -763,11 +763,11 @@ static bool cloth_from_object( if (first) { copy_v3_v3(verts->x, mvert[i].co); - mul_m4_v3(ob->obmat, verts->x); + mul_m4_v3(ob->object_to_world, verts->x); if (shapekey_rest) { copy_v3_v3(verts->xrest, shapekey_rest[i]); - mul_m4_v3(ob->obmat, verts->xrest); + mul_m4_v3(ob->object_to_world, verts->xrest); } else { copy_v3_v3(verts->xrest, verts->x); @@ -1155,7 +1155,7 @@ static void cloth_update_verts(Object *ob, ClothModifierData *clmd, Mesh *mesh) /* vertex count is already ensured to match */ for (i = 0; i < mesh->totvert; i++, verts++) { copy_v3_v3(verts->xrest, mvert[i].co); - mul_m4_v3(ob->obmat, verts->xrest); + mul_m4_v3(ob->object_to_world, verts->xrest); } } diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index a6a6a1ca28f..1f288aef5ad 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -149,7 +149,7 @@ bConstraintOb *BKE_constraints_make_evalob( /* Quats/Axis-Angle, so Eulers should just use default order */ cob->rotOrder = EULER_ORDER_DEFAULT; } - copy_m4_m4(cob->matrix, ob->obmat); + copy_m4_m4(cob->matrix, ob->object_to_world); } else { unit_m4(cob->matrix); @@ -175,7 +175,7 @@ bConstraintOb *BKE_constraints_make_evalob( } /* matrix in world-space */ - mul_m4_m4m4(cob->matrix, ob->obmat, cob->pchan->pose_mat); + mul_m4_m4m4(cob->matrix, ob->object_to_world, cob->pchan->pose_mat); } else { unit_m4(cob->matrix); @@ -216,7 +216,7 @@ void BKE_constraints_clear_evalob(bConstraintOb *cob) /* cob->ob might not exist! */ if (cob->ob) { /* copy new ob-matrix back to owner */ - copy_m4_m4(cob->ob->obmat, cob->matrix); + copy_m4_m4(cob->ob->object_to_world, cob->matrix); /* copy inverse of delta back to owner */ invert_m4_m4(cob->ob->constinv, delta); @@ -276,7 +276,7 @@ void BKE_constraint_mat_convertspace(Object *ob, } else { /* World to pose. */ - invert_m4_m4(imat, ob->obmat); + invert_m4_m4(imat, ob->object_to_world); mul_m4_m4m4(mat, imat, mat); /* Use pose-space as stepping stone for other spaces. */ @@ -319,7 +319,7 @@ void BKE_constraint_mat_convertspace(Object *ob, } else { /* Pose to world. */ - mul_m4_m4m4(mat, ob->obmat, mat); + mul_m4_m4m4(mat, ob->object_to_world, mat); /* Use world-space as stepping stone for other spaces. */ if (to != CONSTRAINT_SPACE_WORLD) { /* Call self with slightly different values. */ @@ -429,7 +429,7 @@ void BKE_constraint_mat_convertspace(Object *ob, /* Check if object has a parent. */ if (ob->parent) { /* 'subtract' parent's effects from owner. */ - mul_m4_m4m4(diff_mat, ob->parent->obmat, ob->parentinv); + mul_m4_m4m4(diff_mat, ob->parent->object_to_world, ob->parentinv); invert_m4_m4_safe(imat, diff_mat); mul_m4_m4m4(mat, imat, mat); } @@ -465,7 +465,7 @@ void BKE_constraint_mat_convertspace(Object *ob, /* check that object has a parent - otherwise this won't work */ if (ob->parent) { /* 'add' parent's effect back to owner */ - mul_m4_m4m4(diff_mat, ob->parent->obmat, ob->parentinv); + mul_m4_m4m4(diff_mat, ob->parent->object_to_world, ob->parentinv); mul_m4_m4m4(mat, diff_mat, mat); } else { @@ -518,7 +518,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[ const int defgroup = BKE_object_defgroup_name_index(ob, substring); /* initialize target matrix using target matrix */ - copy_m4_m4(mat, ob->obmat); + copy_m4_m4(mat, ob->object_to_world); /* get index of vertex group */ if (defgroup == -1) { @@ -584,7 +584,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[ * calc_gizmo_stats, V3D_ORIENT_NORMAL case */ /* We need the transpose of the inverse for a normal. */ - copy_m3_m4(imat, ob->obmat); + copy_m3_m4(imat, ob->object_to_world); invert_m3_m3(tmat, imat); transpose_m3(tmat); @@ -605,7 +605,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[ normalize_m4(mat); /* apply the average coordinate as the new location */ - mul_v3_m4v3(mat[3], ob->obmat, vec); + mul_v3_m4v3(mat[3], ob->object_to_world, vec); } /* function that sets the given matrix based on given vertex group in lattice */ @@ -627,7 +627,7 @@ static void contarget_get_lattice_mat(Object *ob, const char *substring, float m const int defgroup = BKE_object_defgroup_name_index(ob, substring); /* initialize target matrix using target matrix */ - copy_m4_m4(mat, ob->obmat); + copy_m4_m4(mat, ob->object_to_world); /* get index of vertex group */ if (defgroup == -1) { @@ -661,11 +661,11 @@ static void contarget_get_lattice_mat(Object *ob, const char *substring, float m } } - /* find average location, then multiply by ob->obmat to find world-space location */ + /* find average location, then multiply by ob->object_to_world to find world-space location */ if (grouped) { mul_v3_fl(vec, 1.0f / grouped); } - mul_v3_m4v3(tvec, ob->obmat, vec); + mul_v3_m4v3(tvec, ob->object_to_world, vec); /* copy new location to matrix */ copy_v3_v3(mat[3], tvec); @@ -684,7 +684,7 @@ static void constraint_target_to_mat4(Object *ob, { /* Case OBJECT */ if (substring[0] == '\0') { - copy_m4_m4(mat, ob->obmat); + copy_m4_m4(mat, ob->object_to_world); BKE_constraint_mat_convertspace(ob, NULL, cob, mat, from, to, false); } /* Case VERTEXGROUP */ @@ -719,7 +719,7 @@ static void constraint_target_to_mat4(Object *ob, if (headtail < 0.000001f && !(is_bbone && full_bbone)) { /* skip length interpolation if set to head */ - mul_m4_m4m4(mat, ob->obmat, pchan->pose_mat); + mul_m4_m4m4(mat, ob->object_to_world, pchan->pose_mat); } else if (is_bbone && pchan->bone->segments == pchan->runtime.bbone_segments) { /* use point along bbone */ @@ -745,7 +745,7 @@ static void constraint_target_to_mat4(Object *ob, mul_v3_m4v3(tempmat[3], pchan->pose_mat, loc); } - mul_m4_m4m4(mat, ob->obmat, tempmat); + mul_m4_m4m4(mat, ob->object_to_world, tempmat); } else { float tempmat[4][4], loc[3]; @@ -757,11 +757,11 @@ static void constraint_target_to_mat4(Object *ob, copy_m4_m4(tempmat, pchan->pose_mat); copy_v3_v3(tempmat[3], loc); - mul_m4_m4m4(mat, ob->obmat, tempmat); + mul_m4_m4m4(mat, ob->object_to_world, tempmat); } } else { - copy_m4_m4(mat, ob->obmat); + copy_m4_m4(mat, ob->object_to_world); } /* convert matrix space as required */ @@ -1069,7 +1069,7 @@ static void childof_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar if (data->flag & CHILDOF_SET_INVERSE) { invert_m4_m4(data->invmat, parmat); if (cob->pchan != NULL) { - mul_m4_series(data->invmat, data->invmat, cob->ob->obmat); + mul_m4_series(data->invmat, data->invmat, cob->ob->object_to_world); } copy_m4_m4(inverse_matrix, data->invmat); @@ -1388,8 +1388,8 @@ static void kinematic_get_tarmat(struct Depsgraph *UNUSED(depsgraph), else { float vec[3]; /* move grabtarget into world space */ - mul_v3_m4v3(vec, ob->obmat, data->grabtarget); - copy_m4_m4(ct->matrix, ob->obmat); + mul_v3_m4v3(vec, ob->object_to_world, data->grabtarget); + copy_m4_m4(ct->matrix, ob->object_to_world); copy_v3_v3(ct->matrix[3], vec); } } @@ -1528,7 +1528,7 @@ static void followpath_get_tarmat(struct Depsgraph *UNUSED(depsgraph), copy_v3_v3(totmat[3], vec); - mul_m4_m4m4(ct->matrix, ct->tar->obmat, totmat); + mul_m4_m4m4(ct->matrix, ct->tar->object_to_world, totmat); } } } @@ -2557,7 +2557,7 @@ static void armdef_get_tarmat(struct Depsgraph *UNUSED(depsgraph), bPoseChannel *pchan = BKE_pose_channel_find_name(ct->tar->pose, ct->subtarget); if (pchan != NULL) { - mul_m4_m4m4(ct->matrix, ct->tar->obmat, pchan->pose_mat); + mul_m4_m4m4(ct->matrix, ct->tar->object_to_world, pchan->pose_mat); return; } } @@ -2613,7 +2613,7 @@ static void armdef_accumulate_bone(bConstraintTarget *ct, float weight = ct->weight; /* Our object's location in target pose space. */ - invert_m4_m4(iobmat, ct->tar->obmat); + invert_m4_m4(iobmat, ct->tar->object_to_world); mul_v3_m4v3(co, iobmat, wco); /* Multiply by the envelope weight when appropriate. */ @@ -2644,7 +2644,7 @@ static void armdef_accumulate_bone(bConstraintTarget *ct, mul_m4_m4m4(basemat, bone->arm_mat, b_bone_rest_mats[index].mat); } - armdef_accumulate_matrix(ct->tar->obmat, + armdef_accumulate_matrix(ct->tar->object_to_world, iobmat, basemat, b_bone_mats[index + 1].mat, @@ -2657,7 +2657,7 @@ static void armdef_accumulate_bone(bConstraintTarget *ct, mul_m4_m4m4(basemat, bone->arm_mat, b_bone_rest_mats[index + 1].mat); } - armdef_accumulate_matrix(ct->tar->obmat, + armdef_accumulate_matrix(ct->tar->object_to_world, iobmat, basemat, b_bone_mats[index + 2].mat, @@ -2667,8 +2667,13 @@ static void armdef_accumulate_bone(bConstraintTarget *ct, } else { /* Simple bone. This requires DEG_OPCODE_BONE_DONE dependency due to chan_mat. */ - armdef_accumulate_matrix( - ct->tar->obmat, iobmat, bone->arm_mat, pchan->chan_mat, weight, r_sum_mat, r_sum_dq); + armdef_accumulate_matrix(ct->tar->object_to_world, + iobmat, + bone->arm_mat, + pchan->chan_mat, + weight, + r_sum_mat, + r_sum_dq); } /* Accumulate the weight. */ @@ -2694,7 +2699,7 @@ static void armdef_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targ /* For constraints on bones, use the rest position to bind b-bone segments * and envelopes, to allow safely changing the bone location as if parented. */ copy_v3_v3(input_co, cob->pchan->bone->arm_head); - mul_m4_v3(cob->ob->obmat, input_co); + mul_m4_v3(cob->ob->object_to_world, input_co); } else { copy_v3_v3(input_co, cob->matrix[3]); @@ -3927,7 +3932,7 @@ static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar unit_m4(totmat); copy_v3_v3(totmat[3], vec); - mul_m4_m4m4(targetMatrix, ct->tar->obmat, totmat); + mul_m4_m4m4(targetMatrix, ct->tar->object_to_world, totmat); } } @@ -4227,7 +4232,7 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *UNUSED(depsgraph), if (BKE_shrinkwrap_init_tree( &tree, target_eval, scon->shrinkType, scon->shrinkMode, do_track_normal)) { - BLI_space_transform_from_matrices(&transform, cob->matrix, ct->tar->obmat); + BLI_space_transform_from_matrices(&transform, cob->matrix, ct->tar->object_to_world); switch (scon->shrinkType) { case MOD_SHRINKWRAP_NEAREST_SURFACE: @@ -4902,7 +4907,7 @@ static void followtrack_evaluate_using_3d_position_object(FollowTrackContext *co /* Object matrix of the camera. */ float camera_obmat[4][4]; - copy_m4_m4(camera_obmat, camera_object->obmat); + copy_m4_m4(camera_obmat, camera_object->object_to_world); /* Calculate inverted matrix of the solved camera at the current time. */ float reconstructed_camera_mat[4][4]; @@ -5054,10 +5059,10 @@ static void followtrack_project_to_depth_object_if_needed(FollowTrackContext *co } float depth_object_mat_inv[4][4]; - invert_m4_m4(depth_object_mat_inv, depth_object->obmat); + invert_m4_m4(depth_object_mat_inv, depth_object->object_to_world); float ray_start[3], ray_end[3]; - mul_v3_m4v3(ray_start, depth_object_mat_inv, context->camera_object->obmat[3]); + mul_v3_m4v3(ray_start, depth_object_mat_inv, context->camera_object->object_to_world[3]); mul_v3_m4v3(ray_end, depth_object_mat_inv, cob->matrix[3]); float ray_direction[3]; @@ -5080,7 +5085,7 @@ static void followtrack_project_to_depth_object_if_needed(FollowTrackContext *co &tree_data); if (result != -1) { - mul_v3_m4v3(cob->matrix[3], depth_object->obmat, hit.co); + mul_v3_m4v3(cob->matrix[3], depth_object->object_to_world, hit.co); } free_bvhtree_from_mesh(&tree_data); @@ -5128,9 +5133,9 @@ static void followtrack_evaluate_using_2d_position(FollowTrackContext *context, } float disp[3]; - mul_v3_m4v3(disp, camera_object->obmat, vec); + mul_v3_m4v3(disp, camera_object->object_to_world, vec); - copy_m4_m4(rmat, camera_object->obmat); + copy_m4_m4(rmat, camera_object->object_to_world); zero_v3(rmat[3]); mul_m4_m4m4(cob->matrix, cob->matrix, rmat); @@ -5152,10 +5157,10 @@ static void followtrack_evaluate_using_2d_position(FollowTrackContext *context, } float disp[3]; - mul_v3_m4v3(disp, camera_object->obmat, vec); + mul_v3_m4v3(disp, camera_object->object_to_world, vec); /* apply camera rotation so Z-axis would be co-linear */ - copy_m4_m4(rmat, camera_object->obmat); + copy_m4_m4(rmat, camera_object->object_to_world); zero_v3(rmat[3]); mul_m4_m4m4(cob->matrix, cob->matrix, rmat); @@ -5303,7 +5308,7 @@ static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase BKE_tracking_camera_get_reconstructed_interpolate(tracking, object, framenr, mat); invert_m4_m4(imat, mat); - mul_m4_m4m4(parmat, camob->obmat, imat); + mul_m4_m4m4(parmat, camob->object_to_world, imat); copy_m4_m4(obmat, cob->matrix); @@ -5650,7 +5655,7 @@ bool BKE_constraint_apply_for_object(Depsgraph *depsgraph, BLI_freelinkN(&single_con, new_con); /* Apply transform from matrix. */ - BKE_object_apply_mat4(ob, ob_eval->obmat, true, true); + BKE_object_apply_mat4(ob, ob_eval->object_to_world, true, true); return true; } @@ -6237,7 +6242,7 @@ void BKE_constraint_target_matrix_get(struct Depsgraph *depsgraph, cob->ob = (Object *)ownerdata; cob->pchan = NULL; if (cob->ob) { - copy_m4_m4(cob->matrix, cob->ob->obmat); + copy_m4_m4(cob->matrix, cob->ob->object_to_world); copy_m4_m4(cob->startmat, cob->matrix); } else { diff --git a/source/blender/blenkernel/intern/curve_deform.c b/source/blender/blenkernel/intern/curve_deform.c index 9a27ba91c2f..066d8494451 100644 --- a/source/blender/blenkernel/intern/curve_deform.c +++ b/source/blender/blenkernel/intern/curve_deform.c @@ -44,8 +44,8 @@ typedef struct { static void init_curve_deform(const Object *ob_curve, const Object *ob_target, CurveDeform *cd) { float imat[4][4]; - invert_m4_m4(imat, ob_target->obmat); - mul_m4_m4m4(cd->objectspace, imat, ob_curve->obmat); + invert_m4_m4(imat, ob_target->object_to_world); + mul_m4_m4m4(cd->objectspace, imat, ob_curve->object_to_world); invert_m4_m4(cd->curvespace, cd->objectspace); copy_m3_m4(cd->objectspace3, cd->objectspace); cd->no_rot_axis = 0; diff --git a/source/blender/blenkernel/intern/curves.cc b/source/blender/blenkernel/intern/curves.cc index 72e53023d6d..61755a5be9b 100644 --- a/source/blender/blenkernel/intern/curves.cc +++ b/source/blender/blenkernel/intern/curves.cc @@ -412,11 +412,11 @@ void curves_copy_parameters(const Curves &src, Curves &dst) CurvesSurfaceTransforms::CurvesSurfaceTransforms(const Object &curves_ob, const Object *surface_ob) { - this->curves_to_world = curves_ob.obmat; + this->curves_to_world = curves_ob.object_to_world; this->world_to_curves = this->curves_to_world.inverted(); if (surface_ob != nullptr) { - this->surface_to_world = surface_ob->obmat; + this->surface_to_world = surface_ob->object_to_world; this->world_to_surface = this->surface_to_world.inverted(); this->surface_to_curves = this->world_to_curves * this->surface_to_world; this->curves_to_surface = this->world_to_surface * this->curves_to_world; diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index e177250ae5a..b9cec17b6e0 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -3783,7 +3783,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(Depsgraph *depsgraph, numOfVerts_p = mesh_p->totvert; mvert_p = BKE_mesh_verts_for_write(mesh_p); - copy_m4_m4(prev_obmat, ob->obmat); + copy_m4_m4(prev_obmat, ob->object_to_world); /* current frame mesh */ scene->r.cfra = cur_fra; @@ -3816,7 +3816,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(Depsgraph *depsgraph, .brush_vel = *brushVel, .mvert_p = mvert_p, .mvert_c = mvert_c, - .obmat = ob->obmat, + .obmat = ob->object_to_world, .prev_obmat = prev_obmat, .timescale = timescale, }; @@ -3856,7 +3856,7 @@ static void dynamicPaint_brushObjectCalculateVelocity( SUBFRAME_RECURSION, BKE_scene_ctime_get(scene), eModifierType_DynamicPaint); - copy_m4_m4(prev_obmat, ob->obmat); + copy_m4_m4(prev_obmat, ob->object_to_world); /* current frame mesh */ scene->r.cfra = cur_fra; @@ -3871,7 +3871,7 @@ static void dynamicPaint_brushObjectCalculateVelocity( /* calculate speed */ mul_m4_v3(prev_obmat, prev_loc); - mul_m4_v3(ob->obmat, cur_loc); + mul_m4_v3(ob->object_to_world, cur_loc); sub_v3_v3v3(brushVel->v, cur_loc, prev_loc); mul_v3_fl(brushVel->v, 1.0f / timescale); @@ -4279,14 +4279,14 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph, * (Faster than transforming per surface point * coordinates and normals to object space) */ for (ii = 0; ii < numOfVerts; ii++) { - mul_m4_v3(brushOb->obmat, mvert[ii].co); + mul_m4_v3(brushOb->object_to_world, mvert[ii].co); boundInsert(&mesh_bb, mvert[ii].co); /* for proximity project calculate average normal */ if (brush->flags & MOD_DPAINT_PROX_PROJECT && brush->collision != MOD_DPAINT_COL_VOLUME) { float nor[3]; copy_v3_v3(nor, vert_normals[ii]); - mul_mat3_m4_v3(brushOb->obmat, nor); + mul_mat3_m4_v3(brushOb->object_to_world, nor); normalize_v3(nor); add_v3_v3(avg_brushNor, nor); @@ -5870,7 +5870,7 @@ static bool dynamicPaint_surfaceHasMoved(DynamicPaintSurface *surface, Object *o } /* matrix comparison */ - if (!equals_m4m4(bData->prev_obmat, ob->obmat)) { + if (!equals_m4m4(bData->prev_obmat, ob->object_to_world)) { return true; } @@ -5957,7 +5957,7 @@ static void dynamic_paint_generate_bake_data_cb(void *__restrict userdata, mul_v3_v3v3(scaled_nor, temp_nor, ob->scale); bData->bNormal[index].normal_scale = len_v3(scaled_nor); } - mul_mat3_m4_v3(ob->obmat, temp_nor); + mul_mat3_m4_v3(ob->object_to_world, temp_nor); normalize_v3(temp_nor); negate_v3_v3(bData->bNormal[index].invNorm, temp_nor); } @@ -5995,7 +5995,7 @@ static void dynamic_paint_generate_bake_data_cb(void *__restrict userdata, mul_v3_v3v3(scaled_nor, temp_nor, ob->scale); bData->bNormal[index].normal_scale = len_v3(scaled_nor); } - mul_mat3_m4_v3(ob->obmat, temp_nor); + mul_mat3_m4_v3(ob->object_to_world, temp_nor); normalize_v3(temp_nor); negate_v3_v3(bData->bNormal[index].invNorm, temp_nor); } @@ -6113,7 +6113,7 @@ static bool dynamicPaint_generateBakeData(DynamicPaintSurface *surface, bData->mesh_bounds.valid = false; for (index = 0; index < canvasNumOfVerts; index++) { copy_v3_v3(canvas_verts[index].v, mvert[index].co); - mul_m4_v3(ob->obmat, canvas_verts[index].v); + mul_m4_v3(ob->object_to_world, canvas_verts[index].v); boundInsert(&bData->mesh_bounds, canvas_verts[index].v); } @@ -6143,7 +6143,7 @@ static bool dynamicPaint_generateBakeData(DynamicPaintSurface *surface, dynamicPaint_prepareAdjacencyData(surface, false); /* Copy current frame vertices to check against in next frame */ - copy_m4_m4(bData->prev_obmat, ob->obmat); + copy_m4_m4(bData->prev_obmat, ob->object_to_world); memcpy(bData->prev_verts, mvert, canvasNumOfVerts * sizeof(MVert)); bData->clear = 0; diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 42b38854248..983e4b3c6e6 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -154,8 +154,8 @@ static void precalculate_effector(struct Depsgraph *depsgraph, EffectorCache *ef if (eff->ob->runtime.curve_cache->anim_path_accum_length) { BKE_where_on_path( eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL); - mul_m4_v3(eff->ob->obmat, eff->guide_loc); - mul_mat3_m4_v3(eff->ob->obmat, eff->guide_dir); + mul_m4_v3(eff->ob->object_to_world, eff->guide_loc); + mul_mat3_m4_v3(eff->ob->object_to_world, eff->guide_dir); } } } @@ -707,8 +707,8 @@ bool get_effector_data(EffectorCache *eff, copy_v3_v3(efd->loc, verts[*efd->index].co); copy_v3_v3(efd->nor, vert_normals[*efd->index]); - mul_m4_v3(eff->ob->obmat, efd->loc); - mul_mat3_m4_v3(eff->ob->obmat, efd->nor); + mul_m4_v3(eff->ob->object_to_world, efd->loc); + mul_mat3_m4_v3(eff->ob->object_to_world, efd->nor); normalize_v3(efd->nor); @@ -760,23 +760,23 @@ bool get_effector_data(EffectorCache *eff, const Object *ob = eff->ob; /* Use z-axis as normal. */ - normalize_v3_v3(efd->nor, ob->obmat[2]); + normalize_v3_v3(efd->nor, ob->object_to_world[2]); if (eff->pd && ELEM(eff->pd->shape, PFIELD_SHAPE_PLANE, PFIELD_SHAPE_LINE)) { float temp[3], translate[3]; - sub_v3_v3v3(temp, point->loc, ob->obmat[3]); + sub_v3_v3v3(temp, point->loc, ob->object_to_world[3]); project_v3_v3v3(translate, temp, efd->nor); /* for vortex the shape chooses between old / new force */ if (eff->pd->forcefield == PFIELD_VORTEX || eff->pd->shape == PFIELD_SHAPE_LINE) { - add_v3_v3v3(efd->loc, ob->obmat[3], translate); + add_v3_v3v3(efd->loc, ob->object_to_world[3], translate); } else { /* normally efd->loc is closest point on effector xy-plane */ sub_v3_v3v3(efd->loc, point->loc, translate); } } else { - copy_v3_v3(efd->loc, ob->obmat[3]); + copy_v3_v3(efd->loc, ob->object_to_world[3]); } zero_v3(efd->vel); @@ -801,8 +801,8 @@ bool get_effector_data(EffectorCache *eff, } else { /* for some effectors we need the object center every time */ - sub_v3_v3v3(efd->vec_to_point2, point->loc, eff->ob->obmat[3]); - normalize_v3_v3(efd->nor2, eff->ob->obmat[2]); + sub_v3_v3v3(efd->vec_to_point2, point->loc, eff->ob->object_to_world[3]); + normalize_v3_v3(efd->nor2, eff->ob->object_to_world[2]); } } diff --git a/source/blender/blenkernel/intern/fcurve_driver.c b/source/blender/blenkernel/intern/fcurve_driver.c index 9f63e2d3743..3d1439b5530 100644 --- a/source/blender/blenkernel/intern/fcurve_driver.c +++ b/source/blender/blenkernel/intern/fcurve_driver.c @@ -321,7 +321,7 @@ static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar) } else { /* Object. */ - mat[i] = ob->obmat; + mat[i] = ob->object_to_world; } } @@ -399,7 +399,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar) else { /* Convert to world-space. */ copy_v3_v3(tmp_loc, pchan->pose_head); - mul_m4_v3(ob->obmat, tmp_loc); + mul_m4_v3(ob->object_to_world, tmp_loc); } } else { @@ -410,7 +410,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar) float mat[4][4]; /* Extract transform just like how the constraints do it! */ - copy_m4_m4(mat, ob->obmat); + copy_m4_m4(mat, ob->object_to_world); BKE_constraint_mat_convertspace( ob, NULL, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false); @@ -424,7 +424,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar) } else { /* World-space. */ - copy_v3_v3(tmp_loc, ob->obmat[3]); + copy_v3_v3(tmp_loc, ob->object_to_world[3]); } } @@ -500,7 +500,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) } else { /* World-space matrix. */ - mul_m4_m4m4(mat, ob->obmat, pchan->pose_mat); + mul_m4_m4m4(mat, ob->object_to_world, pchan->pose_mat); } } else { @@ -514,7 +514,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) if (dtar->flag & DTAR_FLAG_LOCALSPACE) { if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { /* Just like how the constraints do it! */ - copy_m4_m4(mat, ob->obmat); + copy_m4_m4(mat, ob->object_to_world); BKE_constraint_mat_convertspace( ob, NULL, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false); } @@ -525,7 +525,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) } else { /* World-space matrix - just the good-old one. */ - copy_m4_m4(mat, ob->obmat); + copy_m4_m4(mat, ob->object_to_world); } } diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 5470231cd07..b0e99e10acc 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -433,7 +433,7 @@ static void manta_set_domain_from_mesh(FluidDomainSettings *fds, copy_v3_v3(fds->global_size, size); copy_v3_v3(fds->dp0, min); - invert_m4_m4(fds->imat, ob->obmat); + invert_m4_m4(fds->imat, ob->object_to_world); /* Prevent crash when initializing a plane as domain. */ if (!init_resolution || (size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) || @@ -498,8 +498,8 @@ static bool fluid_modifier_init( zero_v3(fds->shift_f); add_v3_fl(fds->shift_f, 0.5f); zero_v3(fds->prev_loc); - mul_m4_v3(ob->obmat, fds->prev_loc); - copy_m4_m4(fds->obmat, ob->obmat); + mul_m4_v3(ob->object_to_world, fds->prev_loc); + copy_m4_m4(fds->obmat, ob->object_to_world); /* Set resolutions. */ if (fmd->domain->type == FLUID_DOMAIN_TYPE_GAS && @@ -566,11 +566,11 @@ static int get_light(Scene *scene, ViewLayer *view_layer, float *light) Light *la = base_tmp->object->data; if (la->type == LA_LOCAL) { - copy_v3_v3(light, base_tmp->object->obmat[3]); + copy_v3_v3(light, base_tmp->object->object_to_world[3]); return 1; } if (!found_light) { - copy_v3_v3(light, base_tmp->object->obmat[3]); + copy_v3_v3(light, base_tmp->object->object_to_world[3]); found_light = 1; } } @@ -1036,7 +1036,7 @@ static void obstacles_from_mesh(Object *coll_ob, float co[3]; /* Vertex position. */ - mul_m4_v3(coll_ob->obmat, verts[i].co); + mul_m4_v3(coll_ob->object_to_world, verts[i].co); manta_pos_to_cell(fds, verts[i].co); /* Vertex velocity. */ @@ -2099,11 +2099,11 @@ static void emit_from_mesh( float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(me); for (i = 0; i < numverts; i++) { /* Vertex position. */ - mul_m4_v3(flow_ob->obmat, verts[i].co); + mul_m4_v3(flow_ob->object_to_world, verts[i].co); manta_pos_to_cell(fds, verts[i].co); /* Vertex normal. */ - mul_mat3_m4_v3(flow_ob->obmat, vert_normals[i]); + mul_mat3_m4_v3(flow_ob->object_to_world, vert_normals[i]); mul_mat3_m4_v3(fds->imat, vert_normals[i]); normalize_v3(vert_normals[i]); @@ -2121,7 +2121,7 @@ static void emit_from_mesh( /* Calculate emission map bounds. */ bb_boundInsert(bb, verts[i].co); } - mul_m4_v3(flow_ob->obmat, flow_center); + mul_m4_v3(flow_ob->object_to_world, flow_center); manta_pos_to_cell(fds, flow_center); /* Set emission map. @@ -2191,7 +2191,7 @@ static void adaptive_domain_adjust( float frame_shift_f[3]; float ob_loc[3] = {0}; - mul_m4_v3(ob->obmat, ob_loc); + mul_m4_v3(ob->object_to_world, ob_loc); sub_v3_v3v3(frame_shift_f, ob_loc, fds->prev_loc); copy_v3_v3(fds->prev_loc, ob_loc); @@ -3495,8 +3495,8 @@ static Mesh *create_smoke_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obje /* Calculate required shift to match domain's global position * it was originally simulated at (if object moves without manta step). */ - invert_m4_m4(ob->imat, ob->obmat); - mul_m4_v3(ob->obmat, ob_loc); + invert_m4_m4(ob->imat, ob->object_to_world); + mul_m4_v3(ob->object_to_world, ob_loc); mul_m4_v3(fds->obmat, ob_cache_loc); sub_v3_v3v3(fds->obj_shift_f, ob_cache_loc, ob_loc); /* Convert shift to local space and apply to vertices. */ @@ -3525,8 +3525,8 @@ static int manta_step( bool mode_replay = (mode == FLUID_DOMAIN_CACHE_REPLAY); /* Update object state. */ - invert_m4_m4(fds->imat, ob->obmat); - copy_m4_m4(fds->obmat, ob->obmat); + invert_m4_m4(fds->imat, ob->object_to_world); + copy_m4_m4(fds->obmat, ob->object_to_world); /* Gas domain might use adaptive domain. */ if (fds->type == FLUID_DOMAIN_TYPE_GAS) { diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc index e078991187d..2b36020b4e7 100644 --- a/source/blender/blenkernel/intern/geometry_set_instances.cc +++ b/source/blender/blenkernel/intern/geometry_set_instances.cc @@ -98,7 +98,7 @@ static void geometry_set_collect_recursive_collection(const Collection &collecti LISTBASE_FOREACH (const CollectionObject *, collection_object, &collection.gobject) { BLI_assert(collection_object->ob != nullptr); const Object &object = *collection_object->ob; - const float4x4 object_transform = transform * object.obmat; + const float4x4 object_transform = transform * object.object_to_world; geometry_set_collect_recursive_object(object, object_transform, r_sets); } LISTBASE_FOREACH (const CollectionChild *, collection_child, &collection.children) { @@ -220,7 +220,7 @@ void Instances::ensure_geometry_instances() Collection &collection = reference.collection(); FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (&collection, object) { const int handle = instances->add_reference(*object); - instances->add_instance(handle, object->obmat); + instances->add_instance(handle, object->object_to_world); float4x4 &transform = instances->transforms().last(); sub_v3_v3(transform.values[3], collection.instance_offset); } diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 45e56717d6a..666142e3a54 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -2691,7 +2691,7 @@ void BKE_gpencil_layer_transform_matrix_get(const Depsgraph *depsgraph, /* if not layer parented, try with object parented */ if (obparent_eval == NULL) { if ((ob_eval != NULL) && (ob_eval->type == OB_GPENCIL)) { - copy_m4_m4(diff_mat, ob_eval->obmat); + copy_m4_m4(diff_mat, ob_eval->object_to_world); mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat); return; } @@ -2701,8 +2701,8 @@ void BKE_gpencil_layer_transform_matrix_get(const Depsgraph *depsgraph, } if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { - mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse); - add_v3_v3(diff_mat[3], ob_eval->obmat[3]); + mul_m4_m4m4(diff_mat, obparent_eval->object_to_world, gpl->inverse); + add_v3_v3(diff_mat[3], ob_eval->object_to_world[3]); mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat); return; } @@ -2710,14 +2710,14 @@ void BKE_gpencil_layer_transform_matrix_get(const Depsgraph *depsgraph, bPoseChannel *pchan = BKE_pose_channel_find_name(obparent_eval->pose, gpl->parsubstr); if (pchan) { float tmp_mat[4][4]; - mul_m4_m4m4(tmp_mat, obparent_eval->obmat, pchan->pose_mat); + mul_m4_m4m4(tmp_mat, obparent_eval->object_to_world, pchan->pose_mat); mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse); - add_v3_v3(diff_mat[3], ob_eval->obmat[3]); + add_v3_v3(diff_mat[3], ob_eval->object_to_world[3]); } else { /* if bone not found use object (armature) */ - mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse); - add_v3_v3(diff_mat[3], ob_eval->obmat[3]); + mul_m4_m4m4(diff_mat, obparent_eval->object_to_world, gpl->inverse); + add_v3_v3(diff_mat[3], ob_eval->object_to_world[3]); } mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat); return; @@ -2771,12 +2771,12 @@ void BKE_gpencil_update_layer_transforms(const Depsgraph *depsgraph, Object *ob) Object *ob_parent = DEG_get_evaluated_object(depsgraph, gpl->parent); /* calculate new matrix */ if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { - mul_m4_m4m4(cur_mat, ob->imat, ob_parent->obmat); + mul_m4_m4m4(cur_mat, ob->imat, ob_parent->object_to_world); } else if (gpl->partype == PARBONE) { bPoseChannel *pchan = BKE_pose_channel_find_name(ob_parent->pose, gpl->parsubstr); if (pchan != NULL) { - mul_m4_series(cur_mat, ob->imat, ob_parent->obmat, pchan->pose_mat); + mul_m4_series(cur_mat, ob->imat, ob_parent->object_to_world, pchan->pose_mat); } else { unit_m4(cur_mat); diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index f6a409ee3f0..0adf162b4eb 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -355,10 +355,10 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb) BKE_displist_free(<Ob->runtime.curve_cache->disp); } - copy_m4_m4(mat, ltOb->obmat); - unit_m4(ltOb->obmat); + copy_m4_m4(mat, ltOb->object_to_world); + unit_m4(ltOb->object_to_world); BKE_lattice_deform_coords(ltOb, NULL, vert_coords, uNew * vNew * wNew, 0, NULL, 1.0f); - copy_m4_m4(ltOb->obmat, mat); + copy_m4_m4(ltOb->object_to_world, mat); lt->typeu = typeu; lt->typev = typev; diff --git a/source/blender/blenkernel/intern/lattice_deform.c b/source/blender/blenkernel/intern/lattice_deform.c index 3a1c42b9178..892889aa426 100644 --- a/source/blender/blenkernel/intern/lattice_deform.c +++ b/source/blender/blenkernel/intern/lattice_deform.c @@ -79,15 +79,15 @@ LatticeDeformData *BKE_lattice_deform_data_create(const Object *oblatt, const Ob /* for example with a particle system: (ob == NULL) */ if (ob == NULL) { /* In deform-space, calc matrix. */ - invert_m4_m4(latmat, oblatt->obmat); + invert_m4_m4(latmat, oblatt->object_to_world); /* back: put in deform array */ invert_m4_m4(imat, latmat); } else { /* In deform-space, calc matrix. */ - invert_m4_m4(imat, oblatt->obmat); - mul_m4_m4m4(latmat, imat, ob->obmat); + invert_m4_m4(imat, oblatt->object_to_world); + mul_m4_m4m4(latmat, imat, ob->object_to_world); /* back: put in deform array. */ invert_m4_m4(imat, latmat); diff --git a/source/blender/blenkernel/intern/mball_tessellate.cc b/source/blender/blenkernel/intern/mball_tessellate.cc index bb3713e770a..f8a64a7cd8b 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.cc +++ b/source/blender/blenkernel/intern/mball_tessellate.cc @@ -1188,8 +1188,9 @@ static void init_meta(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Obje const eEvaluationMode deg_eval_mode = DEG_get_mode(depsgraph); const short parenting_dupli_transflag = (OB_DUPLIFACES | OB_DUPLIVERTS); - copy_m4_m4(obmat, ob->obmat); /* to cope with duplicators from BKE_scene_base_iter_next */ - invert_m4_m4(obinv, ob->obmat); + copy_m4_m4(obmat, + ob->object_to_world); /* to cope with duplicators from BKE_scene_base_iter_next */ + invert_m4_m4(obinv, ob->object_to_world); BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); @@ -1237,13 +1238,13 @@ static void init_meta(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Obje /* when metaball object has zero scale, then MetaElem to this MetaBall * will not be put to mainb array */ - if (has_zero_axis_m4(bob->obmat)) { + if (has_zero_axis_m4(bob->object_to_world)) { zero_size = 1; } else if (bob->parent) { struct Object *pob = bob->parent; while (pob) { - if (has_zero_axis_m4(pob->obmat)) { + if (has_zero_axis_m4(pob->object_to_world)) { zero_size = 1; break; } @@ -1307,7 +1308,7 @@ static void init_meta(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Obje * rotation -> * ml local space */ - mul_m4_series((float(*)[4])new_ml->mat, obinv, bob->obmat, pos, rot); + mul_m4_series((float(*)[4])new_ml->mat, obinv, bob->object_to_world, pos, rot); /* ml local space -> basis object space */ invert_m4_m4((float(*)[4])new_ml->imat, (float(*)[4])new_ml->mat); diff --git a/source/blender/blenkernel/intern/mesh_mirror.c b/source/blender/blenkernel/intern/mesh_mirror.c index 261bc3d150b..ce3fc5d99c8 100644 --- a/source/blender/blenkernel/intern/mesh_mirror.c +++ b/source/blender/blenkernel/intern/mesh_mirror.c @@ -152,8 +152,8 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, /* tmp is a transform from coords relative to the object's own origin, * to coords relative to the mirror object origin */ - invert_m4_m4(tmp, mirror_ob->obmat); - mul_m4_m4m4(tmp, tmp, ob->obmat); + invert_m4_m4(tmp, mirror_ob->object_to_world); + mul_m4_m4m4(tmp, tmp, ob->object_to_world); /* itmp is the reverse transform back to origin-relative coordinates */ invert_m4_m4(itmp, tmp); @@ -169,9 +169,9 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, /* Account for non-uniform scale in `ob`, see: T87592. */ float ob_scale[3] = { - len_squared_v3(ob->obmat[0]), - len_squared_v3(ob->obmat[1]), - len_squared_v3(ob->obmat[2]), + len_squared_v3(ob->object_to_world[0]), + len_squared_v3(ob->object_to_world[1]), + len_squared_v3(ob->object_to_world[2]), }; /* Scale to avoid precision loss with extreme values. */ const float ob_scale_max = max_fff(UNPACK3(ob_scale)); diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc index d98f5e85028..53e6d47860f 100644 --- a/source/blender/blenkernel/intern/object.cc +++ b/source/blender/blenkernel/intern/object.cc @@ -1330,14 +1330,14 @@ void BKE_object_modifier_hook_reset(Object *ob, HookModifierData *hmd) /* Calculate the world-space matrix for the pose-channel target first, * then carry on as usual. */ - mul_m4_m4m4(mat, hmd->object->obmat, pchan->pose_mat); + mul_m4_m4m4(mat, hmd->object->object_to_world, pchan->pose_mat); invert_m4_m4(imat, mat); - mul_m4_m4m4(hmd->parentinv, imat, ob->obmat); + mul_m4_m4m4(hmd->parentinv, imat, ob->object_to_world); } else { - invert_m4_m4(hmd->object->imat, hmd->object->obmat); - mul_m4_m4m4(hmd->parentinv, hmd->object->imat, ob->obmat); + invert_m4_m4(hmd->object->imat, hmd->object->object_to_world); + mul_m4_m4m4(hmd->parentinv, hmd->object->imat, ob->object_to_world); } } } @@ -1355,14 +1355,14 @@ void BKE_object_modifier_gpencil_hook_reset(Object *ob, HookGpencilModifierData /* Calculate the world-space matrix for the pose-channel target first, * then carry on as usual. */ - mul_m4_m4m4(mat, hmd->object->obmat, pchan->pose_mat); + mul_m4_m4m4(mat, hmd->object->object_to_world, pchan->pose_mat); invert_m4_m4(imat, mat); - mul_m4_m4m4(hmd->parentinv, imat, ob->obmat); + mul_m4_m4m4(hmd->parentinv, imat, ob->object_to_world); } else { - invert_m4_m4(hmd->object->imat, hmd->object->obmat); - mul_m4_m4m4(hmd->parentinv, hmd->object->imat, ob->obmat); + invert_m4_m4(hmd->object->imat, hmd->object->object_to_world); + mul_m4_m4m4(hmd->parentinv, hmd->object->imat, ob->object_to_world); } } @@ -3102,10 +3102,10 @@ void BKE_object_matrix_local_get(struct Object *ob, float r_mat[4][4]) BKE_object_get_parent_matrix(ob, ob->parent, par_imat); invert_m4(par_imat); - mul_m4_m4m4(r_mat, par_imat, ob->obmat); + mul_m4_m4m4(r_mat, par_imat, ob->object_to_world); } else { - copy_m4_m4(r_mat, ob->obmat); + copy_m4_m4(r_mat, ob->object_to_world); } } @@ -3359,32 +3359,32 @@ void BKE_object_get_parent_matrix(Object *ob, Object *par, float r_parentmat[4][ } if (ok) { - mul_m4_m4m4(r_parentmat, par->obmat, tmat); + mul_m4_m4m4(r_parentmat, par->object_to_world, tmat); } else { - copy_m4_m4(r_parentmat, par->obmat); + copy_m4_m4(r_parentmat, par->object_to_world); } break; } case PARBONE: ob_parbone(ob, par, tmat); - mul_m4_m4m4(r_parentmat, par->obmat, tmat); + mul_m4_m4m4(r_parentmat, par->object_to_world, tmat); break; case PARVERT1: unit_m4(r_parentmat); give_parvert(par, ob->par1, vec); - mul_v3_m4v3(r_parentmat[3], par->obmat, vec); + mul_v3_m4v3(r_parentmat[3], par->object_to_world, vec); break; case PARVERT3: ob_parvert3(ob, par, tmat); - mul_m4_m4m4(r_parentmat, par->obmat, tmat); + mul_m4_m4m4(r_parentmat, par->object_to_world, tmat); break; case PARSKEL: - copy_m4_m4(r_parentmat, par->obmat); + copy_m4_m4(r_parentmat, par->object_to_world); break; } } @@ -3422,7 +3422,7 @@ static void solve_parenting( /* origin, for help line */ if (set_origin) { if ((ob->partype & PARTYPE) == PARSKEL) { - copy_v3_v3(ob->runtime.parent_display_origin, par->obmat[3]); + copy_v3_v3(ob->runtime.parent_display_origin, par->object_to_world[3]); } else { copy_v3_v3(ob->runtime.parent_display_origin, totmat[3]); @@ -3441,10 +3441,10 @@ static void object_where_is_calc_ex(Depsgraph *depsgraph, Object *par = ob->parent; /* calculate parent matrix */ - solve_parenting(ob, par, true, ob->obmat, r_originmat); + solve_parenting(ob, par, true, ob->object_to_world, r_originmat); } else { - BKE_object_to_mat4(ob, ob->obmat); + BKE_object_to_mat4(ob, ob->object_to_world); } /* try to fall back to the scene rigid body world if none given */ @@ -3461,7 +3461,7 @@ static void object_where_is_calc_ex(Depsgraph *depsgraph, } /* set negative scale flag in object */ - if (is_negative_m4(ob->obmat)) { + if (is_negative_m4(ob->object_to_world)) { ob->transflag |= OB_NEG_SCALE; } else { @@ -3507,7 +3507,7 @@ void BKE_object_workob_calc_parent(Depsgraph *depsgraph, Scene *scene, Object *o { BKE_object_workob_clear(workob); - unit_m4(workob->obmat); + unit_m4(workob->object_to_world); unit_m4(workob->parentinv); unit_m4(workob->constinv); @@ -3599,7 +3599,7 @@ void BKE_object_apply_parent_inverse(struct Object *ob) * `inv(parent) @ world = parentinv` * `parentinv = inv(parent) @ world` * - * NOTE: If `ob->obmat` has shear, then this `parentinv` is insufficient because + * NOTE: If `ob->object_to_world` has shear, then this `parentinv` is insufficient because * `parent @ parentinv => shearless result` * * Thus, local will have shear which cannot be decomposed into TRS: @@ -3628,7 +3628,7 @@ void BKE_object_apply_parent_inverse(struct Object *ob) copy_m4_m4(ob_local, ob->parentinv); invert_m4(ob_local); mul_m4_m4_post(ob_local, par_imat); - mul_m4_m4_post(ob_local, ob->obmat); + mul_m4_m4_post(ob_local, ob->object_to_world); /* Send use_compat=False so the rotation is predictable. */ BKE_object_apply_mat4(ob, ob_local, false, false); @@ -3793,7 +3793,7 @@ void BKE_object_dimensions_get(Object *ob, float r_vec[3]) const BoundBox *bb = BKE_object_boundbox_get(ob); if (bb) { float3 scale; - mat4_to_size(scale, ob->obmat); + mat4_to_size(scale, ob->object_to_world); r_vec[0] = fabsf(scale[0]) * (bb->vec[4][0] - bb->vec[0][0]); r_vec[1] = fabsf(scale[1]) * (bb->vec[2][1] - bb->vec[0][1]); @@ -3850,19 +3850,19 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us case OB_FONT: case OB_SURF: { const BoundBox bb = *BKE_curve_boundbox_get(ob); - BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max); + BKE_boundbox_minmax(&bb, ob->object_to_world, r_min, r_max); changed = true; break; } case OB_MESH: { const BoundBox bb = *BKE_mesh_boundbox_get(ob); - BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max); + BKE_boundbox_minmax(&bb, ob->object_to_world, r_min, r_max); changed = true; break; } case OB_GPENCIL: { const BoundBox bb = *BKE_gpencil_boundbox_get(ob); - BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max); + BKE_boundbox_minmax(&bb, ob->object_to_world, r_min, r_max); changed = true; break; } @@ -3875,7 +3875,7 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us for (v = 0; v < lt->pntsv; v++) { for (u = 0; u < lt->pntsu; u++, bp++) { float3 vec; - mul_v3_m4v3(vec, ob->obmat, bp->vec); + mul_v3_m4v3(vec, ob->object_to_world, bp->vec); minmax_v3v3_v3(r_min, r_max, vec); } } @@ -3890,7 +3890,8 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us case OB_MBALL: { float ob_min[3], ob_max[3]; - changed = BKE_mball_minmax_ex((const MetaBall *)ob->data, ob_min, ob_max, ob->obmat, 0); + changed = BKE_mball_minmax_ex( + (const MetaBall *)ob->data, ob_min, ob_max, ob->object_to_world, 0); if (changed) { minmax_v3v3_v3(r_min, r_max, ob_min); minmax_v3v3_v3(r_min, r_max, ob_max); @@ -3899,20 +3900,20 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us } case OB_CURVES: { const BoundBox bb = *BKE_curves_boundbox_get(ob); - BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max); + BKE_boundbox_minmax(&bb, ob->object_to_world, r_min, r_max); changed = true; break; } case OB_POINTCLOUD: { const BoundBox bb = *BKE_pointcloud_boundbox_get(ob); - BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max); + BKE_boundbox_minmax(&bb, ob->object_to_world, r_min, r_max); changed = true; break; } case OB_VOLUME: { const BoundBox bb = *BKE_volume_boundbox_get(ob); - BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max); + BKE_boundbox_minmax(&bb, ob->object_to_world, r_min, r_max); changed = true; break; } @@ -3926,14 +3927,14 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us size *= ob->empty_drawsize; } - minmax_v3v3_v3(r_min, r_max, ob->obmat[3]); + minmax_v3v3_v3(r_min, r_max, ob->object_to_world[3]); float3 vec; - copy_v3_v3(vec, ob->obmat[3]); + copy_v3_v3(vec, ob->object_to_world[3]); add_v3_v3(vec, size); minmax_v3v3_v3(r_min, r_max, vec); - copy_v3_v3(vec, ob->obmat[3]); + copy_v3_v3(vec, ob->object_to_world[3]); sub_v3_v3(vec, size); minmax_v3v3_v3(r_min, r_max, vec); } @@ -3980,12 +3981,12 @@ bool BKE_object_empty_image_data_is_visible_in_view3d(const Object *ob, const Re * however the issue with empty objects being visible when viewed from the side * is only noticeable in orthographic views. */ float3 view_dir; - sub_v3_v3v3(view_dir, rv3d->viewinv[3], ob->obmat[3]); - dot = dot_v3v3(ob->obmat[2], view_dir); + sub_v3_v3v3(view_dir, rv3d->viewinv[3], ob->object_to_world[3]); + dot = dot_v3v3(ob->object_to_world[2], view_dir); eps = 0.0f; } else { - dot = dot_v3v3(ob->obmat[2], rv3d->viewinv[2]); + dot = dot_v3v3(ob->object_to_world[2], rv3d->viewinv[2]); eps = 1e-5f; } if (visibility_flag & OB_EMPTY_IMAGE_HIDE_BACK) { @@ -4002,7 +4003,7 @@ bool BKE_object_empty_image_data_is_visible_in_view3d(const Object *ob, const Re if (visibility_flag & OB_EMPTY_IMAGE_HIDE_NON_AXIS_ALIGNED) { float3 proj, ob_z_axis; - normalize_v3_v3(ob_z_axis, ob->obmat[2]); + normalize_v3_v3(ob_z_axis, ob->object_to_world[2]); project_plane_v3_v3v3(proj, ob_z_axis, rv3d->viewinv[2]); const float proj_length_sq = len_squared_v3(proj); if (proj_length_sq > 1e-5f) { @@ -4194,7 +4195,7 @@ void BKE_scene_foreach_display_point(Depsgraph *depsgraph, DEG_ITER_OBJECT_FLAG_DUPLI; DEG_OBJECT_ITER_BEGIN (°_iter_settings, ob) { if ((ob->base_flag & BASE_SELECTED) != 0) { - BKE_object_foreach_display_point(ob, ob->obmat, func_cb, user_data); + BKE_object_foreach_display_point(ob, ob->object_to_world, func_cb, user_data); } } DEG_OBJECT_ITER_END; @@ -4237,7 +4238,7 @@ void *BKE_object_tfm_backup(Object *ob) copy_v3_v3(obtfm->drotAxis, ob->drotAxis); obtfm->rotAngle = ob->rotAngle; obtfm->drotAngle = ob->drotAngle; - copy_m4_m4(obtfm->obmat, ob->obmat); + copy_m4_m4(obtfm->obmat, ob->object_to_world); copy_m4_m4(obtfm->parentinv, ob->parentinv); copy_m4_m4(obtfm->constinv, ob->constinv); copy_m4_m4(obtfm->imat, ob->imat); @@ -4260,7 +4261,7 @@ void BKE_object_tfm_restore(Object *ob, void *obtfm_pt) copy_v3_v3(ob->drotAxis, obtfm->drotAxis); ob->rotAngle = obtfm->rotAngle; ob->drotAngle = obtfm->drotAngle; - copy_m4_m4(ob->obmat, obtfm->obmat); + copy_m4_m4(ob->object_to_world, obtfm->obmat); copy_m4_m4(ob->parentinv, obtfm->parentinv); copy_m4_m4(ob->constinv, obtfm->constinv); copy_m4_m4(ob->imat, obtfm->imat); @@ -5291,7 +5292,7 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot) for (i = 0; i < verts.size(); i++) { if (index[i] != ORIGINDEX_NONE) { float co[3]; - mul_v3_m4v3(co, ob->obmat, verts[i].co); + mul_v3_m4v3(co, ob->object_to_world, verts[i].co); BLI_kdtree_3d_insert(tree, index[i], co); tot++; } @@ -5305,7 +5306,7 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot) for (i = 0; i < tot; i++) { float co[3]; - mul_v3_m4v3(co, ob->obmat, verts[i].co); + mul_v3_m4v3(co, ob->object_to_world, verts[i].co); BLI_kdtree_3d_insert(tree, i, co); } } @@ -5334,7 +5335,7 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot) a = nu->pntsu; while (a--) { float co[3]; - mul_v3_m4v3(co, ob->obmat, bezt->vec[1]); + mul_v3_m4v3(co, ob->object_to_world, bezt->vec[1]); BLI_kdtree_3d_insert(tree, i++, co); bezt++; } @@ -5346,7 +5347,7 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot) a = nu->pntsu * nu->pntsv; while (a--) { float co[3]; - mul_v3_m4v3(co, ob->obmat, bp->vec); + mul_v3_m4v3(co, ob->object_to_world, bp->vec); BLI_kdtree_3d_insert(tree, i++, co); bp++; } @@ -5369,7 +5370,7 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot) for (bp = lt->def; i < tot; bp++) { float co[3]; - mul_v3_m4v3(co, ob->obmat, bp->vec); + mul_v3_m4v3(co, ob->object_to_world, bp->vec); BLI_kdtree_3d_insert(tree, i++, co); } diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index d43eff6f9b4..d029d307d6e 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -197,7 +197,8 @@ static bool copy_dupli_context(DupliContext *r_ctx, /** * Generate a dupli instance. * - * \param mat: is transform of the object relative to current context (including #Object.obmat). + * \param mat: is transform of the object relative to current context (including + * #Object.object_to_world). */ static DupliObject *make_dupli(const DupliContext *ctx, Object *ob, @@ -296,7 +297,7 @@ static DupliObject *make_dupli(const DupliContext *ctx, /** * Recursive dupli-objects. * - * \param space_mat: is the local dupli-space (excluding dupli #Object.obmat). + * \param space_mat: is the local dupli-space (excluding dupli #Object.object_to_world). */ static void make_recursive_duplis(const DupliContext *ctx, Object *ob, @@ -468,8 +469,8 @@ static void make_duplis_collection(const DupliContext *ctx) /* Combine collection offset and `obmat`. */ unit_m4(collection_mat); sub_v3_v3(collection_mat[3], collection->instance_offset); - mul_m4_m4m4(collection_mat, ob->obmat, collection_mat); - /* Don't access 'ob->obmat' from now on. */ + mul_m4_m4m4(collection_mat, ob->object_to_world, collection_mat); + /* Don't access 'ob->object_to_world' from now on. */ eEvaluationMode mode = DEG_get_mode(ctx->depsgraph); FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (collection, cob, mode) { @@ -477,7 +478,7 @@ static void make_duplis_collection(const DupliContext *ctx) float mat[4][4]; /* Collection dupli-offset, should apply after everything else. */ - mul_m4_m4m4(mat, collection_mat, cob->obmat); + mul_m4_m4m4(mat, collection_mat, cob->object_to_world); make_dupli(ctx, cob, mat, _base_id); @@ -584,7 +585,7 @@ static DupliObject *vertex_dupli(const DupliContext *ctx, /* Make offset relative to inst_ob using relative child transform. */ mul_mat3_m4_v3(child_imat, obmat[3]); /* Apply `obmat` _after_ the local vertex transform. */ - mul_m4_m4m4(obmat, inst_ob->obmat, obmat); + mul_m4_m4m4(obmat, inst_ob->object_to_world, obmat); /* Space matrix is constructed by removing `obmat` transform, * this yields the world-space transform for recursive duplis. */ @@ -608,10 +609,10 @@ static void make_child_duplis_verts_from_mesh(const DupliContext *ctx, const MVert *mvert = vdd->mvert; const int totvert = vdd->totvert; - invert_m4_m4(inst_ob->imat, inst_ob->obmat); + invert_m4_m4(inst_ob->imat, inst_ob->object_to_world); /* Relative transform from parent to child space. */ float child_imat[4][4]; - mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->obmat); + mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->object_to_world); for (int i = 0; i < totvert; i++) { DupliObject *dob = vertex_dupli( @@ -630,10 +631,10 @@ static void make_child_duplis_verts_from_editmesh(const DupliContext *ctx, BMEditMesh *em = vdd->em; const bool use_rotation = vdd->params.use_rotation; - invert_m4_m4(inst_ob->imat, inst_ob->obmat); + invert_m4_m4(inst_ob->imat, inst_ob->object_to_world); /* Relative transform from parent to child space. */ float child_imat[4][4]; - mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->obmat); + mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->object_to_world); BMVert *v; BMIter iter; @@ -758,7 +759,7 @@ static void make_duplis_font(const DupliContext *ctx) return; } - copy_m4_m4(pmat, par->obmat); + copy_m4_m4(pmat, par->object_to_world); /* In `par` the family name is stored, use this to find the other objects. */ @@ -803,7 +804,7 @@ static void make_duplis_font(const DupliContext *ctx) mul_m4_v3(pmat, vec); - copy_m4_m4(obmat, par->obmat); + copy_m4_m4(obmat, par->object_to_world); if (UNLIKELY(ct->rot != 0.0f)) { float rmat[4][4]; @@ -951,7 +952,7 @@ static void make_duplis_geometry_set_impl(const DupliContext *ctx, } float instance_matrix[4][4]; - mul_m4_m4m4(instance_matrix, collection_matrix, object->obmat); + mul_m4_m4m4(instance_matrix, collection_matrix, object->object_to_world); make_dupli(&sub_ctx, object, instance_matrix, object_id++); make_recursive_duplis(&sub_ctx, object, collection_matrix, object_id++); @@ -986,7 +987,7 @@ static void make_duplis_geometry_set_impl(const DupliContext *ctx, static void make_duplis_geometry_set(const DupliContext *ctx) { const GeometrySet *geometry_set = ctx->object->runtime.geometry_set_eval; - make_duplis_geometry_set_impl(ctx, *geometry_set, ctx->object->obmat, false, false); + make_duplis_geometry_set_impl(ctx, *geometry_set, ctx->object->object_to_world, false, false); } static const DupliGenerator gen_dupli_geometry_set = { @@ -1092,7 +1093,7 @@ static DupliObject *face_dupli(const DupliContext *ctx, } /* Apply `obmat` _after_ the local face transform. */ - mul_m4_m4m4(obmat, inst_ob->obmat, obmat); + mul_m4_m4m4(obmat, inst_ob->object_to_world, obmat); /* Space matrix is constructed by removing `obmat` transform, * this yields the world-space transform for recursive duplis. */ @@ -1176,9 +1177,9 @@ static void make_child_duplis_faces_from_mesh(const DupliContext *ctx, float child_imat[4][4]; - invert_m4_m4(inst_ob->imat, inst_ob->obmat); + invert_m4_m4(inst_ob->imat, inst_ob->object_to_world); /* Relative transform from parent to child space. */ - mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->obmat); + mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->object_to_world); const float scale_fac = ctx->object->instance_faces_scale; for (a = 0, mp = mpoly; a < totface; a++, mp++) { @@ -1216,9 +1217,9 @@ static void make_child_duplis_faces_from_editmesh(const DupliContext *ctx, BLI_assert((vert_coords == nullptr) || (em->bm->elem_index_dirty & BM_VERT) == 0); - invert_m4_m4(inst_ob->imat, inst_ob->obmat); + invert_m4_m4(inst_ob->imat, inst_ob->object_to_world); /* Relative transform from parent to child space. */ - mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->obmat); + mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->object_to_world); const float scale_fac = ctx->object->instance_faces_scale; BM_ITER_MESH_INDEX (f, &iter, em->bm, BM_FACES_OF_MESH, a) { @@ -1348,7 +1349,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem sim.psys = psys; sim.psmd = psys_get_modifier(par, psys); /* Make sure emitter `imat` is in global coordinates instead of render view coordinates. */ - invert_m4_m4(par->imat, par->obmat); + invert_m4_m4(par->imat, par->object_to_world); /* First check for loops (particle system object used as dupli-object). */ if (part->ren_as == PART_DRAW_OB) { @@ -1535,7 +1536,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem b = 0; FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN ( part->instance_collection, object, mode) { - copy_m4_m4(tmat, oblist[b]->obmat); + copy_m4_m4(tmat, oblist[b]->object_to_world); /* Apply collection instance offset. */ sub_v3_v3(tmat[3], part->instance_collection->instance_offset); @@ -1558,7 +1559,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem } else { float obmat[4][4]; - copy_m4_m4(obmat, ob->obmat); + copy_m4_m4(obmat, ob->object_to_world); float vec[3]; copy_v3_v3(vec, obmat[3]); @@ -1752,7 +1753,7 @@ ListBase *object_duplilist_preview(Depsgraph *depsgraph, *viewer_path)) { ctx.preview_base_geometry = &viewer_log->geometry; make_duplis_geometry_set_impl( - &ctx, viewer_log->geometry, ob_eval->obmat, true, ob_eval->type == OB_CURVES); + &ctx, viewer_log->geometry, ob_eval->object_to_world, true, ob_eval->type == OB_CURVES); } } return duplilist; diff --git a/source/blender/blenkernel/intern/object_update.cc b/source/blender/blenkernel/intern/object_update.cc index e53090bcffe..7ea13bfcc84 100644 --- a/source/blender/blenkernel/intern/object_update.cc +++ b/source/blender/blenkernel/intern/object_update.cc @@ -61,7 +61,7 @@ void BKE_object_eval_local_transform(Depsgraph *depsgraph, Object *ob) DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob); /* calculate local matrix */ - BKE_object_to_mat4(ob, ob->obmat); + BKE_object_to_mat4(ob, ob->object_to_world); } void BKE_object_eval_parent(Depsgraph *depsgraph, Object *ob) @@ -78,18 +78,18 @@ void BKE_object_eval_parent(Depsgraph *depsgraph, Object *ob) /* get local matrix (but don't calculate it, as that was done already!) */ /* XXX: redundant? */ - copy_m4_m4(locmat, ob->obmat); + copy_m4_m4(locmat, ob->object_to_world); /* get parent effect matrix */ BKE_object_get_parent_matrix(ob, par, totmat); /* total */ mul_m4_m4m4(tmat, totmat, ob->parentinv); - mul_m4_m4m4(ob->obmat, tmat, locmat); + mul_m4_m4m4(ob->object_to_world, tmat, locmat); /* origin, for help line */ if ((ob->partype & PARTYPE) == PARSKEL) { - copy_v3_v3(ob->runtime.parent_display_origin, par->obmat[3]); + copy_v3_v3(ob->runtime.parent_display_origin, par->object_to_world[3]); } else { copy_v3_v3(ob->runtime.parent_display_origin, totmat[3]); @@ -121,9 +121,9 @@ void BKE_object_eval_transform_final(Depsgraph *depsgraph, Object *ob) DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob); /* Make sure inverse matrix is always up to date. This way users of it * do not need to worry about recalculating it. */ - invert_m4_m4_safe(ob->imat, ob->obmat); + invert_m4_m4_safe(ob->imat, ob->object_to_world); /* Set negative scale flag in object. */ - if (is_negative_m4(ob->obmat)) { + if (is_negative_m4(ob->object_to_world)) { ob->transflag |= OB_NEG_SCALE; } else { @@ -257,7 +257,7 @@ void BKE_object_sync_to_original(Depsgraph *depsgraph, Object *object) /* Base flags. */ object_orig->base_flag = object->base_flag; /* Transformation flags. */ - copy_m4_m4(object_orig->obmat, object->obmat); + copy_m4_m4(object_orig->object_to_world, object->object_to_world); copy_m4_m4(object_orig->imat, object->imat); copy_m4_m4(object_orig->constinv, object->constinv); object_orig->transflag = object->transflag; diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index 965cd153d00..a39e53662aa 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -1201,7 +1201,7 @@ void BKE_paint_stroke_get_average(Scene *scene, Object *ob, float stroke[3]) mul_v3_v3fl(stroke, ups->average_stroke_accum, fac); } else { - copy_v3_v3(stroke, ob->obmat[3]); + copy_v3_v3(stroke, ob->object_to_world[3]); } } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index d6dd3cf0dbb..f111e2dde17 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -2370,8 +2370,8 @@ void precalc_guides(ParticleSimulationData *sim, ListBase *effectors) 0, 0); - mul_m4_v3(sim->ob->obmat, state.co); - mul_mat3_m4_v3(sim->ob->obmat, state.vel); + mul_m4_v3(sim->ob->object_to_world, state.co); + mul_mat3_m4_v3(sim->ob->object_to_world, state.vel); pd_point_from_particle(sim, pa, &state, &point); @@ -2454,8 +2454,8 @@ bool do_guides(Depsgraph *depsgraph, } } - mul_m4_v3(eff->ob->obmat, guidevec); - mul_mat3_m4_v3(eff->ob->obmat, guidedir); + mul_m4_v3(eff->ob->object_to_world, guidevec); + mul_mat3_m4_v3(eff->ob->object_to_world, guidedir); normalize_v3(guidedir); @@ -2956,7 +2956,7 @@ static void psys_thread_create_path(ParticleTask *task, psys_particle_on_emitter( ctx->sim.psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa->fuv, foffset, co, 0, 0, 0, orco); - mul_m4_v3(ob->obmat, co); + mul_m4_v3(ob->object_to_world, co); for (w = 0; w < 4; w++) { sub_v3_v3v3(off1[w], co, key[w]->co); @@ -3419,7 +3419,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re /* dynamic hair is in object space */ /* keyed and baked are already in global space */ if (hair_mesh) { - mul_m4_v3(sim->ob->obmat, ca->co); + mul_m4_v3(sim->ob->object_to_world, ca->co); } else if (!keyed && !baked && !(psys->flag & PSYS_GLOBAL_HAIR)) { mul_m4_v3(hairmat, ca->co); @@ -3929,7 +3929,7 @@ void psys_mat_hair_to_global( psys_mat_hair_to_object(ob, mesh, from, pa, facemat); - mul_m4_m4m4(hairmat, ob->obmat, facemat); + mul_m4_m4m4(hairmat, ob->object_to_world, facemat); } /************************************************/ @@ -4661,8 +4661,8 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, do_particle_interpolation(psys, p, pa, t, &pind, state); if (pind.mesh) { - mul_m4_v3(sim->ob->obmat, state->co); - mul_mat3_m4_v3(sim->ob->obmat, state->vel); + mul_m4_v3(sim->ob->object_to_world, state->co); + mul_mat3_m4_v3(sim->ob->object_to_world, state->vel); } else if (!keyed && !cached && !(psys->flag & PSYS_GLOBAL_HAIR)) { if ((pa->flag & PARS_REKEY) == 0) { @@ -4685,7 +4685,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, } } else if (totchild) { - // invert_m4_m4(imat, ob->obmat); + // invert_m4_m4(imat, ob->object_to_world); /* interpolate childcache directly if it exists */ if (psys->childcache) { @@ -4733,7 +4733,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, * positioning it accurately to the surface of the emitter. */ // copy_v3_v3(cpa_1st, co); - // mul_m4_v3(ob->obmat, cpa_1st); + // mul_m4_v3(ob->object_to_world, cpa_1st); pa = psys->particles + cpa->parent; diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c index a890812cfc4..6cc7dbc70d0 100644 --- a/source/blender/blenkernel/intern/particle_child.c +++ b/source/blender/blenkernel/intern/particle_child.c @@ -187,7 +187,7 @@ static void do_kink_spiral(ParticleThreadContext *ctx, zero_v3(kink_base); kink_base[part->kink_axis] = 1.0f; - mul_mat3_m4_v3(ctx->sim.ob->obmat, kink_base); + mul_mat3_m4_v3(ctx->sim.ob->object_to_world, kink_base); /* Fill in invariant part of modifier context. */ ParticleChildModifierContext modifier_ctx = {NULL}; @@ -873,7 +873,7 @@ void do_child_modifiers(const ParticleChildModifierContext *modifier_ctx, part->kink_flat, part->kink, part->kink_axis, - sim->ob->obmat, + sim->ob->object_to_world, smooth_start); } } diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index c72bbe2fd08..72733349087 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -750,10 +750,10 @@ void psys_get_birth_coords( /* particles live in global space so */ /* let's convert: */ /* -location */ - mul_m4_v3(ob->obmat, loc); + mul_m4_v3(ob->object_to_world, loc); /* -normal */ - mul_mat3_m4_v3(ob->obmat, nor); + mul_mat3_m4_v3(ob->object_to_world, nor); normalize_v3(nor); /* -tangent */ @@ -771,7 +771,7 @@ void psys_get_birth_coords( fac = -sinf((float)M_PI * (part->tanphase + phase)); madd_v3_v3fl(vtan, utan, fac); - mul_mat3_m4_v3(ob->obmat, vtan); + mul_mat3_m4_v3(ob->object_to_world, vtan); copy_v3_v3(utan, nor); mul_v3_fl(utan, dot_v3v3(vtan, nor)); @@ -786,7 +786,7 @@ void psys_get_birth_coords( r_vel[1] = 2.0f * (psys_frand(psys, p + 11) - 0.5f); r_vel[2] = 2.0f * (psys_frand(psys, p + 12) - 0.5f); - mul_mat3_m4_v3(ob->obmat, r_vel); + mul_mat3_m4_v3(ob->object_to_world, r_vel); normalize_v3(r_vel); } @@ -796,7 +796,7 @@ void psys_get_birth_coords( r_ave[1] = 2.0f * (psys_frand(psys, p + 14) - 0.5f); r_ave[2] = 2.0f * (psys_frand(psys, p + 15) - 0.5f); - mul_mat3_m4_v3(ob->obmat, r_ave); + mul_mat3_m4_v3(ob->object_to_world, r_ave); normalize_v3(r_ave); } @@ -808,7 +808,7 @@ void psys_get_birth_coords( r_rot[3] = 2.0f * (psys_frand(psys, p + 19) - 0.5f); normalize_qt(r_rot); - mat4_to_quat(rot, ob->obmat); + mat4_to_quat(rot, ob->object_to_world); mul_qt_qtqt(r_rot, r_rot, rot); } @@ -822,7 +822,7 @@ void psys_get_birth_coords( /* boids store direction in ave */ if (fabsf(nor[2]) == 1.0f) { - sub_v3_v3v3(state->ave, loc, ob->obmat[3]); + sub_v3_v3v3(state->ave, loc, ob->object_to_world[3]); normalize_v3(state->ave); } else { @@ -868,15 +868,15 @@ void psys_get_birth_coords( /* *emitter object orientation */ if (part->ob_vel[0] != 0.0f) { - normalize_v3_v3(vec, ob->obmat[0]); + normalize_v3_v3(vec, ob->object_to_world[0]); madd_v3_v3fl(vel, vec, part->ob_vel[0]); } if (part->ob_vel[1] != 0.0f) { - normalize_v3_v3(vec, ob->obmat[1]); + normalize_v3_v3(vec, ob->object_to_world[1]); madd_v3_v3fl(vel, vec, part->ob_vel[1]); } if (part->ob_vel[2] != 0.0f) { - normalize_v3_v3(vec, ob->obmat[2]); + normalize_v3_v3(vec, ob->object_to_world[2]); madd_v3_v3fl(vel, vec, part->ob_vel[2]); } @@ -924,7 +924,7 @@ void psys_get_birth_coords( case PART_ROT_OB_X: case PART_ROT_OB_Y: case PART_ROT_OB_Z: - copy_v3_v3(rot_vec, ob->obmat[part->rotmode - PART_ROT_OB_X]); + copy_v3_v3(rot_vec, ob->object_to_world[part->rotmode - PART_ROT_OB_X]); use_global_space = false; break; default: @@ -951,7 +951,7 @@ void psys_get_birth_coords( float q_obmat[4]; float q_imat[4]; - mat4_to_quat(q_obmat, ob->obmat); + mat4_to_quat(q_obmat, ob->object_to_world); invert_qt_qt_normalized(q_imat, q_obmat); if (part->rotmode != PART_ROT_NOR_TAN) { @@ -3364,7 +3364,7 @@ static void hair_create_input_mesh(ParticleSimulationData *sim, use_hair = psys_hair_use_simulation(pa, max_length); psys_mat_hair_to_object(sim->ob, sim->psmd->mesh_final, psys->part->from, pa, hairmat); - mul_m4_m4m4(root_mat, sim->ob->obmat, hairmat); + mul_m4_m4m4(root_mat, sim->ob->object_to_world, hairmat); normalize_m4(root_mat); bending_stiffness = CLAMPIS( @@ -3555,7 +3555,7 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra)) HairKey *key, *root; PARTICLE_P; - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); psys->lattice_deform_data = psys_create_lattice_deform_data(sim); @@ -4380,7 +4380,7 @@ static void particles_fluid_step(ParticleSimulationData *sim, mul_v3_v3(pa->state.co, scaleAbs); /* Match domain scale. */ - mul_m4_v3(ob->obmat, pa->state.co); + mul_m4_v3(ob->object_to_world, pa->state.co); /* Add origin offset to particle position. */ zero_v3(tmp); @@ -4963,7 +4963,7 @@ void particle_system_update(struct Depsgraph *depsgraph, /* Save matrix for duplicators, * at render-time the actual dupli-object's matrix is used so don't update! */ - invert_m4_m4(psys->imat, ob->obmat); + invert_m4_m4(psys->imat, ob->object_to_world); BKE_particle_batch_cache_dirty_tag(psys, BKE_PARTICLE_BATCH_DIRTY_ALL); } diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index ffc6bc8d7a3..a67bb8568c3 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -684,7 +684,7 @@ void BKE_rigidbody_calc_volume(Object *ob, float *r_vol) if (totvert > 0 && tottri > 0) { BKE_mesh_calc_volume(mvert, totvert, lt, tottri, mloop, &volume, NULL); - const float volume_scale = mat4_to_volume_scale(ob->obmat); + const float volume_scale = mat4_to_volume_scale(ob->object_to_world); volume *= fabsf(volume_scale); } } @@ -809,7 +809,7 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool return; } - mat4_to_loc_quat(loc, rot, ob->obmat); + mat4_to_loc_quat(loc, rot, ob->object_to_world); rbo->shared->physics_object = RB_body_new(rbo->shared->physics_shape, loc, rot); @@ -974,7 +974,7 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b rbc->physics_constraint = NULL; } - mat4_to_loc_quat(loc, rot, ob->obmat); + mat4_to_loc_quat(loc, rot, ob->object_to_world); if (rb1 && rb2) { switch (rbc->type) { @@ -1266,7 +1266,7 @@ RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type) rbo->mesh_source = RBO_MESH_DEFORM; /* set initial transform */ - mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat); + mat4_to_loc_quat(rbo->pos, rbo->orn, ob->object_to_world); /* flag cache as outdated */ BKE_rigidbody_cache_reset(rbw); @@ -1689,7 +1689,7 @@ static void rigidbody_update_sim_ob(Depsgraph *depsgraph, Object *ob, RigidBodyO if (!(rbo->flag & RBO_FLAG_KINEMATIC)) { /* update scale for all non kinematic objects */ float new_scale[3], old_scale[3]; - mat4_to_size(new_scale, ob->obmat); + mat4_to_size(new_scale, ob->object_to_world); RB_body_get_scale(rbo->shared->physics_object, old_scale); /* Avoid updating collision shape AABBs if scale didn't change. */ @@ -1886,7 +1886,7 @@ static ListBase rigidbody_create_substep_data(RigidBodyWorld *rbw) copy_v4_v4(data->old_rot, rot); copy_v3_v3(data->old_scale, scale); - mat4_decompose(loc, rot, scale, ob->obmat); + mat4_decompose(loc, rot, scale, ob->object_to_world); copy_v3_v3(data->new_pos, loc); copy_v4_v4(data->new_rot, rot); @@ -2055,15 +2055,15 @@ void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime) quat_to_mat4(mat, rbo->orn); copy_v3_v3(mat[3], rbo->pos); - mat4_to_size(size, ob->obmat); + mat4_to_size(size, ob->object_to_world); size_to_mat4(size_mat, size); mul_m4_m4m4(mat, mat, size_mat); - copy_m4_m4(ob->obmat, mat); + copy_m4_m4(ob->object_to_world, mat); } /* otherwise set rigid body transform to current obmat */ else { - mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat); + mat4_to_loc_quat(rbo->pos, rbo->orn, ob->object_to_world); } } diff --git a/source/blender/blenkernel/intern/scene.cc b/source/blender/blenkernel/intern/scene.cc index bd26075f81f..c921cf603de 100644 --- a/source/blender/blenkernel/intern/scene.cc +++ b/source/blender/blenkernel/intern/scene.cc @@ -2278,13 +2278,13 @@ int BKE_scene_base_iter_next( if (iter->dupli_refob != *ob) { if (iter->dupli_refob) { /* Restore previous object's real matrix. */ - copy_m4_m4(iter->dupli_refob->obmat, iter->omat); + copy_m4_m4(iter->dupli_refob->object_to_world, iter->omat); } /* Backup new object's real matrix. */ iter->dupli_refob = *ob; - copy_m4_m4(iter->omat, iter->dupli_refob->obmat); + copy_m4_m4(iter->omat, iter->dupli_refob->object_to_world); } - copy_m4_m4((*ob)->obmat, iter->dupob->mat); + copy_m4_m4((*ob)->object_to_world, iter->dupob->mat); iter->dupob = iter->dupob->next; } @@ -2294,7 +2294,7 @@ int BKE_scene_base_iter_next( if (iter->dupli_refob) { /* Restore last object's real matrix. */ - copy_m4_m4(iter->dupli_refob->obmat, iter->omat); + copy_m4_m4(iter->dupli_refob->object_to_world, iter->omat); iter->dupli_refob = nullptr; } diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index b35031b9a88..be033f495c7 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -2644,7 +2644,7 @@ static void springs_from_mesh(Object *ob) bp = ob->soft->bpoint; for (a = 0; a < me->totvert; a++, bp++) { copy_v3_v3(bp->origS, verts[a].co); - mul_m4_v3(ob->obmat, bp->origS); + mul_m4_v3(ob->object_to_world, bp->origS); } } /* recalculate spring length for meshes here */ @@ -2809,9 +2809,9 @@ static float globallen(float *v1, float *v2, Object *ob) { float p1[3], p2[3]; copy_v3_v3(p1, v1); - mul_m4_v3(ob->obmat, p1); + mul_m4_v3(ob->object_to_world, p1); copy_v3_v3(p2, v2); - mul_m4_v3(ob->obmat, p2); + mul_m4_v3(ob->object_to_world, p2); return len_v3v3(p1, p2); } @@ -3073,7 +3073,7 @@ static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts, SB_estimate_transform(ob, sb->lcom, sb->lrot, sb->lscale); } /* Inverse matrix is not up to date. */ - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); for (a = 0; a < numVerts; a++, bp++) { copy_v3_v3(vertexCos[a], bp->pos); @@ -3223,7 +3223,7 @@ static void softbody_update_positions(Object *ob, /* copy the position of the goals at desired end time */ copy_v3_v3(bp->origE, vertexCos[a]); /* vertexCos came from local world, go global */ - mul_m4_v3(ob->obmat, bp->origE); + mul_m4_v3(ob->object_to_world, bp->origE); /* just to be save give bp->origT a defined value * will be calculated in interpolate_exciter() */ copy_v3_v3(bp->origT, bp->origE); @@ -3279,7 +3279,7 @@ static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int for (a = 0, bp = sb->bpoint; a < numVerts; a++, bp++) { copy_v3_v3(bp->pos, vertexCos[a]); - mul_m4_v3(ob->obmat, bp->pos); /* Yep, soft-body is global coords. */ + mul_m4_v3(ob->object_to_world, bp->pos); /* Yep, soft-body is global coords. */ copy_v3_v3(bp->origS, bp->pos); copy_v3_v3(bp->origE, bp->pos); copy_v3_v3(bp->origT, bp->pos); diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index d08fba0e657..1aef42ef037 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -1129,9 +1129,9 @@ static void sound_update_base(Scene *scene, Object *object, void *new_set) AUD_SequenceEntry_setConeAngleInner(strip->speaker_handle, speaker->cone_angle_inner); AUD_SequenceEntry_setConeVolumeOuter(strip->speaker_handle, speaker->cone_volume_outer); - mat4_to_quat(quat, object->obmat); + mat4_to_quat(quat, object->object_to_world); AUD_SequenceEntry_setAnimationData( - strip->speaker_handle, AUD_AP_LOCATION, scene->r.cfra, object->obmat[3], 1); + strip->speaker_handle, AUD_AP_LOCATION, scene->r.cfra, object->object_to_world[3], 1); AUD_SequenceEntry_setAnimationData( strip->speaker_handle, AUD_AP_ORIENTATION, scene->r.cfra, quat, 1); AUD_SequenceEntry_setAnimationData( @@ -1171,9 +1171,9 @@ void BKE_sound_update_scene(Depsgraph *depsgraph, Scene *scene) } if (scene->camera) { - mat4_to_quat(quat, scene->camera->obmat); + mat4_to_quat(quat, scene->camera->object_to_world); AUD_Sequence_setAnimationData( - scene->sound_scene, AUD_AP_LOCATION, scene->r.cfra, scene->camera->obmat[3], 1); + scene->sound_scene, AUD_AP_LOCATION, scene->r.cfra, scene->camera->object_to_world[3], 1); AUD_Sequence_setAnimationData(scene->sound_scene, AUD_AP_ORIENTATION, scene->r.cfra, quat, 1); } diff --git a/source/blender/blenkernel/intern/vfont.c b/source/blender/blenkernel/intern/vfont.c index 7ace1a3aa3b..9f48b9b9c4a 100644 --- a/source/blender/blenkernel/intern/vfont.c +++ b/source/blender/blenkernel/intern/vfont.c @@ -1310,14 +1310,14 @@ static bool vfont_to_curve(Object *ob, float timeofs, sizefac; if (ob != NULL) { - invert_m4_m4(imat, ob->obmat); + invert_m4_m4(imat, ob->object_to_world); } else { unit_m4(imat); } copy_m3_m4(imat3, imat); - copy_m3_m4(cmat, cu->textoncurve->obmat); + copy_m3_m4(cmat, cu->textoncurve->object_to_world); mul_m3_m3m3(cmat, cmat, imat3); sizefac = normalize_v3(cmat[0]) / font_size; diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index 7e1b7c2ba56..538474f58b6 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -624,7 +624,7 @@ void BLI_space_transform_apply_normal(const struct SpaceTransform *data, float n void BLI_space_transform_invert_normal(const struct SpaceTransform *data, float no[3]); #define BLI_SPACE_TRANSFORM_SETUP(data, local, target) \ - BLI_space_transform_from_matrices((data), (local)->obmat, (target)->obmat) + BLI_space_transform_from_matrices((data), (local)->object_to_world, (target)->object_to_world) /** \} */ diff --git a/source/blender/blenlib/BLI_uvproject.h b/source/blender/blenlib/BLI_uvproject.h index 75f39de6b7f..a94fd796121 100644 --- a/source/blender/blenlib/BLI_uvproject.h +++ b/source/blender/blenlib/BLI_uvproject.h @@ -15,7 +15,7 @@ struct ProjCameraInfo; /** * Create UV info from the camera, needs to be freed. * - * \param rotmat: can be `obedit->obmat` when uv project is used. + * \param rotmat: can be `obedit->object_to_world` when uv project is used. * \param winx, winy: can be from `scene->r.xsch / ysch`. */ struct ProjCameraInfo *BLI_uvproject_camera_info(struct Object *ob, diff --git a/source/blender/blenlib/intern/uvproject.c b/source/blender/blenlib/intern/uvproject.c index 347166bd57d..0398bf0b3fe 100644 --- a/source/blender/blenlib/intern/uvproject.c +++ b/source/blender/blenlib/intern/uvproject.c @@ -129,7 +129,7 @@ ProjCameraInfo *BLI_uvproject_camera_info(Object *ob, float rotmat[4][4], float uci.camsize = uci.do_persp ? tanf(uci.camangle) : camera->ortho_scale; /* account for scaled cameras */ - copy_m4_m4(uci.caminv, ob->obmat); + copy_m4_m4(uci.caminv, ob->object_to_world); normalize_m4(uci.caminv); if (invert_m4(uci.caminv)) { diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index 4636011e18b..11998860ef3 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -191,8 +191,8 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data) bool is_neg_scale = is_negative_m4(dob->mat); SET_FLAG_FROM_TEST(data->temp_dupli_object.transflag, is_neg_scale, OB_NEG_SCALE); - copy_m4_m4(data->temp_dupli_object.obmat, dob->mat); - invert_m4_m4(data->temp_dupli_object.imat, data->temp_dupli_object.obmat); + copy_m4_m4(data->temp_dupli_object.object_to_world, dob->mat); + invert_m4_m4(data->temp_dupli_object.imat, data->temp_dupli_object.object_to_world); data->next_object = &data->temp_dupli_object; BLI_assert(deg::deg_validate_copy_on_write_datablock(&data->temp_dupli_object.id)); return true; diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index a5b29ae56a9..62a9158928d 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -284,7 +284,7 @@ void invalidate_tagged_evaluated_transform(ID *id) switch (id_type) { case ID_OB: { Object *object = (Object *)id; - copy_vn_fl((float *)object->obmat, 16, NAN); + copy_vn_fl((float *)object->object_to_world, 16, NAN); break; } default: diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index 942ab5502c7..eb111610706 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -403,7 +403,7 @@ static bool eevee_lightprobes_culling_test(Object *ob) const float max[3] = {1.0f, 1.0f, 1.0f}; BKE_boundbox_init_from_minmax(&bbox, min, max); - copy_m4_m4(tmp, ob->obmat); + copy_m4_m4(tmp, ob->object_to_world); normalize_v3(tmp[2]); mul_v3_fl(tmp[2], probe->distinf); @@ -445,7 +445,7 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata /* Debug Display */ DRWCallBuffer *grp = vedata->stl->g_data->planar_display_shgrp; if (grp && (probe->flag & LIGHTPROBE_FLAG_SHOW_DATA)) { - DRW_buffer_add_entry(grp, &pinfo->num_planar, ob->obmat); + DRW_buffer_add_entry(grp, &pinfo->num_planar, ob->object_to_world); } pinfo->num_planar++; @@ -488,30 +488,30 @@ void EEVEE_lightprobes_grid_data_from_object(Object *ob, EEVEE_LightGrid *egrid, mul_v3_v3fl(half_cell_dim, cell_dim, 0.5f); /* Matrix converting world space to cell ranges. */ - invert_m4_m4(egrid->mat, ob->obmat); + invert_m4_m4(egrid->mat, ob->object_to_world); /* First cell. */ copy_v3_fl(egrid->corner, -1.0f); add_v3_v3(egrid->corner, half_cell_dim); - mul_m4_v3(ob->obmat, egrid->corner); + mul_m4_v3(ob->object_to_world, egrid->corner); /* Opposite neighbor cell. */ copy_v3_fl3(egrid->increment_x, cell_dim[0], 0.0f, 0.0f); add_v3_v3(egrid->increment_x, half_cell_dim); add_v3_fl(egrid->increment_x, -1.0f); - mul_m4_v3(ob->obmat, egrid->increment_x); + mul_m4_v3(ob->object_to_world, egrid->increment_x); sub_v3_v3(egrid->increment_x, egrid->corner); copy_v3_fl3(egrid->increment_y, 0.0f, cell_dim[1], 0.0f); add_v3_v3(egrid->increment_y, half_cell_dim); add_v3_fl(egrid->increment_y, -1.0f); - mul_m4_v3(ob->obmat, egrid->increment_y); + mul_m4_v3(ob->object_to_world, egrid->increment_y); sub_v3_v3(egrid->increment_y, egrid->corner); copy_v3_fl3(egrid->increment_z, 0.0f, 0.0f, cell_dim[2]); add_v3_v3(egrid->increment_z, half_cell_dim); add_v3_fl(egrid->increment_z, -1.0f); - mul_m4_v3(ob->obmat, egrid->increment_z); + mul_m4_v3(ob->object_to_world, egrid->increment_z); sub_v3_v3(egrid->increment_z, egrid->corner); /* Visibility bias */ @@ -527,7 +527,7 @@ void EEVEE_lightprobes_cube_data_from_object(Object *ob, EEVEE_LightProbe *eprob LightProbe *probe = (LightProbe *)ob->data; /* Update transforms */ - copy_v3_v3(eprobe->position, ob->obmat[3]); + copy_v3_v3(eprobe->position, ob->object_to_world[3]); /* Attenuation */ eprobe->attenuation_type = probe->attenuation_type; @@ -535,7 +535,7 @@ void EEVEE_lightprobes_cube_data_from_object(Object *ob, EEVEE_LightProbe *eprob unit_m4(eprobe->attenuationmat); scale_m4_fl(eprobe->attenuationmat, probe->distinf); - mul_m4_m4m4(eprobe->attenuationmat, ob->obmat, eprobe->attenuationmat); + mul_m4_m4m4(eprobe->attenuationmat, ob->object_to_world, eprobe->attenuationmat); invert_m4(eprobe->attenuationmat); /* Parallax */ @@ -550,7 +550,7 @@ void EEVEE_lightprobes_cube_data_from_object(Object *ob, EEVEE_LightProbe *eprob scale_m4_fl(eprobe->parallaxmat, probe->distinf); } - mul_m4_m4m4(eprobe->parallaxmat, ob->obmat, eprobe->parallaxmat); + mul_m4_m4m4(eprobe->parallaxmat, ob->object_to_world, eprobe->parallaxmat); invert_m4(eprobe->parallaxmat); } @@ -566,8 +566,8 @@ void EEVEE_lightprobes_planar_data_from_object(Object *ob, vis_test->cached = false; /* Computing mtx : matrix that mirror position around object's XY plane. */ - normalize_m4_m4(normat, ob->obmat); /* object > world */ - invert_m4_m4(imat, normat); /* world > object */ + normalize_m4_m4(normat, ob->object_to_world); /* object > world */ + invert_m4_m4(imat, normat); /* world > object */ /* XY reflection plane */ imat[0][2] = -imat[0][2]; imat[1][2] = -imat[1][2]; @@ -576,38 +576,38 @@ void EEVEE_lightprobes_planar_data_from_object(Object *ob, mul_m4_m4m4(eplanar->mtx, normat, imat); /* world > object > mirrored obj > world */ /* Compute clip plane equation / normal. */ - copy_v3_v3(eplanar->plane_equation, ob->obmat[2]); + copy_v3_v3(eplanar->plane_equation, ob->object_to_world[2]); normalize_v3(eplanar->plane_equation); /* plane normal */ - eplanar->plane_equation[3] = -dot_v3v3(eplanar->plane_equation, ob->obmat[3]); + eplanar->plane_equation[3] = -dot_v3v3(eplanar->plane_equation, ob->object_to_world[3]); eplanar->clipsta = probe->clipsta; /* Compute XY clip planes. */ - normalize_v3_v3(eplanar->clip_vec_x, ob->obmat[0]); - normalize_v3_v3(eplanar->clip_vec_y, ob->obmat[1]); + normalize_v3_v3(eplanar->clip_vec_x, ob->object_to_world[0]); + normalize_v3_v3(eplanar->clip_vec_y, ob->object_to_world[1]); float vec[3] = {0.0f, 0.0f, 0.0f}; vec[0] = 1.0f; vec[1] = 0.0f; vec[2] = 0.0f; - mul_m4_v3(ob->obmat, vec); /* Point on the edge */ + mul_m4_v3(ob->object_to_world, vec); /* Point on the edge */ eplanar->clip_edge_x_pos = dot_v3v3(eplanar->clip_vec_x, vec); vec[0] = 0.0f; vec[1] = 1.0f; vec[2] = 0.0f; - mul_m4_v3(ob->obmat, vec); /* Point on the edge */ + mul_m4_v3(ob->object_to_world, vec); /* Point on the edge */ eplanar->clip_edge_y_pos = dot_v3v3(eplanar->clip_vec_y, vec); vec[0] = -1.0f; vec[1] = 0.0f; vec[2] = 0.0f; - mul_m4_v3(ob->obmat, vec); /* Point on the edge */ + mul_m4_v3(ob->object_to_world, vec); /* Point on the edge */ eplanar->clip_edge_x_neg = dot_v3v3(eplanar->clip_vec_x, vec); vec[0] = 0.0f; vec[1] = -1.0f; vec[2] = 0.0f; - mul_m4_v3(ob->obmat, vec); /* Point on the edge */ + mul_m4_v3(ob->object_to_world, vec); /* Point on the edge */ eplanar->clip_edge_y_neg = dot_v3v3(eplanar->clip_vec_y, vec); /* Facing factors */ diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index 312305a31f7..f8250f9520d 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -132,7 +132,7 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli) const float light_threshold = draw_ctx->scene->eevee.light_threshold; /* Position */ - copy_v3_v3(evli->position, ob->obmat[3]); + copy_v3_v3(evli->position, ob->object_to_world[3]); /* Color */ copy_v3_v3(evli->color, &la->r); @@ -153,7 +153,7 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli) evli->invsqrdist_volume = 1.0f / max_ff(1e-4f, square_f(att_radius_volume)); /* Vectors */ - normalize_m4_m4_ex(mat, ob->obmat, scale); + normalize_m4_m4_ex(mat, ob->object_to_world, scale); copy_v3_v3(evli->forwardvec, mat[2]); normalize_v3(evli->forwardvec); negate_v3(evli->forwardvec); diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c index a3ca19c88e1..9f7fb1c154c 100644 --- a/source/blender/draw/engines/eevee/eevee_motion_blur.c +++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c @@ -292,7 +292,7 @@ void EEVEE_motion_blur_curves_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata) int mb_step = effects->motion_blur_step; /* Store transform. */ - copy_m4_m4(mb_data->obmat[mb_step], ob->obmat); + copy_m4_m4(mb_data->obmat[mb_step], ob->object_to_world); EEVEE_HairMotionData *mb_curves = EEVEE_motion_blur_curves_data_get(mb_data); @@ -362,7 +362,7 @@ void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata), if (mb_data) { int mb_step = effects->motion_blur_step; /* Store transform. */ - copy_m4_m4(mb_data->obmat[mb_step], ob->obmat); + copy_m4_m4(mb_data->obmat[mb_step], ob->object_to_world); EEVEE_GeometryMotionData *mb_geom = EEVEE_motion_blur_geometry_data_get(mb_data); diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c index 9e571b1d15b..1cf3c7c6da1 100644 --- a/source/blender/draw/engines/eevee/eevee_shadows.c +++ b/source/blender/draw/engines/eevee/eevee_shadows.c @@ -153,7 +153,7 @@ void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, Object *ob) for (int i = 0; i < 8; i++) { float vec[3]; copy_v3_v3(vec, bb->vec[i]); - mul_m4_v3(ob->obmat, vec); + mul_m4_v3(ob->object_to_world, vec); minmax_v3v3_v3(min, max, vec); } diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 05b2bafdb3a..872696a8b7c 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -299,7 +299,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, } float size[3]; - mat4_to_size(size, ob->obmat); + mat4_to_size(size, ob->object_to_world); /* Check if any of the axes have 0 length. (see T69070) */ const float epsilon = 1e-8f; if ((size[0] < epsilon) || (size[1] < epsilon) || (size[2] < epsilon)) { diff --git a/source/blender/draw/engines/eevee_next/eevee_light.cc b/source/blender/draw/engines/eevee_next/eevee_light.cc index 8a5de15229d..aa8268dbaa7 100644 --- a/source/blender/draw/engines/eevee_next/eevee_light.cc +++ b/source/blender/draw/engines/eevee_next/eevee_light.cc @@ -58,7 +58,7 @@ void Light::sync(/* ShadowModule &shadows , */ const Object *ob, float threshold this->influence_radius_invsqr_volume = 1.0f / square_f(max_ff(influence_radius_volume, 1e-8f)); this->color = float3(&la->r) * la->energy; - normalize_m4_m4_ex(this->object_mat.ptr(), ob->obmat, scale); + normalize_m4_m4_ex(this->object_mat.ptr(), ob->object_to_world, scale); /* Make sure we have consistent handedness (in case of negatively scaled Z axis). */ float3 cross = math::cross(float3(this->_right), float3(this->_up)); if (math::dot(cross, float3(this->_back)) < 0.0f) { diff --git a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc index e6b37b4ad47..0242f732f27 100644 --- a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc +++ b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc @@ -182,7 +182,7 @@ PassMain::Sub *ForwardPipeline::prepass_transparent_add(const Object *ob, if (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) { state |= DRW_STATE_CULL_BACK; } - float sorting_value = math::dot(float3(ob->obmat[3]), camera_forward_); + float sorting_value = math::dot(float3(ob->object_to_world[3]), camera_forward_); PassMain::Sub *pass = &transparent_ps_.sub(GPU_material_get_name(gpumat), sorting_value); pass->state_set(state); pass->material_set(*inst_.manager, gpumat); @@ -197,7 +197,7 @@ PassMain::Sub *ForwardPipeline::material_transparent_add(const Object *ob, if (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) { state |= DRW_STATE_CULL_BACK; } - float sorting_value = math::dot(float3(ob->obmat[3]), camera_forward_); + float sorting_value = math::dot(float3(ob->object_to_world[3]), camera_forward_); PassMain::Sub *pass = &transparent_ps_.sub(GPU_material_get_name(gpumat), sorting_value); pass->state_set(state); pass->material_set(*inst_.manager, gpumat); diff --git a/source/blender/draw/engines/eevee_next/eevee_velocity.cc b/source/blender/draw/engines/eevee_next/eevee_velocity.cc index b9a78e8547e..52401c8003e 100644 --- a/source/blender/draw/engines/eevee_next/eevee_velocity.cc +++ b/source/blender/draw/engines/eevee_next/eevee_velocity.cc @@ -106,16 +106,16 @@ bool VelocityModule::step_object_sync(Object *ob, vel.obj.ofs[step_] = object_steps_usage[step_]++; vel.obj.resource_id = resource_handle.resource_index(); vel.id = (ID *)ob->data; - object_steps[step_]->get_or_resize(vel.obj.ofs[step_]) = ob->obmat; + object_steps[step_]->get_or_resize(vel.obj.ofs[step_]) = ob->object_to_world; if (step_ == STEP_CURRENT) { /* Replace invalid steps. Can happen if object was hidden in one of those steps. */ if (vel.obj.ofs[STEP_PREVIOUS] == -1) { vel.obj.ofs[STEP_PREVIOUS] = object_steps_usage[STEP_PREVIOUS]++; - object_steps[STEP_PREVIOUS]->get_or_resize(vel.obj.ofs[STEP_PREVIOUS]) = ob->obmat; + object_steps[STEP_PREVIOUS]->get_or_resize(vel.obj.ofs[STEP_PREVIOUS]) = ob->object_to_world; } if (vel.obj.ofs[STEP_NEXT] == -1) { vel.obj.ofs[STEP_NEXT] = object_steps_usage[STEP_NEXT]++; - object_steps[STEP_NEXT]->get_or_resize(vel.obj.ofs[STEP_NEXT]) = ob->obmat; + object_steps[STEP_NEXT]->get_or_resize(vel.obj.ofs[STEP_NEXT]) = ob->object_to_world; } } diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c index a41918e7e0d..06bf531cded 100644 --- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c @@ -39,9 +39,9 @@ GPENCIL_tObject *gpencil_object_cache_add(GPENCIL_PrivateData *pd, Object *ob) tgp_ob->layers.first = tgp_ob->layers.last = NULL; tgp_ob->vfx.first = tgp_ob->vfx.last = NULL; - tgp_ob->camera_z = dot_v3v3(pd->camera_z_axis, ob->obmat[3]); + tgp_ob->camera_z = dot_v3v3(pd->camera_z_axis, ob->object_to_world[3]); tgp_ob->is_drawmode3d = (gpd->draw_mode == GP_DRAWMODE_3D) || pd->draw_depth_only; - tgp_ob->object_scale = mat4_to_scale(ob->obmat); + tgp_ob->object_scale = mat4_to_scale(ob->object_to_world); /* Check if any material with holdout flag enabled. */ tgp_ob->do_mat_holdout = false; @@ -71,7 +71,7 @@ GPENCIL_tObject *gpencil_object_cache_add(GPENCIL_PrivateData *pd, Object *ob) add_v3_fl(size, 1e-8f); rescale_m4(mat, size); /* BBox space to World. */ - mul_m4_m4m4(mat, ob->obmat, mat); + mul_m4_m4m4(mat, ob->object_to_world, mat); if (DRW_view_is_persp_get(NULL)) { /* BBox center to camera vector. */ sub_v3_v3v3(tgp_ob->plane_normal, pd->camera_pos, mat[3]); @@ -96,9 +96,9 @@ GPENCIL_tObject *gpencil_object_cache_add(GPENCIL_PrivateData *pd, Object *ob) unit_m4(tgp_ob->plane_mat); copy_v3_v3(tgp_ob->plane_mat[2], tgp_ob->plane_normal); orthogonalize_m4(tgp_ob->plane_mat, 2); - mul_mat3_m4_v3(ob->obmat, size); + mul_mat3_m4_v3(ob->object_to_world, size); float radius = len_v3(size); - mul_m4_v3(ob->obmat, center); + mul_m4_v3(ob->object_to_world, center); rescale_m4(tgp_ob->plane_mat, (float[3]){radius, radius, radius}); copy_v3_v3(tgp_ob->plane_mat[3], center); diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_data.c b/source/blender/draw/engines/gpencil/gpencil_draw_data.c index e54ac99a888..07b72c97875 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_data.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_data.c @@ -387,20 +387,20 @@ void gpencil_light_pool_populate(GPENCIL_LightPool *lightpool, Object *ob) } else if (la->type == LA_AREA) { /* Simulate area lights using a spot light. */ - normalize_m4_m4(mat, ob->obmat); + normalize_m4_m4(mat, ob->object_to_world); invert_m4(mat); gp_light->type = GP_LIGHT_TYPE_SPOT; gp_light->spot_size = cosf(M_PI_2); gp_light->spot_blend = (1.0f - gp_light->spot_size) * 1.0f; } else if (la->type == LA_SUN) { - normalize_v3_v3(gp_light->forward, ob->obmat[2]); + normalize_v3_v3(gp_light->forward, ob->object_to_world[2]); gp_light->type = GP_LIGHT_TYPE_SUN; } else { gp_light->type = GP_LIGHT_TYPE_POINT; } - copy_v4_v4(gp_light->position, ob->obmat[3]); + copy_v4_v4(gp_light->position, ob->object_to_world[3]); copy_v3_v3(gp_light->color, &la->r); mul_v3_fl(gp_light->color, la->energy * light_power_get(la)); diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c index a7d8570dbaa..9b1129e77be 100644 --- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c +++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c @@ -96,7 +96,7 @@ static void gpencil_vfx_blur(BlurShaderFxData *fx, Object *ob, gpIterVfxData *it float winmat[4][4], persmat[4][4]; float blur_size[2] = {fx->radius[0], fx->radius[1]}; DRW_view_persmat_get(NULL, persmat, false); - const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3])); + const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->object_to_world[3])); if (fx->flag & FX_BLUR_DOF_MODE) { /* Compute circle of confusion size. */ @@ -108,7 +108,7 @@ static void gpencil_vfx_blur(BlurShaderFxData *fx, Object *ob, gpIterVfxData *it DRW_view_winmat_get(NULL, winmat, false); const float *vp_size = DRW_viewport_size_get(); float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR; - float scale = mat4_to_scale(ob->obmat); + float scale = mat4_to_scale(ob->object_to_world); float distance_factor = world_pixel_scale * scale * winmat[1][1] * vp_size[1] / w; mul_v2_fl(blur_size, distance_factor); } @@ -175,11 +175,11 @@ static void gpencil_vfx_rim(RimShaderFxData *fx, Object *ob, gpIterVfxData *iter const float *vp_size = DRW_viewport_size_get(); const float *vp_size_inv = DRW_viewport_invert_size_get(); - const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3])); + const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->object_to_world[3])); /* Modify by distance to camera and object scale. */ float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR; - float scale = mat4_to_scale(ob->obmat); + float scale = mat4_to_scale(ob->object_to_world); float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w; mul_v2_fl(offset, distance_factor); mul_v2_v2(offset, vp_size_inv); @@ -248,8 +248,8 @@ static void gpencil_vfx_pixelize(PixelShaderFxData *fx, Object *ob, gpIterVfxDat mul_v2_v2(pixel_size, vp_size_inv); /* Fixed pixelisation center from object center. */ - const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3])); - mul_v3_m4v3(ob_center, persmat, ob->obmat[3]); + const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->object_to_world[3])); + mul_v3_m4v3(ob_center, persmat, ob->object_to_world[3]); mul_v3_fl(ob_center, 1.0f / w); const bool use_antialiasing = ((fx->flag & FX_PIXEL_FILTER_NEAREST) == 0); @@ -260,7 +260,7 @@ static void gpencil_vfx_pixelize(PixelShaderFxData *fx, Object *ob, gpIterVfxDat /* Modify by distance to camera and object scale. */ float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR; - float scale = mat4_to_scale(ob->obmat); + float scale = mat4_to_scale(ob->object_to_world); mul_v2_fl(pixel_size, (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w); /* Center to texel */ @@ -310,7 +310,9 @@ static void gpencil_vfx_shadow(ShadowShaderFxData *fx, Object *ob, gpIterVfxData const float *vp_size_inv = DRW_viewport_invert_size_get(); const float ratio = vp_size_inv[1] / vp_size_inv[0]; - copy_v3_v3(rot_center, (use_obj_pivot && fx->object) ? fx->object->obmat[3] : ob->obmat[3]); + copy_v3_v3(rot_center, + (use_obj_pivot && fx->object) ? fx->object->object_to_world[3] : + ob->object_to_world[3]); const float w = fabsf(mul_project_m4_v3_zfac(persmat, rot_center)); mul_v3_m4v3(rot_center, persmat, rot_center); @@ -318,7 +320,7 @@ static void gpencil_vfx_shadow(ShadowShaderFxData *fx, Object *ob, gpIterVfxData /* Modify by distance to camera and object scale. */ float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR; - float scale = mat4_to_scale(ob->obmat); + float scale = mat4_to_scale(ob->object_to_world); float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w; mul_v2_fl(offset, distance_factor); mul_v2_v2(offset, vp_size_inv); @@ -485,13 +487,13 @@ static void gpencil_vfx_wave(WaveShaderFxData *fx, Object *ob, gpIterVfxData *it const float *vp_size = DRW_viewport_size_get(); const float *vp_size_inv = DRW_viewport_invert_size_get(); - const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3])); - mul_v3_m4v3(wave_center, persmat, ob->obmat[3]); + const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->object_to_world[3])); + mul_v3_m4v3(wave_center, persmat, ob->object_to_world[3]); mul_v3_fl(wave_center, 1.0f / w); /* Modify by distance to camera and object scale. */ float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR; - float scale = mat4_to_scale(ob->obmat); + float scale = mat4_to_scale(ob->object_to_world); float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w; wave_center[0] = wave_center[0] * 0.5f + 0.5f; @@ -542,7 +544,7 @@ static void gpencil_vfx_swirl(SwirlShaderFxData *fx, Object *UNUSED(ob), gpIterV DRW_view_persmat_get(NULL, persmat, false); const float *vp_size = DRW_viewport_size_get(); - copy_v3_v3(swirl_center, fx->object->obmat[3]); + copy_v3_v3(swirl_center, fx->object->object_to_world[3]); const float w = fabsf(mul_project_m4_v3_zfac(persmat, swirl_center)); mul_v3_m4v3(swirl_center, persmat, swirl_center); @@ -550,7 +552,7 @@ static void gpencil_vfx_swirl(SwirlShaderFxData *fx, Object *UNUSED(ob), gpIterV /* Modify by distance to camera and object scale. */ float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR; - float scale = mat4_to_scale(fx->object->obmat); + float scale = mat4_to_scale(fx->object->object_to_world); float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w; mul_v2_fl(swirl_center, 0.5f); diff --git a/source/blender/draw/engines/overlay/overlay_armature.cc b/source/blender/draw/engines/overlay/overlay_armature.cc index 0cf9d91804a..8c9587e7a9a 100644 --- a/source/blender/draw/engines/overlay/overlay_armature.cc +++ b/source/blender/draw/engines/overlay/overlay_armature.cc @@ -441,7 +441,7 @@ static void drw_shgroup_bone_octahedral(ArmatureDrawContext *ctx, const float outline_color[4]) { BoneInstanceData inst_data; - mul_m4_m4m4(inst_data.mat, ctx->ob->obmat, bone_mat); + mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world, bone_mat); if (ctx->solid) { OVERLAY_bone_instance_data_set_color(&inst_data, bone_color); OVERLAY_bone_instance_data_set_color_hint(&inst_data, hint_color); @@ -461,7 +461,7 @@ static void drw_shgroup_bone_box(ArmatureDrawContext *ctx, const float outline_color[4]) { BoneInstanceData inst_data; - mul_m4_m4m4(inst_data.mat, ctx->ob->obmat, bone_mat); + mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world, bone_mat); if (ctx->solid) { OVERLAY_bone_instance_data_set_color(&inst_data, bone_color); OVERLAY_bone_instance_data_set_color_hint(&inst_data, hint_color); @@ -479,9 +479,9 @@ static void drw_shgroup_bone_wire(ArmatureDrawContext *ctx, const float color[4]) { float head[3], tail[3]; - mul_v3_m4v3(head, ctx->ob->obmat, bone_mat[3]); + mul_v3_m4v3(head, ctx->ob->object_to_world, bone_mat[3]); add_v3_v3v3(tail, bone_mat[3], bone_mat[1]); - mul_m4_v3(ctx->ob->obmat, tail); + mul_m4_v3(ctx->ob->object_to_world, tail); DRW_buffer_add_entry(ctx->wire, head, color); DRW_buffer_add_entry(ctx->wire, tail, color); @@ -496,9 +496,9 @@ static void drw_shgroup_bone_stick(ArmatureDrawContext *ctx, const float col_tail[4]) { float head[3], tail[3]; - mul_v3_m4v3(head, ctx->ob->obmat, bone_mat[3]); + mul_v3_m4v3(head, ctx->ob->object_to_world, bone_mat[3]); add_v3_v3v3(tail, bone_mat[3], bone_mat[1]); - mul_m4_v3(ctx->ob->obmat, tail); + mul_m4_v3(ctx->ob->object_to_world, tail); DRW_buffer_add_entry(ctx->stick, head, tail, col_wire, col_bone, col_head, col_tail); } @@ -517,11 +517,11 @@ static void drw_shgroup_bone_envelope_distance(ArmatureDrawContext *ctx, mul_m4_v4(bone_mat, head_sph); mul_m4_v4(bone_mat, tail_sph); mul_m4_v4(bone_mat, xaxis); - mul_m4_v4(ctx->ob->obmat, head_sph); - mul_m4_v4(ctx->ob->obmat, tail_sph); - mul_m4_v4(ctx->ob->obmat, xaxis); + mul_m4_v4(ctx->ob->object_to_world, head_sph); + mul_m4_v4(ctx->ob->object_to_world, tail_sph); + mul_m4_v4(ctx->ob->object_to_world, xaxis); sub_v3_v3(xaxis, head_sph); - float obscale = mat4_to_scale(ctx->ob->obmat); + float obscale = mat4_to_scale(ctx->ob->object_to_world); head_sph[3] = *radius_head * obscale; head_sph[3] += *distance * obscale; tail_sph[3] = *radius_tail * obscale; @@ -544,10 +544,10 @@ static void drw_shgroup_bone_envelope(ArmatureDrawContext *ctx, mul_m4_v4(bone_mat, head_sph); mul_m4_v4(bone_mat, tail_sph); mul_m4_v4(bone_mat, xaxis); - mul_m4_v4(ctx->ob->obmat, head_sph); - mul_m4_v4(ctx->ob->obmat, tail_sph); - mul_m4_v4(ctx->ob->obmat, xaxis); - float obscale = mat4_to_scale(ctx->ob->obmat); + mul_m4_v4(ctx->ob->object_to_world, head_sph); + mul_m4_v4(ctx->ob->object_to_world, tail_sph); + mul_m4_v4(ctx->ob->object_to_world, xaxis); + float obscale = mat4_to_scale(ctx->ob->object_to_world); head_sph[3] = *radius_head * obscale; tail_sph[3] = *radius_tail * obscale; @@ -651,7 +651,7 @@ static void drw_shgroup_bone_custom_solid_mesh(ArmatureDrawContext *ctx, DRWCallBuffer *buf; if (surf || edges || ledges) { - mul_m4_m4m4(inst_data.mat, ctx->ob->obmat, bone_mat); + mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world, bone_mat); } if (surf && ctx->custom_solid) { @@ -692,7 +692,7 @@ static void drw_shgroup_bone_custom_mesh_wire(ArmatureDrawContext *ctx, if (geom) { DRWCallBuffer *buf = custom_bone_instance_shgroup(ctx, ctx->custom_wire, geom); BoneInstanceData inst_data; - mul_m4_m4m4(inst_data.mat, ctx->ob->obmat, bone_mat); + mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world, bone_mat); OVERLAY_bone_instance_data_set_color_hint(&inst_data, color); OVERLAY_bone_instance_data_set_color(&inst_data, color); DRW_buffer_add_entry_struct(buf, inst_data.mat); @@ -724,7 +724,7 @@ static void drw_shgroup_custom_bone_curve(ArmatureDrawContext *ctx, if (ledges) { BoneInstanceData inst_data; - mul_m4_m4m4(inst_data.mat, ctx->ob->obmat, bone_mat); + mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world, bone_mat); DRWCallBuffer *buf = custom_bone_instance_shgroup(ctx, ctx->custom_wire, ledges); OVERLAY_bone_instance_data_set_color_hint(&inst_data, outline_color); @@ -785,7 +785,7 @@ static void drw_shgroup_bone_custom_empty(ArmatureDrawContext *ctx, { const float final_color[4] = {color[0], color[1], color[2], 1.0f}; float mat[4][4]; - mul_m4_m4m4(mat, ctx->ob->obmat, bone_mat); + mul_m4_m4m4(mat, ctx->ob->object_to_world, bone_mat); switch (custom->empty_drawtype) { case OB_PLAINAXES: @@ -811,7 +811,7 @@ static void drw_shgroup_bone_point(ArmatureDrawContext *ctx, const float outline_color[4]) { BoneInstanceData inst_data; - mul_m4_m4m4(inst_data.mat, ctx->ob->obmat, bone_mat); + mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world, bone_mat); if (ctx->point_solid) { OVERLAY_bone_instance_data_set_color(&inst_data, bone_color); OVERLAY_bone_instance_data_set_color_hint(&inst_data, hint_color); @@ -829,7 +829,7 @@ static void drw_shgroup_bone_axes(ArmatureDrawContext *ctx, const float color[4]) { float mat[4][4]; - mul_m4_m4m4(mat, ctx->ob->obmat, bone_mat); + mul_m4_m4m4(mat, ctx->ob->object_to_world, bone_mat); /* Move to bone tail. */ add_v3_v3(mat[3], mat[1]); OVERLAY_empty_shape(ctx->extras, mat, 0.25f, OB_ARROWS, color); @@ -842,8 +842,8 @@ static void drw_shgroup_bone_relationship_lines_ex(ArmatureDrawContext *ctx, const float color[4]) { float s[3], e[3]; - mul_v3_m4v3(s, ctx->ob->obmat, start); - mul_v3_m4v3(e, ctx->ob->obmat, end); + mul_v3_m4v3(s, ctx->ob->object_to_world, start); + mul_v3_m4v3(e, ctx->ob->object_to_world, end); /* reverse order to have less stipple overlap */ OVERLAY_extra_line_dashed(ctx->extras, s, e, color); } @@ -1909,7 +1909,7 @@ static void draw_bone_degrees_of_freedom(ArmatureDrawContext *ctx, bPoseChannel mul_m4_m4m4(posetrans, posetrans, tmp); /* into world space. */ - mul_m4_m4m4(inst_data.mat, ctx->ob->obmat, posetrans); + mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world, posetrans); if ((pchan->ikflag & BONE_IK_XLIMIT) && (pchan->ikflag & BONE_IK_ZLIMIT)) { bone_instance_data_set_angle_minmax( @@ -2079,7 +2079,7 @@ static void draw_bone_name(ArmatureDrawContext *ctx, float *head = pchan ? pchan->pose_head : eBone->head; float *tail = pchan ? pchan->pose_tail : eBone->tail; mid_v3_v3v3(vec, head, tail); - mul_m4_v3(ctx->ob->obmat, vec); + mul_m4_v3(ctx->ob->object_to_world, vec); DRW_text_cache_add(dt, vec, @@ -2177,7 +2177,8 @@ static bool pchan_culling_test_envelope(const DRWView *view, BoundSphere bsphere; pchan_culling_calc_bsphere(ob, pchan, &bsphere); bsphere.radius += max_ff(pchan->bone->rad_head, pchan->bone->rad_tail) * - mat4_to_size_max_axis(ob->obmat) * mat4_to_size_max_axis(pchan->disp_mat); + mat4_to_size_max_axis(ob->object_to_world) * + mat4_to_size_max_axis(pchan->disp_mat); return DRW_culling_sphere_test(view, &bsphere); } @@ -2188,13 +2189,13 @@ static bool pchan_culling_test_bbone(const DRWView *view, const bArmature *arm = static_cast(ob->data); BLI_assert(arm->drawtype == ARM_B_BONE); UNUSED_VARS_NDEBUG(arm); - const float ob_scale = mat4_to_size_max_axis(ob->obmat); + const float ob_scale = mat4_to_size_max_axis(ob->object_to_world); const Mat4 *bbones_mat = (const Mat4 *)pchan->draw_data->bbone_matrix; for (int i = pchan->bone->segments; i--; bbones_mat++) { BoundSphere bsphere; float size[3]; mat4_to_size(size, bbones_mat->mat); - mul_v3_m4v3(bsphere.center, ob->obmat, bbones_mat->mat[3]); + mul_v3_m4v3(bsphere.center, ob->object_to_world, bbones_mat->mat[3]); bsphere.radius = len_v3(size) * ob_scale; if (DRW_culling_sphere_test(view, &bsphere)) { return true; diff --git a/source/blender/draw/engines/overlay/overlay_edit_text.cc b/source/blender/draw/engines/overlay/overlay_edit_text.cc index ebadaa530e4..d1bca705ae6 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_text.cc +++ b/source/blender/draw/engines/overlay/overlay_edit_text.cc @@ -119,7 +119,7 @@ static void edit_text_cache_populate_select(OVERLAY_Data *vedata, Object *ob) add_v2_v2(box[3], &sb->x); } v2_quad_corners_to_mat4(box, final_mat); - mul_m4_m4m4(final_mat, ob->obmat, final_mat); + mul_m4_m4m4(final_mat, ob->object_to_world, final_mat); DRW_shgroup_call_obmat(pd->edit_text_selection_grp, geom, final_mat); } @@ -134,7 +134,7 @@ static void edit_text_cache_populate_cursor(OVERLAY_Data *vedata, Object *ob) float mat[4][4]; v2_quad_corners_to_mat4(cursor, mat); - mul_m4_m4m4(mat, ob->obmat, mat); + mul_m4_m4m4(mat, ob->object_to_world, mat); struct GPUBatch *geom = DRW_cache_quad_get(); DRW_shgroup_call_obmat(pd->edit_text_cursor_grp, geom, mat); @@ -162,7 +162,7 @@ static void edit_text_cache_populate_boxes(OVERLAY_Data *vedata, Object *ob) vecs[3][1] -= tb->h; for (int j = 0; j < 4; j++) { - mul_v3_m4v3(vecs[j], ob->obmat, vecs[j]); + mul_v3_m4v3(vecs[j], ob->object_to_world, vecs[j]); } for (int j = 0; j < 4; j++) { OVERLAY_extra_line_dashed(cb, vecs[j], vecs[(j + 1) % 4], color); diff --git a/source/blender/draw/engines/overlay/overlay_extra.cc b/source/blender/draw/engines/overlay/overlay_extra.cc index 114123ab36e..27afe49a17b 100644 --- a/source/blender/draw/engines/overlay/overlay_extra.cc +++ b/source/blender/draw/engines/overlay/overlay_extra.cc @@ -331,7 +331,7 @@ void OVERLAY_empty_cache_populate(OVERLAY_Data *vedata, Object *ob) case OB_EMPTY_CONE: case OB_ARROWS: DRW_object_wire_theme_get(ob, view_layer, &color); - OVERLAY_empty_shape(cb, ob->obmat, ob->empty_drawsize, ob->empty_drawtype, color); + OVERLAY_empty_shape(cb, ob->object_to_world, ob->empty_drawsize, ob->empty_drawtype, color); break; case OB_EMPTY_IMAGE: OVERLAY_image_empty_cache_populate(vedata, ob); @@ -372,7 +372,7 @@ static void OVERLAY_bounds(OVERLAY_ExtraCallBuffers *cb, case OB_BOUND_BOX: size_to_mat4(tmp, size); copy_v3_v3(tmp[3], center); - mul_m4_m4m4(tmp, ob->obmat, tmp); + mul_m4_m4m4(tmp, ob->object_to_world, tmp); DRW_buffer_add_entry(cb->empty_cube, color, tmp); break; case OB_BOUND_SPHERE: @@ -380,7 +380,7 @@ static void OVERLAY_bounds(OVERLAY_ExtraCallBuffers *cb, size[1] = size[2] = size[0]; size_to_mat4(tmp, size); copy_v3_v3(tmp[3], center); - mul_m4_m4m4(tmp, ob->obmat, tmp); + mul_m4_m4m4(tmp, ob->object_to_world, tmp); DRW_buffer_add_entry(cb->empty_sphere, color, tmp); break; case OB_BOUND_CYLINDER: @@ -388,7 +388,7 @@ static void OVERLAY_bounds(OVERLAY_ExtraCallBuffers *cb, size[1] = size[0]; size_to_mat4(tmp, size); copy_v3_v3(tmp[3], center); - mul_m4_m4m4(tmp, ob->obmat, tmp); + mul_m4_m4m4(tmp, ob->object_to_world, tmp); DRW_buffer_add_entry(cb->empty_cylinder, color, tmp); break; case OB_BOUND_CONE: @@ -399,7 +399,7 @@ static void OVERLAY_bounds(OVERLAY_ExtraCallBuffers *cb, /* Cone batch has base at 0 and is pointing towards +Y. */ swap_v3_v3(tmp[1], tmp[2]); tmp[3][2] -= size[2]; - mul_m4_m4m4(tmp, ob->obmat, tmp); + mul_m4_m4m4(tmp, ob->object_to_world, tmp); DRW_buffer_add_entry(cb->empty_cone, color, tmp); break; case OB_BOUND_CAPSULE: @@ -408,14 +408,14 @@ static void OVERLAY_bounds(OVERLAY_ExtraCallBuffers *cb, scale_m4_fl(tmp, size[0]); copy_v2_v2(tmp[3], center); tmp[3][2] = center[2] + max_ff(0.0f, size[2] - size[0]); - mul_m4_m4m4(final_mat, ob->obmat, tmp); + mul_m4_m4m4(final_mat, ob->object_to_world, tmp); DRW_buffer_add_entry(cb->empty_capsule_cap, color, final_mat); negate_v3(tmp[2]); tmp[3][2] = center[2] - max_ff(0.0f, size[2] - size[0]); - mul_m4_m4m4(final_mat, ob->obmat, tmp); + mul_m4_m4m4(final_mat, ob->object_to_world, tmp); DRW_buffer_add_entry(cb->empty_capsule_cap, color, final_mat); tmp[2][2] = max_ff(0.0f, size[2] * 2.0f - size[0] * 2.0f); - mul_m4_m4m4(final_mat, ob->obmat, tmp); + mul_m4_m4m4(final_mat, ob->object_to_world, tmp); DRW_buffer_add_entry(cb->empty_capsule_body, color, final_mat); break; } @@ -489,7 +489,7 @@ static void OVERLAY_texture_space(OVERLAY_ExtraCallBuffers *cb, Object *ob, cons unit_m4(mat); } - mul_m4_m4m4(mat, ob->obmat, mat); + mul_m4_m4m4(mat, ob->object_to_world, mat); DRW_buffer_add_entry(cb->empty_cube, color, mat); } @@ -511,7 +511,7 @@ static void OVERLAY_forcefield(OVERLAY_ExtraCallBuffers *cb, Object *ob, ViewLay }; } instdata; - copy_m4_m4(instdata.mat, ob->obmat); + copy_m4_m4(instdata.mat, ob->object_to_world); instdata.size_x = instdata.size_y = instdata.size_z = ob->empty_drawsize; switch (pd->forcefield) { @@ -531,16 +531,16 @@ static void OVERLAY_forcefield(OVERLAY_ExtraCallBuffers *cb, Object *ob, ViewLay instdata.size_x = instdata.size_y = instdata.size_z = pd->f_strength; float pos[4]; BKE_where_on_path(ob, 0.0f, pos, nullptr, nullptr, nullptr, nullptr); - copy_v3_v3(instdata.pos, ob->obmat[3]); + copy_v3_v3(instdata.pos, ob->object_to_world[3]); translate_m4(instdata.mat, pos[0], pos[1], pos[2]); DRW_buffer_add_entry(cb->field_curve, color, &instdata); BKE_where_on_path(ob, 1.0f, pos, nullptr, nullptr, nullptr, nullptr); - copy_v3_v3(instdata.pos, ob->obmat[3]); + copy_v3_v3(instdata.pos, ob->object_to_world[3]); translate_m4(instdata.mat, pos[0], pos[1], pos[2]); DRW_buffer_add_entry(cb->field_sphere_limit, color, &instdata); /* Restore */ - copy_v3_v3(instdata.pos, ob->obmat[3]); + copy_v3_v3(instdata.pos, ob->object_to_world[3]); } break; } @@ -625,7 +625,7 @@ void OVERLAY_light_cache_populate(OVERLAY_Data *vedata, Object *ob) }; } instdata; - copy_m4_m4(instdata.mat, ob->obmat); + copy_m4_m4(instdata.mat, ob->object_to_world); /* FIXME / TODO: clip_end has no meaning nowadays. * In EEVEE, Only clip_sta is used shadow-mapping. * Clip end is computed automatically based on light power. @@ -708,7 +708,7 @@ void OVERLAY_lightprobe_cache_populate(OVERLAY_Data *vedata, Object *ob) }; } instdata; - copy_m4_m4(instdata.mat, ob->obmat); + copy_m4_m4(instdata.mat, ob->object_to_world); switch (prb->type) { case LIGHTPROBE_TYPE_CUBE: @@ -720,15 +720,15 @@ void OVERLAY_lightprobe_cache_populate(OVERLAY_Data *vedata, Object *ob) if (show_influence) { char shape = (prb->attenuation_type == LIGHTPROBE_SHAPE_BOX) ? OB_CUBE : OB_EMPTY_SPHERE; float f = 1.0f - prb->falloff; - OVERLAY_empty_shape(cb, ob->obmat, prb->distinf, shape, color_p); - OVERLAY_empty_shape(cb, ob->obmat, prb->distinf * f, shape, color_p); + OVERLAY_empty_shape(cb, ob->object_to_world, prb->distinf, shape, color_p); + OVERLAY_empty_shape(cb, ob->object_to_world, prb->distinf * f, shape, color_p); } if (show_parallax) { char shape = (prb->parallax_type == LIGHTPROBE_SHAPE_BOX) ? OB_CUBE : OB_EMPTY_SPHERE; float dist = ((prb->flag & LIGHTPROBE_FLAG_CUSTOM_PARALLAX) != 0) ? prb->distpar : prb->distinf; - OVERLAY_empty_shape(cb, ob->obmat, dist, shape, color_p); + OVERLAY_empty_shape(cb, ob->object_to_world, dist, shape, color_p); } break; case LIGHTPROBE_TYPE_GRID: @@ -738,8 +738,8 @@ void OVERLAY_lightprobe_cache_populate(OVERLAY_Data *vedata, Object *ob) if (show_influence) { float f = 1.0f - prb->falloff; - OVERLAY_empty_shape(cb, ob->obmat, 1.0 + prb->distinf, OB_CUBE, color_p); - OVERLAY_empty_shape(cb, ob->obmat, 1.0 + prb->distinf * f, OB_CUBE, color_p); + OVERLAY_empty_shape(cb, ob->object_to_world, 1.0 + prb->distinf, OB_CUBE, color_p); + OVERLAY_empty_shape(cb, ob->object_to_world, 1.0 + prb->distinf * f, OB_CUBE, color_p); } /* Data dots */ @@ -777,7 +777,7 @@ void OVERLAY_lightprobe_cache_populate(OVERLAY_Data *vedata, Object *ob) zero_v3(instdata.mat[2]); DRW_buffer_add_entry(cb->empty_cube, color_p, &instdata); - normalize_m4_m4(instdata.mat, ob->obmat); + normalize_m4_m4(instdata.mat, ob->object_to_world); OVERLAY_empty_shape(cb, instdata.mat, ob->empty_drawsize, OB_SINGLE_ARROW, color_p); break; } @@ -797,7 +797,7 @@ void OVERLAY_speaker_cache_populate(OVERLAY_Data *vedata, Object *ob) float *color_p; DRW_object_wire_theme_get(ob, view_layer, &color_p); - DRW_buffer_add_entry(cb->speaker, color_p, ob->obmat); + DRW_buffer_add_entry(cb->speaker, color_p, ob->object_to_world); } /** \} */ @@ -890,7 +890,7 @@ static void camera_view3d_reconstruction( float object_imat[4][4]; invert_m4_m4(object_imat, object_mat); - mul_m4_m4m4(tracking_object_mat, ob->obmat, object_imat); + mul_m4_m4m4(tracking_object_mat, ob->object_to_world, object_imat); } ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object); @@ -1132,14 +1132,17 @@ void OVERLAY_camera_cache_populate(OVERLAY_Data *vedata, Object *ob) DRW_object_wire_theme_get(ob, view_layer, &color_p); copy_v4_v4(instdata.color, color_p); - normalize_m4_m4(instdata.mat, ob->obmat); + normalize_m4_m4(instdata.mat, ob->object_to_world); /* BKE_camera_multiview_model_matrix already accounts for scale, don't do it here. */ if (is_selection_camera_stereo) { copy_v3_fl(scale, 1.0f); } else { - copy_v3_fl3(scale, len_v3(ob->obmat[0]), len_v3(ob->obmat[1]), len_v3(ob->obmat[2])); + copy_v3_fl3(scale, + len_v3(ob->object_to_world[0]), + len_v3(ob->object_to_world[1]), + len_v3(ob->object_to_world[2])); /* Avoid division by 0. */ if (ELEM(0.0f, scale[0], scale[1], scale[2])) { return; @@ -1255,7 +1258,7 @@ static void OVERLAY_relationship_lines(OVERLAY_ExtraCallBuffers *cb, if (ob->parent && (DRW_object_visibility_in_active_context(ob->parent) & OB_VISIBLE_SELF)) { float *parent_pos = ob->runtime.parent_display_origin; - OVERLAY_extra_line_dashed(cb, parent_pos, ob->obmat[3], relation_color); + OVERLAY_extra_line_dashed(cb, parent_pos, ob->object_to_world[3], relation_color); } /* Drawing the hook lines. */ @@ -1263,9 +1266,9 @@ static void OVERLAY_relationship_lines(OVERLAY_ExtraCallBuffers *cb, if (md->type == eModifierType_Hook) { HookModifierData *hmd = (HookModifierData *)md; float center[3]; - mul_v3_m4v3(center, ob->obmat, hmd->cent); + mul_v3_m4v3(center, ob->object_to_world, hmd->cent); if (hmd->object) { - OVERLAY_extra_line_dashed(cb, hmd->object->obmat[3], center, relation_color); + OVERLAY_extra_line_dashed(cb, hmd->object->object_to_world[3], center, relation_color); } OVERLAY_extra_point(cb, center, relation_color); } @@ -1275,10 +1278,12 @@ static void OVERLAY_relationship_lines(OVERLAY_ExtraCallBuffers *cb, Object *rbc_ob1 = ob->rigidbody_constraint->ob1; Object *rbc_ob2 = ob->rigidbody_constraint->ob2; if (rbc_ob1 && (DRW_object_visibility_in_active_context(rbc_ob1) & OB_VISIBLE_SELF)) { - OVERLAY_extra_line_dashed(cb, rbc_ob1->obmat[3], ob->obmat[3], relation_color); + OVERLAY_extra_line_dashed( + cb, rbc_ob1->object_to_world[3], ob->object_to_world[3], relation_color); } if (rbc_ob2 && (DRW_object_visibility_in_active_context(rbc_ob2) & OB_VISIBLE_SELF)) { - OVERLAY_extra_line_dashed(cb, rbc_ob2->obmat[3], ob->obmat[3], relation_color); + OVERLAY_extra_line_dashed( + cb, rbc_ob2->object_to_world[3], ob->object_to_world[3], relation_color); } } @@ -1307,7 +1312,8 @@ static void OVERLAY_relationship_lines(OVERLAY_ExtraCallBuffers *cb, } if (camob) { - OVERLAY_extra_line_dashed(cb, camob->obmat[3], ob->obmat[3], constraint_color); + OVERLAY_extra_line_dashed( + cb, camob->object_to_world[3], ob->object_to_world[3], constraint_color); } } else { @@ -1330,7 +1336,7 @@ static void OVERLAY_relationship_lines(OVERLAY_ExtraCallBuffers *cb, else { unit_m4(ct->matrix); } - OVERLAY_extra_line_dashed(cb, ct->matrix[3], ob->obmat[3], constraint_color); + OVERLAY_extra_line_dashed(cb, ct->matrix[3], ob->object_to_world[3], constraint_color); } BKE_constraint_targets_flush(curcon, &targets, true); @@ -1387,7 +1393,7 @@ static void OVERLAY_volume_extra(OVERLAY_ExtraCallBuffers *cb, copy_v3_v3(voxel_cubemat[3], min); /* move small cube into the domain (otherwise its centered on vertex of domain object) */ translate_m4(voxel_cubemat, 1.0f, 1.0f, 1.0f); - mul_m4_m4m4(voxel_cubemat, ob->obmat, voxel_cubemat); + mul_m4_m4m4(voxel_cubemat, ob->object_to_world, voxel_cubemat); DRW_buffer_add_entry(cb->empty_cube, color, voxel_cubemat); } @@ -1493,15 +1499,15 @@ static void OVERLAY_object_center(OVERLAY_ExtraCallBuffers *cb, const bool is_library = ID_REAL_USERS(&ob->id) > 1 || ID_IS_LINKED(ob); BKE_view_layer_synced_ensure(scene, view_layer); if (ob == BKE_view_layer_active_object_get(view_layer)) { - DRW_buffer_add_entry(cb->center_active, ob->obmat[3]); + DRW_buffer_add_entry(cb->center_active, ob->object_to_world[3]); } else if (ob->base_flag & BASE_SELECTED) { DRWCallBuffer *cbuf = (is_library) ? cb->center_selected_lib : cb->center_selected; - DRW_buffer_add_entry(cbuf, ob->obmat[3]); + DRW_buffer_add_entry(cbuf, ob->object_to_world[3]); } else if (pd->v3d_flag & V3D_DRAW_CENTERS) { DRWCallBuffer *cbuf = (is_library) ? cb->center_deselected_lib : cb->center_deselected; - DRW_buffer_add_entry(cbuf, ob->obmat[3]); + DRW_buffer_add_entry(cbuf, ob->object_to_world[3]); } } @@ -1513,7 +1519,7 @@ static void OVERLAY_object_name(Object *ob, int theme_id) UI_GetThemeColor4ubv(theme_id, color); DRW_text_cache_add(dt, - ob->obmat[3], + ob->object_to_world[3], ob->id.name + 2, strlen(ob->id.name + 2), 10, @@ -1571,7 +1577,7 @@ void OVERLAY_extra_cache_populate(OVERLAY_Data *vedata, Object *ob) /* Helpers for when we're transforming origins. */ if (draw_xform) { const float color_xform[4] = {0.15f, 0.15f, 0.15f, 0.7f}; - DRW_buffer_add_entry(cb->origin_xform, color_xform, ob->obmat); + DRW_buffer_add_entry(cb->origin_xform, color_xform, ob->object_to_world); } /* don't show object extras in set's */ if (!from_dupli) { @@ -1591,7 +1597,7 @@ void OVERLAY_extra_cache_populate(OVERLAY_Data *vedata, Object *ob) OVERLAY_collision(cb, ob, color); } if (ob->dtx & OB_AXIS) { - DRW_buffer_add_entry(cb->empty_axes, color, ob->obmat); + DRW_buffer_add_entry(cb->empty_axes, color, ob->object_to_world); } if (draw_volume) { OVERLAY_volume_extra(cb, vedata, ob, md, scene, color); diff --git a/source/blender/draw/engines/overlay/overlay_gpencil.cc b/source/blender/draw/engines/overlay/overlay_gpencil.cc index 30765b30ce6..f5988d91e72 100644 --- a/source/blender/draw/engines/overlay/overlay_gpencil.cc +++ b/source/blender/draw/engines/overlay/overlay_gpencil.cc @@ -243,7 +243,7 @@ void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata) copy_v3_v3(col_grid, gpd->grid.color); col_grid[3] = max_ff(v3d->overlay.gpencil_grid_opacity, 0.01f); - copy_m4_m4(mat, ob->obmat); + copy_m4_m4(mat, ob->object_to_world); /* Rotate and scale except align to cursor. */ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); @@ -286,7 +286,7 @@ void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata) copy_v3_v3(mat[3], cursor->location); } else if (ts->gpencil_v3d_align & GP_PROJECT_VIEWSPACE) { - copy_v3_v3(mat[3], ob->obmat[3]); + copy_v3_v3(mat[3], ob->object_to_world[3]); } translate_m4(mat, gpd->grid.offset[0], gpd->grid.offset[1], 0.0f); @@ -397,7 +397,7 @@ static void overlay_gpencil_draw_stroke_color_name(bGPDlayer * /*gpl*/, UI_GetThemeColor4ubv(theme_id, color); float fpt[3]; - mul_v3_m4v3(fpt, ob->obmat, &pt->x); + mul_v3_m4v3(fpt, ob->object_to_world, &pt->x); struct DRWTextStore *dt = DRW_text_cache_ensure(); DRW_text_cache_add(dt, diff --git a/source/blender/draw/engines/overlay/overlay_image.cc b/source/blender/draw/engines/overlay/overlay_image.cc index f42867622e4..7b99bd6bd18 100644 --- a/source/blender/draw/engines/overlay/overlay_image.cc +++ b/source/blender/draw/engines/overlay/overlay_image.cc @@ -392,7 +392,7 @@ void OVERLAY_image_empty_cache_populate(OVERLAY_Data *vedata, Object *ob) float image_aspect[2]; overlay_image_calc_aspect(ima, size, image_aspect); - copy_m4_m4(mat, ob->obmat); + copy_m4_m4(mat, ob->object_to_world); mul_v3_fl(mat[0], image_aspect[0] * 0.5f * ob->empty_drawsize); mul_v3_fl(mat[1], image_aspect[1] * 0.5f * ob->empty_drawsize); madd_v3_v3fl(mat[3], mat[0], ob->ima_ofs[0] * 2.0f + 1.0f); diff --git a/source/blender/draw/engines/overlay/overlay_lattice.cc b/source/blender/draw/engines/overlay/overlay_lattice.cc index 7b59aa78c89..72c3335d871 100644 --- a/source/blender/draw/engines/overlay/overlay_lattice.cc +++ b/source/blender/draw/engines/overlay/overlay_lattice.cc @@ -52,7 +52,7 @@ void OVERLAY_lattice_cache_populate(OVERLAY_Data *vedata, Object *ob) DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color); struct GPUBatch *geom = DRW_cache_lattice_wire_get(ob, false); - OVERLAY_extra_wire(cb, geom, ob->obmat, color); + OVERLAY_extra_wire(cb, geom, ob->object_to_world, color); } void OVERLAY_edit_lattice_draw(OVERLAY_Data *vedata) diff --git a/source/blender/draw/engines/overlay/overlay_metaball.cc b/source/blender/draw/engines/overlay/overlay_metaball.cc index 2fc6910fe44..dd0a862337e 100644 --- a/source/blender/draw/engines/overlay/overlay_metaball.cc +++ b/source/blender/draw/engines/overlay/overlay_metaball.cc @@ -45,10 +45,10 @@ static void metaball_instance_data_set( BoneInstanceData *data, Object *ob, const float *pos, const float radius, const float color[4]) { /* Bone point radius is 0.05. Compensate for that. */ - mul_v3_v3fl(data->mat[0], ob->obmat[0], radius / 0.05f); - mul_v3_v3fl(data->mat[1], ob->obmat[1], radius / 0.05f); - mul_v3_v3fl(data->mat[2], ob->obmat[2], radius / 0.05f); - mul_v3_m4v3(data->mat[3], ob->obmat, pos); + mul_v3_v3fl(data->mat[0], ob->object_to_world[0], radius / 0.05f); + mul_v3_v3fl(data->mat[1], ob->object_to_world[1], radius / 0.05f); + mul_v3_v3fl(data->mat[2], ob->object_to_world[2], radius / 0.05f); + mul_v3_m4v3(data->mat[3], ob->object_to_world, pos); /* WATCH: Reminder, alpha is wire-size. */ OVERLAY_bone_instance_data_set_color(data, color); } diff --git a/source/blender/draw/engines/overlay/overlay_outline.cc b/source/blender/draw/engines/overlay/overlay_outline.cc index 3213fe144e9..c2df665eba3 100644 --- a/source/blender/draw/engines/overlay/overlay_outline.cc +++ b/source/blender/draw/engines/overlay/overlay_outline.cc @@ -43,7 +43,7 @@ static void gpencil_depth_plane(Object *ob, float r_plane[4]) add_v3_fl(size, 1e-8f); rescale_m4(mat, size); /* BBox space to World. */ - mul_m4_m4m4(mat, ob->obmat, mat); + mul_m4_m4m4(mat, ob->object_to_world, mat); /* BBox center in world space. */ copy_v3_v3(center, mat[3]); /* View Vector. */ @@ -188,7 +188,7 @@ static void gpencil_layer_cache_populate(bGPDlayer *gpl, const bool is_screenspace = (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS) != 0; const bool is_stroke_order_3d = (gpd->draw_mode == GP_DRAWMODE_3D); - float object_scale = mat4_to_scale(iter->ob->obmat); + float object_scale = mat4_to_scale(iter->ob->object_to_world); /* Negate thickness sign to tag that strokes are in screen space. * Convert to world units (by default, 1 meter = 2000 pixels). */ float thickness_scale = (is_screenspace) ? -1.0f : (gpd->pixfactor / 2000.0f); diff --git a/source/blender/draw/engines/overlay/overlay_viewer_attribute.cc b/source/blender/draw/engines/overlay/overlay_viewer_attribute.cc index c0d74ea73f3..fd1657b3d59 100644 --- a/source/blender/draw/engines/overlay/overlay_viewer_attribute.cc +++ b/source/blender/draw/engines/overlay/overlay_viewer_attribute.cc @@ -90,7 +90,7 @@ static void populate_cache_for_instance(Object &object, DRWShadingGroup *sub_grp = DRW_shgroup_create_sub(pd.viewer_attribute_instance_grp); DRW_shgroup_uniform_vec4_copy(sub_grp, "ucolor", color); GPUBatch *batch = DRW_cache_curve_edge_wire_get(&object); - DRW_shgroup_call_obmat(sub_grp, batch, object.obmat); + DRW_shgroup_call_obmat(sub_grp, batch, object.object_to_world); break; } case OB_CURVES: { @@ -135,7 +135,7 @@ static void populate_cache_for_geometry(Object &object, if (curves.attributes().contains(".viewer")) { GPUBatch *batch = DRW_cache_curve_edge_wire_viewer_attribute_get(&object); DRW_shgroup_uniform_float_copy(pd.viewer_attribute_curve_grp, "opacity", opacity); - DRW_shgroup_call_obmat(pd.viewer_attribute_curve_grp, batch, object.obmat); + DRW_shgroup_call_obmat(pd.viewer_attribute_curve_grp, batch, object.object_to_world); } break; } diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.cc b/source/blender/draw/engines/overlay/overlay_wireframe.cc index 7ee0e89f2f9..7053d0039cf 100644 --- a/source/blender/draw/engines/overlay/overlay_wireframe.cc +++ b/source/blender/draw/engines/overlay/overlay_wireframe.cc @@ -132,12 +132,12 @@ static void wireframe_hair_cache_populate(OVERLAY_Data *vedata, Object *ob, Part if (collection != nullptr) { sub_v3_v3(dupli_mat[3], collection->instance_offset); } - mul_m4_m4m4(dupli_mat, dupli_parent->obmat, dupli_mat); + mul_m4_m4m4(dupli_mat, dupli_parent->object_to_world, dupli_mat); } else { - copy_m4_m4(dupli_mat, dupli_object->ob->obmat); + copy_m4_m4(dupli_mat, dupli_object->ob->object_to_world); invert_m4(dupli_mat); - mul_m4_m4m4(dupli_mat, ob->obmat, dupli_mat); + mul_m4_m4m4(dupli_mat, ob->object_to_world, dupli_mat); } } else { @@ -217,7 +217,7 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, } if (geom) { - OVERLAY_extra_wire(cb, geom, ob->obmat, color); + OVERLAY_extra_wire(cb, geom, ob->object_to_world, color); } } @@ -230,12 +230,12 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, if (dupli->wire_shgrp == cb->extra_loose_points) { float *color; DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color); - OVERLAY_extra_loose_points(cb, dupli->wire_geom, ob->obmat, color); + OVERLAY_extra_loose_points(cb, dupli->wire_geom, ob->object_to_world, color); } else if (dupli->wire_shgrp == cb->extra_wire) { float *color; DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color); - OVERLAY_extra_wire(cb, dupli->wire_geom, ob->obmat, color); + OVERLAY_extra_wire(cb, dupli->wire_geom, ob->object_to_world, color); } else { DRW_shgroup_call(dupli->wire_shgrp, dupli->wire_geom, ob); @@ -264,7 +264,7 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, struct GPUBatch *geom = DRW_cache_object_face_wireframe_get(ob); if (geom) { - OVERLAY_extra_loose_points(cb, geom, ob->obmat, color); + OVERLAY_extra_loose_points(cb, geom, ob->object_to_world, color); } return; } @@ -318,14 +318,14 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, if (is_mesh_verts_only) { geom = DRW_cache_mesh_all_verts_get(ob); if (geom) { - OVERLAY_extra_loose_points(cb, geom, ob->obmat, color); + OVERLAY_extra_loose_points(cb, geom, ob->object_to_world, color); shgrp = cb->extra_loose_points; } } else { geom = DRW_cache_mesh_loose_edges_get(ob); if (geom) { - OVERLAY_extra_wire(cb, geom, ob->obmat, color); + OVERLAY_extra_wire(cb, geom, ob->object_to_world, color); shgrp = cb->extra_wire; } } diff --git a/source/blender/draw/engines/select/select_engine.c b/source/blender/draw/engines/select/select_engine.c index 026a1f52ac1..07e2a42b808 100644 --- a/source/blender/draw/engines/select/select_engine.c +++ b/source/blender/draw/engines/select/select_engine.c @@ -205,7 +205,7 @@ static void select_cache_populate(void *vedata, Object *ob) struct Mesh *me = ob->data; if (e_data.context.select_mode & SCE_SELECT_FACE) { struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); - DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->obmat); + DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->object_to_world); } else if (ob->dt >= OB_SOLID) { #ifdef USE_CAGE_OCCLUSION @@ -213,17 +213,17 @@ static void select_cache_populate(void *vedata, Object *ob) #else struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_surface(me); #endif - DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->obmat); + DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->object_to_world); } if (e_data.context.select_mode & SCE_SELECT_EDGE) { struct GPUBatch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); - DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_edges, ob->obmat); + DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_edges, ob->object_to_world); } if (e_data.context.select_mode & SCE_SELECT_VERTEX) { struct GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); - DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_verts, ob->obmat); + DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_verts, ob->object_to_world); } return; } @@ -231,7 +231,7 @@ static void select_cache_populate(void *vedata, Object *ob) float min[3], max[3]; select_id_object_min_max(ob, min, max); - if (DRW_culling_min_max_test(stl->g_data->view_subregion, ob->obmat, min, max)) { + if (DRW_culling_min_max_test(stl->g_data->view_subregion, ob->object_to_world, min, max)) { if (sel_data == NULL) { sel_data = (SELECTID_ObjectData *)DRW_drawdata_ensure( &ob->id, &draw_engine_select_type, sizeof(SELECTID_ObjectData), NULL, NULL); diff --git a/source/blender/draw/engines/workbench/workbench_shadow.c b/source/blender/draw/engines/workbench/workbench_shadow.c index 0b34e849049..eb4d546648a 100644 --- a/source/blender/draw/engines/workbench/workbench_shadow.c +++ b/source/blender/draw/engines/workbench/workbench_shadow.c @@ -172,7 +172,7 @@ static const BoundBox *workbench_shadow_object_shadow_bbox_get(WORKBENCH_Private { if (oed->shadow_bbox_dirty || wpd->shadow_changed) { float tmp_mat[4][4]; - mul_m4_m4m4(tmp_mat, wpd->shadow_inv, ob->obmat); + mul_m4_m4m4(tmp_mat, wpd->shadow_inv, ob->object_to_world); /* Get AABB in shadow space. */ INIT_MINMAX(oed->shadow_min, oed->shadow_max); diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c index ce7773e7439..7c6df93f5a3 100644 --- a/source/blender/draw/engines/workbench/workbench_volume.c +++ b/source/blender/draw/engines/workbench/workbench_volume.c @@ -237,7 +237,7 @@ static void workbench_volume_object_cache_populate(WORKBENCH_Data *vedata, /* Combined texture to object, and object to world transform. */ float texture_to_world[4][4]; - mul_m4_m4m4(texture_to_world, ob->obmat, grid->texture_to_object); + mul_m4_m4m4(texture_to_world, ob->object_to_world, grid->texture_to_object); if (use_slice) { float invviewmat[4][4]; @@ -291,7 +291,7 @@ static void workbench_volume_object_cache_populate(WORKBENCH_Data *vedata, /* Compute density scale. */ const float density_scale = volume->display.density * - BKE_volume_density_scale(volume, ob->obmat); + BKE_volume_density_scale(volume, ob->object_to_world); DRW_shgroup_uniform_texture(grp, "densityTexture", grid->texture); /* TODO: implement shadow texture, see manta_smoke_calc_transparency. */ diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.cc b/source/blender/draw/intern/draw_cache_impl_mesh.cc index 5ce658abfe4..031de3e4ef2 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.cc +++ b/source/blender/draw/intern/draw_cache_impl_mesh.cc @@ -1889,7 +1889,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, is_editmode, is_paint_mode, is_mode_active, - ob->obmat, + ob->object_to_world, false, true, scene, @@ -1906,7 +1906,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, is_editmode, is_paint_mode, is_mode_active, - ob->obmat, + ob->object_to_world, false, false, scene, @@ -1922,7 +1922,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, is_editmode, is_paint_mode, is_mode_active, - ob->obmat, + ob->object_to_world, true, false, do_cage, @@ -1943,7 +1943,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, is_editmode, is_paint_mode, is_mode_active, - ob->obmat, + ob->object_to_world, true, false, scene, diff --git a/source/blender/draw/intern/draw_curves.cc b/source/blender/draw/intern/draw_curves.cc index ee9045696be..ee9ed4666e0 100644 --- a/source/blender/draw/intern/draw_curves.cc +++ b/source/blender/draw/intern/draw_curves.cc @@ -390,7 +390,7 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object, DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &curves_cache->final[subdiv].strands_res, 1); DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res); DRW_shgroup_uniform_float_copy(shgrp, "hairRadShape", hair_rad_shape); - DRW_shgroup_uniform_mat4_copy(shgrp, "hairDupliMatrix", object->obmat); + DRW_shgroup_uniform_mat4_copy(shgrp, "hairDupliMatrix", object->object_to_world); DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", hair_rad_root); DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", hair_rad_tip); DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip); diff --git a/source/blender/draw/intern/draw_hair.cc b/source/blender/draw/intern/draw_hair.cc index 08e5d780cba..c5261f26f76 100644 --- a/source/blender/draw/intern/draw_hair.cc +++ b/source/blender/draw/intern/draw_hair.cc @@ -216,12 +216,12 @@ void DRW_hair_duplimat_get(Object *object, if (collection != nullptr) { sub_v3_v3(dupli_mat[3], collection->instance_offset); } - mul_m4_m4m4(dupli_mat, dupli_parent->obmat, dupli_mat); + mul_m4_m4m4(dupli_mat, dupli_parent->object_to_world, dupli_mat); } else { - copy_m4_m4(dupli_mat, dupli_object->ob->obmat); + copy_m4_m4(dupli_mat, dupli_object->ob->object_to_world); invert_m4(dupli_mat); - mul_m4_m4m4(dupli_mat, object->obmat, dupli_mat); + mul_m4_m4m4(dupli_mat, object->object_to_world, dupli_mat); } } else { diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index d0290426af3..4fcfec833eb 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -2801,7 +2801,7 @@ void DRW_draw_depth_object( GPU_matrix_projection_set(rv3d->winmat); GPU_matrix_set(rv3d->viewmat); - GPU_matrix_mul(object->obmat); + GPU_matrix_mul(object->object_to_world); /* Setup frame-buffer. */ GPUTexture *depth_tx = GPU_viewport_depth_texture(viewport); @@ -2821,11 +2821,11 @@ void DRW_draw_depth_object( const bool use_clipping_planes = RV3D_CLIPPING_ENABLED(v3d, rv3d); if (use_clipping_planes) { GPU_clip_distances(6); - ED_view3d_clipping_local(rv3d, object->obmat); + ED_view3d_clipping_local(rv3d, object->object_to_world); for (int i = 0; i < 6; i++) { copy_v4_v4(planes.world[i], rv3d->clip_local[i]); } - copy_m4_m4(planes.ModelMatrix, object->obmat); + copy_m4_m4(planes.ModelMatrix, object->object_to_world); } drw_batch_cache_validate(object); diff --git a/source/blender/draw/intern/draw_manager_data.cc b/source/blender/draw/intern/draw_manager_data.cc index 792db9d0a6b..4aa27e2288c 100644 --- a/source/blender/draw/intern/draw_manager_data.cc +++ b/source/blender/draw/intern/draw_manager_data.cc @@ -724,8 +724,8 @@ static void drw_call_culling_init(DRWCullingState *cull, Object *ob) float corner[3]; /* Get BoundSphere center and radius from the BoundBox. */ mid_v3_v3v3(cull->bsphere.center, bbox->vec[0], bbox->vec[6]); - mul_v3_m4v3(corner, ob->obmat, bbox->vec[0]); - mul_m4_v3(ob->obmat, cull->bsphere.center); + mul_v3_m4v3(corner, ob->object_to_world, bbox->vec[0]); + mul_m4_v3(ob->object_to_world, cull->bsphere.center); cull->bsphere.radius = len_v3v3(cull->bsphere.center, corner); /* Bypass test for very large objects (see T67319). */ @@ -1017,7 +1017,7 @@ void DRW_shgroup_call_ex(DRWShadingGroup *shgroup, if (G.f & G_FLAG_PICKSEL) { drw_command_set_select_id(shgroup, nullptr, DST.select_id); } - DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : obmat, ob); + DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->object_to_world : obmat, ob); drw_command_draw(shgroup, geom, handle); /* Culling data. */ @@ -1042,7 +1042,7 @@ void DRW_shgroup_call_range( if (G.f & G_FLAG_PICKSEL) { drw_command_set_select_id(shgroup, nullptr, DST.select_id); } - DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : nullptr, ob); + DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->object_to_world : nullptr, ob); drw_command_draw_range(shgroup, geom, handle, v_sta, v_num); } @@ -1053,7 +1053,7 @@ void DRW_shgroup_call_instance_range( if (G.f & G_FLAG_PICKSEL) { drw_command_set_select_id(shgroup, nullptr, DST.select_id); } - DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : nullptr, ob); + DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->object_to_world : nullptr, ob); drw_command_draw_intance_range(shgroup, geom, handle, i_sta, i_num); } @@ -1099,7 +1099,7 @@ static void drw_shgroup_call_procedural_add_ex(DRWShadingGroup *shgroup, if (G.f & G_FLAG_PICKSEL) { drw_command_set_select_id(shgroup, nullptr, DST.select_id); } - DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : nullptr, ob); + DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->object_to_world : nullptr, ob); drw_command_draw_procedural(shgroup, geom, handle, vert_count); } @@ -1149,7 +1149,7 @@ void DRW_shgroup_call_procedural_indirect(DRWShadingGroup *shgroup, if (G.f & G_FLAG_PICKSEL) { drw_command_set_select_id(shgroup, nullptr, DST.select_id); } - DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : nullptr, ob); + DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->object_to_world : nullptr, ob); drw_command_draw_indirect(shgroup, geom, handle, indirect_buf); } @@ -1159,7 +1159,7 @@ void DRW_shgroup_call_instances(DRWShadingGroup *shgroup, Object *ob, GPUBatch * if (G.f & G_FLAG_PICKSEL) { drw_command_set_select_id(shgroup, nullptr, DST.select_id); } - DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : nullptr, ob); + DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->object_to_world : nullptr, ob); drw_command_draw_instance(shgroup, geom, handle, count, false); } @@ -1173,7 +1173,7 @@ void DRW_shgroup_call_instances_with_attrs(DRWShadingGroup *shgroup, if (G.f & G_FLAG_PICKSEL) { drw_command_set_select_id(shgroup, nullptr, DST.select_id); } - DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : nullptr, ob); + DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->object_to_world : nullptr, ob); GPUBatch *batch = DRW_temp_batch_instance_request( DST.vmempool->idatalist, nullptr, inst_attributes, geom); drw_command_draw_instance(shgroup, batch, handle, 0, true); @@ -1283,7 +1283,7 @@ static void drw_sculpt_get_frustum_planes(Object *ob, float planes[6][4]) * 4x4 matrix is done by multiplying with the transpose inverse. * The inverse cancels out here since we transform by inverse(obmat). */ float tmat[4][4]; - transpose_m4_m4(tmat, ob->obmat); + transpose_m4_m4(tmat, ob->object_to_world); for (int i = 0; i < 6; i++) { mul_m4_v4(tmat, planes[i]); } @@ -1361,7 +1361,7 @@ static void drw_sculpt_generate_calls(DRWSculptCallbackData *scd) if (SCULPT_DEBUG_BUFFERS) { int debug_node_nr = 0; - DRW_debug_modelmat(scd->ob->obmat); + DRW_debug_modelmat(scd->ob->object_to_world); BKE_pbvh_draw_debug_cb( pbvh, (void (*)(PBVHNode * n, void *d, const float min[3], const float max[3], PBVHNodeFlags f)) diff --git a/source/blender/draw/intern/draw_manager_text.cc b/source/blender/draw/intern/draw_manager_text.cc index 100ef528bc8..239f6fcca73 100644 --- a/source/blender/draw/intern/draw_manager_text.cc +++ b/source/blender/draw/intern/draw_manager_text.cc @@ -305,11 +305,11 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region, if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) { mid_v3_v3v3(vmid, v1_clip, v2_clip); - mul_m4_v3(ob->obmat, vmid); + mul_m4_v3(ob->object_to_world, vmid); if (do_global) { - mul_mat3_m4_v3(ob->obmat, v1); - mul_mat3_m4_v3(ob->obmat, v2); + mul_mat3_m4_v3(ob->object_to_world, v1); + mul_mat3_m4_v3(ob->object_to_world, v2); } if (unit->system) { @@ -373,7 +373,7 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region, float angle; mid_v3_v3v3(vmid, v1_clip, v2_clip); - mul_m4_v3(ob->obmat, vmid); + mul_m4_v3(ob->object_to_world, vmid); if (use_coords) { copy_v3_v3(no_a, poly_normals[BM_elem_index_get(l_a->f)]); @@ -443,16 +443,16 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region, n += 3; if (do_global) { - mul_mat3_m4_v3(ob->obmat, v1); - mul_mat3_m4_v3(ob->obmat, v2); - mul_mat3_m4_v3(ob->obmat, v3); + mul_mat3_m4_v3(ob->object_to_world, v1); + mul_mat3_m4_v3(ob->object_to_world, v2); + mul_mat3_m4_v3(ob->object_to_world, v3); } area += area_tri_v3(v1, v2, v3); } mul_v3_fl(vmid, 1.0f / float(n)); - mul_m4_v3(ob->obmat, vmid); + mul_m4_v3(ob->object_to_world, vmid); if (unit->system) { numstr_len = BKE_unit_value_as_string( @@ -522,9 +522,9 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region, copy_v3_v3(v2_local, v2); if (do_global) { - mul_mat3_m4_v3(ob->obmat, v1); - mul_mat3_m4_v3(ob->obmat, v2); - mul_mat3_m4_v3(ob->obmat, v3); + mul_mat3_m4_v3(ob->object_to_world, v1); + mul_mat3_m4_v3(ob->object_to_world, v2); + mul_mat3_m4_v3(ob->object_to_world, v3); } float angle = angle_v3v3v3(v1, v2, v3); @@ -535,7 +535,7 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region, (is_rad) ? angle : RAD2DEGF(angle), (is_rad) ? "r" : "°"); interp_v3_v3v3(fvec, vmid, v2_local, 0.8f); - mul_m4_v3(ob->obmat, fvec); + mul_m4_v3(ob->object_to_world, fvec); DRW_text_cache_add(dt, fvec, numstr, numstr_len, 0, 0, txt_flag, col); } } @@ -566,7 +566,7 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region, copy_v3_v3(v1, v->co); } - mul_m4_v3(ob->obmat, v1); + mul_m4_v3(ob->object_to_world, v1); numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); DRW_text_cache_add(dt, v1, numstr, numstr_len, 0, 0, txt_flag, col); @@ -595,7 +595,7 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region, if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) { mid_v3_v3v3(vmid, v1_clip, v2_clip); - mul_m4_v3(ob->obmat, vmid); + mul_m4_v3(ob->object_to_world, vmid); numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); DRW_text_cache_add( @@ -629,7 +629,7 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region, BM_face_calc_center_median(f, v1); } - mul_m4_v3(ob->obmat, v1); + mul_m4_v3(ob->object_to_world, v1); numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); DRW_text_cache_add(dt, v1, numstr, numstr_len, 0, 0, txt_flag, col); diff --git a/source/blender/draw/intern/draw_resource.hh b/source/blender/draw/intern/draw_resource.hh index 2df38e32ed2..b116d7fe183 100644 --- a/source/blender/draw/intern/draw_resource.hh +++ b/source/blender/draw/intern/draw_resource.hh @@ -31,7 +31,7 @@ inline void ObjectMatrices::sync(const Object &object) { - model = object.obmat; + model = object.object_to_world; model_inverse = object.imat; } diff --git a/source/blender/draw/intern/draw_volume.cc b/source/blender/draw/intern/draw_volume.cc index 2b4b0e3c089..5c1ce7c3111 100644 --- a/source/blender/draw/intern/draw_volume.cc +++ b/source/blender/draw/intern/draw_volume.cc @@ -127,7 +127,7 @@ static DRWShadingGroup *drw_volume_object_grids_init(Object *ob, grp = DRW_shgroup_create_sub(grp); - volume_infos.density_scale = BKE_volume_density_scale(volume, ob->obmat); + volume_infos.density_scale = BKE_volume_density_scale(volume, ob->object_to_world); volume_infos.color_mul = float4(1.0f); volume_infos.temperature_mul = 1.0f; volume_infos.temperature_bias = 0.0f; diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c index 23c1d68b4d6..4a83bb4c800 100644 --- a/source/blender/editors/animation/anim_motion_paths.c +++ b/source/blender/editors/animation/anim_motion_paths.c @@ -161,11 +161,11 @@ static void motionpaths_calc_bake_targets(ListBase *targets, int cframe) } /* Result must be in world-space. */ - mul_m4_v3(ob_eval->obmat, mpv->co); + mul_m4_v3(ob_eval->object_to_world, mpv->co); } else { /* World-space object location. */ - copy_v3_v3(mpv->co, ob_eval->obmat[3]); + copy_v3_v3(mpv->co, ob_eval->object_to_world[3]); } float mframe = (float)(cframe); diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index c9957b38853..96a9604a6f5 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -1044,12 +1044,12 @@ static float *visualkey_get_values( Object *ob = ptr->data; /* Loc code is specific... */ if (strstr(identifier, "location")) { - copy_v3_v3(buffer, ob->obmat[3]); + copy_v3_v3(buffer, ob->object_to_world[3]); *r_count = 3; return buffer; } - copy_m4_m4(tmat, ob->obmat); + copy_m4_m4(tmat, ob->object_to_world); rotmode = ob->rotmode; } else if (ptr->type == &RNA_PoseBone) { diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index 17484b2b0b7..fbdb375b8a6 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -181,13 +181,13 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op)) const View3DCursor *curs = &scene->cursor; copy_v3_v3(newbone->tail, curs->location); - sub_v3_v3v3(newbone->tail, newbone->tail, obedit->obmat[3]); + sub_v3_v3v3(newbone->tail, newbone->tail, obedit->object_to_world[3]); if (a == 1) { newbone->tail[0] = -newbone->tail[0]; } - copy_m3_m4(mat, obedit->obmat); + copy_m3_m4(mat, obedit->object_to_world); invert_m3_m3(imat, mat); mul_m3_v3(imat, newbone->tail); @@ -1569,7 +1569,7 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op) copy_v3_v3(curs, CTX_data_scene(C)->cursor.location); /* Get inverse point for head and orientation for tail */ - invert_m4_m4(obedit->imat, obedit->obmat); + invert_m4_m4(obedit->imat, obedit->object_to_world); mul_m4_v3(obedit->imat, curs); if (rv3d && (U.flag & USER_ADD_VIEWALIGNED)) { @@ -1579,7 +1579,7 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op) unit_m3(obmat); } - copy_m3_m4(viewmat, obedit->obmat); + copy_m3_m4(viewmat, obedit->object_to_world); mul_m3_m3m3(totmat, obmat, viewmat); invert_m3_m3(imat, totmat); diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c index 9e828ebd501..810279f1b6c 100644 --- a/source/blender/editors/armature/armature_edit.c +++ b/source/blender/editors/armature/armature_edit.c @@ -113,7 +113,7 @@ void ED_armature_origin_set( /* Find the center-point. */ if (centermode == 2) { copy_v3_v3(cent, cursor); - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); mul_m4_v3(ob->imat, cent); } else { @@ -154,7 +154,7 @@ void ED_armature_origin_set( /* Adjust object location for new center-point. */ if (centermode && (is_editmode == false)) { - mul_mat3_m4_v3(ob->obmat, cent); /* omit translation part */ + mul_mat3_m4_v3(ob->object_to_world, cent); /* omit translation part */ add_v3_v3(ob->loc, cent); } } @@ -282,14 +282,14 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op) axis_flip = true; } - copy_m3_m4(imat, ob->obmat); + copy_m3_m4(imat, ob->object_to_world); invert_m3(imat); if (type == CALC_ROLL_CURSOR) { /* Cursor */ float cursor_local[3]; const View3DCursor *cursor = &scene->cursor; - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); copy_v3_v3(cursor_local, cursor->location); mul_m4_v3(ob->imat, cursor_local); @@ -730,7 +730,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op) ebp = points.first; /* Get points - cursor (tail) */ - invert_m4_m4(obedit->imat, obedit->obmat); + invert_m4_m4(obedit->imat, obedit->object_to_world); mul_v3_m4v3(curs, obedit->imat, scene->cursor.location); /* Create a bone */ @@ -767,7 +767,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op) float dist_sq_a, dist_sq_b; /* get cursor location */ - invert_m4_m4(obedit->imat, obedit->obmat); + invert_m4_m4(obedit->imat, obedit->object_to_world); mul_v3_m4v3(curs, obedit->imat, scene->cursor.location); /* get distances */ diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index 9f1883ccac0..fccf2964868 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -289,7 +289,7 @@ int ED_armature_join_objects_exec(bContext *C, wmOperator *op) /* Inverse transform for all selected armatures in this object, * See #object_join_exec for detailed comment on why the safe version is used. */ - invert_m4_m4_safe_ortho(oimat, ob_active->obmat); + invert_m4_m4_safe_ortho(oimat, ob_active->object_to_world); /* Get edit-bones of active armature to add edit-bones to */ ED_armature_to_edit(arm); @@ -321,7 +321,7 @@ int ED_armature_join_objects_exec(bContext *C, wmOperator *op) // BASACT->flag &= ~OB_MODE_POSE; /* Find the difference matrix */ - mul_m4_m4m4(mat, oimat, ob_iter->obmat); + mul_m4_m4m4(mat, oimat, ob_iter->object_to_world); /* Copy bones and posechannels from the object to the edit armature */ for (pchan = opose->chanbase.first; pchan; pchan = pchann) { diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index 6b8f790d30f..3ee0510ca7f 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -1601,8 +1601,8 @@ static const EnumPropertyItem prop_similar_types[] = { static float bone_length_squared_worldspace_get(Object *ob, EditBone *ebone) { float v1[3], v2[3]; - mul_v3_mat3_m4v3(v1, ob->obmat, ebone->head); - mul_v3_mat3_m4v3(v2, ob->obmat, ebone->tail); + mul_v3_mat3_m4v3(v1, ob->object_to_world, ebone->head); + mul_v3_mat3_m4v3(v2, ob->object_to_world, ebone->tail); return len_squared_v3v3(v1, v2); } @@ -1650,8 +1650,8 @@ static void bone_direction_worldspace_get(Object *ob, EditBone *ebone, float *r_ copy_v3_v3(v1, ebone->head); copy_v3_v3(v2, ebone->tail); - mul_m4_v3(ob->obmat, v1); - mul_m4_v3(ob->obmat, v2); + mul_m4_v3(ob->object_to_world, v1); + mul_m4_v3(ob->object_to_world, v2); sub_v3_v3v3(r_dir, v1, v2); normalize_v3(r_dir); diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c index 6155aac621d..3c9c8cf05b3 100644 --- a/source/blender/editors/armature/armature_skinning.c +++ b/source/blender/editors/armature/armature_skinning.c @@ -365,8 +365,8 @@ static void add_verts_to_dgroups(ReportList *reports, copy_v3_v3(tip[j], bone->arm_tail); } - mul_m4_v3(par->obmat, root[j]); - mul_m4_v3(par->obmat, tip[j]); + mul_m4_v3(par->object_to_world, root[j]); + mul_m4_v3(par->object_to_world, tip[j]); /* set selected */ if (wpmode) { @@ -414,7 +414,7 @@ static void add_verts_to_dgroups(ReportList *reports, if (!vertsfilled) { copy_v3_v3(verts[i], mesh_verts[i].co); } - mul_m4_v3(ob->obmat, verts[i]); + mul_m4_v3(ob->object_to_world, verts[i]); } /* compute the weights based on gathered vertices and bones */ @@ -438,7 +438,7 @@ static void add_verts_to_dgroups(ReportList *reports, root, tip, selected, - mat4_to_scale(par->obmat)); + mat4_to_scale(par->object_to_world)); } /* only generated in some cases but can call anyway */ diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 567977e51c4..dfb9e8a79fa 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -1788,11 +1788,11 @@ void ED_mesh_deform_bind_callback(Object *object, mmd_orig->bindcagecos = (float *)mdb.cagecos; mmd_orig->verts_num = mdb.verts_num; mmd_orig->cage_verts_num = mdb.cage_verts_num; - copy_m4_m4(mmd_orig->bindmat, mmd_orig->object->obmat); + copy_m4_m4(mmd_orig->bindmat, mmd_orig->object->object_to_world); /* transform bindcagecos to world space */ for (a = 0; a < mdb.cage_verts_num; a++) { - mul_m4_v3(mmd_orig->object->obmat, mmd_orig->bindcagecos + a * 3); + mul_m4_v3(mmd_orig->object->object_to_world, mmd_orig->bindcagecos + a * 3); } /* free */ diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index f92b72bbb66..51071815823 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -77,10 +77,10 @@ static void applyarmature_fix_boneparents(const bContext *C, Scene *scene, Objec /* apply current transform from parent (not yet destroyed), * then calculate new parent inverse matrix */ - BKE_object_apply_mat4(ob, ob->obmat, false, false); + BKE_object_apply_mat4(ob, ob->object_to_world, false, false); BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob); - invert_m4_m4(ob->parentinv, workob.obmat); + invert_m4_m4(ob->parentinv, workob.object_to_world); } } } diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 61e92f0a1c3..2b6cce25bb7 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -4999,7 +4999,7 @@ bool ed_editnurb_spin( invert_m3_m3(persinv, persmat); /* imat and center and size */ - copy_m3_m4(bmat, obedit->obmat); + copy_m3_m4(bmat, obedit->object_to_world); invert_m3_m3(imat, bmat); axis_angle_to_mat3(cmat, axis, M_PI_4); @@ -5095,7 +5095,7 @@ static int spin_exec(bContext *C, wmOperator *op) continue; } - invert_m4_m4(obedit->imat, obedit->obmat); + invert_m4_m4(obedit->imat, obedit->object_to_world); mul_m4_v3(obedit->imat, cent); if (!ed_editnurb_spin(viewmat, v3d, obedit, axis, cent)) { @@ -5574,7 +5574,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op) RNA_float_get_array(op->ptr, "location", location); - invert_m4_m4(imat, obedit->obmat); + invert_m4_m4(imat, obedit->object_to_world); mul_m4_v3(imat, location); if (ed_editcurve_addvert(cu, editnurb, v3d, location)) { @@ -5614,10 +5614,10 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event) ED_curve_nurb_vert_selected_find(cu, vc.v3d, &nu, &bezt, &bp); if (bezt) { - mul_v3_m4v3(location, vc.obedit->obmat, bezt->vec[1]); + mul_v3_m4v3(location, vc.obedit->object_to_world, bezt->vec[1]); } else if (bp) { - mul_v3_m4v3(location, vc.obedit->obmat, bp->vec); + mul_v3_m4v3(location, vc.obedit->object_to_world, bp->vec); } else { copy_v3_v3(location, vc.scene->cursor.location); @@ -5662,8 +5662,8 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event) /* get the plane */ float plane[4]; /* only normalize to avoid precision errors */ - normalize_v3_v3(plane, vc.obedit->obmat[2]); - plane[3] = -dot_v3v3(plane, vc.obedit->obmat[3]); + normalize_v3_v3(plane, vc.obedit->object_to_world[2]); + plane[3] = -dot_v3v3(plane, vc.obedit->object_to_world[3]); if (fabsf(dot_v3v3(view_dir, plane)) < eps) { /* can't project on an aligned plane. */ @@ -6924,7 +6924,7 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op) /* Inverse transform for all selected curves in this object, * See #object_join_exec for detailed comment on why the safe version is used. */ - invert_m4_m4_safe_ortho(imat, ob_active->obmat); + invert_m4_m4_safe_ortho(imat, ob_active->object_to_world); Curve *cu_active = ob_active->data; @@ -6936,7 +6936,7 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op) if (cu->nurb.first) { /* watch it: switch order here really goes wrong */ - mul_m4_m4m4(cmat, imat, ob_iter->obmat); + mul_m4_m4m4(cmat, imat, ob_iter->object_to_world); /* Compensate for different bevel depth. */ bool do_radius = false; diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c index 7632f1b1e64..1e91e2f48fc 100644 --- a/source/blender/editors/curve/editcurve_paint.c +++ b/source/blender/editors/curve/editcurve_paint.c @@ -148,7 +148,7 @@ static void stroke_elem_pressure_set(const struct CurveDrawData *cdd, const float adjust = stroke_elem_radius_from_pressure(cdd, pressure) - stroke_elem_radius_from_pressure(cdd, selem->pressure); madd_v3_v3fl(selem->location_local, selem->normal_local, adjust); - mul_v3_m4v3(selem->location_world, cdd->vc.obedit->obmat, selem->location_local); + mul_v3_m4v3(selem->location_world, cdd->vc.obedit->object_to_world, selem->location_local); } selem->pressure = pressure; } @@ -249,7 +249,7 @@ static bool stroke_elem_project_fallback(const struct CurveDrawData *cdd, if (!is_zero_v3(r_normal_world)) { copy_v3_v3(r_normal_local, r_normal_world); - mul_transposed_mat3_m4_v3(cdd->vc.obedit->obmat, r_normal_local); + mul_transposed_mat3_m4_v3(cdd->vc.obedit->object_to_world, r_normal_local); normalize_v3(r_normal_local); } else { @@ -367,7 +367,7 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), /* scale to edit-mode space */ GPU_matrix_push(); - GPU_matrix_mul(obedit->obmat); + GPU_matrix_mul(obedit->object_to_world); BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) { @@ -445,7 +445,7 @@ static void curve_draw_event_add(wmOperator *op, const wmEvent *event) struct CurveDrawData *cdd = op->customdata; Object *obedit = cdd->vc.obedit; - invert_m4_m4(obedit->imat, obedit->obmat); + invert_m4_m4(obedit->imat, obedit->object_to_world); struct StrokeElem *selem = BLI_mempool_calloc(cdd->stroke_elem_pool); @@ -758,7 +758,7 @@ static int curve_draw_exec(bContext *C, wmOperator *op) int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool); const bool is_3d = (cu->flag & CU_3D) != 0; - invert_m4_m4(obedit->imat, obedit->obmat); + invert_m4_m4(obedit->imat, obedit->object_to_world); if (BLI_mempool_len(cdd->stroke_elem_pool) == 0) { curve_draw_stroke_from_operator(op); @@ -1073,8 +1073,8 @@ static int curve_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event) if (CU_IS_2D(cu)) { /* 2D overrides other options */ - plane_co = obedit->obmat[3]; - plane_no = obedit->obmat[2]; + plane_co = obedit->object_to_world[3]; + plane_no = obedit->object_to_world[2]; cdd->project.use_plane = true; } else { diff --git a/source/blender/editors/curve/editcurve_pen.c b/source/blender/editors/curve/editcurve_pen.c index f71173f951e..b57ce6fc7cf 100644 --- a/source/blender/editors/curve/editcurve_pen.c +++ b/source/blender/editors/curve/editcurve_pen.c @@ -152,8 +152,8 @@ static void update_location_for_2d_curve(const ViewContext *vc, float location[3 /* Get the plane. */ float plane[4]; /* Only normalize to avoid precision errors. */ - normalize_v3_v3(plane, vc->obedit->obmat[2]); - plane[3] = -dot_v3v3(plane, vc->obedit->obmat[3]); + normalize_v3_v3(plane, vc->obedit->object_to_world[2]); + plane[3] = -dot_v3v3(plane, vc->obedit->object_to_world[3]); if (fabsf(dot_v3v3(view_dir, plane)) < eps) { /* Can't project on an aligned plane. */ @@ -173,7 +173,7 @@ static void update_location_for_2d_curve(const ViewContext *vc, float location[3 } float imat[4][4]; - invert_m4_m4(imat, vc->obedit->obmat); + invert_m4_m4(imat, vc->obedit->object_to_world); mul_m4_v3(imat, location); if (CU_IS_2D(cu)) { @@ -186,7 +186,7 @@ static void screenspace_to_worldspace(const ViewContext *vc, const float depth[3], float r_pos_3d[3]) { - mul_v3_m4v3(r_pos_3d, vc->obedit->obmat, depth); + mul_v3_m4v3(r_pos_3d, vc->obedit->object_to_world, depth); ED_view3d_win_to_3d(vc->v3d, vc->region, r_pos_3d, pos_2d, r_pos_3d); update_location_for_2d_curve(vc, r_pos_3d); } @@ -1082,7 +1082,7 @@ static void extrude_points_from_selected_vertices(const ViewContext *vc, float location[3]; if (sel_exists) { - mul_v3_m4v3(location, vc->obedit->obmat, center); + mul_v3_m4v3(location, vc->obedit->object_to_world, center); } else { copy_v3_v3(location, vc->scene->cursor.location); diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c index 9c0c580f699..da742dd0c61 100644 --- a/source/blender/editors/curve/editcurve_select.c +++ b/source/blender/editors/curve/editcurve_select.c @@ -1517,7 +1517,7 @@ static void nurb_bezt_direction_worldspace_get(Object *ob, { float rsmat[3][3]; BKE_nurb_bezt_calc_normal(nu, bezt, r_dir); - copy_m3_m4(rsmat, ob->obmat); + copy_m3_m4(rsmat, ob->object_to_world); mul_m3_v3(rsmat, r_dir); normalize_v3(r_dir); } @@ -1526,7 +1526,7 @@ static void nurb_bpoint_direction_worldspace_get(Object *ob, Nurb *nu, BPoint *b { float rsmat[3][3]; BKE_nurb_bpoint_calc_normal(nu, bp, r_dir); - copy_m3_m4(rsmat, ob->obmat); + copy_m3_m4(rsmat, ob->object_to_world); mul_m3_v3(rsmat, r_dir); normalize_v3(r_dir); } diff --git a/source/blender/editors/curves/intern/curves_ops.cc b/source/blender/editors/curves/intern/curves_ops.cc index 38b2b2071b8..1d2b1264477 100644 --- a/source/blender/editors/curves/intern/curves_ops.cc +++ b/source/blender/editors/curves/intern/curves_ops.cc @@ -435,7 +435,7 @@ static bke::CurvesGeometry particles_to_curves(Object &object, ParticleSystem &p bke::CurvesGeometry curves(points_num, curves_num); curves.offsets_for_write().copy_from(curve_offsets); - const float4x4 object_to_world_mat = object.obmat; + const float4x4 object_to_world_mat = object.object_to_world; const float4x4 world_to_object_mat = object_to_world_mat.inverted(); MutableSpan positions = curves.positions_for_write(); @@ -497,7 +497,7 @@ static int curves_convert_from_particle_system_exec(bContext *C, wmOperator * /* Object *ob_new = BKE_object_add(&bmain, &scene, &view_layer, OB_CURVES, psys_eval->name); Curves *curves_id = static_cast(ob_new->data); - BKE_object_apply_mat4(ob_new, ob_from_orig->obmat, true, false); + BKE_object_apply_mat4(ob_new, ob_from_orig->object_to_world, true, false); bke::CurvesGeometry::wrap(curves_id->geometry) = particles_to_curves(*ob_from_eval, *psys_eval); DEG_relations_tag_update(&bmain); diff --git a/source/blender/editors/gizmo_library/gizmo_library_presets.c b/source/blender/editors/gizmo_library/gizmo_library_presets.c index 1ac4ce0bcdf..465c72dd44f 100644 --- a/source/blender/editors/gizmo_library/gizmo_library_presets.c +++ b/source/blender/editors/gizmo_library/gizmo_library_presets.c @@ -114,7 +114,7 @@ void ED_gizmo_draw_preset_facemap( } GPU_matrix_push(); - GPU_matrix_mul(ob->obmat); + GPU_matrix_mul(ob->object_to_world); ED_draw_object_facemap(depsgraph, ob, color, facemap); GPU_matrix_pop(); diff --git a/source/blender/editors/gpencil/gpencil_armature.c b/source/blender/editors/gpencil/gpencil_armature.c index 5f5a4b41b27..2b7e09b7f05 100644 --- a/source/blender/editors/gpencil/gpencil_armature.c +++ b/source/blender/editors/gpencil/gpencil_armature.c @@ -329,8 +329,8 @@ static void gpencil_add_verts_to_dgroups( copy_v3_v3(tip[j], bone->arm_tail); } - mul_m4_v3(ob_arm->obmat, root[j]); - mul_m4_v3(ob_arm->obmat, tip[j]); + mul_m4_v3(ob_arm->object_to_world, root[j]); + mul_m4_v3(ob_arm->object_to_world, tip[j]); selected[j] = 1; @@ -364,7 +364,7 @@ static void gpencil_add_verts_to_dgroups( /* transform stroke points to global space */ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { copy_v3_v3(verts[i], &pt->x); - mul_m4_v3(ob->obmat, verts[i]); + mul_m4_v3(ob->object_to_world, verts[i]); } /* loop groups and assign weight */ diff --git a/source/blender/editors/gpencil/gpencil_bake_animation.cc b/source/blender/editors/gpencil/gpencil_bake_animation.cc index 1535fd614fe..4ef2cf9ffd6 100644 --- a/source/blender/editors/gpencil/gpencil_bake_animation.cc +++ b/source/blender/editors/gpencil/gpencil_bake_animation.cc @@ -222,7 +222,7 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0; ob_gpencil = ED_gpencil_add_object(C, scene->cursor.location, local_view_bits); float invmat[4][4]; - invert_m4_m4(invmat, ob_gpencil->obmat); + invert_m4_m4(invmat, ob_gpencil->object_to_world); bGPdata *gpd_dst = (bGPdata *)ob_gpencil->data; gpd_dst->draw_mode = GP_DRAWMODE_2D; @@ -323,7 +323,7 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op bGPDspoint *pt = &gps->points[j]; pt->runtime.idx_orig = 0; pt->runtime.pt_orig = nullptr; - mul_m4_v3(ob_eval->obmat, &pt->x); + mul_m4_v3(ob_eval->object_to_world, &pt->x); mul_m4_v3(invmat, &pt->x); } diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index c6d7eb294fb..0417694d7bd 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -2914,8 +2914,8 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) float offset_global[3]; float offset_local[3]; - sub_v3_v3v3(offset_global, ob_active->loc, ob_iter->obmat[3]); - copy_m3_m4(bmat, ob_active->obmat); + sub_v3_v3v3(offset_global, ob_active->loc, ob_iter->object_to_world[3]); + copy_m3_m4(bmat, ob_active->object_to_world); /* Inverse transform for all selected curves in this object, * See #object_join_exec for detailed comment on why the safe version is used. */ diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 66f86a3e0c1..f9b40a4c79b 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -4162,7 +4162,7 @@ static int gpencil_stroke_outline_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); Object *cam_ob = scene->camera; if (cam_ob != NULL) { - invert_m4_m4(viewmat, cam_ob->obmat); + invert_m4_m4(viewmat, cam_ob->object_to_world); } break; } @@ -4229,7 +4229,7 @@ static int gpencil_stroke_outline_exec(bContext *C, wmOperator *op) /* Apply layer thickness change. */ gps_duplicate->thickness += gpl->line_change; /* Apply object scale to thickness. */ - gps_duplicate->thickness *= mat4_to_scale(ob->obmat); + gps_duplicate->thickness *= mat4_to_scale(ob->object_to_world); CLAMP_MIN(gps_duplicate->thickness, 1.0f); /* Stroke. */ diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index b94b413edc2..5c88e719b8c 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -317,7 +317,7 @@ static void add_endpoint_radius_help(tGPDfill *tgpf, /* Rotate to object rotation. */ sub_v3_v3(&pt->x, endpoint); - mul_mat3_m4_v3(tgpf->ob->obmat, &pt->x); + mul_mat3_m4_v3(tgpf->ob->object_to_world, &pt->x); add_v3_v3(&pt->x, endpoint); } } diff --git a/source/blender/editors/gpencil/gpencil_mesh.cc b/source/blender/editors/gpencil/gpencil_mesh.cc index d847fbe2aea..2b01fce5bf8 100644 --- a/source/blender/editors/gpencil/gpencil_mesh.cc +++ b/source/blender/editors/gpencil/gpencil_mesh.cc @@ -299,7 +299,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) angle, thickness, offset, - ob_eval->obmat, + ob_eval->object_to_world, frame_offset, use_seams, use_faces, diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index a82288e3377..d2ed1720bf8 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -936,7 +936,7 @@ static bGPDstroke *gpencil_stroke_to_outline(tGPsdata *p, bGPDstroke *gps) /* Apply layer thickness change. */ gps_duplicate->thickness += gpl->line_change; /* Apply object scale to thickness. */ - gps_duplicate->thickness *= mat4_to_scale(p->ob->obmat); + gps_duplicate->thickness *= mat4_to_scale(p->ob->object_to_world); CLAMP_MIN(gps_duplicate->thickness, 1.0f); /* Stroke. */ diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index 3b7336f41e8..515bdeb6188 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -671,7 +671,7 @@ static bool gpencil_brush_pinch_apply(tGP_BrushEditData *gso, /* 1) Make this point relative to the cursor/midpoint (dvec) */ float fpt[3]; - mul_v3_m4v3(fpt, gso->object->obmat, &pt->x); + mul_v3_m4v3(fpt, gso->object->object_to_world, &pt->x); sub_v3_v3v3(vec, fpt, gso->dvec); /* 2) Shrink the distance by pulling the point towards the midpoint @@ -743,7 +743,7 @@ static bool gpencil_brush_twist_apply(tGP_BrushEditData *gso, /* Rotate point */ float fpt[3]; - mul_v3_m4v3(fpt, gso->object->obmat, &pt->x); + mul_v3_m4v3(fpt, gso->object->object_to_world, &pt->x); sub_v3_v3v3(vec, fpt, gso->dvec); /* make relative to center * (center is stored in dvec) */ mul_m3_v3(rmat, vec); @@ -1037,7 +1037,7 @@ static void gpencil_brush_clone_add(bContext *C, tGP_BrushEditData *gso) */ for (i = 0, pt = new_stroke->points; i < new_stroke->totpoints; i++, pt++) { /* Rotate around center new position */ - mul_mat3_m4_v3(gso->object->obmat, &pt->x); /* only rotation component */ + mul_mat3_m4_v3(gso->object->object_to_world, &pt->x); /* only rotation component */ /* assume that the delta can just be applied, and then everything works */ add_v3_v3(&pt->x, delta); @@ -1172,7 +1172,7 @@ static bool gpencil_sculpt_brush_init(bContext *C, wmOperator *op) gso->object = ob; if (ob) { float matrix[4][4]; - copy_m4_m4(matrix, ob->obmat); + copy_m4_m4(matrix, ob->object_to_world); zero_axis_bias_m4(matrix); invert_m4_m4(gso->inv_mat, matrix); gso->vrgroup = gso->gpd->vertex_group_active_index - 1; diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index cc13f667e48..7d814b43196 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -900,7 +900,7 @@ void ED_gpencil_drawing_reference_get(const Scene *scene, } else { /* use object location */ - copy_v3_v3(r_vec, ob->obmat[3]); + copy_v3_v3(r_vec, ob->object_to_world[3]); /* Apply layer offset. */ bGPdata *gpd = ob->data; bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); @@ -984,7 +984,7 @@ void ED_gpencil_project_stroke_to_plane(const Scene *scene, /* if object, apply object rotation */ if (ob && (ob->type == OB_GPENCIL)) { float mat[4][4]; - copy_m4_m4(mat, ob->obmat); + copy_m4_m4(mat, ob->object_to_world); /* move origin to cursor */ if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { @@ -1206,7 +1206,7 @@ void ED_gpencil_project_point_to_plane(const Scene *scene, /* if object, apply object rotation */ if (ob && (ob->type == OB_GPENCIL)) { float mat[4][4]; - copy_m4_m4(mat, ob->obmat); + copy_m4_m4(mat, ob->object_to_world); if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { if (gpl != NULL) { add_v3_v3(mat[3], gpl->location); @@ -1233,7 +1233,7 @@ void ED_gpencil_project_point_to_plane(const Scene *scene, /* move origin to object */ if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { - copy_v3_v3(mat[3], ob->obmat[3]); + copy_v3_v3(mat[3], ob->object_to_world[3]); } mul_mat3_m4_v3(mat, plane_normal); @@ -1365,16 +1365,16 @@ void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata if (gpl->parent != NULL) { /* calculate new matrix */ if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { - invert_m4_m4(cur_mat, gpl->parent->obmat); - copy_v3_v3(gpl_loc, obact->obmat[3]); + invert_m4_m4(cur_mat, gpl->parent->object_to_world); + copy_v3_v3(gpl_loc, obact->object_to_world[3]); } else if (gpl->partype == PARBONE) { bPoseChannel *pchan = BKE_pose_channel_find_name(gpl->parent->pose, gpl->parsubstr); if (pchan) { float tmp_mat[4][4]; - mul_m4_m4m4(tmp_mat, gpl->parent->obmat, pchan->pose_mat); + mul_m4_m4m4(tmp_mat, gpl->parent->object_to_world, pchan->pose_mat); invert_m4_m4(cur_mat, tmp_mat); - copy_v3_v3(gpl_loc, obact->obmat[3]); + copy_v3_v3(gpl_loc, obact->object_to_world[3]); } } diff --git a/source/blender/editors/gpencil/gpencil_uv.c b/source/blender/editors/gpencil/gpencil_uv.c index 51cb08cf592..0144ffa07c7 100644 --- a/source/blender/editors/gpencil/gpencil_uv.c +++ b/source/blender/editors/gpencil/gpencil_uv.c @@ -138,7 +138,7 @@ static bool gpencil_uv_transform_init(bContext *C, wmOperator *op) opdata->array_loc = NULL; opdata->array_rot = NULL; opdata->array_scale = NULL; - opdata->ob_scale = mat4_to_scale(opdata->ob->obmat); + opdata->ob_scale = mat4_to_scale(opdata->ob->object_to_world); opdata->vinit_rotation[0] = 1.0f; opdata->vinit_rotation[1] = 0.0f; @@ -158,7 +158,7 @@ static bool gpencil_uv_transform_init(bContext *C, wmOperator *op) float r_center[3]; gpencil_stroke_center(gps, r_center); /* Add object location. */ - add_v3_v3(r_center, opdata->ob->obmat[3]); + add_v3_v3(r_center, opdata->ob->object_to_world[3]); add_v3_v3(center, r_center); i++; } diff --git a/source/blender/editors/interface/eyedroppers/eyedropper_depth.c b/source/blender/editors/interface/eyedroppers/eyedropper_depth.c index 3fb5a74944b..c6d950112b9 100644 --- a/source/blender/editors/interface/eyedroppers/eyedropper_depth.c +++ b/source/blender/editors/interface/eyedroppers/eyedropper_depth.c @@ -162,7 +162,7 @@ static void depthdropper_depth_sample_pt(bContext *C, View3D *v3d = area->spacedata.first; RegionView3D *rv3d = region->regiondata; /* weak, we could pass in some reference point */ - const float *view_co = v3d->camera ? v3d->camera->obmat[3] : rv3d->viewinv[3]; + const float *view_co = v3d->camera ? v3d->camera->object_to_world[3] : rv3d->viewinv[3]; const int mval[2] = {m_xy[0] - region->winrct.xmin, m_xy[1] - region->winrct.ymin}; copy_v2_v2_int(ddr->name_pos, mval); diff --git a/source/blender/editors/mesh/editface.cc b/source/blender/editors/mesh/editface.cc index 888a8340d51..1c6d1747516 100644 --- a/source/blender/editors/mesh/editface.cc +++ b/source/blender/editors/mesh/editface.cc @@ -383,7 +383,7 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3]) return ok; } - copy_m3_m4(bmat, ob->obmat); + copy_m3_m4(bmat, ob->object_to_world); const Span verts = me->verts(); const Span polys = me->polys(); @@ -403,7 +403,7 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3]) const MLoop *ml = &loops[poly.loopstart]; for (int b = 0; b < poly.totloop; b++, ml++) { mul_v3_m3v3(vec, bmat, verts[ml->v].co); - add_v3_v3v3(vec, vec, ob->obmat[3]); + add_v3_v3v3(vec, vec, ob->object_to_world[3]); minmax_v3v3_v3(r_min, r_max, vec); } diff --git a/source/blender/editors/mesh/editmesh_add_gizmo.c b/source/blender/editors/mesh/editmesh_add_gizmo.c index f5090c0143d..ad900c997f8 100644 --- a/source/blender/editors/mesh/editmesh_add_gizmo.c +++ b/source/blender/editors/mesh/editmesh_add_gizmo.c @@ -316,7 +316,7 @@ static int add_primitive_cube_gizmo_exec(bContext *C, wmOperator *op) PropertyRNA *prop_matrix = RNA_struct_find_property(op->ptr, "matrix"); if (RNA_property_is_set(op->ptr, prop_matrix)) { RNA_property_float_get_array(op->ptr, prop_matrix, &matrix[0][0]); - invert_m4_m4(obedit->imat, obedit->obmat); + invert_m4_m4(obedit->imat, obedit->object_to_world); mul_m4_m4m4(matrix, obedit->imat, matrix); } else { diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 3284cd70646..85801668510 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -244,7 +244,7 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) opdata->ob_store = MEM_malloc_arrayN(ob_store_len, sizeof(*opdata->ob_store), __func__); for (uint ob_index = 0; ob_index < ob_store_len; ob_index++) { Object *obedit = objects[ob_index]; - float scale = mat4_to_scale(obedit->obmat); + float scale = mat4_to_scale(obedit->object_to_world); opdata->max_obj_scale = max_ff(opdata->max_obj_scale, scale); BMEditMesh *em = BKE_editmesh_from_object(obedit); if (em->bm->totvertsel > 0) { diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c index 5c5a12b3e64..aab33678bec 100644 --- a/source/blender/editors/mesh/editmesh_bisect.c +++ b/source/blender/editors/mesh/editmesh_bisect.c @@ -314,9 +314,9 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op) copy_v3_v3(plane_co_local, plane_co); copy_v3_v3(plane_no_local, plane_no); - invert_m4_m4(imat, obedit->obmat); + invert_m4_m4(imat, obedit->object_to_world); mul_m4_v3(imat, plane_co_local); - mul_transposed_mat3_m4_v3(obedit->obmat, plane_no_local); + mul_transposed_mat3_m4_v3(obedit->object_to_world, plane_no_local); BMOperator bmop; EDBM_op_init( diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 55e9c32e41b..9df3a521cfa 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -55,8 +55,8 @@ static void edbm_extrude_edge_exclude_mirror( float mtx[4][4]; if (mmd->mirror_ob) { float imtx[4][4]; - invert_m4_m4(imtx, mmd->mirror_ob->obmat); - mul_m4_m4m4(mtx, imtx, obedit->obmat); + invert_m4_m4(imtx, mmd->mirror_ob->object_to_world); + mul_m4_m4m4(mtx, imtx, obedit->object_to_world); } BM_ITER_MESH (edge, &iter, bm, BM_EDGES_OF_MESH) { @@ -293,7 +293,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op) Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); - copy_m3_m4(tmat, obedit->obmat); + copy_m3_m4(tmat, obedit->object_to_world); invert_m3(tmat); mul_v3_m3v3(offset_local, tmat, offset); @@ -736,7 +736,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w } mul_v3_fl(local_center, 1.0f / (float)local_verts_len); - mul_m4_v3(vc.obedit->obmat, local_center); + mul_m4_v3(vc.obedit->object_to_world, local_center); mul_v3_fl(local_center, (float)local_verts_len); add_v3_v3(center, local_center); @@ -761,7 +761,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w continue; } - invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); + invert_m4_m4(vc.obedit->imat, vc.obedit->object_to_world); ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); float local_center[3]; @@ -823,7 +823,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w /* center */ copy_v3_v3(ofs, local_center); - mul_m4_v3(vc.obedit->obmat, ofs); /* view space */ + mul_m4_v3(vc.obedit->object_to_world, ofs); /* view space */ ED_view3d_win_to_3d_int(vc.v3d, vc.region, ofs, event->mval, ofs); mul_m4_v3(vc.obedit->imat, ofs); /* back in object space */ diff --git a/source/blender/editors/mesh/editmesh_extrude_screw.c b/source/blender/editors/mesh/editmesh_extrude_screw.c index be2d04b14a1..9d0bcfe4e90 100644 --- a/source/blender/editors/mesh/editmesh_extrude_screw.c +++ b/source/blender/editors/mesh/editmesh_extrude_screw.c @@ -102,11 +102,11 @@ static int edbm_screw_exec(bContext *C, wmOperator *op) continue; } - copy_v3_v3(nor, obedit->obmat[2]); + copy_v3_v3(nor, obedit->object_to_world[2]); /* calculate dvec */ - mul_v3_m4v3(v1_co_global, obedit->obmat, v1->co); - mul_v3_m4v3(v2_co_global, obedit->obmat, v2->co); + mul_v3_m4v3(v1_co_global, obedit->object_to_world, v1->co); + mul_v3_m4v3(v2_co_global, obedit->object_to_world, v2->co); sub_v3_v3v3(dvec, v1_co_global, v2_co_global); mul_v3_fl(dvec, 1.0f / steps); @@ -126,7 +126,7 @@ static int edbm_screw_exec(bContext *C, wmOperator *op) dvec, turns * steps, DEG2RADF(360.0f * turns), - obedit->obmat, + obedit->object_to_world, false)) { continue; } diff --git a/source/blender/editors/mesh/editmesh_extrude_spin.c b/source/blender/editors/mesh/editmesh_extrude_spin.c index 1b9c98db5eb..756d7f73d10 100644 --- a/source/blender/editors/mesh/editmesh_extrude_spin.c +++ b/source/blender/editors/mesh/editmesh_extrude_spin.c @@ -77,7 +77,7 @@ static int edbm_spin_exec(bContext *C, wmOperator *op) d, steps, -angle, - obedit->obmat, + obedit->object_to_world, use_normal_flip, dupli, use_auto_merge)) { diff --git a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c index 687f06c8dcf..19e23f4f212 100644 --- a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c +++ b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c @@ -362,7 +362,7 @@ static void gizmo_mesh_spin_init_refresh(const bContext *C, wmGizmoGroup *gzgrou } if (totsel) { mul_v3_fl(select_center, 1.0f / totsel); - mul_m4_v3(obedit->obmat, select_center); + mul_m4_v3(obedit->object_to_world, select_center); copy_v3_v3(ggd->data.select_center, select_center); ggd->data.use_select_center = true; } diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c index 068e6215c26..fa4ae7f984c 100644 --- a/source/blender/editors/mesh/editmesh_inset.c +++ b/source/blender/editors/mesh/editmesh_inset.c @@ -136,7 +136,7 @@ static bool edbm_inset_init(bContext *C, wmOperator *op, const bool is_modal) opdata->ob_store = MEM_malloc_arrayN(ob_store_len, sizeof(*opdata->ob_store), __func__); for (uint ob_index = 0; ob_index < ob_store_len; ob_index++) { Object *obedit = objects[ob_index]; - float scale = mat4_to_scale(obedit->obmat); + float scale = mat4_to_scale(obedit->object_to_world); opdata->max_obj_scale = max_ff(opdata->max_obj_scale, scale); BMEditMesh *em = BKE_editmesh_from_object(obedit); if (em->bm->totvertsel > 0) { diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index a147594b25b..369162e80a3 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -586,9 +586,9 @@ static void knifetool_draw_angle(const KnifeTool_OpData *kcd, float axis[3]; float arc_angle; - const float inverse_average_scale = 1 / - (kcd->curr.ob->obmat[0][0] + kcd->curr.ob->obmat[1][1] + - kcd->curr.ob->obmat[2][2]); + const float inverse_average_scale = 1 / (kcd->curr.ob->object_to_world[0][0] + + kcd->curr.ob->object_to_world[1][1] + + kcd->curr.ob->object_to_world[2][2]); const float px_scale = 3.0f * inverse_average_scale * @@ -1194,7 +1194,7 @@ static void knife_bm_tri_cagecos_get_worldspace(const KnifeTool_OpData *kcd, knife_bm_tri_cagecos_get(kcd, ob_index, tri_index, cos); const Object *ob = kcd->objects[ob_index]; for (int i = 0; i < 3; i++) { - mul_m4_v3(ob->obmat, cos[i]); + mul_m4_v3(ob->object_to_world, cos[i]); } } @@ -1744,7 +1744,7 @@ static KnifeVert *get_bm_knife_vert(KnifeTool_OpData *kcd, BMVert *v, Object *ob } float cageco_ws[3]; - mul_v3_m4v3(cageco_ws, ob->obmat, cageco); + mul_v3_m4v3(cageco_ws, ob->object_to_world, cageco); kfv = new_knife_vert(kcd, v->co, cageco_ws); kfv->v = v; @@ -2657,14 +2657,14 @@ static void calc_ortho_extent(KnifeTool_OpData *kcd) if (cagecos) { for (int i = 0; i < em->bm->totvert; i++) { copy_v3_v3(ws, cagecos[i]); - mul_m4_v3(ob->obmat, ws); + mul_m4_v3(ob->object_to_world, ws); minmax_v3v3_v3(min, max, ws); } } else { BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { copy_v3_v3(ws, v->co); - mul_m4_v3(ob->obmat, ws); + mul_m4_v3(ob->object_to_world, ws); minmax_v3v3_v3(min, max, ws); } } @@ -5072,7 +5072,7 @@ void EDBM_mesh_knife(ViewContext *vc, BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) { float cent[3], cent_ss[2]; BM_face_calc_point_in_face(f, cent); - mul_m4_v3(ob->obmat, cent); + mul_m4_v3(ob->object_to_world, cent); knife_project_v2(kcd, cent, cent_ss); if (edbm_mesh_knife_point_isect(polys, cent_ss)) { BM_elem_flag_enable(f, BM_ELEM_TAG); @@ -5113,7 +5113,7 @@ void EDBM_mesh_knife(ViewContext *vc, if (found) { float cent[3], cent_ss[2]; BM_face_calc_point_in_face(f, cent); - mul_m4_v3(ob->obmat, cent); + mul_m4_v3(ob->object_to_world, cent); knife_project_v2(kcd, cent, cent_ss); if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, (BMElem *)f)) && edbm_mesh_knife_point_isect(polys, cent_ss)) { diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 494e0ff4a27..9a91d7836fe 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -88,7 +88,7 @@ typedef struct RingSelOpData { static void ringsel_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void *arg) { RingSelOpData *lcd = arg; - EDBM_preselect_edgering_draw(lcd->presel_edgering, lcd->ob->obmat); + EDBM_preselect_edgering_draw(lcd->presel_edgering, lcd->ob->object_to_world); } static void edgering_select(RingSelOpData *lcd) diff --git a/source/blender/editors/mesh/editmesh_polybuild.c b/source/blender/editors/mesh/editmesh_polybuild.c index bf9664fa10d..63e37b18827 100644 --- a/source/blender/editors/mesh/editmesh_polybuild.c +++ b/source/blender/editors/mesh/editmesh_polybuild.c @@ -124,7 +124,7 @@ static int edbm_polybuild_transform_at_cursor_invoke(bContext *C, BMEditMesh *em = vc.em; BMesh *bm = em->bm; - invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); + invert_m4_m4(vc.obedit->imat, vc.obedit->object_to_world); ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); if (!ele_act) { @@ -192,7 +192,7 @@ static int edbm_polybuild_delete_at_cursor_invoke(bContext *C, BMEditMesh *em = vc.em; BMesh *bm = em->bm; - invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); + invert_m4_m4(vc.obedit->imat, vc.obedit->object_to_world); ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); if (!ele_act) { @@ -286,7 +286,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con BMEditMesh *em = vc.em; BMesh *bm = em->bm; - invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); + invert_m4_m4(vc.obedit->imat, vc.obedit->object_to_world); ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX); @@ -294,7 +294,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con if (ele_act == NULL || ele_act->head.htype == BM_FACE) { /* Just add vert */ copy_v3_v3(center, vc.scene->cursor.location); - mul_v3_m4v3(center, vc.obedit->obmat, center); + mul_v3_m4v3(center, vc.obedit->object_to_world, center); ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center); mul_m4_v3(vc.obedit->imat, center); @@ -309,7 +309,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con BMFace *f_reference = e_act->l ? e_act->l->f : NULL; mid_v3_v3v3(center, e_act->v1->co, e_act->v2->co); - mul_m4_v3(vc.obedit->obmat, center); + mul_m4_v3(vc.obedit->object_to_world, center); ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center); mul_m4_v3(vc.obedit->imat, center); if (f_reference->len == 3 && RNA_boolean_get(op->ptr, "create_quads")) { @@ -364,7 +364,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con BMFace *f_reference = e_pair[0]->l ? e_pair[0]->l->f : NULL; - mul_v3_m4v3(center, vc.obedit->obmat, v_act->co); + mul_v3_m4v3(center, vc.obedit->object_to_world, v_act->co); ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center); mul_m4_v3(vc.obedit->imat, center); @@ -386,7 +386,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con } else { /* Just add edge */ - mul_m4_v3(vc.obedit->obmat, center); + mul_m4_v3(vc.obedit->object_to_world, center); ED_view3d_win_to_3d_int(vc.v3d, vc.region, v_act->co, event->mval, center); mul_m4_v3(vc.obedit->imat, center); @@ -464,7 +464,7 @@ static int edbm_polybuild_split_at_cursor_invoke(bContext *C, BMEditMesh *em = vc.em; BMesh *bm = em->bm; - invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); + invert_m4_m4(vc.obedit->imat, vc.obedit->object_to_world); ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX); @@ -475,7 +475,7 @@ static int edbm_polybuild_split_at_cursor_invoke(bContext *C, if (ele_act->head.htype == BM_EDGE) { BMEdge *e_act = (BMEdge *)ele_act; mid_v3_v3v3(center, e_act->v1->co, e_act->v2->co); - mul_m4_v3(vc.obedit->obmat, center); + mul_m4_v3(vc.obedit->object_to_world, center); ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center); mul_m4_v3(vc.obedit->imat, center); diff --git a/source/blender/editors/mesh/editmesh_preselect_elem.c b/source/blender/editors/mesh/editmesh_preselect_elem.c index cf73e579700..732f39e4123 100644 --- a/source/blender/editors/mesh/editmesh_preselect_elem.c +++ b/source/blender/editors/mesh/editmesh_preselect_elem.c @@ -243,7 +243,7 @@ static void view3d_preselect_update_preview_triangle_from_vert(struct EditMesh_P } if (e_pair[1] != NULL) { - mul_v3_m4v3(center, vc->obedit->obmat, v_act->co); + mul_v3_m4v3(center, vc->obedit->object_to_world, v_act->co); ED_view3d_win_to_3d_int(vc->v3d, vc->region, center, mval, center); mul_m4_v3(vc->obedit->imat, center); @@ -311,7 +311,7 @@ static void view3d_preselect_update_preview_triangle_from_edge(struct EditMesh_P psel->preview_tris = MEM_mallocN(sizeof(*psel->preview_tris), __func__); psel->preview_lines = MEM_mallocN(sizeof(*psel->preview_lines) * 3, __func__); mid_v3_v3v3(center, eed->v1->co, eed->v2->co); - mul_m4_v3(vc->obedit->obmat, center); + mul_m4_v3(vc->obedit->object_to_world, center); ED_view3d_win_to_3d_int(vc->v3d, vc->region, center, mval, center); mul_m4_v3(vc->obedit->imat, center); diff --git a/source/blender/editors/mesh/editmesh_select.cc b/source/blender/editors/mesh/editmesh_select.cc index 76d0bab8a52..2ef2772d404 100644 --- a/source/blender/editors/mesh/editmesh_select.cc +++ b/source/blender/editors/mesh/editmesh_select.cc @@ -1060,7 +1060,7 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc, float imat3[3][3]; ED_view3d_viewcontext_init_object(vc, obedit); - copy_m3_m4(imat3, obedit->obmat); + copy_m3_m4(imat3, obedit->object_to_world); invert_m3(imat3); const float(*coords)[3] = nullptr; @@ -1085,7 +1085,8 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc, for (uint j = 0; j < 2; j++) { BMVert *v = *((&e->v1) + j); float point[3]; - mul_v3_m4v3(point, obedit->obmat, coords ? coords[BM_elem_index_get(v)] : v->co); + mul_v3_m4v3( + point, obedit->object_to_world, coords ? coords[BM_elem_index_get(v)] : v->co); const float dist_sq_test = dist_squared_to_ray_v3_normalized( ray_origin, ray_direction, point); if (dist_sq_test < dist_sq_best_vert) { @@ -1114,7 +1115,7 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc, else { mid_v3_v3v3(point, e->v1->co, e->v2->co); } - mul_m4_v3(obedit->obmat, point); + mul_m4_v3(obedit->object_to_world, point); const float dist_sq_test = dist_squared_to_ray_v3_normalized( ray_origin, ray_direction, point); if (dist_sq_test < dist_sq_best_edge) { @@ -1139,7 +1140,8 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc, BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == false) { float point[3]; - mul_v3_m4v3(point, obedit->obmat, coords ? coords[BM_elem_index_get(v)] : v->co); + mul_v3_m4v3( + point, obedit->object_to_world, coords ? coords[BM_elem_index_get(v)] : v->co); const float dist_sq_test = dist_squared_to_ray_v3_normalized( ray_origin, ray_direction, point); if (dist_sq_test < dist_sq_best_vert) { @@ -1169,7 +1171,7 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc, else { mid_v3_v3v3(point, e->v1->co, e->v2->co); } - mul_m4_v3(obedit->obmat, point); + mul_m4_v3(obedit->object_to_world, point); const float dist_sq_test = dist_squared_to_ray_v3_normalized( ray_origin, ray_direction, point); if (dist_sq_test < dist_sq_best_edge) { @@ -1198,7 +1200,7 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc, else { BM_face_calc_center_median(f, point); } - mul_m4_v3(obedit->obmat, point); + mul_m4_v3(obedit->object_to_world, point); const float dist_sq_test = dist_squared_to_ray_v3_normalized( ray_origin, ray_direction, point); if (dist_sq_test < dist_sq_best_face) { @@ -4947,7 +4949,7 @@ static int edbm_select_axis_exec(bContext *C, wmOperator *op) { float vertex_world[3]; - mul_v3_m4v3(vertex_world, obedit->obmat, v_act->co); + mul_v3_m4v3(vertex_world, obedit->object_to_world, v_act->co); value = dot_v3v3(axis_vector, vertex_world); } @@ -4977,7 +4979,7 @@ static int edbm_select_axis_exec(bContext *C, wmOperator *op) BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN | BM_ELEM_SELECT)) { float v_iter_world[3]; - mul_v3_m4v3(v_iter_world, obedit_iter->obmat, v->co); + mul_v3_m4v3(v_iter_world, obedit_iter->object_to_world, v->co); const float value_iter = dot_v3v3(axis_vector, v_iter_world); switch (sign) { case SELECT_AXIS_ALIGN: diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c index 47c76b7709b..9469639718f 100644 --- a/source/blender/editors/mesh/editmesh_select_similar.c +++ b/source/blender/editors/mesh/editmesh_select_similar.c @@ -137,7 +137,7 @@ static void face_to_plane(const Object *ob, BMFace *face, float r_plane[4]) copy_v3_v3(normal, face->no); mul_transposed_mat3_m4_v3(ob->imat, normal); normalize_v3(normal); - mul_v3_m4v3(co, ob->obmat, BM_FACE_FIRST_LOOP(face)->v->co); + mul_v3_m4v3(co, ob->object_to_world, BM_FACE_FIRST_LOOP(face)->v->co); plane_from_point_normal_v3(r_plane, co, normal); } @@ -206,7 +206,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op) BMEditMesh *em = BKE_editmesh_from_object(ob); BMesh *bm = em->bm; Material ***material_array = NULL; - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); int custom_data_offset = 0; if (bm->totfacesel == 0) { @@ -214,7 +214,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op) } float ob_m3[3][3]; - copy_m3_m4(ob_m3, ob->obmat); + copy_m3_m4(ob_m3, ob->object_to_world); switch (type) { case SIMFACE_MATERIAL: { @@ -335,7 +335,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op) int custom_data_offset; float ob_m3[3][3]; - copy_m3_m4(ob_m3, ob->obmat); + copy_m3_m4(ob_m3, ob->object_to_world); bool has_custom_data_layer = false; switch (type) { @@ -559,8 +559,8 @@ static void edge_pos_direction_worldspace_get(Object *ob, BMEdge *edge, float *r copy_v3_v3(v1, edge->v1->co); copy_v3_v3(v2, edge->v2->co); - mul_m4_v3(ob->obmat, v1); - mul_m4_v3(ob->obmat, v2); + mul_m4_v3(ob->object_to_world, v1); + mul_m4_v3(ob->object_to_world, v2); sub_v3_v3v3(r_dir, v1, v2); normalize_v3(r_dir); @@ -586,8 +586,8 @@ static float edge_length_squared_worldspace_get(Object *ob, BMEdge *edge) { float v1[3], v2[3]; - mul_v3_mat3_m4v3(v1, ob->obmat, edge->v1->co); - mul_v3_mat3_m4v3(v2, ob->obmat, edge->v2->co); + mul_v3_mat3_m4v3(v1, ob->object_to_world, edge->v1->co); + mul_v3_mat3_m4v3(v2, ob->object_to_world, edge->v2->co); return len_squared_v3v3(v1, v2); } @@ -705,7 +705,7 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op) } float ob_m3[3][3], ob_m3_inv[3][3]; - copy_m3_m4(ob_m3, ob->obmat); + copy_m3_m4(ob_m3, ob->object_to_world); invert_m3_m3(ob_m3_inv, ob_m3); BMEdge *edge; /* Mesh edge. */ @@ -812,7 +812,7 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op) } float ob_m3[3][3], ob_m3_inv[3][3]; - copy_m3_m4(ob_m3, ob->obmat); + copy_m3_m4(ob_m3, ob->object_to_world); invert_m3_m3(ob_m3_inv, ob_m3); BMEdge *edge; /* Mesh edge. */ @@ -1028,7 +1028,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) BLI_bitmap *defbase_selected = NULL; int defbase_len = 0; - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); if (bm->totvertsel == 0) { continue; diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 9f3ef8af17d..9f5c0d74ced 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -3356,7 +3356,7 @@ static bool merge_target(BMEditMesh *em, if (use_cursor) { vco = scene->cursor.location; copy_v3_v3(co, vco); - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); mul_m4_v3(ob->imat, co); } else { @@ -6684,7 +6684,7 @@ static void sort_bmelem_flag(bContext *C, int coidx = (action == SRT_VIEW_ZAXIS) ? 2 : 0; /* Apply the view matrix to the object matrix. */ - mul_m4_m4m4(mat, rv3d->viewmat, ob->obmat); + mul_m4_m4m4(mat, rv3d->viewmat, ob->object_to_world); if (totelem[0]) { pb = pblock[0] = MEM_callocN(sizeof(char) * totelem[0], "sort_bmelem vert pblock"); @@ -6753,7 +6753,7 @@ static void sort_bmelem_flag(bContext *C, copy_v3_v3(cur, scene->cursor.location); - invert_m4_m4(mat, ob->obmat); + invert_m4_m4(mat, ob->object_to_world); mul_m4_v3(mat, cur); if (totelem[0]) { diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 4fc44f01ea0..10acfc96ca8 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -1858,7 +1858,7 @@ bool BMBVH_EdgeVisible(struct BMBVHTree *tree, ED_view3d_win_to_segment_clipped(depsgraph, region, v3d, mval_f, origin, end, false); - invert_m4_m4(invmat, obedit->obmat); + invert_m4_m4(invmat, obedit->object_to_world); mul_m4_v3(invmat, origin); copy_v3_v3(co1, e->v1->co); diff --git a/source/blender/editors/mesh/meshtools.cc b/source/blender/editors/mesh/meshtools.cc index 4d75ab7f041..147c26e521f 100644 --- a/source/blender/editors/mesh/meshtools.cc +++ b/source/blender/editors/mesh/meshtools.cc @@ -132,7 +132,7 @@ static void join_mesh_single(Depsgraph *depsgraph, float cmat[4][4]; /* Watch this: switch matrix multiplication order really goes wrong. */ - mul_m4_m4m4(cmat, imat, ob_src->obmat); + mul_m4_m4m4(cmat, imat, ob_src->object_to_world); /* transform vertex coordinates into new space */ for (a = 0; a < me->totvert; a++, mvert++) { @@ -386,7 +386,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) * NOTE: This doesn't apply recursive parenting. */ if (join_parent) { ob->parent = nullptr; - BKE_object_apply_mat4_ex(ob, ob->obmat, ob->parent, ob->parentinv, false); + BKE_object_apply_mat4_ex(ob, ob->object_to_world, ob->parent, ob->parentinv, false); } /* that way the active object is always selected */ @@ -594,7 +594,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) /* Inverse transform for all selected meshes in this object, * See #object_join_exec for detailed comment on why the safe version is used. */ - invert_m4_m4_safe_ortho(imat, ob->obmat); + invert_m4_m4_safe_ortho(imat, ob->object_to_world); /* Add back active mesh first. * This allows to keep things similar as they were, as much as possible diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc index f6eee7c0c9e..6075e4250eb 100644 --- a/source/blender/editors/object/object_add.cc +++ b/source/blender/editors/object/object_add.cc @@ -322,7 +322,7 @@ void ED_object_base_init_transform_on_add(Object *object, const float loc[3], co copy_v3_v3(object->rot, rot); } - BKE_object_to_mat4(object, object->obmat); + BKE_object_to_mat4(object, object->object_to_world); } float ED_object_new_primitive_matrix(bContext *C, @@ -342,14 +342,14 @@ float ED_object_new_primitive_matrix(bContext *C, invert_m3(rmat); /* inverse transform for initial rotation and object */ - copy_m3_m4(mat, obedit->obmat); + copy_m3_m4(mat, obedit->object_to_world); mul_m3_m3m3(cmat, rmat, mat); invert_m3_m3(imat, cmat); copy_m4_m3(r_primmat, imat); /* center */ copy_v3_v3(r_primmat[3], loc); - sub_v3_v3v3(r_primmat[3], r_primmat[3], obedit->obmat[3]); + sub_v3_v3v3(r_primmat[3], r_primmat[3], obedit->object_to_world[3]); invert_m3_m3(imat, mat); mul_m3_v3(imat, r_primmat[3]); @@ -2084,7 +2084,7 @@ static int object_curves_empty_hair_add_exec(bContext *C, wmOperator *op) Object *curves_ob = ED_object_add_type( C, OB_CURVES, nullptr, nullptr, nullptr, false, local_view_bits); - BKE_object_apply_mat4(curves_ob, surface_ob->obmat, false, false); + BKE_object_apply_mat4(curves_ob, surface_ob->object_to_world, false, false); /* Set surface object. */ Curves *curves_id = static_cast(curves_ob->data); @@ -2561,8 +2561,8 @@ static void make_object_duplilist_real(bContext *C, id_us_min((ID *)ob_dst->instance_collection); ob_dst->instance_collection = nullptr; - copy_m4_m4(ob_dst->obmat, dob->mat); - BKE_object_apply_mat4(ob_dst, ob_dst->obmat, false, false); + copy_m4_m4(ob_dst->object_to_world, dob->mat); + BKE_object_apply_mat4(ob_dst, ob_dst->object_to_world, false, false); BLI_ghash_insert(dupli_gh, dob, ob_dst); if (parent_gh) { @@ -3017,7 +3017,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0; float loc[3], size[3], rot[3][3], eul[3]; float matrix[4][4]; - mat4_to_loc_rot_size(loc, rot, size, ob->obmat); + mat4_to_loc_rot_size(loc, rot, size, ob->object_to_world); mat3_to_eul(eul, rot); Object *ob_gpencil = ED_gpencil_add_object(C, loc, local_view_bits); @@ -3871,8 +3871,8 @@ static int object_add_named_exec(bContext *C, wmOperator *op) PropertyRNA *prop_matrix = RNA_struct_find_property(op->ptr, "matrix"); if (RNA_property_is_set(op->ptr, prop_matrix)) { Object *ob_add = basen->object; - RNA_property_float_get_array(op->ptr, prop_matrix, &ob_add->obmat[0][0]); - BKE_object_apply_mat4(ob_add, ob_add->obmat, true, true); + RNA_property_float_get_array(op->ptr, prop_matrix, &ob_add->object_to_world[0][0]); + BKE_object_apply_mat4(ob_add, ob_add->object_to_world, true, true); DEG_id_tag_update(&ob_add->id, ID_RECALC_TRANSFORM); } @@ -3969,7 +3969,7 @@ static int object_transform_to_mouse_exec(bContext *C, wmOperator *op) float mat_dst_unit[4][4]; float final_delta[4][4]; - normalize_m4_m4(mat_src_unit, ob->obmat); + normalize_m4_m4(mat_src_unit, ob->object_to_world); normalize_m4_m4(mat_dst_unit, matrix); invert_m4(mat_src_unit); mul_m4_m4m4(final_delta, mat_dst_unit, mat_src_unit); @@ -4124,7 +4124,7 @@ static int object_join_exec(bContext *C, wmOperator *op) * If the zero scale is removed, the data on this axis remains un-scaled * (something that wouldn't work for #invert_m4_m4_safe). */ float imat_test[4][4]; - if (!invert_m4_m4(imat_test, ob->obmat)) { + if (!invert_m4_m4(imat_test, ob->object_to_world)) { BKE_report(op->reports, RPT_WARNING, "Active object final transform has one or more zero scaled axes"); diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 781866db6a0..d05badc8fee 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -1518,10 +1518,10 @@ static int bake(const BakeAPIRender *bkr, highpoly[i].me = BKE_mesh_new_from_object(NULL, highpoly[i].ob_eval, false, false); /* Low-poly to high-poly transformation matrix. */ - copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat); + copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->object_to_world); invert_m4_m4(highpoly[i].imat, highpoly[i].obmat); - highpoly[i].is_flip_object = is_negative_m4(highpoly[i].ob->obmat); + highpoly[i].is_flip_object = is_negative_m4(highpoly[i].ob->object_to_world); i++; } @@ -1540,18 +1540,19 @@ static int bake(const BakeAPIRender *bkr, pixel_array_high = MEM_mallocN(sizeof(BakePixel) * targets.pixels_num, "bake pixels high poly"); - if (!RE_bake_pixels_populate_from_objects(me_low_eval, - pixel_array_low, - pixel_array_high, - highpoly, - tot_highpoly, - targets.pixels_num, - ob_cage != NULL, - bkr->cage_extrusion, - bkr->max_ray_distance, - ob_low_eval->obmat, - (ob_cage ? ob_cage->obmat : ob_low_eval->obmat), - me_cage_eval)) { + if (!RE_bake_pixels_populate_from_objects( + me_low_eval, + pixel_array_low, + pixel_array_high, + highpoly, + tot_highpoly, + targets.pixels_num, + ob_cage != NULL, + bkr->cage_extrusion, + bkr->max_ray_distance, + ob_low_eval->object_to_world, + (ob_cage ? ob_cage->object_to_world : ob_low_eval->object_to_world), + me_cage_eval)) { BKE_report(reports, RPT_ERROR, "Error handling selected objects"); goto cleanup; } @@ -1629,7 +1630,7 @@ static int bake(const BakeAPIRender *bkr, targets.result, me_low_eval, bkr->normal_swizzle, - ob_low_eval->obmat); + ob_low_eval->object_to_world); } else { /* From multi-resolution. */ @@ -1655,7 +1656,7 @@ static int bake(const BakeAPIRender *bkr, targets.result, (me_nores) ? me_nores : me_low_eval, bkr->normal_swizzle, - ob_low_eval->obmat); + ob_low_eval->object_to_world); if (md) { BKE_id_free(NULL, &me_nores->id); diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index fa9ded0f989..1386da5dbde 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -2327,14 +2327,14 @@ static bool get_new_constraint_target( /* Since by default, IK targets the tip of the last bone, * use the tip of the active PoseChannel if adding a target for an IK Constraint. */ if (con_type == CONSTRAINT_TYPE_KINEMATIC) { - mul_v3_m4v3(obt->loc, obact->obmat, pchanact->pose_tail); + mul_v3_m4v3(obt->loc, obact->object_to_world, pchanact->pose_tail); } else { - mul_v3_m4v3(obt->loc, obact->obmat, pchanact->pose_head); + mul_v3_m4v3(obt->loc, obact->object_to_world, pchanact->pose_head); } } else { - copy_v3_v3(obt->loc, obact->obmat[3]); + copy_v3_v3(obt->loc, obact->object_to_world[3]); } /* restore, BKE_object_add sets active */ diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 27659042f50..63093692e43 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -535,7 +535,7 @@ static int add_hook_object(const bContext *C, ob = add_hook_object_new(bmain, scene, view_layer, v3d, obedit); /* transform cent to global coords for loc */ - mul_v3_m4v3(ob->loc, obedit->obmat, cent); + mul_v3_m4v3(ob->loc, obedit->object_to_world, cent); } md = obedit->modifiers.first; @@ -556,13 +556,13 @@ static int add_hook_object(const bContext *C, unit_m4(pose_mat); - invert_m4_m4(obedit->imat, obedit->obmat); + invert_m4_m4(obedit->imat, obedit->object_to_world); if (mode == OBJECT_ADDHOOK_NEWOB) { /* pass */ } else { /* may overwrite with pose-bone location, below */ - mul_v3_m4v3(cent, obedit->imat, ob->obmat[3]); + mul_v3_m4v3(cent, obedit->imat, ob->object_to_world[3]); } if (mode == OBJECT_ADDHOOK_SELOB_BONE) { @@ -576,7 +576,7 @@ static int add_hook_object(const bContext *C, pchan_act = BKE_pose_channel_active_if_layer_visible(ob); if (LIKELY(pchan_act)) { invert_m4_m4(pose_mat, pchan_act->pose_mat); - mul_v3_m4v3(cent, ob->obmat, pchan_act->pose_mat[3]); + mul_v3_m4v3(cent, ob->object_to_world, pchan_act->pose_mat[3]); mul_v3_m4v3(cent, obedit->imat, cent); } } @@ -588,16 +588,16 @@ static int add_hook_object(const bContext *C, copy_v3_v3(hmd->cent, cent); /* matrix calculus */ - /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */ + /* vert x (obmat x hook->imat) x hook->object_to_world x ob->imat */ /* (parentinv ) */ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); BKE_object_transform_copy(object_eval, ob); BKE_object_where_is_calc(depsgraph, scene_eval, object_eval); - invert_m4_m4(object_eval->imat, object_eval->obmat); + invert_m4_m4(object_eval->imat, object_eval->object_to_world); /* apparently this call goes from right to left... */ - mul_m4_series(hmd->parentinv, pose_mat, object_eval->imat, obedit->obmat); + mul_m4_series(hmd->parentinv, pose_mat, object_eval->imat, obedit->object_to_world); DEG_relations_tag_update(bmain); @@ -834,10 +834,10 @@ static int object_hook_recenter_exec(bContext *C, wmOperator *op) } /* recenter functionality */ - copy_m3_m4(bmat, ob->obmat); + copy_m3_m4(bmat, ob->object_to_world); invert_m3_m3(imat, bmat); - sub_v3_v3v3(hmd->cent, scene->cursor.location, ob->obmat[3]); + sub_v3_v3v3(hmd->cent, scene->cursor.location, ob->object_to_world[3]); mul_m3_v3(imat, hmd->cent); DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 5da19d76259..10068def991 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -272,7 +272,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) /* inverse parent matrix */ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob); - invert_m4_m4(ob->parentinv, workob.obmat); + invert_m4_m4(ob->parentinv, workob.object_to_world); } else { ob->partype = PARVERT1; @@ -280,7 +280,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) /* inverse parent matrix */ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob); - invert_m4_m4(ob->parentinv, workob.obmat); + invert_m4_m4(ob->parentinv, workob.object_to_world); } } } @@ -401,7 +401,7 @@ void ED_object_parent_clear(Object *ob, const int type) /* remove parent, and apply the parented transform * result as object's local transforms */ ob->parent = NULL; - BKE_object_apply_mat4(ob, ob->obmat, true, false); + BKE_object_apply_mat4(ob, ob->object_to_world, true, false); break; } case CLEAR_PARENT_INVERSE: { @@ -584,7 +584,7 @@ bool ED_object_parent_set(ReportList *reports, if (keep_transform) { /* Was removed because of bug T23577, * but this can be handy in some cases too T32616, so make optional. */ - BKE_object_apply_mat4(ob, ob->obmat, false, false); + BKE_object_apply_mat4(ob, ob->object_to_world, false, false); } /* Set the parent (except for follow-path constraint option). */ @@ -706,7 +706,7 @@ bool ED_object_parent_set(ReportList *reports, BKE_constraint_target_matrix_get( depsgraph, scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra); - sub_v3_v3v3(vec, ob->obmat[3], cmat[3]); + sub_v3_v3v3(vec, ob->object_to_world[3], cmat[3]); copy_v3_v3(ob->loc, vec); } @@ -729,7 +729,7 @@ bool ED_object_parent_set(ReportList *reports, ob->partype = PAROBJECT; BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob); - invert_m4_m4(ob->parentinv, workob.obmat); + invert_m4_m4(ob->parentinv, workob.object_to_world); } else if (is_armature_parent && (ob->type == OB_GPENCIL) && (par->type == OB_ARMATURE)) { if (partype == PAR_ARMATURE) { @@ -747,7 +747,7 @@ bool ED_object_parent_set(ReportList *reports, ob->partype = PAROBJECT; BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob); - invert_m4_m4(ob->parentinv, workob.obmat); + invert_m4_m4(ob->parentinv, workob.object_to_world); } else if ((ob->type == OB_GPENCIL) && (par->type == OB_LATTICE)) { /* Add Lattice modifier */ @@ -758,12 +758,12 @@ bool ED_object_parent_set(ReportList *reports, ob->partype = PAROBJECT; BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob); - invert_m4_m4(ob->parentinv, workob.obmat); + invert_m4_m4(ob->parentinv, workob.object_to_world); } else { /* calculate inverse parent matrix */ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob); - invert_m4_m4(ob->parentinv, workob.obmat); + invert_m4_m4(ob->parentinv, workob.object_to_world); } DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); @@ -772,7 +772,7 @@ bool ED_object_parent_set(ReportList *reports, static void parent_set_vert_find(KDTree_3d *tree, Object *child, int vert_par[3], bool is_tri) { - const float *co_find = child->obmat[3]; + const float *co_find = child->object_to_world[3]; if (is_tri) { KDTreeNearest_3d nearest[3]; int tot; @@ -1186,7 +1186,7 @@ static int object_track_clear_exec(bContext *C, wmOperator *op) } if (type == CLEAR_TRACK_KEEP_TRANSFORM) { - BKE_object_apply_mat4(ob, ob->obmat, true, true); + BKE_object_apply_mat4(ob, ob->object_to_world, true, true); } } CTX_DATA_END; diff --git a/source/blender/editors/object/object_remesh.cc b/source/blender/editors/object/object_remesh.cc index 8358bf632d3..c653610d6fe 100644 --- a/source/blender/editors/object/object_remesh.cc +++ b/source/blender/editors/object/object_remesh.cc @@ -296,7 +296,7 @@ static void voxel_size_edit_draw(const bContext *C, ARegion * /*ar*/, void *arg) uint pos3d = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_matrix_push(); - GPU_matrix_mul(cd->active_object->obmat); + GPU_matrix_mul(cd->active_object->object_to_world); /* Draw Rect */ immUniformColor4f(0.9f, 0.9f, 0.9f, 0.8f); @@ -494,7 +494,7 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev float view_normal[3] = {0.0f, 0.0f, 1.0f}; /* Calculate the view normal. */ - invert_m4_m4(active_object->imat, active_object->obmat); + invert_m4_m4(active_object->imat, active_object->object_to_world); copy_m3_m4(mat, rv3d->viewinv); mul_m3_v3(mat, view_normal); copy_m3_m4(mat, active_object->imat); @@ -535,7 +535,7 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev /* Project the selected face in the previous step of the Bounding Box. */ for (int i = 0; i < 4; i++) { float preview_plane_world_space[3]; - mul_v3_m4v3(preview_plane_world_space, active_object->obmat, cd->preview_plane[i]); + mul_v3_m4v3(preview_plane_world_space, active_object->object_to_world, cd->preview_plane[i]); ED_view3d_project_v2(region, preview_plane_world_space, preview_plane_proj[i]); } @@ -582,7 +582,7 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev /* Invert object scale. */ float scale[3]; - mat4_to_size(scale, active_object->obmat); + mat4_to_size(scale, active_object->object_to_world); invert_v3(scale); size_to_mat4(scale_mat, scale); @@ -593,7 +593,7 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev /* Scale the text to constant viewport size. */ float text_pos_word_space[3]; - mul_v3_m4v3(text_pos_word_space, active_object->obmat, text_pos); + mul_v3_m4v3(text_pos_word_space, active_object->object_to_world, text_pos); const float pixelsize = ED_view3d_pixel_size(rv3d, text_pos_word_space); scale_m4_fl(scale_mat, pixelsize * 0.5f); mul_m4_m4_post(cd->text_mat, scale_mat); diff --git a/source/blender/editors/object/object_transform.cc b/source/blender/editors/object/object_transform.cc index 6604e3da4d2..a863e9ac324 100644 --- a/source/blender/editors/object/object_transform.cc +++ b/source/blender/editors/object/object_transform.cc @@ -527,9 +527,9 @@ static void ignore_parent_tx(Main *bmain, Depsgraph *depsgraph, Scene *scene, Ob LISTBASE_FOREACH (Object *, ob_child, &bmain->objects) { if (ob_child->parent == ob) { Object *ob_child_eval = DEG_get_evaluated_object(depsgraph, ob_child); - BKE_object_apply_mat4(ob_child_eval, ob_child_eval->obmat, true, false); + BKE_object_apply_mat4(ob_child_eval, ob_child_eval->object_to_world, true, false); BKE_object_workob_calc_parent(depsgraph, scene, ob_child_eval, &workob); - invert_m4_m4(ob_child->parentinv, workob.obmat); + invert_m4_m4(ob_child->parentinv, workob.object_to_world); /* Copy result of BKE_object_apply_mat4(). */ BKE_object_transform_copy(ob_child, ob_child_eval); /* Make sure evaluated object is in a consistent state with the original one. @@ -660,11 +660,11 @@ static int apply_objects_internal(bContext *C, if (do_multi_user) { obact = CTX_data_active_object(C); - invert_m4_m4(obact_invmat, obact->obmat); + invert_m4_m4(obact_invmat, obact->object_to_world); Object workob; BKE_object_workob_calc_parent(depsgraph, scene, obact, &workob); - copy_m4_m4(obact_parent, workob.obmat); + copy_m4_m4(obact_parent, workob.object_to_world); copy_m4_m4(obact_parentinv, obact->parentinv); if (apply_objects_internal_need_single_user(C)) { @@ -989,7 +989,7 @@ static int apply_objects_internal(bContext *C, float _obmat[4][4], _iobmat[4][4]; float _mat[4][4]; - copy_m4_m4(_obmat, ob->obmat); + copy_m4_m4(_obmat, ob->object_to_world); invert_m4_m4(_iobmat, _obmat); copy_m4_m4(_mat, _obmat); @@ -1075,7 +1075,7 @@ static int visual_transform_apply_exec(bContext *C, wmOperator * /*op*/) CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); BKE_object_where_is_calc(depsgraph, scene, ob_eval); - BKE_object_apply_mat4(ob_eval, ob_eval->obmat, true, true); + BKE_object_apply_mat4(ob_eval, ob_eval->object_to_world, true, true); BKE_object_transform_copy(ob, ob_eval); /* update for any children that may get moved */ @@ -1274,7 +1274,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) if (centermode == ORIGIN_TO_CURSOR) { copy_v3_v3(cent, cursor); - invert_m4_m4(obedit->imat, obedit->obmat); + invert_m4_m4(obedit->imat, obedit->object_to_world); mul_m4_v3(obedit->imat, cent); } else { @@ -1342,7 +1342,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) if (centermode == ORIGIN_TO_CURSOR) { copy_v3_v3(cent, cursor); - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); mul_m4_v3(ob->imat, cent); } @@ -1363,7 +1363,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) INIT_MINMAX(min, max); BKE_object_minmax_dupli(depsgraph, scene, ob, min, max, true); mid_v3_v3v3(cent, min, max); - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); mul_m4_v3(ob->imat, cent); } @@ -1554,7 +1554,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) if (centermode == ORIGIN_TO_GEOMETRY) { zero_v3(gpcenter); BKE_gpencil_centroid_3d(gpd, gpcenter); - add_v3_v3(gpcenter, ob->obmat[3]); + add_v3_v3(gpcenter, ob->object_to_world[3]); } if (centermode == ORIGIN_TO_CURSOR) { copy_v3_v3(gpcenter, cursor); @@ -1566,8 +1566,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) float offset_local[3]; int i; - sub_v3_v3v3(offset_global, gpcenter, ob->obmat[3]); - copy_m3_m4(bmat, obact->obmat); + sub_v3_v3v3(offset_global, gpcenter, ob->object_to_world[3]); + copy_m3_m4(bmat, obact->object_to_world); invert_m3_m3(imat, bmat); mul_m3_v3(imat, offset_global); mul_v3_m3v3(offset_local, imat, offset_global); @@ -1699,7 +1699,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) ob_other->flag |= OB_DONE; DEG_id_tag_update(&ob_other->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */ + mul_v3_mat3_m4v3(centn, ob_other->object_to_world, cent); /* omit translation part */ add_v3_v3(ob_other->loc, centn); Object *ob_other_eval = DEG_get_evaluated_object(depsgraph, ob_other); @@ -1873,9 +1873,9 @@ static void object_transform_axis_target_calc_depth_init(XFormAxisData *xfd, con int center_tot = 0; for (XFormAxisItem &item : xfd->object_data) { const Object *ob = item.ob; - const float *ob_co_a = ob->obmat[3]; + const float *ob_co_a = ob->object_to_world[3]; float ob_co_b[3]; - add_v3_v3v3(ob_co_b, ob->obmat[3], ob->obmat[2]); + add_v3_v3v3(ob_co_b, ob->object_to_world[3], ob->object_to_world[2]); float view_isect[3], ob_isect[3]; if (isect_line_line_v3(view_co_a, view_co_b, ob_co_a, ob_co_b, view_isect, ob_isect)) { add_v3_v3(center, view_isect); @@ -1946,7 +1946,7 @@ static void object_apply_location(Object *ob, const float loc[3]) /* quick but weak */ Object ob_prev = blender::dna::shallow_copy(*ob); float mat[4][4]; - copy_m4_m4(mat, ob->obmat); + copy_m4_m4(mat, ob->object_to_world); copy_v3_v3(mat[3], loc); BKE_object_apply_mat4(ob, mat, true, true); copy_v3_v3(mat[3], ob->loc); @@ -1961,7 +1961,7 @@ static bool object_orient_to_location(Object *ob, const bool z_flip) { float delta[3]; - sub_v3_v3v3(delta, ob->obmat[3], location); + sub_v3_v3v3(delta, ob->object_to_world[3], location); if (normalize_v3(delta) != 0.0f) { if (z_flip) { negate_v3(delta); @@ -2139,7 +2139,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const float xform_rot_offset_inv_first[3][3]; for (const int i : xfd->object_data.index_range()) { XFormAxisItem &item = xfd->object_data[i]; - copy_m3_m4(item.xform_rot_offset, item.ob->obmat); + copy_m3_m4(item.xform_rot_offset, item.ob->object_to_world); normalize_m3(item.xform_rot_offset); if (i == 0) { @@ -2158,8 +2158,8 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const XFormAxisItem &item = xfd->object_data[i]; if (is_translate_init) { float ob_axis[3]; - item.xform_dist = len_v3v3(item.ob->obmat[3], location_world); - normalize_v3_v3(ob_axis, item.ob->obmat[2]); + item.xform_dist = len_v3v3(item.ob->object_to_world[3], location_world); + normalize_v3_v3(ob_axis, item.ob->object_to_world[2]); /* Scale to avoid adding distance when moving between surfaces. */ if (normal_found) { float scale = fabsf(dot_v3v3(ob_axis, normal)); @@ -2173,7 +2173,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const copy_v3_v3(target_normal, normal); } else { - normalize_v3_v3(target_normal, item.ob->obmat[2]); + normalize_v3_v3(target_normal, item.ob->object_to_world[2]); } #ifdef USE_RELATIVE_ROTATION @@ -2190,7 +2190,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const madd_v3_v3fl(loc, target_normal, item.xform_dist); object_apply_location(item.ob, loc); /* so orient behaves as expected */ - copy_v3_v3(item.ob->obmat[3], loc); + copy_v3_v3(item.ob->object_to_world[3], loc); } object_orient_to_location( diff --git a/source/blender/editors/object/object_utils.c b/source/blender/editors/object/object_utils.c index 50ba5b8af5f..1387282357f 100644 --- a/source/blender/editors/object/object_utils.c +++ b/source/blender/editors/object/object_utils.c @@ -114,20 +114,20 @@ bool ED_object_calc_active_center(Object *ob, const bool select_only, float r_ce { if (ob->mode & OB_MODE_EDIT) { if (ED_object_calc_active_center_for_editmode(ob, select_only, r_center)) { - mul_m4_v3(ob->obmat, r_center); + mul_m4_v3(ob->object_to_world, r_center); return true; } return false; } if (ob->mode & OB_MODE_POSE) { if (ED_object_calc_active_center_for_posemode(ob, select_only, r_center)) { - mul_m4_v3(ob->obmat, r_center); + mul_m4_v3(ob->object_to_world, r_center); return true; } return false; } if (!select_only || (ob->base_flag & BASE_SELECTED)) { - copy_v3_v3(r_center, ob->obmat[3]); + copy_v3_v3(r_center, ob->object_to_world[3]); return true; } return false; @@ -245,11 +245,11 @@ void ED_object_xform_skip_child_container_item_ensure(struct XFormObjectSkipChil if (!BLI_ghash_ensure_p(xcs->obchild_in_obmode_map, ob, &xf_p)) { struct XFormObjectSkipChild *xf = MEM_mallocN(sizeof(*xf), __func__); copy_m4_m4(xf->parentinv_orig, ob->parentinv); - copy_m4_m4(xf->obmat_orig, ob->obmat); - copy_m4_m4(xf->parent_obmat_orig, ob->parent->obmat); - invert_m4_m4(xf->parent_obmat_inv_orig, ob->parent->obmat); + copy_m4_m4(xf->obmat_orig, ob->object_to_world); + copy_m4_m4(xf->parent_obmat_orig, ob->parent->object_to_world); + invert_m4_m4(xf->parent_obmat_inv_orig, ob->parent->object_to_world); if (ob_parent_recurse) { - copy_m4_m4(xf->parent_recurse_obmat_orig, ob_parent_recurse->obmat); + copy_m4_m4(xf->parent_recurse_obmat_orig, ob_parent_recurse->object_to_world); } xf->mode = mode; xf->ob_parent_recurse = ob_parent_recurse; @@ -274,14 +274,14 @@ void ED_object_xform_skip_child_container_update_all(struct XFormObjectSkipChild if (xf->mode == XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM) { /* Parent is transformed, this isn't so compensate. */ Object *ob_parent_eval = DEG_get_evaluated_object(depsgraph, ob->parent); - mul_m4_m4m4(dmat, xf->parent_obmat_inv_orig, ob_parent_eval->obmat); + mul_m4_m4m4(dmat, xf->parent_obmat_inv_orig, ob_parent_eval->object_to_world); invert_m4(dmat); } else if (xf->mode == XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM_INDIRECT) { /* Calculate parent matrix (from the root transform). */ Object *ob_parent_recurse_eval = DEG_get_evaluated_object(depsgraph, xf->ob_parent_recurse); float parent_recurse_obmat_inv[4][4]; - invert_m4_m4(parent_recurse_obmat_inv, ob_parent_recurse_eval->obmat); + invert_m4_m4(parent_recurse_obmat_inv, ob_parent_recurse_eval->object_to_world); mul_m4_m4m4(dmat, xf->parent_recurse_obmat_orig, parent_recurse_obmat_inv); invert_m4(dmat); float parent_obmat_calc[4][4]; @@ -296,7 +296,7 @@ void ED_object_xform_skip_child_container_update_all(struct XFormObjectSkipChild /* Transform this - without transform data. */ Object *ob_parent_recurse_eval = DEG_get_evaluated_object(depsgraph, xf->ob_parent_recurse); float parent_recurse_obmat_inv[4][4]; - invert_m4_m4(parent_recurse_obmat_inv, ob_parent_recurse_eval->obmat); + invert_m4_m4(parent_recurse_obmat_inv, ob_parent_recurse_eval->object_to_world); mul_m4_m4m4(dmat, xf->parent_recurse_obmat_orig, parent_recurse_obmat_inv); invert_m4(dmat); float obmat_calc[4][4]; @@ -350,7 +350,7 @@ void ED_object_data_xform_container_item_ensure(struct XFormObjectData_Container void **xf_p; if (!BLI_ghash_ensure_p(xds->obdata_in_obmode_map, ob->data, &xf_p)) { struct XFormObjectData_Extra *xf = MEM_mallocN(sizeof(*xf), __func__); - copy_m4_m4(xf->obmat_orig, ob->obmat); + copy_m4_m4(xf->obmat_orig, ob->object_to_world); xf->ob = ob; /* Result may be NULL, that's OK. */ xf->xod = ED_object_data_xform_create(ob->data); @@ -378,7 +378,7 @@ void ED_object_data_xform_container_update_all(struct XFormObjectData_Container Object *ob_eval = DEG_get_evaluated_object(depsgraph, xf->ob); float imat[4][4], dmat[4][4]; invert_m4_m4(imat, xf->obmat_orig); - mul_m4_m4m4(dmat, imat, ob_eval->obmat); + mul_m4_m4m4(dmat, imat, ob_eval->object_to_world); invert_m4(dmat); ED_object_data_xform_by_mat4(xf->xod, dmat); diff --git a/source/blender/editors/object/object_warp.c b/source/blender/editors/object/object_warp.c index a1d53cadd06..d1e6e7000d9 100644 --- a/source/blender/editors/object/object_warp.c +++ b/source/blender/editors/object/object_warp.c @@ -38,7 +38,7 @@ static void object_warp_calc_view_matrix(float r_mat_view[4][4], mul_m4_m4m4(viewmat_roll, mat_offset, viewmat); /* apply the view and the object matrix */ - mul_m4_m4m4(r_mat_view, viewmat_roll, obedit->obmat); + mul_m4_m4m4(r_mat_view, viewmat_roll, obedit->object_to_world); /* get the view-space cursor */ mul_v3_m4v3(r_center_view, viewmat_roll, center); diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index e6d0aca7902..6dc3860fdf2 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -3930,7 +3930,7 @@ static void brush_puff(PEData *data, int point_index, float mouse_distance) copy_v3_v3(co_root, co); copy_v3_v3(no_root, &edit->emitter_cosnos[point_index * 6 + 3]); - mul_mat3_m4_v3(data->ob->obmat, no_root); /* normal into global-space */ + mul_mat3_m4_v3(data->ob->object_to_world, no_root); /* normal into global-space */ normalize_v3(no_root); if (puff_volume) { @@ -4016,8 +4016,8 @@ static void brush_puff(PEData *data, int point_index, float mouse_distance) point_index = BLI_kdtree_3d_find_nearest(edit->emitter_field, kco, NULL); if (point_index != -1) { copy_v3_v3(onor, &edit->emitter_cosnos[point_index * 6 + 3]); - mul_mat3_m4_v3(data->ob->obmat, onor); /* Normal into world-space. */ - mul_mat3_m4_v3(imat, onor); /* World-space into particle-space. */ + mul_mat3_m4_v3(data->ob->object_to_world, onor); /* Normal into world-space. */ + mul_mat3_m4_v3(imat, onor); /* World-space into particle-space. */ normalize_v3(onor); } else { @@ -4412,7 +4412,7 @@ static int brush_add(const bContext *C, PEData *data, short number) short size = pset->brush[PE_BRUSH_ADD].size; RNG *rng; - invert_m4_m4(imat, ob->obmat); + invert_m4_m4(imat, ob->object_to_world); if (psys->flag & PSYS_GLOBAL_HAIR) { return 0; @@ -4797,7 +4797,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) data.combfac = 1.0f - data.combfac; } - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); ED_view3d_win_to_delta(region, xy_delta, bedit->zfac, vec); data.dvec = vec; @@ -4865,7 +4865,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) } data.invert = (brush->invert ^ flip); - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); foreach_mouse_hit_point(&data, brush_puff, selected); } @@ -4895,7 +4895,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) data.smoothfac = brush->strength; - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); foreach_mouse_hit_key(&data, brush_smooth_get, selected); diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index 210757173eb..852156f9403 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -726,8 +726,8 @@ static bool remap_hair_emitter(Depsgraph *depsgraph, edit_point = target_edit ? target_edit->points : NULL; - invert_m4_m4(from_ob_imat, ob->obmat); - invert_m4_m4(to_ob_imat, target_ob->obmat); + invert_m4_m4(from_ob_imat, ob->object_to_world); + invert_m4_m4(to_ob_imat, target_ob->object_to_world); invert_m4_m4(from_imat, from_mat); invert_m4_m4(to_imat, to_mat); @@ -843,7 +843,7 @@ static bool remap_hair_emitter(Depsgraph *depsgraph, float offset[3]; if (to_global) { - copy_m4_m4(imat, target_ob->obmat); + copy_m4_m4(imat, target_ob->object_to_world); } else { /* NOTE: using target_dm here, which is in target_ob object space and has full modifiers. @@ -923,8 +923,8 @@ static bool connect_hair(Depsgraph *depsgraph, Scene *scene, Object *ob, Particl ob, psys, psys->edit, - ob->obmat, - ob->obmat, + ob->object_to_world, + ob->object_to_world, psys->flag & PSYS_GLOBAL_HAIR, false); if (ok) { @@ -1174,8 +1174,8 @@ static bool copy_particle_systems_to_object(const bContext *C, to_mat = I; break; case PAR_COPY_SPACE_WORLD: - from_mat = ob_from->obmat; - to_mat = ob_to->obmat; + from_mat = ob_from->object_to_world; + to_mat = ob_to->object_to_world; break; default: /* should not happen */ diff --git a/source/blender/editors/render/render_preview.cc b/source/blender/editors/render/render_preview.cc index 140199209da..5aae48b1138 100644 --- a/source/blender/editors/render/render_preview.cc +++ b/source/blender/editors/render/render_preview.cc @@ -785,7 +785,7 @@ static Object *object_preview_camera_create(Main *preview_main, float rotmat[3][3]; float dummyscale[3]; - mat4_to_loc_rot_size(camera->loc, rotmat, dummyscale, preview_object->obmat); + mat4_to_loc_rot_size(camera->loc, rotmat, dummyscale, preview_object->object_to_world); /* Camera is Y up, so needs additional rotations to obliquely face the front. */ float drotmat[3][3]; diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc index e276bae6697..8172eb8a5d7 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc @@ -185,7 +185,7 @@ std::optional sample_curves_3d_brush(const Depsgraph &depsgraph, /* Shorten ray when the surface object is hit. */ if (surface_object_eval != nullptr) { - const float4x4 surface_to_world_mat = surface_object->obmat; + const float4x4 surface_to_world_mat = surface_object->object_to_world; const float4x4 world_to_surface_mat = surface_to_world_mat.inverted(); Mesh *surface_eval = BKE_object_get_evaluated_mesh(surface_object_eval); @@ -218,7 +218,7 @@ std::optional sample_curves_3d_brush(const Depsgraph &depsgraph, } } - const float4x4 curves_to_world_mat = curves_object.obmat; + const float4x4 curves_to_world_mat = curves_object.object_to_world; const float4x4 world_to_curves_mat = curves_to_world_mat.inverted(); const float3 center_ray_start_cu = world_to_curves_mat * center_ray_start_wo; diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc index 6366da310b6..a627437b972 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc @@ -786,7 +786,7 @@ static void select_grow_invoke_per_curve(Curves &curves_id, }); }); - float4x4 curves_to_world_mat = curves_ob.obmat; + float4x4 curves_to_world_mat = curves_ob.object_to_world; float4x4 world_to_curves_mat = curves_to_world_mat.inverted(); float4x4 projection; diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 71ec444098e..b85b878af7d 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -1071,7 +1071,7 @@ static void cursor_draw_tiling_preview(const uint gpuattr, for (int dim = 0; dim < 3; dim++) { location[dim] = cur[dim] * step[dim] + orgLoc[dim]; } - cursor_draw_point_screen_space(gpuattr, region, location, ob->obmat, 3); + cursor_draw_point_screen_space(gpuattr, region, location, ob->object_to_world, 3); } } } @@ -1092,7 +1092,7 @@ static void cursor_draw_point_with_symmetry(const uint gpuattr, /* Axis Symmetry. */ flip_v3_v3(location, true_location, (char)i); - cursor_draw_point_screen_space(gpuattr, region, location, ob->obmat, 3); + cursor_draw_point_screen_space(gpuattr, region, location, ob->object_to_world, 3); /* Tiling. */ cursor_draw_tiling_preview(gpuattr, region, location, sd, ob, radius); @@ -1107,7 +1107,7 @@ static void cursor_draw_point_with_symmetry(const uint gpuattr, mul_m4_v3(symm_rot_mat, location); cursor_draw_tiling_preview(gpuattr, region, location, sd, ob, radius); - cursor_draw_point_screen_space(gpuattr, region, location, ob->obmat, 3); + cursor_draw_point_screen_space(gpuattr, region, location, ob->object_to_world, 3); } } } @@ -1334,7 +1334,7 @@ static void paint_cursor_update_pixel_radius(PaintCursorContext *pcontext) } copy_v3_v3(pcontext->scene_space_location, pcontext->location); - mul_m4_v3(pcontext->vc.obact->obmat, pcontext->scene_space_location); + mul_m4_v3(pcontext->vc.obact->object_to_world, pcontext->scene_space_location); } else { Sculpt *sd = CTX_data_tool_settings(pcontext->C)->sculpt; @@ -1464,7 +1464,7 @@ static void paint_cursor_drawing_setup_cursor_space(PaintCursorContext *pcontext float cursor_trans[4][4], cursor_rot[4][4]; const float z_axis[4] = {0.0f, 0.0f, 1.0f, 0.0f}; float quat[4]; - copy_m4_m4(cursor_trans, pcontext->vc.obact->obmat); + copy_m4_m4(cursor_trans, pcontext->vc.obact->object_to_world); translate_m4(cursor_trans, pcontext->location[0], pcontext->location[1], pcontext->location[2]); rotation_between_vecs_to_quat(quat, z_axis, pcontext->normal); quat_to_mat4(cursor_rot, quat); @@ -1508,7 +1508,7 @@ static void paint_cursor_pose_brush_origins_draw(PaintCursorContext *pcontext) cursor_draw_point_screen_space(pcontext->pos, pcontext->region, ss->pose_ik_chain_preview->segments[i].initial_orig, - pcontext->vc.obact->obmat, + pcontext->vc.obact->object_to_world, 3); } } @@ -1526,7 +1526,7 @@ static void paint_cursor_preview_boundary_data_pivot_draw(PaintCursorContext *pc pcontext->pos, pcontext->region, SCULPT_vertex_co_get(pcontext->ss, pcontext->ss->boundary_preview->pivot_vertex), - pcontext->vc.obact->obmat, + pcontext->vc.obact->object_to_world, 3); } @@ -1634,7 +1634,7 @@ static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext * pcontext->pos, pcontext->region, SCULPT_vertex_co_get(pcontext->ss, pcontext->ss->expand_cache->initial_active_vertex), - pcontext->vc.obact->obmat, + pcontext->vc.obact->object_to_world, 2); } @@ -1656,7 +1656,7 @@ static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext * NULL); GPU_matrix_push(); - GPU_matrix_mul(pcontext->vc.obact->obmat); + GPU_matrix_mul(pcontext->vc.obact->object_to_world); /* Drawing Cursor overlays in 3D object space. */ if (is_brush_tool && brush->sculpt_tool == SCULPT_TOOL_GRAB && @@ -1747,7 +1747,7 @@ static void paint_cursor_cursor_draw_3d_view_brush_cursor_active(PaintCursorCont NULL, NULL); GPU_matrix_push(); - GPU_matrix_mul(pcontext->vc.obact->obmat); + GPU_matrix_mul(pcontext->vc.obact->object_to_world); /* Draw the special active cursors different tools may have. */ diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index d9aa11a2847..ea33449f0dd 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -3684,7 +3684,7 @@ static void proj_paint_state_viewport_init(ProjPaintState *ps, const char symmet ps->viewDir[1] = 0.0f; ps->viewDir[2] = 1.0f; - copy_m4_m4(ps->obmat, ps->ob->obmat); + copy_m4_m4(ps->obmat, ps->ob->object_to_world); if (symmetry_flag) { int i; @@ -3742,7 +3742,7 @@ static void proj_paint_state_viewport_init(ProjPaintState *ps, const char symmet CameraParams params; /* viewmat & viewinv */ - copy_m4_m4(viewinv, cam_ob_eval->obmat); + copy_m4_m4(viewinv, cam_ob_eval->object_to_world); normalize_m4(viewinv); invert_m4_m4(viewmat, viewinv); @@ -4462,7 +4462,7 @@ static void project_paint_begin(const bContext *C, if (ps->source == PROJ_SRC_VIEW) { /* faster clipping lookups */ - ED_view3d_clipping_local(ps->rv3d, ps->ob->obmat); + ED_view3d_clipping_local(ps->rv3d, ps->ob->object_to_world); } ps->do_face_sel = ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) != 0); diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index 571ebd79764..c3e3109ac87 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -1009,11 +1009,12 @@ static void sculpt_gesture_trim_shape_origin_normal_get(SculptGestureContext *sg copy_v3_v3(r_normal, sgcontext->world_space_view_normal); break; case SCULPT_GESTURE_TRIM_ORIENTATION_SURFACE: - mul_v3_m4v3(r_origin, sgcontext->vc.obact->obmat, sgcontext->ss->gesture_initial_location); + mul_v3_m4v3( + r_origin, sgcontext->vc.obact->object_to_world, sgcontext->ss->gesture_initial_location); /* Transforming the normal does not take non uniform scaling into account. Sculpt mode is not * expected to work on object with non uniform scaling. */ copy_v3_v3(r_normal, sgcontext->ss->gesture_initial_normal); - mul_mat3_m4_v3(sgcontext->vc.obact->obmat, r_normal); + mul_mat3_m4_v3(sgcontext->vc.obact->object_to_world, r_normal); break; } } @@ -1044,7 +1045,7 @@ static void sculpt_gesture_trim_calculate_depth(SculptGestureContext *sgcontext) * mesh, coordinates are first calculated in world space, then converted to object space to * store them. */ float world_space_vco[3]; - mul_v3_m4v3(world_space_vco, vc->obact->obmat, vco); + mul_v3_m4v3(world_space_vco, vc->obact->object_to_world, vco); const float dist = dist_signed_to_plane_v3(world_space_vco, shape_plane); trim_operation->depth_front = min_ff(dist, trim_operation->depth_front); trim_operation->depth_back = max_ff(dist, trim_operation->depth_back); @@ -1052,8 +1053,9 @@ static void sculpt_gesture_trim_calculate_depth(SculptGestureContext *sgcontext) if (trim_operation->use_cursor_depth) { float world_space_gesture_initial_location[3]; - mul_v3_m4v3( - world_space_gesture_initial_location, vc->obact->obmat, ss->gesture_initial_location); + mul_v3_m4v3(world_space_gesture_initial_location, + vc->obact->object_to_world, + ss->gesture_initial_location); float mid_point_depth; if (trim_operation->orientation == SCULPT_GESTURE_TRIM_ORIENTATION_VIEW) { diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index bc4c6dc4148..a70924b0626 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -564,7 +564,7 @@ static void paint_brush_stroke_add_step( if (SCULPT_stroke_get_location( C, world_space_position, stroke->last_mouse_position, stroke->original)) { copy_v3_v3(stroke->last_world_space_position, world_space_position); - mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position); + mul_m4_v3(stroke->vc.obact->object_to_world, stroke->last_world_space_position); } else { add_v3_v3(stroke->last_world_space_position, stroke->last_scene_spacing_delta); @@ -825,7 +825,7 @@ static int paint_space_stroke(bContext *C, if (use_scene_spacing) { float world_space_position[3]; bool hit = SCULPT_stroke_get_location(C, world_space_position, final_mouse, stroke->original); - mul_m4_v3(stroke->vc.obact->obmat, world_space_position); + mul_m4_v3(stroke->vc.obact->object_to_world, world_space_position); if (hit && stroke->stroke_over_mesh) { sub_v3_v3v3(d_world_space_position, world_space_position, stroke->last_world_space_position); length = len_v3(d_world_space_position); @@ -1216,8 +1216,8 @@ static void paint_line_strokes_spacing(bContext *C, C, world_space_position_old, old_pos, stroke->original); bool hit_new = SCULPT_stroke_get_location( C, world_space_position_new, new_pos, stroke->original); - mul_m4_v3(stroke->vc.obact->obmat, world_space_position_old); - mul_m4_v3(stroke->vc.obact->obmat, world_space_position_new); + mul_m4_v3(stroke->vc.obact->object_to_world, world_space_position_old); + mul_m4_v3(stroke->vc.obact->object_to_world, world_space_position_new); if (hit_old && hit_new && stroke->stroke_over_mesh) { sub_v3_v3v3(d_world_space_position, world_space_position_new, world_space_position_old); length = len_v3(d_world_space_position); @@ -1360,7 +1360,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str if (paint_stroke_use_scene_spacing(br, BKE_paintmode_get_active_from_context(C))) { stroke->stroke_over_mesh = SCULPT_stroke_get_location( C, stroke->last_world_space_position, data + 2 * j, stroke->original); - mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position); + mul_m4_v3(stroke->vc.obact->object_to_world, stroke->last_world_space_position); } stroke->stroke_started = stroke->test_start(C, op, stroke->last_mouse_position); @@ -1492,7 +1492,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintS if (paint_stroke_use_scene_spacing(br, mode)) { stroke->stroke_over_mesh = SCULPT_stroke_get_location( C, stroke->last_world_space_position, sample_average.mouse, stroke->original); - mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position); + mul_m4_v3(stroke->vc.obact->object_to_world, stroke->last_world_space_position); } stroke->stroke_started = stroke->test_start(C, op, sample_average.mouse); BLI_assert((stroke->stroke_started & ~1) == 0); /* 0/1 */ diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index ce4a5151a20..f87ca073c82 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -135,12 +135,12 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3], flo float delta[3], scale, loc[3]; const float xy_delta[2] = {pixel_radius, 0.0f}; - mul_v3_m4v3(loc, ob->obmat, center); + mul_v3_m4v3(loc, ob->object_to_world, center); const float zfac = ED_view3d_calc_zfac(vc->rv3d, loc); ED_view3d_win_to_delta(vc->region, xy_delta, zfac, delta); - scale = fabsf(mat4_to_scale(ob->obmat)); + scale = fabsf(mat4_to_scale(ob->object_to_world)); scale = (scale == 0.0f) ? 1.0f : scale; return len_v3(delta) / scale; @@ -297,7 +297,7 @@ static void imapaint_pick_uv( GPU_matrix_model_view_get(matrix); GPU_matrix_projection_get(proj); view[0] = view[1] = 0; - mul_m4_m4m4(matrix, matrix, ob_eval->obmat); + mul_m4_m4m4(matrix, matrix, ob_eval->object_to_world); mul_m4_m4m4(matrix, proj, matrix); minabsw = 1e10; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.cc b/source/blender/editors/sculpt_paint/paint_vertex.cc index acd8b1a6bb1..ac5ad62c91f 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex.cc @@ -1647,7 +1647,7 @@ static void vwpaint_update_cache_invariants( /* cache projection matrix */ ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat); - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); copy_m3_m4(mat, cache->vc->rv3d->viewinv); mul_m3_v3(mat, view_dir); copy_m3_m4(mat, ob->imat); @@ -2518,7 +2518,7 @@ static void wpaint_stroke_update_step(bContext *C, ED_view3d_init_mats_rv3d(ob, vc->rv3d); /* load projection matrix */ - mul_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat); + mul_m4_m4m4(mat, vc->rv3d->persmat, ob->object_to_world); Mesh *mesh = static_cast(ob->data); @@ -2556,7 +2556,7 @@ static void wpaint_stroke_update_step(bContext *C, /* Calculate pivot for rotation around selection if needed. * also needed for "Frame Selected" on last stroke. */ float loc_world[3]; - mul_v3_m4v3(loc_world, ob->obmat, ss->cache->true_location); + mul_v3_m4v3(loc_world, ob->object_to_world, ss->cache->true_location); paint_last_stroke_update(scene, loc_world); BKE_mesh_batch_cache_dirty_tag(mesh, BKE_MESH_BATCH_DIRTY_ALL); @@ -3847,7 +3847,7 @@ static void vpaint_stroke_update_step_intern(bContext *C, PaintStroke *stroke, P ED_view3d_init_mats_rv3d(ob, vc->rv3d); /* load projection matrix */ - mul_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat); + mul_m4_m4m4(mat, vc->rv3d->persmat, ob->object_to_world); swap_m4m4(vc->rv3d->persmat, mat); @@ -3870,7 +3870,7 @@ static void vpaint_stroke_update_step_intern(bContext *C, PaintStroke *stroke, P /* Calculate pivot for rotation around selection if needed. * also needed for "Frame Selected" on last stroke. */ float loc_world[3]; - mul_v3_m4v3(loc_world, ob->obmat, ss->cache->true_location); + mul_v3_m4v3(loc_world, ob->object_to_world, ss->cache->true_location); paint_last_stroke_update(scene, loc_world); ED_region_tag_redraw(vc->region); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 34d0158f187..24c6f1b0c3d 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -2793,7 +2793,7 @@ static void calc_brush_local_mat(const Brush *brush, Object *ob, float local_mat float up[3]; /* Ensure `ob->imat` is up to date. */ - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); /* Initialize last column of matrix. */ mat[0][3] = 0.0f; @@ -2833,7 +2833,7 @@ void SCULPT_tilt_apply_to_normal(float r_normal[3], StrokeCache *cache, const fl return; } const float rot_max = M_PI_2 * tilt_strength * SCULPT_TILT_SENSITIVITY; - mul_v3_mat3_m4v3(r_normal, cache->vc->obact->obmat, r_normal); + mul_v3_mat3_m4v3(r_normal, cache->vc->obact->object_to_world, r_normal); float normal_tilt_y[3]; rotate_v3_v3v3fl(normal_tilt_y, r_normal, cache->vc->rv3d->viewinv[0], cache->y_tilt * rot_max); float normal_tilt_xy[3]; @@ -3284,7 +3284,7 @@ static void sculpt_topology_update(Sculpt *sd, /* Update average stroke position. */ copy_v3_v3(location, ss->cache->true_location); - mul_m4_v3(ob->obmat, location); + mul_m4_v3(ob->object_to_world, location); } static void do_brush_action_task_cb(void *__restrict userdata, @@ -3615,7 +3615,7 @@ static void do_brush_action(Sculpt *sd, /* Update average stroke position. */ copy_v3_v3(location, ss->cache->true_location); - mul_m4_v3(ob->obmat, location); + mul_m4_v3(ob->object_to_world, location); add_v3_v3(ups->average_stroke_accum, location); ups->average_stroke_counter++; @@ -4201,8 +4201,8 @@ static void sculpt_init_mirror_clipping(Object *ob, SculptSession *ss) /* Store matrix for mirror object clipping. */ if (mmd->mirror_ob) { float imtx_mirror_ob[4][4]; - invert_m4_m4(imtx_mirror_ob, mmd->mirror_ob->obmat); - mul_m4_m4m4(ss->cache->clip_mirror_mtx, imtx_mirror_ob, ob->obmat); + invert_m4_m4(imtx_mirror_ob, mmd->mirror_ob->object_to_world); + mul_m4_m4m4(ss->cache->clip_mirror_mtx, imtx_mirror_ob, ob->object_to_world); } } } @@ -4354,7 +4354,7 @@ static void sculpt_update_cache_invariants( /* Cache projection matrix. */ ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat); - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); copy_m3_m4(mat, cache->vc->rv3d->viewinv); mul_m3_v3(mat, viewDir); copy_m3_m4(mat, ob->imat); @@ -4373,7 +4373,7 @@ static void sculpt_update_cache_invariants( if (sd->gravity_object) { Object *gravity_object = sd->gravity_object; - copy_v3_v3(cache->true_gravity_direction, gravity_object->obmat[2]); + copy_v3_v3(cache->true_gravity_direction, gravity_object->object_to_world[2]); } else { cache->true_gravity_direction[0] = cache->true_gravity_direction[1] = 0.0f; @@ -4527,27 +4527,27 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru } /* Compute 3d coordinate at same z from original location + mval. */ - mul_v3_m4v3(loc, ob->obmat, cache->orig_grab_location); + mul_v3_m4v3(loc, ob->object_to_world, cache->orig_grab_location); ED_view3d_win_to_3d(cache->vc->v3d, cache->vc->region, loc, mval, grab_location); /* Compute delta to move verts by. */ if (!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { if (sculpt_needs_delta_from_anchored_origin(brush)) { sub_v3_v3v3(delta, grab_location, cache->old_grab_location); - invert_m4_m4(imat, ob->obmat); + invert_m4_m4(imat, ob->object_to_world); mul_mat3_m4_v3(imat, delta); add_v3_v3(cache->grab_delta, delta); } else if (sculpt_needs_delta_for_tip_orientation(brush)) { if (brush->flag & BRUSH_ANCHORED) { float orig[3]; - mul_v3_m4v3(orig, ob->obmat, cache->orig_grab_location); + mul_v3_m4v3(orig, ob->object_to_world, cache->orig_grab_location); sub_v3_v3v3(cache->grab_delta, grab_location, orig); } else { sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location); } - invert_m4_m4(imat, ob->obmat); + invert_m4_m4(imat, ob->object_to_world); mul_mat3_m4_v3(imat, cache->grab_delta); } else { @@ -4592,7 +4592,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru /* Handle 'rake' */ cache->is_rake_rotation_valid = false; - invert_m4_m4(imat, ob->obmat); + invert_m4_m4(imat, ob->object_to_world); mul_mat3_m4_v3(imat, grab_location); if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { @@ -4913,7 +4913,7 @@ float SCULPT_raycast_init(ViewContext *vc, ED_view3d_win_to_segment_clipped( vc->depsgraph, vc->region, vc->v3d, mval, ray_start, ray_end, true); - invert_m4_m4(obimat, ob->obmat); + invert_m4_m4(obimat, ob->object_to_world); mul_m4_v3(obimat, ray_start); mul_m4_v3(obimat, ray_end); @@ -5021,7 +5021,7 @@ bool SCULPT_cursor_geometry_info_update(bContext *C, float radius; /* Update cursor data in SculptSession. */ - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); copy_m3_m4(mat, vc.rv3d->viewinv); mul_m3_v3(mat, viewDir); copy_m3_m4(mat, ob->imat); @@ -5512,7 +5512,8 @@ static void sculpt_stroke_update_step(bContext *C, sculpt_restore_mesh(sd, ob); if (sd->flags & (SCULPT_DYNTOPO_DETAIL_CONSTANT | SCULPT_DYNTOPO_DETAIL_MANUAL)) { - float object_space_constant_detail = 1.0f / (sd->constant_detail * mat4_to_scale(ob->obmat)); + float object_space_constant_detail = 1.0f / (sd->constant_detail * + mat4_to_scale(ob->object_to_world)); BKE_pbvh_bmesh_detail_size_set(ss->pbvh, object_space_constant_detail); } else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) { diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index b6bb4c185f9..cf7e1d027f7 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -667,15 +667,15 @@ static void cloth_brush_solve_collision(Object *object, BVHTreeRayHit hit; float obmat_inv[4][4]; - invert_m4_m4(obmat_inv, object->obmat); + invert_m4_m4(obmat_inv, object->object_to_world); for (collider_cache = cloth_sim->collider_list->first; collider_cache; collider_cache = collider_cache->next) { float ray_start[3], ray_normal[3]; float pos_world_space[3], prev_pos_world_space[3]; - mul_v3_m4v3(pos_world_space, object->obmat, cloth_sim->pos[i]); - mul_v3_m4v3(prev_pos_world_space, object->obmat, cloth_sim->last_iteration_pos[i]); + mul_v3_m4v3(pos_world_space, object->object_to_world, cloth_sim->pos[i]); + mul_v3_m4v3(prev_pos_world_space, object->object_to_world, cloth_sim->last_iteration_pos[i]); sub_v3_v3v3(ray_normal, pos_world_space, prev_pos_world_space); copy_v3_v3(ray_start, prev_pos_world_space); hit.index = -1; @@ -1419,7 +1419,7 @@ static void cloth_filter_apply_forces_task_cb(void *__restrict userdata, float sculpt_gravity[3] = {0.0f}; if (sd->gravity_object) { - copy_v3_v3(sculpt_gravity, sd->gravity_object->obmat[2]); + copy_v3_v3(sculpt_gravity, sd->gravity_object->object_to_world[2]); } else { sculpt_gravity[2] = -1.0f; diff --git a/source/blender/editors/sculpt_paint/sculpt_detail.c b/source/blender/editors/sculpt_paint/sculpt_detail.c index 6dd718d6a0c..0e46fd50f3b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_detail.c +++ b/source/blender/editors/sculpt_paint/sculpt_detail.c @@ -102,7 +102,8 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *op) size = max_fff(dim[0], dim[1], dim[2]); /* Update topology size. */ - float object_space_constant_detail = 1.0f / (sd->constant_detail * mat4_to_scale(ob->obmat)); + float object_space_constant_detail = 1.0f / + (sd->constant_detail * mat4_to_scale(ob->object_to_world)); BKE_pbvh_bmesh_detail_size_set(ss->pbvh, object_space_constant_detail); SCULPT_undo_push_begin(ob, op); @@ -223,7 +224,7 @@ static void sample_detail_dyntopo(bContext *C, ViewContext *vc, const int mval[2 if (srd.hit && srd.edge_length > 0.0f) { /* Convert edge length to world space detail resolution. */ - sd->constant_detail = 1 / (srd.edge_length * mat4_to_scale(ob->obmat)); + sd->constant_detail = 1 / (srd.edge_length * mat4_to_scale(ob->object_to_world)); } } @@ -473,8 +474,8 @@ static void dyntopo_detail_size_parallel_lines_draw(uint pos3d, bool flip, const float angle) { - float object_space_constant_detail = 1.0f / - (cd->detail_size * mat4_to_scale(cd->active_object->obmat)); + float object_space_constant_detail = 1.0f / (cd->detail_size * + mat4_to_scale(cd->active_object->object_to_world)); /* The constant detail represents the maximum edge length allowed before subdividing it. If the * triangle grid preview is created with this value it will represent an ideal mesh density where @@ -592,7 +593,8 @@ static void dyntopo_detail_size_sample_from_surface(Object *ob, if (num_neighbors > 0) { const float avg_edge_len = len_accum / num_neighbors; /* Use 0.7 as the average of min and max dyntopo edge length. */ - const float detail_size = 0.7f / (avg_edge_len * mat4_to_scale(cd->active_object->obmat)); + const float detail_size = 0.7f / + (avg_edge_len * mat4_to_scale(cd->active_object->object_to_world)); cd->detail_size = clamp_f(detail_size, 1.0f, 500.0f); } } @@ -716,7 +718,7 @@ static int dyntopo_detail_size_edit_invoke(bContext *C, wmOperator *op, const wm float cursor_trans[4][4], cursor_rot[4][4]; const float z_axis[4] = {0.0f, 0.0f, 1.0f, 0.0f}; float quat[4]; - copy_m4_m4(cursor_trans, active_object->obmat); + copy_m4_m4(cursor_trans, active_object->object_to_world); translate_m4( cursor_trans, ss->cursor_location[0], ss->cursor_location[1], ss->cursor_location[2]); diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.cc b/source/blender/editors/sculpt_paint/sculpt_face_set.cc index 8fb4dea668e..40835172be9 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.cc +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.cc @@ -917,7 +917,7 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op) UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings; float location[3]; copy_v3_v3(location, SCULPT_active_vertex_co_get(ss)); - mul_m4_v3(ob->obmat, location); + mul_m4_v3(ob->object_to_world, location); copy_v3_v3(ups->average_stroke_accum, location); ups->average_stroke_counter = 1; ups->last_stroke_valid = true; diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index 1fa53eaa006..078f0217416 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -146,8 +146,8 @@ void SCULPT_filter_cache_init(bContext *C, 0, ss->filter_cache->totnode, &data, filter_cache_init_task_cb, &settings); /* Setup orientation matrices. */ - copy_m4_m4(ss->filter_cache->obmat, ob->obmat); - invert_m4_m4(ss->filter_cache->obmat_inv, ob->obmat); + copy_m4_m4(ss->filter_cache->obmat, ob->object_to_world); + invert_m4_m4(ss->filter_cache->obmat_inv, ob->object_to_world); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); ViewContext vc; @@ -203,7 +203,7 @@ void SCULPT_filter_cache_init(bContext *C, /* Update last stroke location */ - mul_m4_v3(ob->obmat, co); + mul_m4_v3(ob->object_to_world, co); add_v3_v3(ups->average_stroke_accum, co); ups->average_stroke_counter++; @@ -221,7 +221,7 @@ void SCULPT_filter_cache_init(bContext *C, ED_view3d_ob_project_mat_get(vc.rv3d, ob, projection_mat); - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); copy_m3_m4(mat, vc.rv3d->viewinv); mul_m3_v3(mat, viewDir); copy_m3_m4(mat, ob->imat); diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.c b/source/blender/editors/sculpt_paint/sculpt_ops.c index a740ec2773b..8affb0e9d53 100644 --- a/source/blender/editors/sculpt_paint/sculpt_ops.c +++ b/source/blender/editors/sculpt_paint/sculpt_ops.c @@ -323,7 +323,7 @@ void ED_object_sculptmode_enter_ex(Main *bmain, BKE_report( reports, RPT_WARNING, "Object has non-uniform scale, sculpting may be unpredictable"); } - else if (is_negative_m4(ob->obmat)) { + else if (is_negative_m4(ob->object_to_world)) { BKE_report(reports, RPT_WARNING, "Object has negative scale, sculpting may be unpredictable"); } diff --git a/source/blender/editors/space_view3d/space_view3d.cc b/source/blender/editors/space_view3d/space_view3d.cc index 635fbd75d74..05fb0c6a720 100644 --- a/source/blender/editors/space_view3d/space_view3d.cc +++ b/source/blender/editors/space_view3d/space_view3d.cc @@ -175,11 +175,11 @@ bool ED_view3d_area_user_region(const ScrArea *area, const View3D *v3d, ARegion void ED_view3d_init_mats_rv3d(const struct Object *ob, struct RegionView3D *rv3d) { /* local viewmat and persmat, to calculate projections */ - mul_m4_m4m4(rv3d->viewmatob, rv3d->viewmat, ob->obmat); - mul_m4_m4m4(rv3d->persmatob, rv3d->persmat, ob->obmat); + mul_m4_m4m4(rv3d->viewmatob, rv3d->viewmat, ob->object_to_world); + mul_m4_m4m4(rv3d->persmatob, rv3d->persmat, ob->object_to_world); /* initializes object space clipping, speeds up clip tests */ - ED_view3d_clipping_local(rv3d, ob->obmat); + ED_view3d_clipping_local(rv3d, ob->object_to_world); } void ED_view3d_init_mats_rv3d_gl(const struct Object *ob, struct RegionView3D *rv3d) @@ -189,7 +189,7 @@ void ED_view3d_init_mats_rv3d_gl(const struct Object *ob, struct RegionView3D *r /* We have to multiply instead of loading `viewmatob` to make * it work with duplis using display-lists, otherwise it will * override the dupli-matrix. */ - GPU_matrix_mul(ob->obmat); + GPU_matrix_mul(ob->object_to_world); } #ifdef DEBUG @@ -710,7 +710,7 @@ static void view3d_ob_drop_matrix_from_snap(V3DSnapCursorState *snap_state, copy_v3_v3(obmat_final[3], snap_data->loc); float scale[3]; - mat4_to_size(scale, ob->obmat); + mat4_to_size(scale, ob->object_to_world); rescale_m4(obmat_final, scale); const BoundBox *bb = BKE_object_boundbox_get(ob); diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 4153f19f8be..83835535d49 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -474,7 +474,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float /* Location, X/Y/Z */ mul_v3_fl(median_basis.generic.location, 1.0f / (float)tot); if (v3d->flag & V3D_GLOBAL_STATS) { - mul_m4_v3(ob->obmat, median_basis.generic.location); + mul_m4_v3(ob->object_to_world, median_basis.generic.location); } if (has_meshdata) { @@ -954,7 +954,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float memcpy(&ve_median_basis, &tfp->ve_median, sizeof(tfp->ve_median)); if (v3d->flag & V3D_GLOBAL_STATS) { - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); mul_m4_v3(ob->imat, median_basis.generic.location); mul_m4_v3(ob->imat, ve_median_basis.generic.location); } @@ -1215,7 +1215,7 @@ static void v3d_object_dimension_buts(bContext *C, uiLayout *layout, View3D *v3d BKE_object_dimensions_get(ob, tfp->ob_dims); copy_v3_v3(tfp->ob_dims_orig, tfp->ob_dims); copy_v3_v3(tfp->ob_scale_orig, ob->scale); - copy_m4_m4(tfp->ob_obmat_orig, ob->obmat); + copy_m4_m4(tfp->ob_obmat_orig, ob->object_to_world); uiDefBut(block, UI_BTYPE_LABEL, diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c index b5962647278..299c8638b02 100644 --- a/source/blender/editors/space_view3d/view3d_camera_control.c +++ b/source/blender/editors/space_view3d/view3d_camera_control.c @@ -142,7 +142,7 @@ struct View3DCameraControl *ED_view3d_cameracontrol_acquire(Depsgraph *depsgraph vctrl->obtfm = BKE_object_tfm_backup(ob_back); BKE_object_where_is_calc(depsgraph, scene, v3d->camera); - negate_v3_v3(rv3d->ofs, v3d->camera->obmat[3]); + negate_v3_v3(rv3d->ofs, v3d->camera->object_to_world[3]); rv3d->dist = 0.0; } @@ -251,7 +251,7 @@ void ED_view3d_cameracontrol_update(View3DCameraControl *vctrl, invert_m4_m4(prev_view_imat, vctrl->view_mat_prev); mul_m4_m4m4(diff_mat, view_mat, prev_view_imat); - mul_m4_m4m4(parent_mat, diff_mat, vctrl->root_parent->obmat); + mul_m4_m4m4(parent_mat, diff_mat, vctrl->root_parent->object_to_world); if (object_apply_mat4_with_protect(vctrl->root_parent, parent_mat, false, rv3d, view_mat)) { /* Calculate again since the view locking changes the matrix. */ diff --git a/source/blender/editors/space_view3d/view3d_draw.cc b/source/blender/editors/space_view3d/view3d_draw.cc index 8a86889f2d0..31b26ba4cda 100644 --- a/source/blender/editors/space_view3d/view3d_draw.cc +++ b/source/blender/editors/space_view3d/view3d_draw.cc @@ -2066,7 +2066,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph, rv3d.persp = RV3D_CAMOB; - copy_m4_m4(rv3d.viewinv, v3d.camera->obmat); + copy_m4_m4(rv3d.viewinv, v3d.camera->object_to_world); normalize_m4(rv3d.viewinv); invert_m4_m4(rv3d.viewmat, rv3d.viewinv); diff --git a/source/blender/editors/space_view3d/view3d_gizmo_armature.c b/source/blender/editors/space_view3d/view3d_gizmo_armature.c index 4f73e2fada2..8a4301d1314 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_armature.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_armature.c @@ -188,7 +188,7 @@ static void WIDGETGROUP_armature_spline_refresh(const bContext *C, wmGizmoGroup bspline_group->handles[i].index = i; float mat[4][4]; - mul_m4_m4m4(mat, ob->obmat, (i == 0) ? pchan->disp_mat : pchan->disp_tail_mat); + mul_m4_m4m4(mat, ob->object_to_world, (i == 0) ? pchan->disp_mat : pchan->disp_tail_mat); copy_m4_m4(gz->matrix_space, mat); /* need to set property here for undo. TODO: would prefer to do this in _init. */ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_camera.c b/source/blender/editors/space_view3d/view3d_gizmo_camera.c index 952ef56710b..56a1f6212a0 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_camera.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_camera.c @@ -85,7 +85,7 @@ static void WIDGETGROUP_camera_setup(const bContext *C, wmGizmoGroup *gzgroup) struct CameraWidgetGroup *cagzgroup = MEM_callocN(sizeof(struct CameraWidgetGroup), __func__); gzgroup->customdata = cagzgroup; - negate_v3_v3(dir, ob->obmat[2]); + negate_v3_v3(dir, ob->object_to_world[2]); /* dof distance */ { @@ -138,11 +138,11 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup) RNA_pointer_create(&ca->id, &RNA_Camera, ca, &camera_ptr); - negate_v3_v3(dir, ob->obmat[2]); + negate_v3_v3(dir, ob->object_to_world[2]); if ((ca->flag & CAM_SHOWLIMITS) && (v3d->gizmo_show_camera & V3D_GIZMO_SHOW_CAMERA_DOF_DIST)) { - WM_gizmo_set_matrix_location(cagzgroup->dop_dist, ob->obmat[3]); - WM_gizmo_set_matrix_rotation_from_yz_axis(cagzgroup->dop_dist, ob->obmat[1], dir); + WM_gizmo_set_matrix_location(cagzgroup->dop_dist, ob->object_to_world[3]); + WM_gizmo_set_matrix_rotation_from_yz_axis(cagzgroup->dop_dist, ob->object_to_world[1], dir); WM_gizmo_set_scale(cagzgroup->dop_dist, ca->drawsize); WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, false); @@ -183,17 +183,17 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup) aspect[1] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? aspy / aspx : 1.0f; unit_m4(widget->matrix_basis); - WM_gizmo_set_matrix_location(widget, ob->obmat[3]); - WM_gizmo_set_matrix_rotation_from_yz_axis(widget, ob->obmat[1], dir); + WM_gizmo_set_matrix_location(widget, ob->object_to_world[3]); + WM_gizmo_set_matrix_rotation_from_yz_axis(widget, ob->object_to_world[1], dir); if (is_ortho) { scale_matrix = ca->ortho_scale * 0.5f; } else { const float ob_scale_inv[3] = { - 1.0f / len_v3(ob->obmat[0]), - 1.0f / len_v3(ob->obmat[1]), - 1.0f / len_v3(ob->obmat[2]), + 1.0f / len_v3(ob->object_to_world[0]), + 1.0f / len_v3(ob->object_to_world[1]), + 1.0f / len_v3(ob->object_to_world[2]), }; const float ob_scale_uniform_inv = (ob_scale_inv[0] + ob_scale_inv[1] + ob_scale_inv[2]) / 3.0f; diff --git a/source/blender/editors/space_view3d/view3d_gizmo_empty.c b/source/blender/editors/space_view3d/view3d_gizmo_empty.c index 41a763192ce..03fc7328e39 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_empty.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_empty.c @@ -139,7 +139,7 @@ static void WIDGETGROUP_empty_image_refresh(const bContext *C, wmGizmoGroup *gzg BKE_view_layer_synced_ensure(scene, view_layer); Object *ob = BKE_view_layer_active_object_get(view_layer); - copy_m4_m4(gz->matrix_basis, ob->obmat); + copy_m4_m4(gz->matrix_basis, ob->object_to_world); RNA_enum_set(gz->ptr, "transform", diff --git a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c index 58b43301397..d194e2a6279 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c @@ -87,8 +87,8 @@ static void WIDGETGROUP_forcefield_refresh(const bContext *C, wmGizmoGroup *gzgr PointerRNA field_ptr; RNA_pointer_create(&ob->id, &RNA_FieldSettings, pd, &field_ptr); - WM_gizmo_set_matrix_location(gz, ob->obmat[3]); - WM_gizmo_set_matrix_rotation_from_z_axis(gz, ob->obmat[2]); + WM_gizmo_set_matrix_location(gz, ob->object_to_world[3]); + WM_gizmo_set_matrix_rotation_from_z_axis(gz, ob->object_to_world[2]); WM_gizmo_set_matrix_offset_location(gz, ofs); WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); WM_gizmo_target_property_def_rna(gz, "offset", &field_ptr, "strength", -1); diff --git a/source/blender/editors/space_view3d/view3d_gizmo_light.c b/source/blender/editors/space_view3d/view3d_gizmo_light.c index 4401dbf7935..0b115bc0604 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_light.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_light.c @@ -85,10 +85,10 @@ static void WIDGETGROUP_light_spot_refresh(const bContext *C, wmGizmoGroup *gzgr Light *la = ob->data; float dir[3]; - negate_v3_v3(dir, ob->obmat[2]); + negate_v3_v3(dir, ob->object_to_world[2]); WM_gizmo_set_matrix_rotation_from_z_axis(gz, dir); - WM_gizmo_set_matrix_location(gz, ob->obmat[3]); + WM_gizmo_set_matrix_location(gz, ob->object_to_world[3]); /* need to set property here for undo. TODO: would prefer to do this in _init. */ PointerRNA lamp_ptr; @@ -199,7 +199,7 @@ static void WIDGETGROUP_light_area_refresh(const bContext *C, wmGizmoGroup *gzgr Light *la = ob->data; wmGizmo *gz = wwrapper->gizmo; - copy_m4_m4(gz->matrix_basis, ob->obmat); + copy_m4_m4(gz->matrix_basis, ob->object_to_world); int flag = ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE; if (ELEM(la->area_shape, LA_AREA_SQUARE, LA_AREA_DISK)) { @@ -296,7 +296,7 @@ static void WIDGETGROUP_light_target_draw_prepare(const bContext *C, wmGizmoGrou Object *ob = BKE_view_layer_active_object_get(view_layer); wmGizmo *gz = wwrapper->gizmo; - normalize_m4_m4(gz->matrix_basis, ob->obmat); + normalize_m4_m4(gz->matrix_basis, ob->object_to_world); unit_m4(gz->matrix_offset); if (ob->type == OB_LAMP) { diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.cc b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.cc index 793ada4f577..86aecfb6c34 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.cc +++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.cc @@ -97,7 +97,7 @@ static void gizmo_preselect_elem_draw(const bContext *C, wmGizmo *gz) MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; if (gz_ele->base_index != -1) { Object *ob = gz_ele->bases[gz_ele->base_index]->object; - EDBM_preselect_elem_draw(gz_ele->psel, ob->obmat); + EDBM_preselect_elem_draw(gz_ele->psel, ob->object_to_world); } } @@ -185,7 +185,7 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int BMVert *vert = (BMVert *)eve_test; float vert_p_co[2], vert_co[3]; const float mval_f[2] = {float(vc.mval[0]), float(vc.mval[1])}; - mul_v3_m4v3(vert_co, gz_ele->bases[base_index_vert]->object->obmat, vert->co); + mul_v3_m4v3(vert_co, gz_ele->bases[base_index_vert]->object->object_to_world, vert->co); ED_view3d_project_v2(vc.region, vert_co, vert_p_co); float len = len_v2v2(vert_p_co, mval_f); if (len < 35) { @@ -330,7 +330,7 @@ static void gizmo_preselect_edgering_draw(const bContext *C, wmGizmo *gz) MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; if (gz_ring->base_index != -1) { Object *ob = gz_ring->bases[gz_ring->base_index]->object; - EDBM_preselect_edgering_draw(gz_ring->psel, ob->obmat); + EDBM_preselect_edgering_draw(gz_ring->psel, ob->object_to_world); } } diff --git a/source/blender/editors/space_view3d/view3d_iterators.cc b/source/blender/editors/space_view3d/view3d_iterators.cc index 932563863fe..aaa817ec00c 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.cc +++ b/source/blender/editors/space_view3d/view3d_iterators.cc @@ -307,7 +307,7 @@ void meshobject_foreachScreenVert( &me->vdata, CD_PROP_BOOL, ".hide_vert"); if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { - ED_view3d_clipping_local(vc->rv3d, vc->obact->obmat); + ED_view3d_clipping_local(vc->rv3d, vc->obact->object_to_world); } BKE_mesh_foreach_mapped_vert(me, meshobject_foreachScreenVert__mapFunc, &data, MESH_FOREACH_NOP); @@ -353,7 +353,8 @@ void mesh_foreachScreenVert( data.clip_flag = clip_flag; if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { - ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */ + ED_view3d_clipping_local(vc->rv3d, + vc->obedit->object_to_world); /* for local clipping lookups */ } BM_mesh_elem_table_ensure(vc->em->bm, BM_VERT); @@ -422,7 +423,8 @@ void mesh_foreachScreenEdge(ViewContext *vc, data.clip_flag = clip_flag; if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { - ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */ + ED_view3d_clipping_local(vc->rv3d, + vc->obedit->object_to_world); /* for local clipping lookups */ } if (clip_flag & V3D_PROJ_TEST_CLIP_CONTENT) { @@ -520,7 +522,8 @@ void mesh_foreachScreenEdge_clip_bb_segment(ViewContext *vc, BM_mesh_elem_table_ensure(vc->em->bm, BM_EDGE); if ((clip_flag & V3D_PROJ_TEST_CLIP_BB) && (vc->rv3d->clipbb != nullptr)) { - ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups. */ + ED_view3d_clipping_local(vc->rv3d, + vc->obedit->object_to_world); /* for local clipping lookups. */ BKE_mesh_foreach_mapped_edge( me, vc->em->bm->totedge, mesh_foreachScreenEdge_clip_bb_segment__mapFunc, &data); } @@ -612,7 +615,8 @@ void nurbs_foreachScreenVert(ViewContext *vc, ED_view3d_check_mats_rv3d(vc->rv3d); if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { - ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */ + ED_view3d_clipping_local(vc->rv3d, + vc->obedit->object_to_world); /* for local clipping lookups */ } LISTBASE_FOREACH (Nurb *, nu, nurbs) { @@ -732,7 +736,7 @@ void lattice_foreachScreenVert(ViewContext *vc, ED_view3d_check_mats_rv3d(vc->rv3d); if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { - ED_view3d_clipping_local(vc->rv3d, obedit->obmat); /* for local clipping lookups */ + ED_view3d_clipping_local(vc->rv3d, obedit->object_to_world); /* for local clipping lookups */ } for (i = 0; i < N; i++, bp++, co += 3) { diff --git a/source/blender/editors/space_view3d/view3d_navigate.c b/source/blender/editors/space_view3d/view3d_navigate.c index 25073d02a7f..7d2beecd9a3 100644 --- a/source/blender/editors/space_view3d/view3d_navigate.c +++ b/source/blender/editors/space_view3d/view3d_navigate.c @@ -185,7 +185,7 @@ bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3]) copy_v3_v3(lastofs, stroke); } else { - copy_v3_v3(lastofs, ob_act_eval->obmat[3]); + copy_v3_v3(lastofs, ob_act_eval->object_to_world[3]); } is_set = true; } @@ -199,7 +199,7 @@ bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3]) } mul_v2_fl(lastofs, 1.0f / 4.0f); - mul_m4_v3(ob_act_eval->obmat, lastofs); + mul_m4_v3(ob_act_eval->object_to_world, lastofs); is_set = true; } @@ -219,11 +219,11 @@ bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3]) BKE_boundbox_calc_center_aabb(ob_eval->runtime.bb, cent); - mul_m4_v3(ob_eval->obmat, cent); + mul_m4_v3(ob_eval->object_to_world, cent); add_v3_v3(select_center, cent); } else { - add_v3_v3(select_center, ob_eval->obmat[3]); + add_v3_v3(select_center, ob_eval->object_to_world[3]); } tot++; } @@ -626,7 +626,7 @@ static void view3d_object_calc_minmax(Depsgraph *depsgraph, if (BKE_object_minmax_dupli(depsgraph, scene, ob_eval, min, max, false) == 0) { /* Use if duplis aren't found. */ if (only_center) { - minmax_v3v3_v3(min, max, ob_eval->obmat[3]); + minmax_v3v3_v3(min, max, ob_eval->object_to_world[3]); } else { BKE_object_minmax(ob_eval, min, max, false); @@ -934,8 +934,8 @@ static int viewselected_exec(bContext *C, wmOperator *op) CTX_DATA_END; if ((ob_eval) && (ok)) { - mul_m4_v3(ob_eval->obmat, min); - mul_m4_v3(ob_eval->obmat, max); + mul_m4_v3(ob_eval->object_to_world, min); + mul_m4_v3(ob_eval->object_to_world, max); } } else if (is_face_map) { diff --git a/source/blender/editors/space_view3d/view3d_navigate_smoothview.c b/source/blender/editors/space_view3d/view3d_navigate_smoothview.c index 6b150d1e771..a5eee436fdb 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_smoothview.c +++ b/source/blender/editors/space_view3d/view3d_navigate_smoothview.c @@ -259,7 +259,7 @@ void ED_view3d_smooth_view_ex( Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, sview->camera); if (sview->ofs != NULL) { sms.dst.dist = ED_view3d_offset_distance( - ob_camera_eval->obmat, sview->ofs, VIEW3D_DIST_FALLBACK); + ob_camera_eval->object_to_world, sview->ofs, VIEW3D_DIST_FALLBACK); } ED_view3d_from_object(ob_camera_eval, sms.dst.ofs, sms.dst.quat, &sms.dst.dist, &sms.dst.lens); sms.to_camera = true; /* restore view3d values in end */ @@ -282,7 +282,8 @@ void ED_view3d_smooth_view_ex( if (sview->camera_old) { Object *ob_camera_old_eval = DEG_get_evaluated_object(depsgraph, sview->camera_old); if (sview->ofs != NULL) { - sms.src.dist = ED_view3d_offset_distance(ob_camera_old_eval->obmat, sview->ofs, 0.0f); + sms.src.dist = ED_view3d_offset_distance( + ob_camera_old_eval->object_to_world, sview->ofs, 0.0f); } ED_view3d_from_object( ob_camera_old_eval, sms.src.ofs, sms.src.quat, &sms.src.dist, &sms.src.lens); diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index c5f951bd64c..2718f14c855 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -80,7 +80,7 @@ eV3DProjStatus ED_view3d_project_base(const struct ARegion *region, float r_co[2]) { eV3DProjStatus ret = ED_view3d_project_float_global( - region, base->object->obmat[3], r_co, V3D_PROJ_TEST_CLIP_DEFAULT); + region, base->object->object_to_world[3], r_co, V3D_PROJ_TEST_CLIP_DEFAULT); /* Prevent uninitialized values when projection fails, * although the callers should check the return value. */ @@ -687,7 +687,7 @@ void ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, const Object *ob, fl { float vmat[4][4]; - mul_m4_m4m4(vmat, rv3d->viewmat, ob->obmat); + mul_m4_m4m4(vmat, rv3d->viewmat, ob->object_to_world); mul_m4_m4m4(r_pmat, rv3d->winmat, vmat); } diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc index 2a84d61c561..9c450e85d23 100644 --- a/source/blender/editors/space_view3d/view3d_select.cc +++ b/source/blender/editors/space_view3d/view3d_select.cc @@ -2303,7 +2303,7 @@ static Base *mouse_select_object_center(ViewContext *vc, Base *startbase, const if (BASE_SELECTABLE(v3d, base)) { float screen_co[2]; if (ED_view3d_project_float_global( - region, base->object->obmat[3], screen_co, V3D_PROJ_TEST_CLIP_DEFAULT) == + region, base->object->object_to_world[3], screen_co, V3D_PROJ_TEST_CLIP_DEFAULT) == V3D_PROJ_RET_OK) { float dist_test = len_manhattan_v2v2(mval_fl, screen_co); if (base == oldbasact) { @@ -4728,9 +4728,10 @@ static bool object_circle_select(ViewContext *vc, LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (BASE_SELECTABLE(v3d, base) && ((base->flag & BASE_SELECTED) != select_flag)) { float screen_co[2]; - if (ED_view3d_project_float_global( - vc->region, base->object->obmat[3], screen_co, V3D_PROJ_TEST_CLIP_DEFAULT) == - V3D_PROJ_RET_OK) { + if (ED_view3d_project_float_global(vc->region, + base->object->object_to_world[3], + screen_co, + V3D_PROJ_TEST_CLIP_DEFAULT) == V3D_PROJ_RET_OK) { if (len_squared_v2v2(mval_fl, screen_co) <= radius_squared) { ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT); changed = true; diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index ee6b1886dc2..f2b952c4f46 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -86,18 +86,18 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) } if (tvs.transverts_tot != 0) { - copy_m3_m4(bmat, obedit->obmat); + copy_m3_m4(bmat, obedit->object_to_world); invert_m3_m3(imat, bmat); tv = tvs.transverts; for (a = 0; a < tvs.transverts_tot; a++, tv++) { copy_v3_v3(vec, tv->loc); mul_m3_v3(bmat, vec); - add_v3_v3(vec, obedit->obmat[3]); + add_v3_v3(vec, obedit->object_to_world[3]); vec[0] = gridf * floorf(0.5f + vec[0] / gridf); vec[1] = gridf * floorf(0.5f + vec[1] / gridf); vec[2] = gridf * floorf(0.5f + vec[2] / gridf); - sub_v3_v3(vec, obedit->obmat[3]); + sub_v3_v3(vec, obedit->object_to_world[3]); mul_m3_v3(imat, vec); copy_v3_v3(tv->loc, vec); @@ -118,7 +118,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) bPoseChannel *pchan_eval; bArmature *arm_eval = ob_eval->data; - invert_m4_m4(ob_eval->imat, ob_eval->obmat); + invert_m4_m4(ob_eval->imat, ob_eval->object_to_world); for (pchan_eval = ob_eval->pose->chanbase.first; pchan_eval; pchan_eval = pchan_eval->next) { if (pchan_eval->bone->flag & BONE_SELECTED) { @@ -129,7 +129,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) /* get nearest grid point to snap to */ copy_v3_v3(nLoc, pchan_eval->pose_mat[3]); /* We must operate in world space! */ - mul_m4_v3(ob_eval->obmat, nLoc); + mul_m4_v3(ob_eval->object_to_world, nLoc); vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf); vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf); vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf); @@ -214,9 +214,12 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) for (int ob_index = 0; ob_index < objects_eval_len; ob_index++) { Object *ob_eval = objects_eval[ob_index]; Object *ob = DEG_get_original_object(ob_eval); - vec[0] = -ob_eval->obmat[3][0] + gridf * floorf(0.5f + ob_eval->obmat[3][0] / gridf); - vec[1] = -ob_eval->obmat[3][1] + gridf * floorf(0.5f + ob_eval->obmat[3][1] / gridf); - vec[2] = -ob_eval->obmat[3][2] + gridf * floorf(0.5f + ob_eval->obmat[3][2] / gridf); + vec[0] = -ob_eval->object_to_world[3][0] + + gridf * floorf(0.5f + ob_eval->object_to_world[3][0] / gridf); + vec[1] = -ob_eval->object_to_world[3][1] + + gridf * floorf(0.5f + ob_eval->object_to_world[3][1] / gridf); + vec[2] = -ob_eval->object_to_world[3][2] + + gridf * floorf(0.5f + ob_eval->object_to_world[3][2] / gridf); if (ob->parent) { float originmat[3][3]; @@ -343,11 +346,11 @@ static bool snap_selected_to_location(bContext *C, } if (tvs.transverts_tot != 0) { - copy_m3_m4(bmat, obedit->obmat); + copy_m3_m4(bmat, obedit->object_to_world); invert_m3_m3(imat, bmat); /* get the cursor in object space */ - sub_v3_v3v3(snap_target_local, snap_target_global, obedit->obmat[3]); + sub_v3_v3v3(snap_target_local, snap_target_global, obedit->object_to_world[3]); mul_m3_v3(imat, snap_target_local); if (use_offset) { @@ -384,7 +387,7 @@ static bool snap_selected_to_location(bContext *C, bArmature *arm = ob->data; float snap_target_local[3]; - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); mul_v3_m4v3(snap_target_local, ob->imat, snap_target_global); for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { @@ -409,7 +412,7 @@ static bool snap_selected_to_location(bContext *C, float cursor_pose[3]; if (use_offset) { - mul_v3_m4v3(cursor_pose, ob->obmat, pchan->pose_mat[3]); + mul_v3_m4v3(cursor_pose, ob->object_to_world, pchan->pose_mat[3]); add_v3_v3(cursor_pose, offset_global); mul_m4_v3(ob->imat, cursor_pose); @@ -510,13 +513,13 @@ static bool snap_selected_to_location(bContext *C, float cursor_parent[3]; /* parent-relative */ if (use_offset) { - add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global); + add_v3_v3v3(cursor_parent, ob->object_to_world[3], offset_global); } else { copy_v3_v3(cursor_parent, snap_target_global); } - sub_v3_v3(cursor_parent, ob->obmat[3]); + sub_v3_v3(cursor_parent, ob->object_to_world[3]); if (ob->parent) { float originmat[3][3], parentmat[4][4]; @@ -730,7 +733,7 @@ static void bundle_midpoint(Scene *scene, Object *ob, float r_vec[3]) tracking = &clip->tracking; - copy_m4_m4(cammat, ob->obmat); + copy_m4_m4(cammat, ob->object_to_world); BKE_tracking_get_camera_object_matrix(ob, mat); @@ -809,13 +812,13 @@ static bool snap_curs_to_sel_ex(bContext *C, const int pivot_point, float r_curs count += tvs.transverts_tot; if (tvs.transverts_tot != 0) { Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit); - copy_m3_m4(bmat, obedit_eval->obmat); + copy_m3_m4(bmat, obedit_eval->object_to_world); tv = tvs.transverts; for (int i = 0; i < tvs.transverts_tot; i++, tv++) { copy_v3_v3(vec, tv->loc); mul_m3_v3(bmat, vec); - add_v3_v3(vec, obedit_eval->obmat[3]); + add_v3_v3(vec, obedit_eval->object_to_world[3]); add_v3_v3(centroid, vec); minmax_v3v3_v3(min, max, vec); } @@ -835,7 +838,7 @@ static bool snap_curs_to_sel_ex(bContext *C, const int pivot_point, float r_curs if (arm->layer & pchan->bone->layer) { if (pchan->bone->flag & BONE_SELECTED) { copy_v3_v3(vec, pchan->pose_head); - mul_m4_v3(obact_eval->obmat, vec); + mul_m4_v3(obact_eval->object_to_world, vec); add_v3_v3(centroid, vec); minmax_v3v3_v3(min, max, vec); count++; @@ -845,7 +848,7 @@ static bool snap_curs_to_sel_ex(bContext *C, const int pivot_point, float r_curs } else { FOREACH_SELECTED_OBJECT_BEGIN (view_layer_eval, v3d, ob_eval) { - copy_v3_v3(vec, ob_eval->obmat[3]); + copy_v3_v3(vec, ob_eval->object_to_world[3]); /* special case for camera -- snap to bundles */ if (ob_eval->type == OB_CAMERA) { @@ -1008,7 +1011,7 @@ bool ED_view3d_minmax_verts(Object *obedit, float r_min[3], float r_max[3]) float ob_min[3], ob_max[3]; bool changed; - changed = BKE_mball_minmax_ex(obedit->data, ob_min, ob_max, obedit->obmat, SELECT); + changed = BKE_mball_minmax_ex(obedit->data, ob_min, ob_max, obedit->object_to_world, SELECT); if (changed) { minmax_v3v3_v3(r_min, r_max, ob_min); minmax_v3v3_v3(r_min, r_max, ob_max); @@ -1024,13 +1027,13 @@ bool ED_view3d_minmax_verts(Object *obedit, float r_min[3], float r_max[3]) return false; } - copy_m3_m4(bmat, obedit->obmat); + copy_m3_m4(bmat, obedit->object_to_world); tv = tvs.transverts; for (int a = 0; a < tvs.transverts_tot; a++, tv++) { copy_v3_v3(vec, (tv->flag & TX_VERT_USE_MAPLOC) ? tv->maploc : tv->loc); mul_m3_v3(bmat, vec); - add_v3_v3(vec, obedit->obmat[3]); + add_v3_v3(vec, obedit->object_to_world[3]); add_v3_v3(centroid, vec); minmax_v3v3_v3(r_min, r_max, vec); } diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index 1fc16939f3f..fc26e6b4a06 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -281,7 +281,7 @@ void ED_view3d_clipping_calc( /* optionally transform to object space */ if (ob) { float imat[4][4]; - invert_m4_m4(imat, ob->obmat); + invert_m4_m4(imat, ob->object_to_world); for (int val = 0; val < 8; val++) { mul_m4_v3(imat, bb->vec[val]); @@ -291,7 +291,7 @@ void ED_view3d_clipping_calc( /* verify if we have negative scale. doing the transform before cross * product flips the sign of the vector compared to doing cross product * before transform then, so we correct for that. */ - int flip_sign = (ob) ? is_negative_m4(ob->obmat) : false; + int flip_sign = (ob) ? is_negative_m4(ob->object_to_world) : false; ED_view3d_clipping_calc_from_boundbox(planes, bb, flip_sign); } @@ -466,7 +466,8 @@ void ED_view3d_persp_switch_from_camera(const Depsgraph *depsgraph, if (v3d->camera) { Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); - rv3d->dist = ED_view3d_offset_distance(ob_camera_eval->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK); + rv3d->dist = ED_view3d_offset_distance( + ob_camera_eval->object_to_world, rv3d->ofs, VIEW3D_DIST_FALLBACK); ED_view3d_from_object(ob_camera_eval, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL); } @@ -558,7 +559,7 @@ void ED_view3d_camera_lock_init_ex(const Depsgraph *depsgraph, if (calc_dist) { /* using a fallback dist is OK here since ED_view3d_from_object() compensates for it */ rv3d->dist = ED_view3d_offset_distance( - ob_camera_eval->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK); + ob_camera_eval->object_to_world, rv3d->ofs, VIEW3D_DIST_FALLBACK); } ED_view3d_from_object(ob_camera_eval, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL); } @@ -592,12 +593,12 @@ bool ED_view3d_camera_lock_sync(const Depsgraph *depsgraph, View3D *v3d, RegionV ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); - normalize_m4_m4(tmat, ob_camera_eval->obmat); + normalize_m4_m4(tmat, ob_camera_eval->object_to_world); invert_m4_m4(imat, tmat); mul_m4_m4m4(diff_mat, view_mat, imat); - mul_m4_m4m4(parent_mat, diff_mat, root_parent_eval->obmat); + mul_m4_m4m4(parent_mat, diff_mat, root_parent_eval->object_to_world); BKE_object_tfm_protected_backup(root_parent, &obtfm); BKE_object_apply_mat4(root_parent, parent_mat, true, false); @@ -1508,7 +1509,7 @@ void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], c void ED_view3d_from_object(const Object *ob, float ofs[3], float quat[4], float *dist, float *lens) { - ED_view3d_from_m4(ob->obmat, ofs, quat, dist); + ED_view3d_from_m4(ob->object_to_world, ofs, quat, dist); if (lens) { CameraParams params; @@ -1555,7 +1556,7 @@ static bool view3d_camera_to_view_selected_impl(struct Main *bmain, is_ortho_camera = true; } - copy_m4_m4(obmat_new, camera_ob_eval->obmat); + copy_m4_m4(obmat_new, camera_ob_eval->object_to_world); copy_v3_v3(obmat_new[3], co); /* only touch location */ diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index d0db4de0c47..c630a1a5653 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -365,7 +365,7 @@ static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob) rv3d->view = RV3D_VIEW_USER; /* don't show the grid */ - normalize_m4_m4(bmat, ob->obmat); + normalize_m4_m4(bmat, ob->object_to_world); invert_m4_m4(rv3d->viewmat, bmat); /* view quat calculation, needed for add object */ @@ -404,12 +404,12 @@ void view3d_viewmatrix_set(Depsgraph *depsgraph, Object *ob_eval = DEG_get_evaluated_object(depsgraph, v3d->ob_center); float vec[3]; - copy_v3_v3(vec, ob_eval->obmat[3]); + copy_v3_v3(vec, ob_eval->object_to_world[3]); if (ob_eval->type == OB_ARMATURE && v3d->ob_center_bone[0]) { bPoseChannel *pchan = BKE_pose_channel_find_name(ob_eval->pose, v3d->ob_center_bone); if (pchan) { copy_v3_v3(vec, pchan->pose_mat[3]); - mul_m4_v3(ob_eval->obmat, vec); + mul_m4_v3(ob_eval->object_to_world, vec); } } translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]); diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 90f2795184b..1e260ecd292 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -469,7 +469,8 @@ typedef struct TransDataContainer { /** * Store matrix, this avoids having to have duplicate check all over - * Typically: 'obedit->obmat' or 'poseobj->obmat', but may be used elsewhere too. + * Typically: 'obedit->object_to_world' or 'poseobj->object_to_world', but may be used elsewhere + * too. */ bool use_local_mat; diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index 7a68ee1bfbf..a5b2442f11c 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -981,7 +981,7 @@ static void init_TransDataContainers(TransInfo *t, if (tc->use_local_mat) { BLI_assert((t->flag & T_2D_EDIT) == 0); - copy_m4_m4(tc->mat, objects[i]->obmat); + copy_m4_m4(tc->mat, objects[i]->object_to_world); copy_m3_m4(tc->mat3, tc->mat); /* for non-invertible scale matrices, invert_m4_m4_fallback() * can still provide a valid pivot */ @@ -1235,8 +1235,8 @@ void transform_convert_clip_mirror_modifier_apply(TransDataContainer *tc) if (mmd->mirror_ob) { float obinv[4][4]; - invert_m4_m4(obinv, mmd->mirror_ob->obmat); - mul_m4_m4m4(mtx, obinv, ob->obmat); + invert_m4_m4(obinv, mmd->mirror_ob->object_to_world); + mul_m4_m4m4(mtx, obinv, ob->object_to_world); invert_m4_m4(imtx, mtx); } diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index 6fd25d26c31..2e37f6b7c34 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -593,7 +593,7 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr td->ext->rotOrder = pchan->rotmode; /* proper way to get parent transform + own transform + constraints transform */ - copy_m3_m4(omat, ob->obmat); + copy_m3_m4(omat, ob->object_to_world); /* New code, using "generic" BKE_bone_parent_transform_calc_from_pchan(). */ { @@ -955,7 +955,7 @@ static void createTransArmatureVerts(bContext *UNUSED(C), TransInfo *t) bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0); BoneInitData *bid = tc->custom.type.data; - copy_m3_m4(mtx, tc->obedit->obmat); + copy_m3_m4(mtx, tc->obedit->object_to_world); pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransEditBone"); diff --git a/source/blender/editors/transform/transform_convert_curve.c b/source/blender/editors/transform/transform_convert_curve.c index 404b1293208..13ba28ec3d0 100644 --- a/source/blender/editors/transform/transform_convert_curve.c +++ b/source/blender/editors/transform/transform_convert_curve.c @@ -174,7 +174,7 @@ static void createTransCurveVerts(bContext *UNUSED(C), TransInfo *t) transform_mode_use_local_origins(t)); float mtx[3][3], smtx[3][3]; - copy_m3_m4(mtx, tc->obedit->obmat); + copy_m3_m4(mtx, tc->obedit->object_to_world); pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); TransData *td = tc->data; diff --git a/source/blender/editors/transform/transform_convert_lattice.c b/source/blender/editors/transform/transform_convert_lattice.c index b77538dc249..e9b3401974b 100644 --- a/source/blender/editors/transform/transform_convert_lattice.c +++ b/source/blender/editors/transform/transform_convert_lattice.c @@ -66,7 +66,7 @@ static void createTransLatticeVerts(bContext *UNUSED(C), TransInfo *t) } tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Lattice EditMode)"); - copy_m3_m4(mtx, tc->obedit->obmat); + copy_m3_m4(mtx, tc->obedit->object_to_world); pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); td = tc->data; diff --git a/source/blender/editors/transform/transform_convert_mball.c b/source/blender/editors/transform/transform_convert_mball.c index 7ae93524d0b..c90052e9e8c 100644 --- a/source/blender/editors/transform/transform_convert_mball.c +++ b/source/blender/editors/transform/transform_convert_mball.c @@ -61,7 +61,7 @@ static void createTransMBallVerts(bContext *UNUSED(C), TransInfo *t) tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), "MetaElement_TransExtension"); - copy_m3_m4(mtx, tc->obedit->obmat); + copy_m3_m4(mtx, tc->obedit->object_to_world); pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); for (ml = mb->editelems->first; ml; ml = ml->next) { diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index 7e237c9eb32..3192b1b6786 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -1527,7 +1527,7 @@ static void createTransEditVerts(bContext *UNUSED(C), TransInfo *t) em, calc_single_islands, calc_island_center, calc_island_axismtx, &island_data); } - copy_m3_m4(mtx, tc->obedit->obmat); + copy_m3_m4(mtx, tc->obedit->object_to_world); /* we use a pseudo-inverse so that when one of the axes is scaled to 0, * matrix inversion still works and we can still moving along the other */ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); diff --git a/source/blender/editors/transform/transform_convert_mesh_edge.c b/source/blender/editors/transform/transform_convert_mesh_edge.c index 0ce4c592f53..fd62b199345 100644 --- a/source/blender/editors/transform/transform_convert_mesh_edge.c +++ b/source/blender/editors/transform/transform_convert_mesh_edge.c @@ -62,7 +62,7 @@ static void createTransEdge(bContext *UNUSED(C), TransInfo *t) td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransCrease"); - copy_m3_m4(mtx, tc->obedit->obmat); + copy_m3_m4(mtx, tc->obedit->object_to_world); pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); /* create data we need */ diff --git a/source/blender/editors/transform/transform_convert_mesh_skin.c b/source/blender/editors/transform/transform_convert_mesh_skin.c index 376e559181e..cb6108a4c45 100644 --- a/source/blender/editors/transform/transform_convert_mesh_skin.c +++ b/source/blender/editors/transform/transform_convert_mesh_skin.c @@ -130,7 +130,7 @@ static void createTransMeshSkin(bContext *UNUSED(C), TransInfo *t) em, calc_single_islands, calc_island_center, calc_island_axismtx, &island_data); } - copy_m3_m4(mtx, tc->obedit->obmat); + copy_m3_m4(mtx, tc->obedit->object_to_world); /* we use a pseudo-inverse so that when one of the axes is scaled to 0, * matrix inversion still works and we can still moving along the other */ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); diff --git a/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c b/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c index 59836180166..d253261f458 100644 --- a/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c +++ b/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c @@ -131,7 +131,7 @@ static void createTransMeshVertCData(bContext *UNUSED(C), TransInfo *t) em, calc_single_islands, calc_island_center, calc_island_axismtx, &island_data); } - copy_m3_m4(mtx, tc->obedit->obmat); + copy_m3_m4(mtx, tc->obedit->object_to_world); /* we use a pseudo-inverse so that when one of the axes is scaled to 0, * matrix inversion still works and we can still moving along the other */ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c index 0dcfd7206ad..55f7cd9b23d 100644 --- a/source/blender/editors/transform/transform_convert_object.c +++ b/source/blender/editors/transform/transform_convert_object.c @@ -158,14 +158,14 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) copy_qt_qt(td->ext->oquat, ob->quat); } /* update object's loc/rot to get current rigid body transform */ - mat4_to_loc_rot_size(ob->loc, rot, scale, ob->obmat); + mat4_to_loc_rot_size(ob->loc, rot, scale, ob->object_to_world); sub_v3_v3(ob->loc, ob->dloc); BKE_object_mat3_to_rot(ob, rot, false); /* drot is already corrected here */ } } /* axismtx has the real orientation */ - transform_orientations_create_from_axis(td->axismtx, UNPACK3(ob->obmat)); + transform_orientations_create_from_axis(td->axismtx, UNPACK3(ob->object_to_world)); if (t->orient_type_mask & (1 << V3D_ORIENT_GIMBAL)) { if (!gimbal_axis_object(ob, td->ext->axismtx_gimbal)) { copy_m3_m3(td->ext->axismtx_gimbal, td->axismtx); @@ -192,7 +192,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) * More proper solution would be to make a shallow copy of the object and * evaluate that, and access matrix of that evaluated copy of the object. * Might be more tricky than it sounds, if some logic later on accesses the - * object matrix via td->ob->obmat. */ + * object matrix via td->ob->object_to_world. */ Object *object_eval = DEG_get_evaluated_object(t->depsgraph, ob); if (skip_invert == false && constinv == false) { object_eval->transflag |= OB_NO_CONSTRAINTS; /* BKE_object_where_is_calc checks this */ @@ -208,7 +208,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) } /* Copy newly evaluated fields to the original object, similar to how * active dependency graph will do it. */ - copy_m4_m4(ob->obmat, object_eval->obmat); + copy_m4_m4(ob->object_to_world, object_eval->object_to_world); /* Only copy negative scale flag, this is the only flag which is modified by * the BKE_object_where_is_calc(). The rest of the flags we need to keep, * otherwise we might lose dupli flags (see T61787). */ @@ -258,9 +258,9 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) copy_v3_v3(td->ext->isize, ob->scale); copy_v3_v3(td->ext->dscale, ob->dscale); - copy_v3_v3(td->center, ob->obmat[3]); + copy_v3_v3(td->center, ob->object_to_world[3]); - copy_m4_m4(td->ext->obmat, ob->obmat); + copy_m4_m4(td->ext->obmat, ob->object_to_world); /* is there a need to set the global<->data space conversion matrices? */ if (ob->parent || constinv) { @@ -271,7 +271,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) * done, as it doesn't work well. */ BKE_object_to_mat3(ob, obmtx); - copy_m3_m4(totmat, ob->obmat); + copy_m3_m4(totmat, ob->object_to_world); /* If the object scale is zero on any axis, this might result in a zero matrix. * In this case, the transformation would not do anything, see: T50103. */ diff --git a/source/blender/editors/transform/transform_convert_object_texspace.c b/source/blender/editors/transform/transform_convert_object_texspace.c index 839bf6b77b3..b4c1c134d49 100644 --- a/source/blender/editors/transform/transform_convert_object_texspace.c +++ b/source/blender/editors/transform/transform_convert_object_texspace.c @@ -67,8 +67,8 @@ static void createTransTexspace(bContext *UNUSED(C), TransInfo *t) td->flag = TD_SELECTED; td->ob = ob; - copy_m3_m4(td->mtx, ob->obmat); - copy_m3_m4(td->axismtx, ob->obmat); + copy_m3_m4(td->mtx, ob->object_to_world); + copy_m3_m4(td->axismtx, ob->object_to_world); normalize_m3(td->axismtx); pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON); diff --git a/source/blender/editors/transform/transform_convert_particle.c b/source/blender/editors/transform/transform_convert_particle.c index 3e056b6a048..f212f042773 100644 --- a/source/blender/editors/transform/transform_convert_particle.c +++ b/source/blender/editors/transform/transform_convert_particle.c @@ -95,7 +95,7 @@ static void createTransParticleVerts(bContext *UNUSED(C), TransInfo *t) unit_m4(mat); - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) { TransData *head, *tail; diff --git a/source/blender/editors/transform/transform_convert_sculpt.c b/source/blender/editors/transform/transform_convert_sculpt.c index f4f2e2a1c6e..cdbf497c584 100644 --- a/source/blender/editors/transform/transform_convert_sculpt.c +++ b/source/blender/editors/transform/transform_convert_sculpt.c @@ -49,7 +49,7 @@ static void createTransSculpt(bContext *C, TransInfo *t) td->flag = TD_SELECTED; copy_v3_v3(td->center, ss->pivot_pos); - mul_m4_v3(ob->obmat, td->center); + mul_m4_v3(ob->object_to_world, td->center); td->ob = ob; td->loc = ss->pivot_pos; @@ -60,16 +60,16 @@ static void createTransSculpt(bContext *C, TransInfo *t) } float obmat_inv[3][3]; - copy_m3_m4(obmat_inv, ob->obmat); + copy_m3_m4(obmat_inv, ob->object_to_world); invert_m3(obmat_inv); td->ext->rot = NULL; td->ext->rotAxis = NULL; td->ext->rotAngle = NULL; td->ext->quat = ss->pivot_rot; - copy_m4_m4(td->ext->obmat, ob->obmat); + copy_m4_m4(td->ext->obmat, ob->object_to_world); copy_m3_m3(td->ext->l_smtx, obmat_inv); - copy_m3_m4(td->ext->r_mtx, ob->obmat); + copy_m3_m4(td->ext->r_mtx, ob->object_to_world); copy_m3_m3(td->ext->r_smtx, obmat_inv); copy_qt_qt(td->ext->iquat, ss->pivot_rot); @@ -83,8 +83,8 @@ static void createTransSculpt(bContext *C, TransInfo *t) copy_v3_v3(td->ext->isize, ss->init_pivot_scale); copy_m3_m3(td->smtx, obmat_inv); - copy_m3_m4(td->mtx, ob->obmat); - copy_m3_m4(td->axismtx, ob->obmat); + copy_m3_m4(td->mtx, ob->object_to_world); + copy_m3_m4(td->axismtx, ob->object_to_world); BLI_assert(!(t->options & CTX_PAINT_CURVE)); ED_sculpt_init_transform(C, ob, t->mval, t->undo_name); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 301eac4536e..e1f93bf881b 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1063,7 +1063,7 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]) } if (tc->obedit) { if (ED_object_calc_active_center_for_editmode(tc->obedit, select_only, r_center)) { - mul_m4_v3(tc->obedit->obmat, r_center); + mul_m4_v3(tc->obedit->object_to_world, r_center); return true; } } @@ -1071,7 +1071,7 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]) BKE_view_layer_synced_ensure(t->scene, t->view_layer); Object *ob = BKE_view_layer_active_object_get(t->view_layer); if (ED_object_calc_active_center_for_posemode(ob, select_only, r_center)) { - mul_m4_v3(ob->obmat, r_center); + mul_m4_v3(ob->object_to_world, r_center); return true; } } @@ -1088,7 +1088,7 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]) BKE_view_layer_synced_ensure(t->scene, t->view_layer); Base *base = BKE_view_layer_active_base_get(t->view_layer); if (base && ((!select_only) || ((base->flag & BASE_SELECTED) != 0))) { - copy_v3_v3(r_center, base->object->obmat[3]); + copy_v3_v3(r_center, base->object->object_to_world[3]); return true; } } diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index f3d17559a63..2be210d24e7 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -581,12 +581,12 @@ bool gimbal_axis_pose(Object *ob, const bPoseChannel *pchan, float gmat[3][3]) mul_m3_m3m3(mat, parent_mat, tmat); /* needed if object transformation isn't identity */ - copy_m3_m4(obmat, ob->obmat); + copy_m3_m4(obmat, ob->object_to_world); mul_m3_m3m3(gmat, obmat, mat); } else { /* needed if object transformation isn't identity */ - copy_m3_m4(obmat, ob->obmat); + copy_m3_m4(obmat, ob->object_to_world); mul_m3_m3m3(gmat, obmat, tmat); } @@ -608,7 +608,7 @@ bool gimbal_axis_object(Object *ob, float gmat[3][3]) if (ob->parent) { float parent_mat[3][3]; - copy_m3_m4(parent_mat, ob->parent->obmat); + copy_m3_m4(parent_mat, ob->parent->object_to_world); normalize_m3(parent_mat); mul_m3_m3m3(gmat, parent_mat, gmat); } @@ -675,14 +675,14 @@ int ED_transform_calc_gizmo_stats(const bContext *C, copy_m3_m4(tbounds->axis, rv3d->twmat); if (params->use_local_axis && (ob && ob->mode & (OB_MODE_EDIT | OB_MODE_POSE))) { float diff_mat[3][3]; - copy_m3_m4(diff_mat, ob->obmat); + copy_m3_m4(diff_mat, ob->object_to_world); normalize_m3(diff_mat); invert_m3(diff_mat); mul_m3_m3m3(tbounds->axis, tbounds->axis, diff_mat); normalize_m3(tbounds->axis); tbounds->use_matrix_space = true; - copy_m4_m4(tbounds->matrix_space, ob->obmat); + copy_m4_m4(tbounds->matrix_space, ob->object_to_world); } if (is_gp_edit) { @@ -751,7 +751,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, #define FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) \ { \ - invert_m4_m4(obedit->imat, obedit->obmat); \ + invert_m4_m4(obedit->imat, obedit->object_to_world); \ uint objects_len = 0; \ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( \ scene, view_layer, CTX_wm_view3d(C), &objects_len); \ @@ -780,7 +780,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, float mat_local[4][4]; if (use_mat_local) { - mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat); + mul_m4_m4m4(mat_local, obedit->imat, ob_iter->object_to_world); } BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { @@ -800,7 +800,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, float mat_local[4][4]; if (use_mat_local) { - mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat); + mul_m4_m4m4(mat_local, obedit->imat, ob_iter->object_to_world); } LISTBASE_FOREACH (EditBone *, ebo, arm->edbo) { if (EBONE_VISIBLE(arm, ebo)) { @@ -833,7 +833,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, float mat_local[4][4]; if (use_mat_local) { - mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat); + mul_m4_m4m4(mat_local, obedit->imat, ob_iter->object_to_world); } nu = nurbs->first; @@ -893,7 +893,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, float mat_local[4][4]; if (use_mat_local) { - mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat); + mul_m4_m4m4(mat_local, obedit->imat, ob_iter->object_to_world); } LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) { @@ -913,7 +913,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, float mat_local[4][4]; if (use_mat_local) { - mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat); + mul_m4_m4m4(mat_local, obedit->imat, ob_iter->object_to_world); } while (a--) { @@ -933,13 +933,13 @@ int ED_transform_calc_gizmo_stats(const bContext *C, /* selection center */ if (totsel) { mul_v3_fl(tbounds->center, 1.0f / (float)totsel); /* centroid! */ - mul_m4_v3(obedit->obmat, tbounds->center); - mul_m4_v3(obedit->obmat, tbounds->min); - mul_m4_v3(obedit->obmat, tbounds->max); + mul_m4_v3(obedit->object_to_world, tbounds->center); + mul_m4_v3(obedit->object_to_world, tbounds->min); + mul_m4_v3(obedit->object_to_world, tbounds->max); } } else if (ob && (ob->mode & OB_MODE_POSE)) { - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); uint objects_len = 0; Object **objects = BKE_object_pose_array_get(scene, view_layer, v3d, &objects_len); @@ -954,7 +954,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, float mat_local[4][4]; if (use_mat_local) { - mul_m4_m4m4(mat_local, ob->imat, ob_iter->obmat); + mul_m4_m4m4(mat_local, ob->imat, ob_iter->object_to_world); } /* Use channels to get stats. */ @@ -971,18 +971,18 @@ int ED_transform_calc_gizmo_stats(const bContext *C, if (totsel) { mul_v3_fl(tbounds->center, 1.0f / (float)totsel); /* centroid! */ - mul_m4_v3(ob->obmat, tbounds->center); - mul_m4_v3(ob->obmat, tbounds->min); - mul_m4_v3(ob->obmat, tbounds->max); + mul_m4_v3(ob->object_to_world, tbounds->center); + mul_m4_v3(ob->object_to_world, tbounds->min); + mul_m4_v3(ob->object_to_world, tbounds->max); } } else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) { if (ob->mode & OB_MODE_SCULPT) { totsel = 1; - calc_tw_center_with_matrix(tbounds, ob->sculpt->pivot_pos, false, ob->obmat); - mul_m4_v3(ob->obmat, tbounds->center); - mul_m4_v3(ob->obmat, tbounds->min); - mul_m4_v3(ob->obmat, tbounds->max); + calc_tw_center_with_matrix(tbounds, ob->sculpt->pivot_pos, false, ob->object_to_world); + mul_m4_v3(ob->object_to_world, tbounds->center); + mul_m4_v3(ob->object_to_world, tbounds->min); + mul_m4_v3(ob->object_to_world, tbounds->max); } } else if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) { @@ -1037,12 +1037,12 @@ int ED_transform_calc_gizmo_stats(const bContext *C, } if (params->use_only_center || (bb == NULL)) { - calc_tw_center(tbounds, base->object->obmat[3]); + calc_tw_center(tbounds, base->object->object_to_world[3]); } else { for (uint j = 0; j < 8; j++) { float co[3]; - mul_v3_m4v3(co, base->object->obmat, bb->vec[j]); + mul_v3_m4v3(co, base->object->object_to_world, bb->vec[j]); calc_tw_center(tbounds, co); } } diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index 2eaeaf92c86..aeceedf0690 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -1041,7 +1041,7 @@ void ElementResize(const TransInfo *t, if (t->options & CTX_POSE_BONE) { /* Without this, the resulting location of scaled bones aren't correct, * especially noticeable scaling root or disconnected bones around the cursor, see T92515. */ - mul_mat3_m4_v3(tc->poseobj->obmat, vec); + mul_mat3_m4_v3(tc->poseobj->object_to_world, vec); } mul_m3_v3(td->smtx, vec); } diff --git a/source/blender/editors/transform/transform_mode_edge_slide.c b/source/blender/editors/transform/transform_mode_edge_slide.c index 5baf06006d9..5cdb4d3bf61 100644 --- a/source/blender/editors/transform/transform_mode_edge_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_slide.c @@ -1149,7 +1149,7 @@ void drawEdgeSlide(TransInfo *t) GPU_blend(GPU_BLEND_ALPHA); GPU_matrix_push(); - GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); + GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->object_to_world); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); diff --git a/source/blender/editors/transform/transform_mode_vert_slide.c b/source/blender/editors/transform/transform_mode_vert_slide.c index d7c4d862b23..cc1ea188fbc 100644 --- a/source/blender/editors/transform/transform_mode_vert_slide.c +++ b/source/blender/editors/transform/transform_mode_vert_slide.c @@ -167,7 +167,7 @@ static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2] float dir_dot; sub_v3_v3v3(tdir, sv->co_orig_3d, sv->co_link_orig_3d[j]); - mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, tdir); + mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->object_to_world, tdir); project_plane_v3_v3v3(tdir, tdir, t->viewinv[2]); normalize_v3(tdir); @@ -382,7 +382,7 @@ void drawVertSlide(TransInfo *t) GPU_blend(GPU_BLEND_ALPHA); GPU_matrix_push(); - GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); + GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->object_to_world); GPU_line_width(line_size); @@ -437,14 +437,15 @@ void drawVertSlide(TransInfo *t) xy_delta[0] = t->mval[0] - t->mouse.imval[0]; xy_delta[1] = t->mval[1] - t->mouse.imval[1]; - mul_v3_m4v3( - co_orig_3d, TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, curr_sv->co_orig_3d); + mul_v3_m4v3(co_orig_3d, + TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->object_to_world, + curr_sv->co_orig_3d); zfac = ED_view3d_calc_zfac(t->region->regiondata, co_orig_3d); ED_view3d_win_to_delta(t->region, xy_delta, zfac, co_dest_3d); invert_m4_m4(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat, - TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); + TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->object_to_world); mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat, co_dest_3d); add_v3_v3(co_dest_3d, curr_sv->co_orig_3d); diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 212df5978e4..66fee01f864 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -126,7 +126,7 @@ static TransformOrientation *createObjectSpace(bContext *C, ob = base->object; - copy_m3_m4(mat, ob->obmat); + copy_m3_m4(mat, ob->object_to_world); normalize_m3(mat); /* use object name if no name is given */ @@ -532,7 +532,7 @@ short ED_transform_calc_orientation_from_type_ex(const Scene *scene, ED_getTransformOrientationMatrix(scene, view_layer, v3d, ob, obedit, pivot_point, r_mat); } else { - transform_orientations_create_from_axis(r_mat, UNPACK3(ob->obmat)); + transform_orientations_create_from_axis(r_mat, UNPACK3(ob->object_to_world)); } break; } @@ -764,7 +764,7 @@ int getTransformOrientation_ex(const Scene *scene, float imat[3][3], mat[3][3]; /* we need the transpose of the inverse for a normal... */ - copy_m3_m4(imat, ob->obmat); + copy_m3_m4(imat, ob->object_to_world); invert_m3_m3(mat, imat); transpose_m3(mat); @@ -1192,8 +1192,8 @@ int getTransformOrientation_ex(const Scene *scene, if (result == ORIENTATION_EDGE) { float tvec[3]; - mul_mat3_m4_v3(ob->obmat, normal); - mul_mat3_m4_v3(ob->obmat, plane); + mul_mat3_m4_v3(ob->object_to_world, normal); + mul_mat3_m4_v3(ob->object_to_world, plane); /* align normal to edge direction (so normal is perpendicular to the plane). * 'ORIENTATION_EDGE' will do the other way around. @@ -1235,7 +1235,7 @@ int getTransformOrientation_ex(const Scene *scene, /* use for both active & all */ if (ok) { /* we need the transpose of the inverse for a normal... */ - copy_m3_m4(imat, ob->obmat); + copy_m3_m4(imat, ob->object_to_world); invert_m3_m3(mat, imat); transpose_m3(mat); @@ -1267,8 +1267,8 @@ int getTransformOrientation_ex(const Scene *scene, } if (ok) { - copy_v3_v3(normal, ob->obmat[2]); - copy_v3_v3(plane, ob->obmat[1]); + copy_v3_v3(normal, ob->object_to_world[2]); + copy_v3_v3(plane, ob->object_to_world[1]); } } result = ORIENTATION_NORMAL; diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 672d947936d..11cb57dc911 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -372,7 +372,7 @@ static bool applyFaceProject(TransInfo *t, TransDataContainer *tc, TransData *td } else if (t->options & CTX_OBJECT) { BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); - copy_v3_v3(iloc, td->ob->obmat[3]); + copy_v3_v3(iloc, td->ob->object_to_world[3]); } if (ED_view3d_project_float_global(t->region, iloc, mval_fl, V3D_PROJ_TEST_NOP) != @@ -444,7 +444,7 @@ static void applyFaceNearest(TransInfo *t, TransDataContainer *tc, TransData *td } else if (t->options & CTX_OBJECT) { BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); - copy_v3_v3(init_loc, td->ob->obmat[3]); + copy_v3_v3(init_loc, td->ob->object_to_world[3]); } eSnapMode hit = ED_transform_snap_object_project_view3d( diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc index 7971e1ca9af..24d76a50117 100644 --- a/source/blender/editors/transform/transform_snap_object.cc +++ b/source/blender/editors/transform/transform_snap_object.cc @@ -565,7 +565,7 @@ static void iter_snap_objects(SnapObjectContext *sctx, free_object_duplilist(lb); } - sob_callback(sctx, params, obj_eval, obj_eval->obmat, is_object_active, data); + sob_callback(sctx, params, obj_eval, obj_eval->object_to_world, is_object_active, data); } } @@ -1145,7 +1145,7 @@ static void raycast_obj_fn(SnapObjectContext *sctx, * \param r_index: Hit index or -1 when no valid index is found. * (currently only set to the polygon index when using `snap_to == SCE_SNAP_MODE_FACE_RAYCAST`). * \param r_ob: Hit object. - * \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances). + * \param r_obmat: Object matrix (may not be #Object.object_to_world with dupli-instances). * \param r_hit_list: List of #SnapObjectHitDepth (caller must free). */ static bool raycastObjects(SnapObjectContext *sctx, @@ -1483,7 +1483,7 @@ static void nearest_world_object_fn(SnapObjectContext *sctx, * \param r_no: Normal of nearest point on target surface. * \param r_index: Index of nearest polygon on target surface. * \param r_ob: Nearest target object. - * \param r_obmat: Nearest target matrix (may not be #Object.obmat with dupli-instances). + * \param r_obmat: Nearest target matrix (may not be #Object.object_to_world with dupli-instances). */ static bool nearestWorldObjects(SnapObjectContext *sctx, const struct SnapObjectParams *params, @@ -3177,7 +3177,7 @@ static void snap_obj_fn(SnapObjectContext *sctx, * \param r_index: Hit index or -1 when no valid index is found. * (currently only set to the polygon index when using `snap_to == SCE_SNAP_MODE_FACE_RAYCAST`). * \param r_ob: Hit object. - * \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances). + * \param r_obmat: Object matrix (may not be #Object.object_to_world with dupli-instances). */ static eSnapMode snapObjectsRay(SnapObjectContext *sctx, const SnapObjectParams *params, diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c index 7dd223a9252..777cc1d97e4 100644 --- a/source/blender/editors/uvedit/uvedit_select.c +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -4705,7 +4705,7 @@ static int uv_select_similar_vert_exec(bContext *C, wmOperator *op) const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); float ob_m3[3][3]; - copy_m3_m4(ob_m3, ob->obmat); + copy_m3_m4(ob_m3, ob->object_to_world); BMFace *face; BMIter iter; @@ -4742,7 +4742,7 @@ static int uv_select_similar_vert_exec(bContext *C, wmOperator *op) bool changed = false; const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); float ob_m3[3][3]; - copy_m3_m4(ob_m3, ob->obmat); + copy_m3_m4(ob_m3, ob->object_to_world); BMFace *face; BMIter iter; @@ -4818,7 +4818,7 @@ static int uv_select_similar_edge_exec(bContext *C, wmOperator *op) const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); float ob_m3[3][3]; - copy_m3_m4(ob_m3, ob->obmat); + copy_m3_m4(ob_m3, ob->object_to_world); BMFace *face; BMIter iter; @@ -4859,7 +4859,7 @@ static int uv_select_similar_edge_exec(bContext *C, wmOperator *op) bool changed = false; const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); float ob_m3[3][3]; - copy_m3_m4(ob_m3, ob->obmat); + copy_m3_m4(ob_m3, ob->object_to_world); BMFace *face; BMIter iter; @@ -4927,7 +4927,7 @@ static int uv_select_similar_face_exec(bContext *C, wmOperator *op) BMesh *bm = em->bm; float ob_m3[3][3]; - copy_m3_m4(ob_m3, ob->obmat); + copy_m3_m4(ob_m3, ob->object_to_world); const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); @@ -4963,7 +4963,7 @@ static int uv_select_similar_face_exec(bContext *C, wmOperator *op) const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); float ob_m3[3][3]; - copy_m3_m4(ob_m3, ob->obmat); + copy_m3_m4(ob_m3, ob->object_to_world); BMFace *face; BMIter iter; @@ -5053,7 +5053,7 @@ static int uv_select_similar_island_exec(bContext *C, wmOperator *op) } float ob_m3[3][3]; - copy_m3_m4(ob_m3, obedit->obmat); + copy_m3_m4(ob_m3, obedit->object_to_world); int index; LISTBASE_FOREACH_INDEX (struct FaceIsland *, island, &island_list_ptr[ob_index], index) { @@ -5082,7 +5082,7 @@ static int uv_select_similar_island_exec(bContext *C, wmOperator *op) continue; } float ob_m3[3][3]; - copy_m3_m4(ob_m3, obedit->obmat); + copy_m3_m4(ob_m3, obedit->object_to_world); bool changed = false; int index; diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 92efaf79de7..de1c88fe896 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -1388,7 +1388,7 @@ static void uv_map_transform_center(const Scene *scene, } case V3D_AROUND_CURSOR: /* cursor center */ { - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); mul_v3_m4v3(r_center, ob->imat, scene->cursor.location); break; } @@ -1439,7 +1439,7 @@ static void uv_map_rotation_matrix_ex(float result[4][4], zero_v3(viewmatrix[3]); /* get rotation of the current object matrix */ - copy_m4_m4(rotobj, ob->obmat); + copy_m4_m4(rotobj, ob->object_to_world); zero_v3(rotobj[3]); /* but shifting */ @@ -1948,7 +1948,7 @@ static int unwrap_exec(bContext *C, wmOperator *op) continue; } - mat4_to_size(obsize, obedit->obmat); + mat4_to_size(obsize, obedit->object_to_world); if (!(fabsf(obsize[0] - obsize[1]) < 1e-4f && fabsf(obsize[1] - obsize[2]) < 1e-4f)) { if ((reported_errors & UNWRAP_ERROR_NONUNIFORM) == 0) { BKE_report(op->reports, @@ -1958,7 +1958,7 @@ static int unwrap_exec(bContext *C, wmOperator *op) reported_errors |= UNWRAP_ERROR_NONUNIFORM; } } - else if (is_negative_m4(obedit->obmat)) { + else if (is_negative_m4(obedit->object_to_world)) { if ((reported_errors & UNWRAP_ERROR_NEGATIVE) == 0) { BKE_report( op->reports, @@ -2538,7 +2538,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op) float objects_pos_avg[4] = {0}; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - add_v4_v4(objects_pos_avg, objects[ob_index]->obmat[3]); + add_v4_v4(objects_pos_avg, objects[ob_index]->object_to_world[3]); } mul_v4_fl(objects_pos_avg, 1.0f / objects_len); @@ -2576,7 +2576,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op) const bool camera_bounds = RNA_boolean_get(op->ptr, "camera_bounds"); struct ProjCameraInfo *uci = BLI_uvproject_camera_info( v3d->camera, - obedit->obmat, + obedit->object_to_world, camera_bounds ? (scene->r.xsch * scene->r.xasp) : 1.0f, camera_bounds ? (scene->r.ysch * scene->r.yasp) : 1.0f); @@ -2597,7 +2597,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op) } } else { - copy_m4_m4(rotmat, obedit->obmat); + copy_m4_m4(rotmat, obedit->object_to_world); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) { diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp index 0d41b5a773d..53c2b1d235b 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -431,7 +431,7 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id) // Compute matrix including camera transform float obmat[4][4], nmat[4][4]; - mul_m4_m4m4(obmat, viewmat, ob->obmat); + mul_m4_m4m4(obmat, viewmat, ob->object_to_world); invert_m4_m4(nmat, obmat); transpose_m4(nmat); diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index c649bde06ca..2d9c23df348 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -433,7 +433,7 @@ static void foreach_geometry_in_reference( int index = 0; FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (&collection, object) { const GeometrySet object_geometry_set = object_get_evaluated_geometry_set(*object); - const float4x4 matrix = base_transform * offset_matrix * object->obmat; + const float4x4 matrix = base_transform * offset_matrix * object->object_to_world; const int sub_id = noise::hash(id, index); fn(object_geometry_set, matrix, sub_id); index++; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c index 8bb61136cc2..e51fe8832f0 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c @@ -104,9 +104,9 @@ static void BKE_gpencil_instance_modifier_instance_tfm(Object *ob, if (mmd->flag & GP_ARRAY_USE_OFFSET) { add_v3_v3(mat_offset[3], mmd->offset); } - invert_m4_m4(obinv, ob->obmat); + invert_m4_m4(obinv, ob->object_to_world); - mul_m4_series(r_offset, mat_offset, obinv, mmd->object->obmat); + mul_m4_series(r_offset, mat_offset, obinv, mmd->object->object_to_world); copy_m4_m4(mat_offset, r_offset); /* clear r_mat locations to avoid double transform */ diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c index 3c971ec6af0..49ac3275c82 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c @@ -303,8 +303,8 @@ static void build_sequential(Object *ob, /* Compute distance to control object if set, and build according to that order. */ if (mmd->object) { float sv1[3], sv2[3]; - mul_v3_m4v3(sv1, ob->obmat, &gps->points[0].x); - mul_v3_m4v3(sv2, ob->obmat, &gps->points[gps->totpoints - 1].x); + mul_v3_m4v3(sv1, ob->object_to_world, &gps->points[0].x); + mul_v3_m4v3(sv2, ob->object_to_world, &gps->points[gps->totpoints - 1].x); float dist_l = len_v3v3(sv1, mmd->object->loc); float dist_r = len_v3v3(sv2, mmd->object->loc); if (dist_r < dist_l) { diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c index 1a2bfebdc55..6e31fffd11d 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c @@ -234,13 +234,13 @@ static void deformStroke(GpencilModifierData *md, /* get world-space matrix of target, corrected for the space the verts are in */ if (mmd->subtarget[0] && pchan) { /* bone target if there's a matching pose-channel */ - mul_m4_m4m4(dmat, mmd->object->obmat, pchan->pose_mat); + mul_m4_m4m4(dmat, mmd->object->object_to_world, pchan->pose_mat); } else { /* just object target */ - copy_m4_m4(dmat, mmd->object->obmat); + copy_m4_m4(dmat, mmd->object->object_to_world); } - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); mul_m4_series(tData.mat, ob->imat, dmat, mmd->parentinv); /* loop points and apply deform */ diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c index 326e86091c5..bc91094e80e 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c @@ -81,8 +81,8 @@ static void update_mirror_object(Object *ob, float tmp[4][4]; float itmp[4][4]; - invert_m4_m4(tmp, mmd->object->obmat); - mul_m4_m4m4(tmp, tmp, ob->obmat); + invert_m4_m4(tmp, mmd->object->object_to_world); + mul_m4_m4m4(tmp, tmp, ob->object_to_world); invert_m4_m4(itmp, tmp); mul_m4_series(mtx, itmp, mtx, tmp); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c index 1cf11a694ac..cb4a7893080 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c @@ -109,7 +109,7 @@ static void duplicateStroke(Object *ob, float opacity_factor; /* Apply object scale to offset distance. */ - offset *= mat4_to_scale(ob->obmat); + offset *= mat4_to_scale(ob->object_to_world); BKE_gpencil_stroke_normal(gps, stroke_normal); if (len_v3(stroke_normal) < FLT_EPSILON) { diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciloutline.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciloutline.c index 387e3c2d5ce..455d8b0b528 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpenciloutline.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciloutline.c @@ -116,7 +116,7 @@ static void convert_stroke(GpencilModifierData *md, /* Apply layer thickness change. */ gps_duplicate->thickness += gpl->line_change; /* Apply object scale to thickness. */ - gps_duplicate->thickness *= mat4_to_scale(ob->obmat); + gps_duplicate->thickness *= mat4_to_scale(ob->object_to_world); CLAMP_MIN(gps_duplicate->thickness, 1.0f); /* Stroke. */ @@ -197,7 +197,7 @@ static void generateStrokes(GpencilModifierData *md, Depsgraph *depsgraph, Objec } Object *cam_ob = scene->camera; float viewmat[4][4]; - invert_m4_m4(viewmat, cam_ob->obmat); + invert_m4_m4(viewmat, cam_ob->object_to_world); LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { bGPDframe *gpf = BKE_gpencil_frame_retime_get(depsgraph, scene, ob, gpl); @@ -240,7 +240,7 @@ static void bakeModifier(Main *UNUSED(bmain), BKE_scene_graph_update_for_newframe(depsgraph); /* Ensure the camera is the right one. */ BKE_scene_camera_switch_update(scene); - invert_m4_m4(viewmat, cam_ob->obmat); + invert_m4_m4(viewmat, cam_ob->object_to_world); /* Prepare transform matrix. */ float diff_mat[4][4]; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c index 94d8cb98290..7add5c7b84e 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c @@ -144,7 +144,7 @@ static void deformStroke(GpencilModifierData *md, float coba_res[4]; float matrix[4][4]; if (is_gradient) { - mul_m4_m4m4(matrix, mmd->object->imat, ob->obmat); + mul_m4_m4m4(matrix, mmd->object->imat, ob->object_to_world); } /* loop points and apply color. */ diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilweight_angle.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilweight_angle.c index 3ecff4bf447..e9761732614 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilweight_angle.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilweight_angle.c @@ -97,7 +97,7 @@ static void deformStroke(GpencilModifierData *md, /* Apply the rotation of the object. */ if (mmd->space == GP_SPACE_LOCAL) { - mul_mat3_m4_v3(ob->obmat, vec_ref); + mul_mat3_m4_v3(ob->object_to_world, vec_ref); } /* Ensure there is a vertex group. */ @@ -122,8 +122,8 @@ static void deformStroke(GpencilModifierData *md, bGPDspoint *pt1 = (i > 0) ? &gps->points[i] : &gps->points[i + 1]; bGPDspoint *pt2 = (i > 0) ? &gps->points[i - 1] : &gps->points[i]; float fpt1[3], fpt2[3]; - mul_v3_m4v3(fpt1, ob->obmat, &pt1->x); - mul_v3_m4v3(fpt2, ob->obmat, &pt2->x); + mul_v3_m4v3(fpt1, ob->object_to_world, &pt1->x); + mul_v3_m4v3(fpt2, ob->object_to_world, &pt2->x); float vec[3]; sub_v3_v3v3(vec, fpt1, fpt2); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilweight_proximity.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilweight_proximity.c index f64c83443d8..ddf852bcd11 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilweight_proximity.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilweight_proximity.c @@ -64,8 +64,8 @@ static float calc_point_weight_by_distance(Object *ob, { float weight; float gvert[3]; - mul_v3_m4v3(gvert, ob->obmat, &pt->x); - float dist = len_v3v3(mmd->object->obmat[3], gvert); + mul_v3_m4v3(gvert, ob->object_to_world, &pt->x); + float dist = len_v3v3(mmd->object->object_to_world[3], gvert); if (dist > dist_max) { weight = 1.0f; diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c index c1e71bde254..4b5c40c0e38 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c @@ -2633,7 +2633,7 @@ void lineart_main_load_geometries(Depsgraph *depsgraph, scene, eval_ob, eval_ob, - eval_ob->obmat, + eval_ob->object_to_world, is_render, olti, thread_count, @@ -3589,11 +3589,11 @@ static LineartData *lineart_create_render_buffer(Scene *scene, clipping_offset = 0.0001; } - copy_v3db_v3fl(ld->conf.camera_pos, camera->obmat[3]); + copy_v3db_v3fl(ld->conf.camera_pos, camera->object_to_world[3]); if (active_camera) { - copy_v3db_v3fl(ld->conf.active_camera_pos, active_camera->obmat[3]); + copy_v3db_v3fl(ld->conf.active_camera_pos, active_camera->object_to_world[3]); } - copy_m4_m4(ld->conf.cam_obmat, camera->obmat); + copy_m4_m4(ld->conf.cam_obmat, camera->object_to_world); ld->conf.cam_is_persp = (c->type == CAM_PERSP); ld->conf.near_clip = c->clip_start + clipping_offset; @@ -3620,8 +3620,8 @@ static LineartData *lineart_create_render_buffer(Scene *scene, if (lmd->light_contour_object) { Object *light_obj = lmd->light_contour_object; - copy_v3db_v3fl(ld->conf.camera_pos_secondary, light_obj->obmat[3]); - copy_m4_m4(ld->conf.cam_obmat_secondary, light_obj->obmat); + copy_v3db_v3fl(ld->conf.camera_pos_secondary, light_obj->object_to_world[3]); + copy_m4_m4(ld->conf.cam_obmat_secondary, light_obj->object_to_world); ld->conf.light_reference_available = true; if (light_obj->type == OB_LAMP) { ld->conf.cam_is_persp_secondary = ((Light *)light_obj->data)->type != LA_SUN; @@ -5418,7 +5418,7 @@ void MOD_lineart_gpencil_generate(LineartCache *cache, } float gp_obmat_inverse[4][4]; - invert_m4_m4(gp_obmat_inverse, ob->obmat); + invert_m4_m4(gp_obmat_inverse, ob->object_to_world); lineart_gpencil_generate(cache, depsgraph, ob, diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_shadow.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_shadow.c index e34e6fc43ea..edea052e728 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_shadow.c +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_shadow.c @@ -1167,7 +1167,7 @@ bool lineart_main_try_generate_shadow(Depsgraph *depsgraph, copy_v3_v3_db(ld->conf.camera_pos_secondary, ld->conf.camera_pos); copy_m4_m4(ld->conf.cam_obmat_secondary, ld->conf.cam_obmat); - copy_m4_m4(ld->conf.cam_obmat, lmd->light_contour_object->obmat); + copy_m4_m4(ld->conf.cam_obmat, lmd->light_contour_object->object_to_world); copy_v3db_v3fl(ld->conf.camera_pos, ld->conf.cam_obmat[3]); ld->conf.cam_is_persp_secondary = ld->conf.cam_is_persp; ld->conf.cam_is_persp = is_persp; diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c index 6d99fde9df6..c467e48d21e 100644 --- a/source/blender/ikplugin/intern/iksolver_plugin.c +++ b/source/blender/ikplugin/intern/iksolver_plugin.c @@ -406,7 +406,7 @@ static void execute_posetree(struct Depsgraph *depsgraph, } copy_v3_v3(rootmat[3], pchan->pose_head); - mul_m4_m4m4(imat, ob->obmat, rootmat); + mul_m4_m4m4(imat, ob->object_to_world, rootmat); invert_m4_m4(goalinv, imat); for (target = tree->targets.first; target; target = target->next) { @@ -465,7 +465,7 @@ static void execute_posetree(struct Depsgraph *depsgraph, /* end effector in world space */ copy_m4_m4(end_pose, pchan->pose_mat); copy_v3_v3(end_pose[3], pchan->pose_tail); - mul_m4_series(world_pose, goalinv, ob->obmat, end_pose); + mul_m4_series(world_pose, goalinv, ob->object_to_world, end_pose); /* blend position */ goalpos[0] = fac * goalpos[0] + mfac * world_pose[3][0]; diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp index 9317f14b7f1..2878bbb6da7 100644 --- a/source/blender/ikplugin/intern/itasc_plugin.cpp +++ b/source/blender/ikplugin/intern/itasc_plugin.cpp @@ -586,10 +586,10 @@ static bool target_callback(const iTaSC::Timestamp ×tamp, float chanmat[4][4]; copy_m4_m4(chanmat, pchan->pose_mat); copy_v3_v3(chanmat[3], pchan->pose_tail); - mul_m4_series(restmat, target->owner->obmat, chanmat, target->eeRest); + mul_m4_series(restmat, target->owner->object_to_world, chanmat, target->eeRest); } else { - mul_m4_m4m4(restmat, target->owner->obmat, target->eeRest); + mul_m4_m4m4(restmat, target->owner->object_to_world, target->eeRest); } /* blend the target */ blend_m4_m4m4(tarmat, restmat, tarmat, constraint->enforce); @@ -620,10 +620,10 @@ static bool base_callback(const iTaSC::Timestamp ×tamp, ikscene->baseFrame.setValue(&chanmat[0][0]); /* iTaSC armature is scaled to object scale, scale the base frame too */ ikscene->baseFrame.p *= ikscene->blScale; - mul_m4_m4m4(rootmat, ikscene->blArmature->obmat, chanmat); + mul_m4_m4m4(rootmat, ikscene->blArmature->object_to_world, chanmat); } else { - copy_m4_m4(rootmat, ikscene->blArmature->obmat); + copy_m4_m4(rootmat, ikscene->blArmature->object_to_world); ikscene->baseFrame = iTaSC::F_identity; } next.setValue(&rootmat[0][0]); @@ -1065,7 +1065,7 @@ static void convert_pose(IK_Scene *ikscene) int a, joint; /* assume uniform scaling and take Y scale as general scale for the armature */ - scale = len_v3(ikscene->blArmature->obmat[1]); + scale = len_v3(ikscene->blArmature->object_to_world[1]); rot = ikscene->jointArray(0); for (joint = a = 0, ikchan = ikscene->channels; a < ikscene->numchan && joint < ikscene->numjoint; @@ -1105,7 +1105,7 @@ static void BKE_pose_rest(IK_Scene *ikscene) int a, joint; /* assume uniform scaling and take Y scale as general scale for the armature */ - scale = len_v3(ikscene->blArmature->obmat[1]); + scale = len_v3(ikscene->blArmature->object_to_world[1]); /* rest pose is 0 */ SetToZero(ikscene->jointArray); /* except for transY joints */ @@ -1183,7 +1183,7 @@ static IK_Scene *convert_tree( } ikscene->blArmature = ob; /* assume uniform scaling and take Y scale as general scale for the armature */ - ikscene->blScale = len_v3(ob->obmat[1]); + ikscene->blScale = len_v3(ob->object_to_world[1]); ikscene->blInvScale = (ikscene->blScale < KDL::epsilon) ? 0.0f : 1.0f / ikscene->blScale; std::string joint; @@ -1667,7 +1667,7 @@ static void create_scene(struct Depsgraph *depsgraph, Scene *scene, Object *ob, static int init_scene(Object *ob) { /* check also if scaling has changed */ - float scale = len_v3(ob->obmat[1]); + float scale = len_v3(ob->object_to_world[1]); IK_Scene *scene; if (ob->pose->ikdata) { diff --git a/source/blender/io/alembic/exporter/abc_writer_hair.cc b/source/blender/io/alembic/exporter/abc_writer_hair.cc index f872943ad5c..13136372c56 100644 --- a/source/blender/io/alembic/exporter/abc_writer_hair.cc +++ b/source/blender/io/alembic/exporter/abc_writer_hair.cc @@ -118,7 +118,7 @@ void ABCHairWriter::write_hair_sample(const HierarchyContext &context, { /* Get untransformed vertices, there's a xform under the hair. */ float inv_mat[4][4]; - invert_m4_m4_safe(inv_mat, context.object->obmat); + invert_m4_m4_safe(inv_mat, context.object->object_to_world); MTFace *mtface = (MTFace *)CustomData_get_layer(&mesh->fdata, CD_MTFACE); MFace *mface = (MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE); @@ -241,7 +241,7 @@ void ABCHairWriter::write_hair_child_sample(const HierarchyContext &context, { /* Get untransformed vertices, there's a xform under the hair. */ float inv_mat[4][4]; - invert_m4_m4_safe(inv_mat, context.object->obmat); + invert_m4_m4_safe(inv_mat, context.object->object_to_world); MFace *mface = (MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE); MTFace *mtface = (MTFace *)CustomData_get_layer(&mesh->fdata, CD_MTFACE); diff --git a/source/blender/io/alembic/intern/abc_axis_conversion.cc b/source/blender/io/alembic/intern/abc_axis_conversion.cc index 00e5890e9d3..35a19d0fbc0 100644 --- a/source/blender/io/alembic/intern/abc_axis_conversion.cc +++ b/source/blender/io/alembic/intern/abc_axis_conversion.cc @@ -134,15 +134,15 @@ void create_transform_matrix(Object *obj, if (mode == ABC_MATRIX_LOCAL && obj->parent) { /* Note that this produces another matrix than the local matrix, due to * constraints and modifiers as well as the obj->parentinv matrix. */ - invert_m4_m4(obj->parent->imat, obj->parent->obmat); - mul_m4_m4m4(zup_mat, obj->parent->imat, obj->obmat); + invert_m4_m4(obj->parent->imat, obj->parent->object_to_world); + mul_m4_m4m4(zup_mat, obj->parent->imat, obj->object_to_world); } else { - copy_m4_m4(zup_mat, obj->obmat); + copy_m4_m4(zup_mat, obj->object_to_world); } if (proxy_from) { - mul_m4_m4m4(zup_mat, proxy_from->obmat, zup_mat); + mul_m4_m4m4(zup_mat, proxy_from->object_to_world, zup_mat); } copy_m44_axis_swap(r_yup_mat, zup_mat, ABC_YUP_FROM_ZUP); diff --git a/source/blender/io/alembic/intern/abc_reader_object.cc b/source/blender/io/alembic/intern/abc_reader_object.cc index af26565f8d6..f3a07eaad3f 100644 --- a/source/blender/io/alembic/intern/abc_reader_object.cc +++ b/source/blender/io/alembic/intern/abc_reader_object.cc @@ -165,7 +165,7 @@ void AbcObjectReader::setupObjectTransform(const chrono_t time) /* Apply the matrix to the object. */ BKE_object_apply_mat4(m_object, transform_from_alembic, true, false); - BKE_object_to_mat4(m_object, m_object->obmat); + BKE_object_to_mat4(m_object, m_object->object_to_world); if (!is_constant || m_settings->always_add_cache_reader) { bConstraint *con = BKE_constraint_add_for_object( diff --git a/source/blender/io/collada/AnimationImporter.cpp b/source/blender/io/collada/AnimationImporter.cpp index 2d872377bbf..826d7864067 100644 --- a/source/blender/io/collada/AnimationImporter.cpp +++ b/source/blender/io/collada/AnimationImporter.cpp @@ -332,8 +332,8 @@ void AnimationImporter::read_node_transform(COLLADAFW::Node *node, Object *ob) float mat[4][4]; TransformReader::get_node_mat(mat, node, &uid_animated_map, ob); if (ob) { - copy_m4_m4(ob->obmat, mat); - BKE_object_apply_mat4(ob, ob->obmat, false, false); + copy_m4_m4(ob->object_to_world, mat); + BKE_object_apply_mat4(ob, ob->object_to_world, false, false); } } @@ -2097,7 +2097,7 @@ Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, if (par_job) { float temp[4][4], ipar[4][4]; - invert_m4_m4(ipar, par_job->obmat); + invert_m4_m4(ipar, par_job->object_to_world); copy_m4_m4(temp, mat); mul_m4_m4m4(mat, ipar, temp); } diff --git a/source/blender/io/collada/ArmatureImporter.cpp b/source/blender/io/collada/ArmatureImporter.cpp index 1310337f501..7de08f89b7d 100644 --- a/source/blender/io/collada/ArmatureImporter.cpp +++ b/source/blender/io/collada/ArmatureImporter.cpp @@ -114,7 +114,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, Object *ob_arm = skin->BKE_armature_from_object(); if (ob_arm) { float invmat[4][4]; - invert_m4_m4(invmat, ob_arm->obmat); + invert_m4_m4(invmat, ob_arm->object_to_world); mul_m4_m4m4(mat, invmat, mat); } @@ -708,7 +708,7 @@ void ArmatureImporter::set_pose(Object *ob_arm, copy_m4_m4(mat, obmat); float invObmat[4][4]; - invert_m4_m4(invObmat, ob_arm->obmat); + invert_m4_m4(invObmat, ob_arm->object_to_world); mul_m4_m4m4(pchan->pose_mat, invObmat, mat); } diff --git a/source/blender/io/collada/ControllerExporter.cpp b/source/blender/io/collada/ControllerExporter.cpp index 6bf8d904a41..62bcdc5bf4c 100644 --- a/source/blender/io/collada/ControllerExporter.cpp +++ b/source/blender/io/collada/ControllerExporter.cpp @@ -406,7 +406,7 @@ void ControllerExporter::add_bind_shape_mat(Object *ob) bc_add_global_transform(f_obmat, export_settings.get_global_transform()); } - // UnitConverter::mat4_to_dae_double(bind_mat, ob->obmat); + // UnitConverter::mat4_to_dae_double(bind_mat, ob->object_to_world); UnitConverter::mat4_to_dae_double(bind_mat, f_obmat); if (this->export_settings.get_limit_precision()) { BCMatrix::sanitize(bind_mat, LIMITTED_PRECISION); @@ -523,7 +523,7 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, } /* make world-space matrix (bind_mat is armature-space) */ - mul_m4_m4m4(world, ob_arm->obmat, bind_mat); + mul_m4_m4m4(world, ob_arm->object_to_world, bind_mat); if (!has_bindmat) { if (export_settings.get_apply_global_orientation()) { diff --git a/source/blender/io/collada/DocumentImporter.cpp b/source/blender/io/collada/DocumentImporter.cpp index 5e432682564..dae1c4ba894 100644 --- a/source/blender/io/collada/DocumentImporter.cpp +++ b/source/blender/io/collada/DocumentImporter.cpp @@ -412,8 +412,8 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, } } /* calc new matrix and apply */ - mul_m4_m4m4(obn->obmat, obn->obmat, mat); - BKE_object_apply_mat4(obn, obn->obmat, false, false); + mul_m4_m4m4(obn->object_to_world, obn->object_to_world, mat); + BKE_object_apply_mat4(obn, obn->object_to_world, false, false); } } else { diff --git a/source/blender/io/collada/SkinInfo.cpp b/source/blender/io/collada/SkinInfo.cpp index 0654bae3730..b4615635318 100644 --- a/source/blender/io/collada/SkinInfo.cpp +++ b/source/blender/io/collada/SkinInfo.cpp @@ -214,12 +214,12 @@ void SkinInfo::link_armature(bContext *C, ob->partype = PAROBJECT; BKE_object_workob_calc_parent(scene, ob, &workob); - invert_m4_m4(ob->parentinv, workob.obmat); + invert_m4_m4(ob->parentinv, workob.object_to_world); DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); #endif - copy_m4_m4(ob->obmat, bind_shape_matrix); - BKE_object_apply_mat4(ob, ob->obmat, false, false); + copy_m4_m4(ob->object_to_world, bind_shape_matrix); + BKE_object_apply_mat4(ob, ob->object_to_world, false, false); amd->deformflag = ARM_DEF_VGROUP; diff --git a/source/blender/io/collada/collada_utils.cpp b/source/blender/io/collada/collada_utils.cpp index 22a73cd7db2..96ff78a715a 100644 --- a/source/blender/io/collada/collada_utils.cpp +++ b/source/blender/io/collada/collada_utils.cpp @@ -129,7 +129,7 @@ bool bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space) const bool keep_transform = false; if (par && is_parent_space) { - mul_m4_m4m4(ob->obmat, par->obmat, ob->obmat); + mul_m4_m4m4(ob->object_to_world, par->object_to_world, ob->object_to_world); } bool ok = ED_object_parent_set( @@ -348,10 +348,10 @@ std::string bc_replace_string(std::string data, void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene) { if (scale_to_scene) { - mul_m4_m4m4(ob->obmat, bc_unit.get_scale(), ob->obmat); + mul_m4_m4m4(ob->object_to_world, bc_unit.get_scale(), ob->object_to_world); } - mul_m4_m4m4(ob->obmat, bc_unit.get_rotation(), ob->obmat); - BKE_object_apply_mat4(ob, ob->obmat, false, false); + mul_m4_m4m4(ob->object_to_world, bc_unit.get_rotation(), ob->object_to_world); + BKE_object_apply_mat4(ob, ob->object_to_world, false, false); } void bc_match_scale(std::vector *objects_done, diff --git a/source/blender/io/common/intern/abstract_hierarchy_iterator.cc b/source/blender/io/common/intern/abstract_hierarchy_iterator.cc index 03c1ba94d94..d559b0efe82 100644 --- a/source/blender/io/common/intern/abstract_hierarchy_iterator.cc +++ b/source/blender/io/common/intern/abstract_hierarchy_iterator.cc @@ -416,7 +416,7 @@ void AbstractHierarchyIterator::visit_object(Object *object, context->original_export_path = ""; context->higher_up_export_path = ""; - copy_m4_m4(context->matrix_world, object->obmat); + copy_m4_m4(context->matrix_world, object->object_to_world); ExportGraph::key_type graph_index = determine_graph_index_object(context); context_update_for_graph_index(context, graph_index); diff --git a/source/blender/io/gpencil/intern/gpencil_io_base.cc b/source/blender/io/gpencil/intern/gpencil_io_base.cc index b9d7b6719b1..6cc977bfced 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_base.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_base.cc @@ -79,7 +79,7 @@ void GpencilIO::prepare_camera_params(Scene *scene, const GpencilIOParams *ipara BKE_camera_params_compute_matrix(¶ms); float viewmat[4][4]; - invert_m4_m4(viewmat, cam_ob->obmat); + invert_m4_m4(viewmat, cam_ob->object_to_world); mul_m4_m4m4(persmat_, params.winmat, viewmat); } @@ -152,7 +152,7 @@ void GpencilIO::create_object_list() /* Save z-depth from view to sort from back to front. */ if (is_camera_) { - float camera_z = dot_v3v3(camera_z_axis, object->obmat[3]); + float camera_z = dot_v3v3(camera_z_axis, object->object_to_world[3]); ObjectZ obz = {camera_z, object}; ob_list_.append(obz); } @@ -160,10 +160,10 @@ void GpencilIO::create_object_list() float zdepth = 0; if (rv3d_) { if (rv3d_->is_persp) { - zdepth = ED_view3d_calc_zfac(rv3d_, object->obmat[3]); + zdepth = ED_view3d_calc_zfac(rv3d_, object->object_to_world[3]); } else { - zdepth = -dot_v3v3(rv3d_->viewinv[2], object->obmat[3]); + zdepth = -dot_v3v3(rv3d_->viewinv[2], object->object_to_world[3]); } ObjectZ obz = {zdepth * -1.0f, object}; ob_list_.append(obz); diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc index ddd72f816b0..c042ca597c8 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc @@ -177,7 +177,7 @@ void GpencilExporterPDF::export_gpencil_layers() /* Apply layer thickness change. */ gps_duplicate->thickness += gpl->line_change; /* Apply object scale to thickness. */ - gps_duplicate->thickness *= mat4_to_scale(ob->obmat); + gps_duplicate->thickness *= mat4_to_scale(ob->object_to_world); CLAMP_MIN(gps_duplicate->thickness, 1.0f); /* Fill. */ if ((is_fill) && (params_.flag & GP_EXPORT_FILL)) { diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc b/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc index 58f12e9b8b1..8acb87f8e58 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc @@ -197,7 +197,7 @@ void GpencilExporterSVG::export_gpencil_layers() /* Apply layer thickness change. */ gps_duplicate->thickness += gpl->line_change; /* Apply object scale to thickness. */ - gps_duplicate->thickness *= mat4_to_scale(ob->obmat); + gps_duplicate->thickness *= mat4_to_scale(ob->object_to_world); CLAMP_MIN(gps_duplicate->thickness, 1.0f); const bool is_normalized = ((params_.flag & GP_EXPORT_NORM_THICKNESS) != 0) || diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc index d00c09b9013..f5a94b1fc8a 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc @@ -124,10 +124,11 @@ void OBJMesh::set_world_axes_transform(const eIOAxis forward, const eIOAxis up) unit_m3(axes_transform); /* +Y-forward and +Z-up are the default Blender axis settings. */ mat3_from_axis_conversion(forward, up, IO_AXIS_Y, IO_AXIS_Z, axes_transform); - mul_m4_m3m4(world_and_axes_transform_, axes_transform, export_object_eval_.obmat); + mul_m4_m3m4(world_and_axes_transform_, axes_transform, export_object_eval_.object_to_world); /* mul_m4_m3m4 does not transform last row of obmat, i.e. location data. */ - mul_v3_m3v3(world_and_axes_transform_[3], axes_transform, export_object_eval_.obmat[3]); - world_and_axes_transform_[3][3] = export_object_eval_.obmat[3][3]; + mul_v3_m3v3( + world_and_axes_transform_[3], axes_transform, export_object_eval_.object_to_world[3]); + world_and_axes_transform_[3][3] = export_object_eval_.object_to_world[3][3]; /* Normals need inverse transpose of the regular matrix to handle non-uniform scale. */ float normal_matrix[3][3]; diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_nurbs.cc b/source/blender/io/wavefront_obj/exporter/obj_export_nurbs.cc index 812c3e7b5d4..1b1ee5f8386 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_nurbs.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_nurbs.cc @@ -31,10 +31,10 @@ void OBJCurve::set_world_axes_transform(const eIOAxis forward, const eIOAxis up) unit_m3(axes_transform); /* +Y-forward and +Z-up are the Blender's default axis settings. */ mat3_from_axis_conversion(forward, up, IO_AXIS_Y, IO_AXIS_Z, axes_transform); - mul_m4_m3m4(world_axes_transform_, axes_transform, export_object_eval_->obmat); - /* #mul_m4_m3m4 does not transform last row of #Object.obmat, i.e. location data. */ - mul_v3_m3v3(world_axes_transform_[3], axes_transform, export_object_eval_->obmat[3]); - world_axes_transform_[3][3] = export_object_eval_->obmat[3][3]; + mul_m4_m3m4(world_axes_transform_, axes_transform, export_object_eval_->object_to_world); + /* #mul_m4_m3m4 does not transform last row of #Object.object_to_world, i.e. location data. */ + mul_v3_m3v3(world_axes_transform_[3], axes_transform, export_object_eval_->object_to_world[3]); + world_axes_transform_[3][3] = export_object_eval_->object_to_world[3][3]; } const char *OBJCurve::get_curve_name() const diff --git a/source/blender/makesdna/DNA_object_defaults.h b/source/blender/makesdna/DNA_object_defaults.h index 14683869bc4..2a5796d2aea 100644 --- a/source/blender/makesdna/DNA_object_defaults.h +++ b/source/blender/makesdna/DNA_object_defaults.h @@ -23,7 +23,7 @@ \ .constinv = _DNA_DEFAULT_UNIT_M4, \ .parentinv = _DNA_DEFAULT_UNIT_M4, \ - .obmat = _DNA_DEFAULT_UNIT_M4, \ + .object_to_world = _DNA_DEFAULT_UNIT_M4, \ \ .scale = {1, 1, 1}, \ .dscale = {1, 1, 1}, \ diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 8296855ec29..3ef32d28e85 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -323,7 +323,7 @@ typedef struct Object { /** Axis angle rotation - angle part. */ float rotAngle, drotAngle; /** Final world-space matrix with constraints & animsys applied. */ - float obmat[4][4]; + float object_to_world[4][4]; /** Inverse result of parent, so that object doesn't 'stick' to parent. */ float parentinv[4][4]; /** Inverse result of constraints. @@ -333,7 +333,7 @@ typedef struct Object { * Inverse matrix of 'obmat' for any other use than rendering! * * \note this isn't assured to be valid as with 'obmat', - * before using this value you should do: `invert_m4_m4(ob->imat, ob->obmat)` + * before using this value you should do: `invert_m4_m4(ob->imat, ob->object_to_world)` */ float imat[4][4]; diff --git a/source/blender/makesdna/intern/dna_rename_defs.h b/source/blender/makesdna/intern/dna_rename_defs.h index ec624bcb64e..4a009a88f1a 100644 --- a/source/blender/makesdna/intern/dna_rename_defs.h +++ b/source/blender/makesdna/intern/dna_rename_defs.h @@ -96,6 +96,7 @@ DNA_STRUCT_RENAME_ELEM(Object, dup_group, instance_collection) DNA_STRUCT_RENAME_ELEM(Object, dupfacesca, instance_faces_scale) DNA_STRUCT_RENAME_ELEM(Object, restrictflag, visibility_flag) DNA_STRUCT_RENAME_ELEM(Object, size, scale) +DNA_STRUCT_RENAME_ELEM(Object, obmat, object_to_world) DNA_STRUCT_RENAME_ELEM(Object_Runtime, crazyspace_num_verts, crazyspace_verts_num) DNA_STRUCT_RENAME_ELEM(MEdge, bweight, bweight_legacy) DNA_STRUCT_RENAME_ELEM(MEdge, crease, crease_legacy) diff --git a/source/blender/makesrna/intern/rna_depsgraph.c b/source/blender/makesrna/intern/rna_depsgraph.c index db5b3c33c59..9af76de2a2b 100644 --- a/source/blender/makesrna/intern/rna_depsgraph.c +++ b/source/blender/makesrna/intern/rna_depsgraph.c @@ -168,7 +168,7 @@ static void rna_DepsgraphObjectInstance_matrix_world_get(PointerRNA *ptr, float /* We can return actual object's matrix here, no reason to return identity matrix * when this is not actually an instance... */ Object *ob = (Object *)di->iter.current; - copy_m4_m4((float(*)[4])mat, ob->obmat); + copy_m4_m4((float(*)[4])mat, ob->object_to_world); } } diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index cf0ff546d41..a55a1b0ffcd 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -334,13 +334,13 @@ static int rna_GPencilLayer_active_frame_editable(PointerRNA *ptr, const char ** static void set_parent(bGPDlayer *gpl, Object *par, const int type, const char *substr) { if (type == PAROBJECT) { - invert_m4_m4(gpl->inverse, par->obmat); + invert_m4_m4(gpl->inverse, par->object_to_world); gpl->parent = par; gpl->partype |= PAROBJECT; gpl->parsubstr[0] = 0; } else if (type == PARSKEL) { - invert_m4_m4(gpl->inverse, par->obmat); + invert_m4_m4(gpl->inverse, par->object_to_world); gpl->parent = par; gpl->partype |= PARSKEL; gpl->parsubstr[0] = 0; @@ -349,7 +349,7 @@ static void set_parent(bGPDlayer *gpl, Object *par, const int type, const char * bPoseChannel *pchan = BKE_pose_channel_find_name(par->pose, substr); if (pchan) { float tmp_mat[4][4]; - mul_m4_m4m4(tmp_mat, par->obmat, pchan->pose_mat); + mul_m4_m4m4(tmp_mat, par->object_to_world, pchan->pose_mat); invert_m4_m4(gpl->inverse, tmp_mat); gpl->parent = par; @@ -357,7 +357,7 @@ static void set_parent(bGPDlayer *gpl, Object *par, const int type, const char * BLI_strncpy(gpl->parsubstr, substr, sizeof(gpl->parsubstr)); } else { - invert_m4_m4(gpl->inverse, par->obmat); + invert_m4_m4(gpl->inverse, par->object_to_world); gpl->parent = par; gpl->partype |= PAROBJECT; gpl->parsubstr[0] = 0; diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 7f4ed39c001..1d6b3d5d69e 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -356,7 +356,8 @@ static void rna_Object_internal_update_draw(Main *UNUSED(bmain), static void rna_Object_matrix_world_update(Main *bmain, Scene *scene, PointerRNA *ptr) { /* don't use compat so we get predictable rotation */ - BKE_object_apply_mat4((Object *)ptr->owner_id, ((Object *)ptr->owner_id)->obmat, false, true); + BKE_object_apply_mat4( + (Object *)ptr->owner_id, ((Object *)ptr->owner_id)->object_to_world, false, true); rna_Object_internal_update(bmain, scene, ptr); } @@ -3390,7 +3391,7 @@ static void rna_def_object(BlenderRNA *brna) /* matrix */ prop = RNA_def_property(srna, "matrix_world", PROP_FLOAT, PROP_MATRIX); - RNA_def_property_float_sdna(prop, NULL, "obmat"); + RNA_def_property_float_sdna(prop, NULL, "object_to_world"); RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 07702f3b4b6..02105c7b425 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -471,7 +471,7 @@ static void rna_ParticleSystem_co_hair( if (step >= 0 && step <= max_k) { copy_v3_v3(n_co, (cache + step)->co); mul_m4_v3(particlesystem->imat, n_co); - mul_m4_v3(object->obmat, n_co); + mul_m4_v3(object->object_to_world, n_co); } } diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index bf534b0d586..2d725af7fe4 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -456,13 +456,13 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, float result_mat[4][4]; if (ctx->object) { - invert_m4_m4(obinv, ctx->object->obmat); + invert_m4_m4(obinv, ctx->object->object_to_world); } else { unit_m4(obinv); } - mul_m4_series(result_mat, offset, obinv, amd->offset_ob->obmat); + mul_m4_series(result_mat, offset, obinv, amd->offset_ob->object_to_world); copy_m4_m4(offset, result_mat); } @@ -474,7 +474,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, Object *curve_ob = amd->curve_ob; CurveCache *curve_cache = curve_ob->runtime.curve_cache; if (curve_cache != NULL && curve_cache->anim_path_accum_length != NULL) { - float scale_fac = mat4_to_scale(curve_ob->obmat); + float scale_fac = mat4_to_scale(curve_ob->object_to_world); length = scale_fac * BKE_anim_path_get_length(curve_cache); } } diff --git a/source/blender/modifiers/intern/MOD_boolean.cc b/source/blender/modifiers/intern/MOD_boolean.cc index 7ad49f43e1b..21f05158e8b 100644 --- a/source/blender/modifiers/intern/MOD_boolean.cc +++ b/source/blender/modifiers/intern/MOD_boolean.cc @@ -139,8 +139,8 @@ static Mesh *get_quick_mesh( float imat[4][4]; float omat[4][4]; - invert_m4_m4(imat, ob_self->obmat); - mul_m4_m4m4(omat, imat, ob_operand_ob->obmat); + invert_m4_m4(imat, ob_self->object_to_world); + mul_m4_m4m4(omat, imat, ob_operand_ob->object_to_world); MutableSpan verts = result->verts_for_write(); for (const int i : verts.index_range()) { @@ -227,7 +227,8 @@ static BMesh *BMD_mesh_bm_create( SCOPED_TIMER(__func__); #endif - *r_is_flip = (is_negative_m4(object->obmat) != is_negative_m4(operand_ob->obmat)); + *r_is_flip = (is_negative_m4(object->object_to_world) != + is_negative_m4(operand_ob->object_to_world)); const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh, mesh_operand_ob); @@ -294,8 +295,8 @@ static void BMD_mesh_intersection(BMesh *bm, float imat[4][4]; float omat[4][4]; - invert_m4_m4(imat, object->obmat); - mul_m4_m4m4(omat, imat, operand_ob->obmat); + invert_m4_m4(imat, object->object_to_world); + mul_m4_m4m4(omat, imat, operand_ob->object_to_world); BMVert *eve; i = 0; @@ -414,7 +415,7 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd, } meshes.append(mesh); - obmats.append((float4x4 *)&ctx->object->obmat); + obmats.append((float4x4 *)&ctx->object->object_to_world); material_remaps.append({}); if (mesh->totcol == 0) { /* Necessary for faces using the default material when there are no material slots. */ @@ -431,7 +432,7 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd, } BKE_mesh_wrapper_ensure_mdata(mesh_operand); meshes.append(mesh_operand); - obmats.append((float4x4 *)&bmd->object->obmat); + obmats.append((float4x4 *)&bmd->object->object_to_world); material_remaps.append(get_material_remap(*bmd->object, *mesh_operand, materials)); } else if (bmd->flag & eBooleanModifierFlag_Collection) { @@ -446,7 +447,7 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd, } BKE_mesh_wrapper_ensure_mdata(collection_mesh); meshes.append(collection_mesh); - obmats.append((float4x4 *)&ob->obmat); + obmats.append((float4x4 *)&ob->object_to_world); material_remaps.append(get_material_remap(*ob, *collection_mesh, materials)); } } @@ -456,14 +457,15 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd, const bool use_self = (bmd->flag & eBooleanModifierFlag_Self) != 0; const bool hole_tolerant = (bmd->flag & eBooleanModifierFlag_HoleTolerant) != 0; - Mesh *result = blender::meshintersect::direct_mesh_boolean(meshes, - obmats, - *(float4x4 *)&ctx->object->obmat, - material_remaps, - use_self, - hole_tolerant, - bmd->operation, - nullptr); + Mesh *result = blender::meshintersect::direct_mesh_boolean( + meshes, + obmats, + *(float4x4 *)&ctx->object->object_to_world, + material_remaps, + use_self, + hole_tolerant, + bmd->operation, + nullptr); MEM_SAFE_FREE(result->mat); result->mat = (Material **)MEM_malloc_arrayN(materials.size(), sizeof(Material *), __func__); result->totcol = materials.size(); diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c index 30be1d33653..7581b2aa8e5 100644 --- a/source/blender/modifiers/intern/MOD_cast.c +++ b/source/blender/modifiers/intern/MOD_cast.c @@ -126,13 +126,13 @@ static void sphere_do(CastModifierData *cmd, * we use its location, transformed to ob's local space */ if (ctrl_ob) { if (flag & MOD_CAST_USE_OB_TRANSFORM) { - invert_m4_m4(imat, ctrl_ob->obmat); - mul_m4_m4m4(mat, imat, ob->obmat); + invert_m4_m4(imat, ctrl_ob->object_to_world); + mul_m4_m4m4(mat, imat, ob->object_to_world); invert_m4_m4(imat, mat); } - invert_m4_m4(ob->imat, ob->obmat); - mul_v3_m4v3(center, ob->imat, ctrl_ob->obmat[3]); + invert_m4_m4(ob->imat, ob->object_to_world); + mul_v3_m4v3(center, ob->imat, ctrl_ob->object_to_world[3]); } /* now we check which options the user wants */ @@ -275,13 +275,13 @@ static void cuboid_do(CastModifierData *cmd, if (ctrl_ob) { if (flag & MOD_CAST_USE_OB_TRANSFORM) { - invert_m4_m4(imat, ctrl_ob->obmat); - mul_m4_m4m4(mat, imat, ob->obmat); + invert_m4_m4(imat, ctrl_ob->object_to_world); + mul_m4_m4m4(mat, imat, ob->object_to_world); invert_m4_m4(imat, mat); } - invert_m4_m4(ob->imat, ob->obmat); - mul_v3_m4v3(center, ob->imat, ctrl_ob->obmat[3]); + invert_m4_m4(ob->imat, ob->object_to_world); + mul_v3_m4v3(center, ob->imat, ctrl_ob->object_to_world[3]); } if ((flag & MOD_CAST_SIZE_FROM_RADIUS) && has_radius) { diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c index e38bf96500e..82faf08b349 100644 --- a/source/blender/modifiers/intern/MOD_collision.c +++ b/source/blender/modifiers/intern/MOD_collision.c @@ -149,7 +149,7 @@ static void deformVerts(ModifierData *md, for (uint i = 0; i < mvert_num; i++) { /* we save global positions */ - mul_m4_v3(ob->obmat, collmd->x[i].co); + mul_m4_v3(ob->object_to_world, collmd->x[i].co); } collmd->xnew = MEM_dupallocN(collmd->x); /* Frame end position. */ @@ -188,7 +188,7 @@ static void deformVerts(ModifierData *md, for (uint i = 0; i < mvert_num; i++) { /* we save global positions */ - mul_m4_v3(ob->obmat, collmd->xnew[i].co); + mul_m4_v3(ob->object_to_world, collmd->xnew[i].co); /* detect motion */ is_static = is_static && equals_v3v3(collmd->x[i].co, collmd->xnew[i].co); diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index ad5be57ad68..fc12a9c2aad 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -322,7 +322,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd, } else if (ELEM(direction, MOD_DISP_DIR_X, MOD_DISP_DIR_Y, MOD_DISP_DIR_Z, MOD_DISP_DIR_RGB_XYZ) && use_global_direction) { - copy_m4_m4(local_mat, ob->obmat); + copy_m4_m4(local_mat, ob->object_to_world); } DisplaceUserdata data = {NULL}; diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index af167bf9b32..96bf836fa4a 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -985,7 +985,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, MTFace *mtface = CustomData_get_layer_named(&explode->fdata, CD_MTFACE, emd->uvname); /* getting back to object space */ - invert_m4_m4(imat, ctx->object->obmat); + invert_m4_m4(imat, ctx->object->object_to_world); psmd->psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); @@ -1020,7 +1020,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, psys_get_particle_state(&sim, ed_v2, &state, 1); vertco = explode_verts[v].co; - mul_m4_v3(ctx->object->obmat, vertco); + mul_m4_v3(ctx->object->object_to_world, vertco); sub_v3_v3(vertco, birth.co); diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c index 11bc9ee9574..6cf2e1538e9 100644 --- a/source/blender/modifiers/intern/MOD_hook.c +++ b/source/blender/modifiers/intern/MOD_hook.c @@ -338,13 +338,13 @@ static void deformVerts_do(HookModifierData *hmd, /* get world-space matrix of target, corrected for the space the verts are in */ if (hmd->subtarget[0] && pchan) { /* bone target if there's a matching pose-channel */ - mul_m4_m4m4(dmat, ob_target->obmat, pchan->pose_mat); + mul_m4_m4m4(dmat, ob_target->object_to_world, pchan->pose_mat); } else { /* just object target */ - copy_m4_m4(dmat, ob_target->obmat); + copy_m4_m4(dmat, ob_target->object_to_world); } - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); mul_m4_series(hd.mat, ob->imat, dmat, hmd->parentinv); /* --- done with 'hd' init --- */ diff --git a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc index cad9fdfe30d..778f12d6745 100644 --- a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc +++ b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc @@ -135,7 +135,7 @@ static Volume *mesh_to_volume(ModifierData *md, BKE_mesh_wrapper_ensure_mdata(mesh); const float4x4 mesh_to_own_object_space_transform = float4x4(ctx->object->imat) * - float4x4(object_to_convert->obmat); + float4x4(object_to_convert->object_to_world); geometry::MeshToVolumeResolution resolution; resolution.mode = (MeshToVolumeModifierResolutionMode)mvmd->resolution_mode; if (resolution.mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT) { diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index d7ed346a61f..2aaaee2ccc7 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -358,8 +358,8 @@ static void meshdeformModifier_do(ModifierData *md, } /* compute matrices to go in and out of cage object space */ - invert_m4_m4(imat, ob_target->obmat); - mul_m4_m4m4(cagemat, imat, ob->obmat); + invert_m4_m4(imat, ob_target->object_to_world); + mul_m4_m4m4(cagemat, imat, ob->object_to_world); mul_m4_m4m4(cmat, mmd->bindmat, cagemat); invert_m4_m4(iobmat, cmat); copy_m3_m4(icagemat, iobmat); diff --git a/source/blender/modifiers/intern/MOD_normal_edit.cc b/source/blender/modifiers/intern/MOD_normal_edit.cc index 43ded18fcc4..7d422826cf8 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.cc +++ b/source/blender/modifiers/intern/MOD_normal_edit.cc @@ -94,8 +94,8 @@ static void generate_vert_coordinates(Mesh *mesh, /* Translate our coordinates so that center of ob_center is at (0, 0, 0). */ /* Get ob_center (world) coordinates in ob local coordinates. * No need to take into account ob_center's space here, see T44027. */ - invert_m4_m4(inv_obmat, ob->obmat); - mul_v3_m4v3(diff, inv_obmat, ob_center->obmat[3]); + invert_m4_m4(inv_obmat, ob->object_to_world); + mul_v3_m4v3(diff, inv_obmat, ob_center->object_to_world[3]); negate_v3(diff); do_diff = true; @@ -383,8 +383,8 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, /* Get target's center coordinates in ob local coordinates. */ float mat[4][4]; - invert_m4_m4(mat, ob->obmat); - mul_m4_m4m4(mat, mat, ob_target->obmat); + invert_m4_m4(mat, ob->object_to_world); + mul_m4_m4m4(mat, mat, ob_target->object_to_world); copy_v3_v3(target_co, mat[3]); if (use_parallel_normals) { diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index aab48101351..f65f8bc4fb3 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -273,7 +273,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * break; case eParticleInstanceSpace_Local: /* get particle states in the particle object's local space */ - invert_m4_m4(spacemat, pimd->ob->obmat); + invert_m4_m4(spacemat, pimd->ob->object_to_world); break; default: /* should not happen */ diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index 91f8947bbc3..afd7f5a2e48 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -274,8 +274,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * if (ob_axis != NULL) { /* Calculate the matrix relative to the axis object. */ - invert_m4_m4(mtx_tmp_a, ctx->object->obmat); - copy_m4_m4(mtx_tx_inv, ob_axis->obmat); + invert_m4_m4(mtx_tmp_a, ctx->object->object_to_world); + copy_m4_m4(mtx_tx_inv, ob_axis->object_to_world); mul_m4_m4m4(mtx_tx, mtx_tmp_a, mtx_tx_inv); /* Calculate the axis vector. */ diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c index c5e117635b5..a34d66f394b 100644 --- a/source/blender/modifiers/intern/MOD_surface.c +++ b/source/blender/modifiers/intern/MOD_surface.c @@ -154,7 +154,7 @@ static void deformVerts(ModifierData *md, MVert *verts = BKE_mesh_verts_for_write(surmd->mesh); for (i = 0, x = surmd->x, v = surmd->v; i < mesh_verts_num; i++, x++, v++) { float *vec = verts[i].co; - mul_m4_v3(ctx->object->obmat, vec); + mul_m4_v3(ctx->object->object_to_world, vec); if (init) { v->co[0] = v->co[1] = v->co[2] = 0.0f; diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index 53bfdc35b31..6a9321a78a2 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -1466,8 +1466,8 @@ static void surfacedeformModifier_do(ModifierData *md, ob, md); float tmp_mat[4][4]; - invert_m4_m4(tmp_mat, ob->obmat); - mul_m4_m4m4(smd_orig->mat, tmp_mat, ob_target->obmat); + invert_m4_m4(tmp_mat, ob->object_to_world); + mul_m4_m4m4(smd_orig->mat, tmp_mat, ob_target->object_to_world); /* Avoid converting edit-mesh data, binding is an exception. */ BKE_mesh_wrapper_ensure_mdata(target); diff --git a/source/blender/modifiers/intern/MOD_util.cc b/source/blender/modifiers/intern/MOD_util.cc index 589a3d28ad9..a94fc6732a0 100644 --- a/source/blender/modifiers/intern/MOD_util.cc +++ b/source/blender/modifiers/intern/MOD_util.cc @@ -75,15 +75,15 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd, bPoseChannel *pchan = BKE_pose_channel_find_name(map_object->pose, dmd->map_bone); if (pchan) { float mat_bone_world[4][4]; - mul_m4_m4m4(mat_bone_world, map_object->obmat, pchan->pose_mat); + mul_m4_m4m4(mat_bone_world, map_object->object_to_world, pchan->pose_mat); invert_m4_m4(mapref_imat, mat_bone_world); } else { - invert_m4_m4(mapref_imat, map_object->obmat); + invert_m4_m4(mapref_imat, map_object->object_to_world); } } else { - invert_m4_m4(mapref_imat, map_object->obmat); + invert_m4_m4(mapref_imat, map_object->object_to_world); } } else { /* if there is no map object, default to local */ @@ -138,10 +138,10 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd, copy_v3_v3(*r_texco, cos != nullptr ? *cos : mv->co); break; case MOD_DISP_MAP_GLOBAL: - mul_v3_m4v3(*r_texco, ob->obmat, cos != nullptr ? *cos : mv->co); + mul_v3_m4v3(*r_texco, ob->object_to_world, cos != nullptr ? *cos : mv->co); break; case MOD_DISP_MAP_OBJECT: - mul_v3_m4v3(*r_texco, ob->obmat, cos != nullptr ? *cos : mv->co); + mul_v3_m4v3(*r_texco, ob->object_to_world, cos != nullptr ? *cos : mv->co); mul_m4_v3(mapref_imat, *r_texco); break; } diff --git a/source/blender/modifiers/intern/MOD_uvproject.cc b/source/blender/modifiers/intern/MOD_uvproject.cc index c07b2059b5b..895572d9477 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.cc +++ b/source/blender/modifiers/intern/MOD_uvproject.cc @@ -132,7 +132,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, float offsetmat[4][4]; Camera *cam = nullptr; /* calculate projection matrix */ - invert_m4_m4(projectors[i].projmat, projectors[i].ob->obmat); + invert_m4_m4(projectors[i].projmat, projectors[i].ob->object_to_world); projectors[i].uci = nullptr; @@ -178,7 +178,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, projectors[i].normal[0] = 0; projectors[i].normal[1] = 0; projectors[i].normal[2] = 1; - mul_mat3_m4_v3(projectors[i].ob->obmat, projectors[i].normal); + mul_mat3_m4_v3(projectors[i].ob->object_to_world, projectors[i].normal); } polys_num = mesh->totpoly; @@ -192,7 +192,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, /* Convert coords to world-space. */ for (i = 0, co = coords; i < verts_num; i++, co++) { - mul_m4_v3(ob->obmat, *co); + mul_m4_v3(ob->object_to_world, *co); } /* if only one projector, project coords to UVs */ diff --git a/source/blender/modifiers/intern/MOD_uvwarp.cc b/source/blender/modifiers/intern/MOD_uvwarp.cc index 4ec273bcbc6..a96b28b4e2e 100644 --- a/source/blender/modifiers/intern/MOD_uvwarp.cc +++ b/source/blender/modifiers/intern/MOD_uvwarp.cc @@ -72,10 +72,10 @@ static void matrix_from_obj_pchan(float mat[4][4], Object *ob, const char *bonen { bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bonename); if (pchan) { - mul_m4_m4m4(mat, ob->obmat, pchan->pose_mat); + mul_m4_m4m4(mat, ob->object_to_world, pchan->pose_mat); } else { - copy_m4_m4(mat, ob->obmat); + copy_m4_m4(mat, ob->object_to_world); } } diff --git a/source/blender/modifiers/intern/MOD_volume_displace.cc b/source/blender/modifiers/intern/MOD_volume_displace.cc index e66793d7cce..fbd5f27f69a 100644 --- a/source/blender/modifiers/intern/MOD_volume_displace.cc +++ b/source/blender/modifiers/intern/MOD_volume_displace.cc @@ -254,14 +254,14 @@ struct DisplaceGridOp { return index_to_object; } case MOD_VOLUME_DISPLACE_MAP_GLOBAL: { - const openvdb::Mat4s object_to_world = matrix_to_openvdb(ctx.object->obmat); + const openvdb::Mat4s object_to_world = matrix_to_openvdb(ctx.object->object_to_world); return index_to_object * object_to_world; } case MOD_VOLUME_DISPLACE_MAP_OBJECT: { if (vdmd.texture_map_object == nullptr) { return index_to_object; } - const openvdb::Mat4s object_to_world = matrix_to_openvdb(ctx.object->obmat); + const openvdb::Mat4s object_to_world = matrix_to_openvdb(ctx.object->object_to_world); const openvdb::Mat4s world_to_texture = matrix_to_openvdb(vdmd.texture_map_object->imat); return index_to_object * object_to_world * world_to_texture; } diff --git a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc index 35fd5a4af42..b4ac23b5c61 100644 --- a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc +++ b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc @@ -157,7 +157,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * volume_grid); openvdb::math::Transform::Ptr transform = local_grid->transform().copy(); - transform->postMult(openvdb::Mat4d((float *)vmmd->object->obmat)); + transform->postMult(openvdb::Mat4d((float *)vmmd->object->object_to_world)); openvdb::Mat4d imat = openvdb::Mat4d((float *)ctx->object->imat); /* `imat` had floating point issues and wasn't affine. */ imat.setCol(3, openvdb::Vec4d(0, 0, 0, 1)); diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c index 3fafbd97fee..791eed28a71 100644 --- a/source/blender/modifiers/intern/MOD_warp.c +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -93,11 +93,11 @@ static void matrix_from_obj_pchan(float mat[4][4], bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bonename); if (pchan) { float mat_bone_world[4][4]; - mul_m4_m4m4(mat_bone_world, ob->obmat, pchan->pose_mat); + mul_m4_m4m4(mat_bone_world, ob->object_to_world, pchan->pose_mat); mul_m4_m4m4(mat, obinv, mat_bone_world); } else { - mul_m4_m4m4(mat, obinv, ob->obmat); + mul_m4_m4m4(mat, obinv, ob->object_to_world); } } @@ -215,7 +215,7 @@ static void warpModifier_do(WarpModifierData *wmd, BKE_curvemapping_init(wmd->curfalloff); } - invert_m4_m4(obinv, ob->obmat); + invert_m4_m4(obinv, ob->object_to_world); /* Checks that the objects/bones are available. */ matrix_from_obj_pchan(mat_from, obinv, wmd->object_from, wmd->bone_from); diff --git a/source/blender/modifiers/intern/MOD_wave.cc b/source/blender/modifiers/intern/MOD_wave.cc index 647e0324707..1489927ba34 100644 --- a/source/blender/modifiers/intern/MOD_wave.cc +++ b/source/blender/modifiers/intern/MOD_wave.cc @@ -152,8 +152,8 @@ static void waveModifier_do(WaveModifierData *md, if (wmd->objectcenter != nullptr) { float mat[4][4]; /* get the control object's location in local coordinates */ - invert_m4_m4(ob->imat, ob->obmat); - mul_m4_m4m4(mat, ob->imat, wmd->objectcenter->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); + mul_m4_m4m4(mat, ob->imat, wmd->objectcenter->object_to_world); wmd->startx = mat[3][0]; wmd->starty = mat[3][1]; diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.cc b/source/blender/modifiers/intern/MOD_weightvgproximity.cc index 93052f4215d..e4e03a2cbc9 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.cc +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.cc @@ -223,9 +223,9 @@ static void get_vert2ob_distance( while (i-- > 0) { /* Get world-coordinates of the vertex (constraints and anim included). */ - mul_v3_m4v3(v_wco, ob->obmat, v_cos[i]); + mul_v3_m4v3(v_wco, ob->object_to_world, v_cos[i]); /* Return distance between both coordinates. */ - dist[i] = len_v3v3(v_wco, obr->obmat[3]); + dist[i] = len_v3v3(v_wco, obr->object_to_world[3]); } } @@ -235,7 +235,7 @@ static void get_vert2ob_distance( */ static float get_ob2ob_distance(const Object *ob, const Object *obr) { - return len_v3v3(ob->obmat[3], obr->obmat[3]); + return len_v3v3(ob->object_to_world[3], obr->object_to_world[3]); } /** diff --git a/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc b/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc index df677e1c399..51393ed8709 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc @@ -112,7 +112,7 @@ static void node_geo_exec(GeoNodeExecParams params) else { sub_v3_v3(transform.values[3], collection->instance_offset); } - mul_m4_m4_post(transform.values, child_object->obmat); + mul_m4_m4_post(transform.values, child_object->object_to_world); } entries.append({handle, &(child_object->id.name[2]), transform}); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc index bf064c6fcbe..dc35607fe45 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc @@ -45,7 +45,7 @@ static void node_geo_exec(GeoNodeExecParams params) return; } - const float4x4 &object_matrix = object->obmat; + const float4x4 &object_matrix = object->object_to_world; const float4x4 transform = float4x4(self_object->imat) * object_matrix; if (transform_space_relative) { diff --git a/source/blender/render/intern/bake.c b/source/blender/render/intern/bake.c index 8fd62f7ec34..9b56e18bb26 100644 --- a/source/blender/render/intern/bake.c +++ b/source/blender/render/intern/bake.c @@ -967,7 +967,7 @@ void RE_bake_normal_world_to_object(const BakePixel pixel_array[], size_t i; float iobmat[4][4]; - invert_m4_m4(iobmat, ob->obmat); + invert_m4_m4(iobmat, ob->object_to_world); for (i = 0; i < pixels_num; i++) { size_t offset; diff --git a/source/blender/render/intern/texture_pointdensity.c b/source/blender/render/intern/texture_pointdensity.c index 2a2b62be1f0..b285bbd1459 100644 --- a/source/blender/render/intern/texture_pointdensity.c +++ b/source/blender/render/intern/texture_pointdensity.c @@ -175,7 +175,7 @@ static void pointdensity_cache_psys( sim.psmd = psys_get_modifier(ob, psys); /* in case ob->imat isn't up-to-date */ - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob->imat, ob->object_to_world); total_particles = psys->totpart + psys->totchild; psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); @@ -399,12 +399,12 @@ static void pointdensity_cache_object(PointDensity *pd, Object *ob) case TEX_PD_OBJECTSPACE: break; case TEX_PD_OBJECTLOC: - mul_m4_v3(ob->obmat, co); + mul_m4_v3(ob->object_to_world, co); sub_v3_v3(co, ob->loc); break; case TEX_PD_WORLDSPACE: default: - mul_m4_v3(ob->obmat, co); + mul_m4_v3(ob->object_to_world, co); break; } @@ -778,7 +778,7 @@ static void particle_system_minmax(Depsgraph *depsgraph, sim.psys = psys; sim.psmd = psys_get_modifier(object, psys); - invert_m4_m4(imat, object->obmat); + invert_m4_m4(imat, object->object_to_world); total_particles = psys->totpart + psys->totchild; psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); diff --git a/source/blender/windowmanager/xr/intern/wm_xr_session.c b/source/blender/windowmanager/xr/intern/wm_xr_session.c index abc41833de6..aefc3afff66 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_session.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_session.c @@ -178,7 +178,7 @@ static void wm_xr_session_base_pose_calc(const Scene *scene, float tmp_quat[4]; float tmp_eul[3]; - mat4_to_loc_quat(r_base_pose->position, tmp_quat, base_pose_object->obmat); + mat4_to_loc_quat(r_base_pose->position, tmp_quat, base_pose_object->object_to_world); /* Only use rotation around Z-axis to align view with floor. */ quat_to_eul(tmp_eul, tmp_quat); -- cgit v1.2.3 From d2406ad17d30d64947afd66d6ca7abcc973d8c97 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 1 Nov 2022 11:28:46 +0100 Subject: Update OCLOC version used on Windows This only affects Windows since Linux uses pre-compiled OCLOC version. --- build_files/config/pipeline_config.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build_files/config/pipeline_config.yaml b/build_files/config/pipeline_config.yaml index 82cd009ea95..3359f89c41e 100644 --- a/build_files/config/pipeline_config.yaml +++ b/build_files/config/pipeline_config.yaml @@ -58,6 +58,8 @@ buildbot: version: '5.2.21440' optix: version: '7.3.0' + ocloc: + version: '101.3430' cmake: default: version: any -- cgit v1.2.3 From 3136fb886e218379a53944ea463dfd772efcc954 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 1 Nov 2022 11:45:17 +0100 Subject: Command line: Tweaked doc of --gpu-backend. There was a trailing ')' without any '(' in the generated documentation. --- source/creator/creator_args.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index ba905f91f97..2ebdcdb35ba 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -1122,7 +1122,7 @@ static const char arg_handle_gpu_backend_set_doc[] = # ifdef WITH_METAL_BACKEND "'metal', " # endif - "'opengl')."; + "'opengl'."; static int arg_handle_gpu_backend_set(int argc, const char **argv, void *UNUSED(data)) { if (argc == 0) { -- cgit v1.2.3 From 3f91540cef7e28e372248804b1f6fbe2fc271bbb Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Thu, 29 Sep 2022 12:57:48 +0200 Subject: Fix T101062: sculpt curves crash using a paintcurve brush For one, paintcurves were not considered in curves sculpt mode at all (so you couldnt draw them). This is now enabled. And the second issue was that since curves sculpt mode uses the reguar paint_stroke_modal() [which handles paintcurves], this was actually excuted, freeing the PaintStroke from SculptCurvesBrushStrokeData (but not the CurvesSculptStrokeOperation) and immediately return OPERATOR_FINISHED from modal (resulting in a double MEM_delete of SculptCurvesBrushStrokeData -- in both invoke and modal). There might be better ways to handle the memory free, for now the double freeing is prevented by setting the operator customdata to NULL (and check for that later). Maniphest Tasks: T101062 Differential Revision: https://developer.blender.org/D16099 --- .../blender/editors/sculpt_paint/curves_sculpt_ops.cc | 17 +++++++++++------ source/blender/editors/sculpt_paint/paint_curve.c | 5 ++++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc index a627437b972..df7dd871a94 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc @@ -220,8 +220,10 @@ static int sculpt_curves_stroke_invoke(bContext *C, wmOperator *op, const wmEven int return_value = op->type->modal(C, op, event); if (return_value == OPERATOR_FINISHED) { - paint_stroke_free(C, op, op_data->stroke); - MEM_delete(op_data); + if (op->customdata != nullptr) { + paint_stroke_free(C, op, op_data->stroke); + MEM_delete(op_data); + } return OPERATOR_FINISHED; } @@ -236,16 +238,19 @@ static int sculpt_curves_stroke_modal(bContext *C, wmOperator *op, const wmEvent int return_value = paint_stroke_modal(C, op, event, &op_data->stroke); if (ELEM(return_value, OPERATOR_FINISHED, OPERATOR_CANCELLED)) { MEM_delete(op_data); + op->customdata = nullptr; } return return_value; } static void sculpt_curves_stroke_cancel(bContext *C, wmOperator *op) { - SculptCurvesBrushStrokeData *op_data = static_cast( - op->customdata); - paint_stroke_cancel(C, op, op_data->stroke); - MEM_delete(op_data); + if (op->customdata != nullptr) { + SculptCurvesBrushStrokeData *op_data = static_cast( + op->customdata); + paint_stroke_cancel(C, op, op_data->stroke); + MEM_delete(op_data); + } } static void SCULPT_CURVES_OT_brush_stroke(struct wmOperatorType *ot) diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c index 22d6626ab16..26f76d46f85 100644 --- a/source/blender/editors/sculpt_paint/paint_curve.c +++ b/source/blender/editors/sculpt_paint/paint_curve.c @@ -44,7 +44,7 @@ bool paint_curve_poll(bContext *C) RegionView3D *rv3d = CTX_wm_region_view3d(C); SpaceImage *sima; - if (rv3d && !(ob && ((ob->mode & OB_MODE_ALL_PAINT) != 0))) { + if (rv3d && !(ob && ((ob->mode & (OB_MODE_ALL_PAINT | OB_MODE_SCULPT_CURVES)) != 0))) { return false; } @@ -676,6 +676,9 @@ static int paintcurve_draw_exec(bContext *C, wmOperator *UNUSED(op)) case PAINT_MODE_SCULPT: name = "SCULPT_OT_brush_stroke"; break; + case PAINT_MODE_SCULPT_CURVES: + name = "SCULPT_CURVES_OT_brush_stroke"; + break; default: return OPERATOR_PASS_THROUGH; } -- cgit v1.2.3 From 4269559215e742e557739a21fbacb918cce1d1f3 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 1 Nov 2022 14:34:17 +0100 Subject: Build: bump expat version to 2.5.0 to address CVE-2022-43680 --- build_files/build_environment/cmake/versions.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake index 89b0a8d72de..328f5b8efc3 100644 --- a/build_files/build_environment/cmake/versions.cmake +++ b/build_files/build_environment/cmake/versions.cmake @@ -371,10 +371,10 @@ set(PYSTRING_HASH f2c68786b359f5e4e62bed53bc4fb86d) set(PYSTRING_HASH_TYPE MD5) set(PYSTRING_FILE pystring-${PYSTRING_VERSION}.tar.gz) -set(EXPAT_VERSION 2_4_9) -set(EXPAT_VERSION_DOTS 2.4.9) +set(EXPAT_VERSION 2_5_0) +set(EXPAT_VERSION_DOTS 2.5.0) set(EXPAT_URI https://github.com/libexpat/libexpat/archive/R_${EXPAT_VERSION}.tar.gz) -set(EXPAT_HASH b59a2aa796be1ee177bbab3b7231dfa5) +set(EXPAT_HASH d375fa3571c0abb945873f5061a8f2e2) set(EXPAT_HASH_TYPE MD5) set(EXPAT_FILE libexpat-${EXPAT_VERSION}.tar.gz) set(EXPAT_CPE "cpe:2.3:a:libexpat_project:libexpat:${EXPAT_VERSION_DOTS}:*:*:*:*:*:*:*") -- cgit v1.2.3 From 108b3ee33e6eae9d0bcbd6fd7693694b871f51c1 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 1 Nov 2022 15:18:53 +0100 Subject: Cleanup: Use bool for binary (true-ish/false-ish) return value --- source/blender/blenkernel/BKE_context.h | 46 +++++++++++------------ source/blender/blenkernel/intern/context.c | 60 +++++++++++++++--------------- 2 files changed, 53 insertions(+), 53 deletions(-) diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index b7068720469..e1406e63ce1 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -285,7 +285,7 @@ bool CTX_data_dir(const char *member); CTX_DATA_BEGIN (C, Type, instance, member) \ Type_id instance_id = (Type_id)ctx_link->ptr.owner_id; -int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBase *)); +int ctx_data_list_count(const bContext *C, bool (*func)(const bContext *, ListBase *)); #define CTX_DATA_COUNT(C, member) ctx_data_list_count(C, CTX_data_##member) @@ -316,22 +316,22 @@ void CTX_data_main_set(bContext *C, struct Main *bmain); void CTX_data_scene_set(bContext *C, struct Scene *scene); /* Only Outliner currently! */ -int CTX_data_selected_ids(const bContext *C, ListBase *list); +bool CTX_data_selected_ids(const bContext *C, ListBase *list); -int CTX_data_selected_editable_objects(const bContext *C, ListBase *list); -int CTX_data_selected_editable_bases(const bContext *C, ListBase *list); +bool CTX_data_selected_editable_objects(const bContext *C, ListBase *list); +bool CTX_data_selected_editable_bases(const bContext *C, ListBase *list); -int CTX_data_editable_objects(const bContext *C, ListBase *list); -int CTX_data_editable_bases(const bContext *C, ListBase *list); +bool CTX_data_editable_objects(const bContext *C, ListBase *list); +bool CTX_data_editable_bases(const bContext *C, ListBase *list); -int CTX_data_selected_objects(const bContext *C, ListBase *list); -int CTX_data_selected_bases(const bContext *C, ListBase *list); +bool CTX_data_selected_objects(const bContext *C, ListBase *list); +bool CTX_data_selected_bases(const bContext *C, ListBase *list); -int CTX_data_visible_objects(const bContext *C, ListBase *list); -int CTX_data_visible_bases(const bContext *C, ListBase *list); +bool CTX_data_visible_objects(const bContext *C, ListBase *list); +bool CTX_data_visible_bases(const bContext *C, ListBase *list); -int CTX_data_selectable_objects(const bContext *C, ListBase *list); -int CTX_data_selectable_bases(const bContext *C, ListBase *list); +bool CTX_data_selectable_objects(const bContext *C, ListBase *list); +bool CTX_data_selectable_bases(const bContext *C, ListBase *list); struct Object *CTX_data_active_object(const bContext *C); struct Base *CTX_data_active_base(const bContext *C); @@ -345,25 +345,25 @@ struct Mask *CTX_data_edit_mask(const bContext *C); struct CacheFile *CTX_data_edit_cachefile(const bContext *C); -int CTX_data_selected_nodes(const bContext *C, ListBase *list); +bool CTX_data_selected_nodes(const bContext *C, ListBase *list); struct EditBone *CTX_data_active_bone(const bContext *C); -int CTX_data_selected_bones(const bContext *C, ListBase *list); -int CTX_data_selected_editable_bones(const bContext *C, ListBase *list); -int CTX_data_visible_bones(const bContext *C, ListBase *list); -int CTX_data_editable_bones(const bContext *C, ListBase *list); +bool CTX_data_selected_bones(const bContext *C, ListBase *list); +bool CTX_data_selected_editable_bones(const bContext *C, ListBase *list); +bool CTX_data_visible_bones(const bContext *C, ListBase *list); +bool CTX_data_editable_bones(const bContext *C, ListBase *list); struct bPoseChannel *CTX_data_active_pose_bone(const bContext *C); -int CTX_data_selected_pose_bones(const bContext *C, ListBase *list); -int CTX_data_selected_pose_bones_from_active_object(const bContext *C, ListBase *list); -int CTX_data_visible_pose_bones(const bContext *C, ListBase *list); +bool CTX_data_selected_pose_bones(const bContext *C, ListBase *list); +bool CTX_data_selected_pose_bones_from_active_object(const bContext *C, ListBase *list); +bool CTX_data_visible_pose_bones(const bContext *C, ListBase *list); struct bGPdata *CTX_data_gpencil_data(const bContext *C); struct bGPDlayer *CTX_data_active_gpencil_layer(const bContext *C); struct bGPDframe *CTX_data_active_gpencil_frame(const bContext *C); -int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list); -int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list); -int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list); +bool CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list); +bool CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list); +bool CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list); const struct AssetLibraryReference *CTX_wm_asset_library_ref(const bContext *C); struct AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid); diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index d7bd0038d3c..1d6092849cc 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -393,37 +393,37 @@ static void *ctx_data_pointer_get(const bContext *C, const char *member) return NULL; } -static int ctx_data_pointer_verify(const bContext *C, const char *member, void **pointer) +static bool ctx_data_pointer_verify(const bContext *C, const char *member, void **pointer) { /* if context is NULL, pointer must be NULL too and that is a valid return */ if (C == NULL) { *pointer = NULL; - return 1; + return true; } bContextDataResult result; if (ctx_data_get((bContext *)C, member, &result) == CTX_RESULT_OK) { BLI_assert(result.type == CTX_DATA_TYPE_POINTER); *pointer = result.ptr.data; - return 1; + return true; } *pointer = NULL; - return 0; + return false; } -static int ctx_data_collection_get(const bContext *C, const char *member, ListBase *list) +static bool ctx_data_collection_get(const bContext *C, const char *member, ListBase *list) { bContextDataResult result; if (ctx_data_get((bContext *)C, member, &result) == CTX_RESULT_OK) { BLI_assert(result.type == CTX_DATA_TYPE_COLLECTION); *list = result.list; - return 1; + return true; } BLI_listbase_clear(list); - return 0; + return false; } static int ctx_data_base_collection_get(const bContext *C, const char *member, ListBase *list) @@ -681,7 +681,7 @@ void CTX_data_list_add_ptr(bContextDataResult *result, const PointerRNA *ptr) BLI_addtail(&result->list, link); } -int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBase *)) +int ctx_data_list_count(const bContext *C, bool (*func)(const bContext *, ListBase *)) { ListBase list; @@ -1291,62 +1291,62 @@ ToolSettings *CTX_data_tool_settings(const bContext *C) return NULL; } -int CTX_data_selected_ids(const bContext *C, ListBase *list) +bool CTX_data_selected_ids(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selected_ids", list); } -int CTX_data_selected_nodes(const bContext *C, ListBase *list) +bool CTX_data_selected_nodes(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selected_nodes", list); } -int CTX_data_selected_editable_objects(const bContext *C, ListBase *list) +bool CTX_data_selected_editable_objects(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selected_editable_objects", list); } -int CTX_data_selected_editable_bases(const bContext *C, ListBase *list) +bool CTX_data_selected_editable_bases(const bContext *C, ListBase *list) { return ctx_data_base_collection_get(C, "selected_editable_objects", list); } -int CTX_data_editable_objects(const bContext *C, ListBase *list) +bool CTX_data_editable_objects(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "editable_objects", list); } -int CTX_data_editable_bases(const bContext *C, ListBase *list) +bool CTX_data_editable_bases(const bContext *C, ListBase *list) { return ctx_data_base_collection_get(C, "editable_objects", list); } -int CTX_data_selected_objects(const bContext *C, ListBase *list) +bool CTX_data_selected_objects(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selected_objects", list); } -int CTX_data_selected_bases(const bContext *C, ListBase *list) +bool CTX_data_selected_bases(const bContext *C, ListBase *list) { return ctx_data_base_collection_get(C, "selected_objects", list); } -int CTX_data_visible_objects(const bContext *C, ListBase *list) +bool CTX_data_visible_objects(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "visible_objects", list); } -int CTX_data_visible_bases(const bContext *C, ListBase *list) +bool CTX_data_visible_bases(const bContext *C, ListBase *list) { return ctx_data_base_collection_get(C, "visible_objects", list); } -int CTX_data_selectable_objects(const bContext *C, ListBase *list) +bool CTX_data_selectable_objects(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selectable_objects", list); } -int CTX_data_selectable_bases(const bContext *C, ListBase *list) +bool CTX_data_selectable_bases(const bContext *C, ListBase *list) { return ctx_data_base_collection_get(C, "selectable_objects", list); } @@ -1404,22 +1404,22 @@ struct CacheFile *CTX_data_edit_cachefile(const bContext *C) return ctx_data_pointer_get(C, "edit_cachefile"); } -int CTX_data_selected_bones(const bContext *C, ListBase *list) +bool CTX_data_selected_bones(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selected_bones", list); } -int CTX_data_selected_editable_bones(const bContext *C, ListBase *list) +bool CTX_data_selected_editable_bones(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selected_editable_bones", list); } -int CTX_data_visible_bones(const bContext *C, ListBase *list) +bool CTX_data_visible_bones(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "visible_bones", list); } -int CTX_data_editable_bones(const bContext *C, ListBase *list) +bool CTX_data_editable_bones(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "editable_bones", list); } @@ -1429,17 +1429,17 @@ struct bPoseChannel *CTX_data_active_pose_bone(const bContext *C) return ctx_data_pointer_get(C, "active_pose_bone"); } -int CTX_data_selected_pose_bones(const bContext *C, ListBase *list) +bool CTX_data_selected_pose_bones(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selected_pose_bones", list); } -int CTX_data_selected_pose_bones_from_active_object(const bContext *C, ListBase *list) +bool CTX_data_selected_pose_bones_from_active_object(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selected_pose_bones_from_active_object", list); } -int CTX_data_visible_pose_bones(const bContext *C, ListBase *list) +bool CTX_data_visible_pose_bones(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "visible_pose_bones", list); } @@ -1459,17 +1459,17 @@ bGPDframe *CTX_data_active_gpencil_frame(const bContext *C) return ctx_data_pointer_get(C, "active_gpencil_frame"); } -int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list) +bool CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "visible_gpencil_layers", list); } -int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list) +bool CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "editable_gpencil_layers", list); } -int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list) +bool CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "editable_gpencil_strokes", list); } -- cgit v1.2.3 From e6823f32e9a7372ca06a5989d56d855df31afea8 Mon Sep 17 00:00:00 2001 From: Michael Kowalski Date: Tue, 1 Nov 2022 10:32:36 -0400 Subject: USD tests: replace deprecated imaging code. UsdImagingCapsuleAdapter static functions GetMeshPoints() and GetTopology() have been removed in USD 22.11. In anticipation of this upcoming change, I've updated the test code to call the corresponding virtual functions instead. --- source/blender/io/usd/tests/usd_imaging_test.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/blender/io/usd/tests/usd_imaging_test.cc b/source/blender/io/usd/tests/usd_imaging_test.cc index 5cd3c042e59..80c232ad099 100644 --- a/source/blender/io/usd/tests/usd_imaging_test.cc +++ b/source/blender/io/usd/tests/usd_imaging_test.cc @@ -42,8 +42,8 @@ TEST_F(USDImagingTest, CapsuleAdapterTest) } pxr::UsdImagingCapsuleAdapter capsule_adapter; - pxr::VtValue points_value = pxr::UsdImagingCapsuleAdapter::GetMeshPoints( - capsule.GetPrim(), pxr::UsdTimeCode::Default()); + pxr::VtValue points_value = capsule_adapter.GetPoints(capsule.GetPrim(), + pxr::UsdTimeCode::Default()); if (!points_value.IsHolding>()) { FAIL() << "Mesh points value holding unexpected type."; return; @@ -52,7 +52,8 @@ TEST_F(USDImagingTest, CapsuleAdapterTest) pxr::VtArray points = points_value.Get>(); EXPECT_FALSE(points.empty()); - pxr::VtValue topology_value = pxr::UsdImagingCapsuleAdapter::GetMeshTopology(); + pxr::VtValue topology_value = capsule_adapter.GetTopology( + capsule.GetPrim(), pxr::SdfPath(), pxr::UsdTimeCode::Default()); if (!topology_value.IsHolding()) { FAIL() << "Mesh topology value holding unexpected type."; -- cgit v1.2.3 From cf985180551da833d4160afcdf2cb4292e138174 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 1 Nov 2022 16:09:49 +0100 Subject: Nodes: Add node group assets in add menu This patch builds on the work from bdb57541475f to add node group assets directly in the node editor add menu. Assets are added after separators to distinguish them, but otherwise they look like any other node. The catalog trees from all configured libraries are used to build the menu hierarchy. Only catalogs with matching asset types are used though. There are a few limitations of this initial version. For now this only supports geometry nodes. Support for other built-in node systems just requires some refactoring of the corresponding add menu though. Lazy loading will be added in a followup commit. For now there is a label the first time the menu is opened. Like the search menu integration, re-saving asset library files in 3.4 is required, if it hasn't been done already. Implementation wise, there is a some ugly code here. A lot of that is because the asset system isn't complete. The RNA API doesn't work well yet, and the system isn't built to interact with multiple libraries at once. It's also ugly because of the way we combine automatic menu generation with builtin menus. As noted in a code comment, these two systems could be merged completely so that the menus for builtin nodes are also generated in the same way. Differential Revision: https://developer.blender.org/D16135 --- release/scripts/startup/bl_ui/node_add_menu.py | 6 + .../startup/bl_ui/node_add_menu_geometry.py | 23 ++ source/blender/blenkernel/BKE_asset_catalog.hh | 11 +- .../blender/blenkernel/BKE_asset_catalog_path.hh | 2 +- source/blender/blenkernel/BKE_asset_library.hh | 11 +- source/blender/blenkernel/intern/asset_catalog.cc | 36 +++ .../blenkernel/intern/asset_catalog_path.cc | 2 +- source/blender/blenkernel/intern/asset_library.cc | 30 +++ .../blenkernel/intern/asset_library_service.cc | 36 +++ .../blenkernel/intern/asset_library_service.hh | 3 + source/blender/editors/asset/ED_asset_list.h | 1 + source/blender/editors/asset/intern/asset_list.cc | 12 + source/blender/editors/include/UI_interface.h | 1 + source/blender/editors/space_node/CMakeLists.txt | 1 + .../blender/editors/space_node/add_menu_assets.cc | 297 +++++++++++++++++++++ source/blender/editors/space_node/node_add.cc | 143 ++++++++-- source/blender/editors/space_node/node_intern.hh | 17 ++ source/blender/editors/space_node/node_ops.cc | 1 + source/blender/editors/space_node/space_node.cc | 3 + source/blender/makesrna/intern/rna_asset.c | 7 + source/blender/makesrna/intern/rna_ui_api.c | 4 + 21 files changed, 619 insertions(+), 28 deletions(-) create mode 100644 source/blender/editors/space_node/add_menu_assets.cc diff --git a/release/scripts/startup/bl_ui/node_add_menu.py b/release/scripts/startup/bl_ui/node_add_menu.py index 31b84b8f08a..d393dc04963 100644 --- a/release/scripts/startup/bl_ui/node_add_menu.py +++ b/release/scripts/startup/bl_ui/node_add_menu.py @@ -58,6 +58,12 @@ def draw_node_group_add_menu(context, layout): ops.name = "node_tree" ops.value = "bpy.data.node_groups[%r]" % group.name +def draw_assets_for_catalog(layout, catalog_path): + layout.template_node_asset_menu_items(catalog_path=catalog_path) + +def draw_root_assets(layout): + layout.menu_contents("NODE_MT_node_add_root_catalogs") + classes = ( ) diff --git a/release/scripts/startup/bl_ui/node_add_menu_geometry.py b/release/scripts/startup/bl_ui/node_add_menu_geometry.py index e1b57ec4f43..c076cd7395a 100644 --- a/release/scripts/startup/bl_ui/node_add_menu_geometry.py +++ b/release/scripts/startup/bl_ui/node_add_menu_geometry.py @@ -16,6 +16,7 @@ class NODE_MT_geometry_node_GEO_ATTRIBUTE(Menu): node_add_menu.add_node_type(layout, "GeometryNodeAttributeDomainSize") node_add_menu.add_node_type(layout, "GeometryNodeRemoveAttribute") node_add_menu.add_node_type(layout, "GeometryNodeStoreNamedAttribute") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_geometry_node_GEO_COLOR(Menu): @@ -32,6 +33,7 @@ class NODE_MT_geometry_node_GEO_COLOR(Menu): ops.value = "'RGBA'" node_add_menu.add_node_type(layout, "ShaderNodeRGBCurve") node_add_menu.add_node_type(layout, "FunctionNodeSeparateColor") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_geometry_node_GEO_CURVE(Menu): @@ -70,6 +72,7 @@ class NODE_MT_geometry_node_GEO_CURVE(Menu): node_add_menu.add_node_type(layout, "GeometryNodeSetSplineCyclic") node_add_menu.add_node_type(layout, "GeometryNodeSetSplineResolution") node_add_menu.add_node_type(layout, "GeometryNodeCurveSplineType") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_geometry_node_GEO_PRIMITIVES_CURVE(Menu): @@ -86,6 +89,7 @@ class NODE_MT_geometry_node_GEO_PRIMITIVES_CURVE(Menu): node_add_menu.add_node_type(layout, "GeometryNodeCurveQuadraticBezier") node_add_menu.add_node_type(layout, "GeometryNodeCurvePrimitiveQuadrilateral") node_add_menu.add_node_type(layout, "GeometryNodeCurveStar") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_geometry_node_curve_topology(Menu): @@ -97,6 +101,7 @@ class NODE_MT_geometry_node_curve_topology(Menu): node_add_menu.add_node_type(layout, "GeometryNodeOffsetPointInCurve") node_add_menu.add_node_type(layout, "GeometryNodeCurveOfPoint") node_add_menu.add_node_type(layout, "GeometryNodePointsOfCurve") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_geometry_node_GEO_GEOMETRY(Menu): @@ -122,6 +127,7 @@ class NODE_MT_geometry_node_GEO_GEOMETRY(Menu): layout.separator() node_add_menu.add_node_type(layout, "GeometryNodeSetID") node_add_menu.add_node_type(layout, "GeometryNodeSetPosition") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_geometry_node_GEO_INPUT(Menu): @@ -149,6 +155,7 @@ class NODE_MT_geometry_node_GEO_INPUT(Menu): node_add_menu.add_node_type(layout, "GeometryNodeInputPosition") node_add_menu.add_node_type(layout, "GeometryNodeInputRadius") node_add_menu.add_node_type(layout, "GeometryNodeInputSceneTime") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_geometry_node_GEO_INSTANCE(Menu): @@ -166,6 +173,7 @@ class NODE_MT_geometry_node_GEO_INSTANCE(Menu): layout.separator() node_add_menu.add_node_type(layout, "GeometryNodeInputInstanceRotation") node_add_menu.add_node_type(layout, "GeometryNodeInputInstanceScale") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_geometry_node_GEO_MATERIAL(Menu): @@ -181,6 +189,7 @@ class NODE_MT_geometry_node_GEO_MATERIAL(Menu): layout.separator() node_add_menu.add_node_type(layout, "GeometryNodeSetMaterial") node_add_menu.add_node_type(layout, "GeometryNodeSetMaterialIndex") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_geometry_node_GEO_MESH(Menu): @@ -219,6 +228,7 @@ class NODE_MT_geometry_node_GEO_MESH(Menu): node_add_menu.add_node_type(layout, "GeometryNodeInputMeshVertexNeighbors") layout.separator() node_add_menu.add_node_type(layout, "GeometryNodeSetShadeSmooth") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_category_PRIMITIVES_MESH(Menu): @@ -235,6 +245,7 @@ class NODE_MT_category_PRIMITIVES_MESH(Menu): node_add_menu.add_node_type(layout, "GeometryNodeMeshCircle") node_add_menu.add_node_type(layout, "GeometryNodeMeshLine") node_add_menu.add_node_type(layout, "GeometryNodeMeshUVSphere") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_geometry_node_mesh_topology(Menu): @@ -250,6 +261,7 @@ class NODE_MT_geometry_node_mesh_topology(Menu): node_add_menu.add_node_type(layout, "GeometryNodeFaceOfCorner"), node_add_menu.add_node_type(layout, "GeometryNodeOffsetCornerInFace"), node_add_menu.add_node_type(layout, "GeometryNodeVertexOfCorner"), + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_category_GEO_OUTPUT(Menu): @@ -259,6 +271,7 @@ class NODE_MT_category_GEO_OUTPUT(Menu): def draw(self, _context): layout = self.layout node_add_menu.add_node_type(layout, "GeometryNodeViewer") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_category_GEO_POINT(Menu): @@ -274,6 +287,7 @@ class NODE_MT_category_GEO_POINT(Menu): node_add_menu.add_node_type(layout, "GeometryNodePointsToVolume") layout.separator() node_add_menu.add_node_type(layout, "GeometryNodeSetPointRadius") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_category_GEO_TEXT(Menu): @@ -290,6 +304,7 @@ class NODE_MT_category_GEO_TEXT(Menu): node_add_menu.add_node_type(layout, "FunctionNodeValueToString") layout.separator() node_add_menu.add_node_type(layout, "FunctionNodeInputSpecialCharacters") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_category_GEO_TEXTURE(Menu): @@ -308,6 +323,7 @@ class NODE_MT_category_GEO_TEXTURE(Menu): node_add_menu.add_node_type(layout, "ShaderNodeTexVoronoi") node_add_menu.add_node_type(layout, "ShaderNodeTexWave") node_add_menu.add_node_type(layout, "ShaderNodeTexWhiteNoise") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_category_GEO_UTILITIES(Menu): @@ -331,6 +347,7 @@ class NODE_MT_category_GEO_UTILITIES(Menu): node_add_menu.add_node_type(layout, "FunctionNodeRandomValue") node_add_menu.add_node_type(layout, "FunctionNodeRotateEuler") node_add_menu.add_node_type(layout, "GeometryNodeSwitch") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_category_GEO_UV(Menu): @@ -341,6 +358,7 @@ class NODE_MT_category_GEO_UV(Menu): layout = self.layout node_add_menu.add_node_type(layout, "GeometryNodeUVPackIslands") node_add_menu.add_node_type(layout, "GeometryNodeUVUnwrap") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_category_GEO_VECTOR(Menu): @@ -354,6 +372,7 @@ class NODE_MT_category_GEO_VECTOR(Menu): node_add_menu.add_node_type(layout, "ShaderNodeVectorCurve") node_add_menu.add_node_type(layout, "ShaderNodeVectorMath") node_add_menu.add_node_type(layout, "ShaderNodeVectorRotate") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_category_GEO_VOLUME(Menu): @@ -364,6 +383,7 @@ class NODE_MT_category_GEO_VOLUME(Menu): layout = self.layout node_add_menu.add_node_type(layout, "GeometryNodeVolumeCube") node_add_menu.add_node_type(layout, "GeometryNodeVolumeToMesh") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_category_GEO_GROUP(Menu): @@ -373,6 +393,7 @@ class NODE_MT_category_GEO_GROUP(Menu): def draw(self, context): layout = self.layout node_add_menu.draw_node_group_add_menu(context, layout) + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_category_GEO_LAYOUT(Menu): @@ -383,6 +404,7 @@ class NODE_MT_category_GEO_LAYOUT(Menu): layout = self.layout node_add_menu.add_node_type(layout, "NodeFrame") node_add_menu.add_node_type(layout, "NodeReroute") + node_add_menu.draw_assets_for_catalog(layout, self.bl_label) class NODE_MT_geometry_node_add_all(Menu): @@ -413,6 +435,7 @@ class NODE_MT_geometry_node_add_all(Menu): layout.menu("NODE_MT_category_GEO_VOLUME") layout.menu("NODE_MT_category_GEO_GROUP") layout.menu("NODE_MT_category_GEO_LAYOUT") + node_add_menu.draw_root_assets(layout) classes = ( diff --git a/source/blender/blenkernel/BKE_asset_catalog.hh b/source/blender/blenkernel/BKE_asset_catalog.hh index caed12d4fdf..73c2e00c4c4 100644 --- a/source/blender/blenkernel/BKE_asset_catalog.hh +++ b/source/blender/blenkernel/BKE_asset_catalog.hh @@ -307,7 +307,7 @@ class AssetCatalogTreeItem { /** Iterate over children calling \a callback for each of them, but do not recurse into their * children. */ - void foreach_child(const ItemIterFn callback); + void foreach_child(ItemIterFn callback); protected: /** Child tree items, ordered by their names. */ @@ -345,10 +345,15 @@ class AssetCatalogTree { /** Ensure an item representing \a path is in the tree, adding it if necessary. */ void insert_item(const AssetCatalog &catalog); - void foreach_item(const AssetCatalogTreeItem::ItemIterFn callback); + void foreach_item(ItemIterFn callback); /** Iterate over root items calling \a callback for each of them, but do not recurse into their * children. */ - void foreach_root_item(const ItemIterFn callback); + void foreach_root_item(ItemIterFn callback); + + bool is_empty() const; + + AssetCatalogTreeItem *find_item(const AssetCatalogPath &path); + AssetCatalogTreeItem *find_root_item(const AssetCatalogPath &path); protected: /** Child tree items, ordered by their names. */ diff --git a/source/blender/blenkernel/BKE_asset_catalog_path.hh b/source/blender/blenkernel/BKE_asset_catalog_path.hh index 135906dd064..93ab0389daf 100644 --- a/source/blender/blenkernel/BKE_asset_catalog_path.hh +++ b/source/blender/blenkernel/BKE_asset_catalog_path.hh @@ -49,7 +49,7 @@ class AssetCatalogPath { AssetCatalogPath() = default; AssetCatalogPath(StringRef path); - AssetCatalogPath(const std::string &path); + AssetCatalogPath(std::string path); AssetCatalogPath(const char *path); AssetCatalogPath(const AssetCatalogPath &other_path) = default; AssetCatalogPath(AssetCatalogPath &&other_path) noexcept; diff --git a/source/blender/blenkernel/BKE_asset_library.hh b/source/blender/blenkernel/BKE_asset_library.hh index e0a39e3aee8..2058df71f6a 100644 --- a/source/blender/blenkernel/BKE_asset_library.hh +++ b/source/blender/blenkernel/BKE_asset_library.hh @@ -10,6 +10,8 @@ # error This is a C++-only header file. Use BKE_asset_library.h instead. #endif +#include "DNA_asset_types.h" + #include "BKE_asset_library.h" #include "BKE_asset_catalog.hh" @@ -44,19 +46,24 @@ struct AssetLibrary { * No-op if the catalog cannot be found. This could be the kind of "the * catalog definition file is corrupt/lost" scenario that the simple name is * meant to help recover from. */ - void refresh_catalog_simplename(struct AssetMetaData *asset_data); + void refresh_catalog_simplename(AssetMetaData *asset_data); void on_blend_save_handler_register(); void on_blend_save_handler_unregister(); - void on_blend_save_post(struct Main *, struct PointerRNA **pointers, int num_pointers); + void on_blend_save_post(Main *bmain, PointerRNA **pointers, int num_pointers); private: bCallbackFuncStore on_save_callback_store_{}; }; +Vector all_valid_asset_library_refs(); + } // namespace blender::bke +blender::bke::AssetLibrary *BKE_asset_library_load(const Main *bmain, + const AssetLibraryReference &library_reference); + blender::bke::AssetCatalogService *BKE_asset_library_get_catalog_service( const ::AssetLibrary *library); blender::bke::AssetCatalogTree *BKE_asset_library_get_catalog_tree(const ::AssetLibrary *library); diff --git a/source/blender/blenkernel/intern/asset_catalog.cc b/source/blender/blenkernel/intern/asset_catalog.cc index 38c712d7e75..62d03b2d79b 100644 --- a/source/blender/blenkernel/intern/asset_catalog.cc +++ b/source/blender/blenkernel/intern/asset_catalog.cc @@ -9,6 +9,7 @@ #include "BKE_asset_catalog.hh" #include "BKE_asset_library.h" +#include "BKE_asset_library.hh" #include "BLI_fileops.hh" #include "BLI_path_util.h" @@ -787,6 +788,41 @@ void AssetCatalogTree::foreach_root_item(const ItemIterFn callback) } } +bool AssetCatalogTree::is_empty() const +{ + return root_items_.empty(); +} + +AssetCatalogTreeItem *AssetCatalogTree::find_item(const AssetCatalogPath &path) +{ + AssetCatalogTreeItem *result = nullptr; + this->foreach_item([&](AssetCatalogTreeItem &item) { + if (result) { + /* There is no way to stop iteration. */ + return; + } + if (item.catalog_path() == path) { + result = &item; + } + }); + return result; +} + +AssetCatalogTreeItem *AssetCatalogTree::find_root_item(const AssetCatalogPath &path) +{ + AssetCatalogTreeItem *result = nullptr; + this->foreach_root_item([&](AssetCatalogTreeItem &item) { + if (result) { + /* There is no way to stop iteration. */ + return; + } + if (item.catalog_path() == path) { + result = &item; + } + }); + return result; +} + /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/intern/asset_catalog_path.cc b/source/blender/blenkernel/intern/asset_catalog_path.cc index 669adb7adf4..9c653c1a137 100644 --- a/source/blender/blenkernel/intern/asset_catalog_path.cc +++ b/source/blender/blenkernel/intern/asset_catalog_path.cc @@ -12,7 +12,7 @@ namespace blender::bke { const char AssetCatalogPath::SEPARATOR = '/'; -AssetCatalogPath::AssetCatalogPath(const std::string &path) : path_(path) +AssetCatalogPath::AssetCatalogPath(std::string path) : path_(std::move(path)) { } diff --git a/source/blender/blenkernel/intern/asset_library.cc b/source/blender/blenkernel/intern/asset_library.cc index 968873cbcbe..b8420af1168 100644 --- a/source/blender/blenkernel/intern/asset_library.cc +++ b/source/blender/blenkernel/intern/asset_library.cc @@ -10,6 +10,7 @@ #include "BKE_main.h" #include "BKE_preferences.h" +#include "BLI_fileops.h" #include "BLI_path_util.h" #include "DNA_asset_types.h" @@ -19,6 +20,13 @@ bool blender::bke::AssetLibrary::save_catalogs_when_file_is_saved = true; +blender::bke::AssetLibrary *BKE_asset_library_load(const Main *bmain, + const AssetLibraryReference &library_reference) +{ + blender::bke::AssetLibraryService *service = blender::bke::AssetLibraryService::get(); + return service->get_asset_library(bmain, library_reference); +} + /** * Loading an asset library at this point only means loading the catalogs. Later on this should * invoke reading of asset representations too. @@ -172,4 +180,26 @@ void AssetLibrary::refresh_catalog_simplename(struct AssetMetaData *asset_data) } STRNCPY(asset_data->catalog_simple_name, catalog->simple_name.c_str()); } + +Vector all_valid_asset_library_refs() +{ + Vector result; + int i; + LISTBASE_FOREACH_INDEX (const bUserAssetLibrary *, asset_library, &U.asset_libraries, i) { + if (!BLI_is_dir(asset_library->path)) { + continue; + } + AssetLibraryReference library_ref{}; + library_ref.custom_library_index = i; + library_ref.type = ASSET_LIBRARY_CUSTOM; + result.append(library_ref); + } + + AssetLibraryReference library_ref{}; + library_ref.custom_library_index = -1; + library_ref.type = ASSET_LIBRARY_LOCAL; + result.append(library_ref); + return result; +} + } // namespace blender::bke diff --git a/source/blender/blenkernel/intern/asset_library_service.cc b/source/blender/blenkernel/intern/asset_library_service.cc index a4f97234042..cd8de7908bf 100644 --- a/source/blender/blenkernel/intern/asset_library_service.cc +++ b/source/blender/blenkernel/intern/asset_library_service.cc @@ -7,11 +7,15 @@ #include "asset_library_service.hh" #include "BKE_blender.h" +#include "BKE_preferences.h" #include "BLI_fileops.h" /* For PATH_MAX (at least on Windows). */ #include "BLI_path_util.h" #include "BLI_string_ref.hh" +#include "DNA_asset_types.h" +#include "DNA_userdef_types.h" + #include "CLG_log.h" static CLG_LogRef LOG = {"bke.asset_service"}; @@ -38,6 +42,38 @@ void AssetLibraryService::destroy() instance_.reset(); } +AssetLibrary *AssetLibraryService::get_asset_library( + const Main *bmain, const AssetLibraryReference &library_reference) +{ + if (library_reference.type == ASSET_LIBRARY_LOCAL) { + /* For the "Current File" library we get the asset library root path based on main. */ + char root_path[FILE_MAX]; + if (bmain) { + BKE_asset_library_find_suitable_root_path_from_main(bmain, root_path); + } + else { + root_path[0] = '\0'; + } + + if (root_path[0] == '\0') { + /* File wasn't saved yet. */ + return get_asset_library_current_file(); + } + + return get_asset_library_on_disk(root_path); + } + if (library_reference.type == ASSET_LIBRARY_CUSTOM) { + bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index( + &U, library_reference.custom_library_index); + + if (user_library) { + return get_asset_library_on_disk(user_library->path); + } + } + + return nullptr; +} + namespace { std::string normalize_directory_path(StringRefNull directory) { diff --git a/source/blender/blenkernel/intern/asset_library_service.hh b/source/blender/blenkernel/intern/asset_library_service.hh index 277fb9db6cc..c22c6b182ce 100644 --- a/source/blender/blenkernel/intern/asset_library_service.hh +++ b/source/blender/blenkernel/intern/asset_library_service.hh @@ -44,6 +44,9 @@ class AssetLibraryService { /** Destroy the AssetLibraryService singleton. It will be reallocated by #get() if necessary. */ static void destroy(); + AssetLibrary *get_asset_library(const Main *bmain, + const AssetLibraryReference &library_reference); + /** * Get the given asset library. Opens it (i.e. creates a new AssetLibrary instance) if necessary. */ diff --git a/source/blender/editors/asset/ED_asset_list.h b/source/blender/editors/asset/ED_asset_list.h index b54f81004f2..3d2aaa3bda1 100644 --- a/source/blender/editors/asset/ED_asset_list.h +++ b/source/blender/editors/asset/ED_asset_list.h @@ -23,6 +23,7 @@ struct wmNotifier; */ void ED_assetlist_storage_fetch(const struct AssetLibraryReference *library_reference, const struct bContext *C); +bool ED_assetlist_is_loaded(const struct AssetLibraryReference *library_reference); void ED_assetlist_ensure_previews_job(const struct AssetLibraryReference *library_reference, const struct bContext *C); void ED_assetlist_clear(const struct AssetLibraryReference *library_reference, struct bContext *C); diff --git a/source/blender/editors/asset/intern/asset_list.cc b/source/blender/editors/asset/intern/asset_list.cc index 7fdb924d769..01a6dc46c48 100644 --- a/source/blender/editors/asset/intern/asset_list.cc +++ b/source/blender/editors/asset/intern/asset_list.cc @@ -422,6 +422,18 @@ void ED_assetlist_storage_fetch(const AssetLibraryReference *library_reference, AssetListStorage::fetch_library(*library_reference, *C); } +bool ED_assetlist_is_loaded(const AssetLibraryReference *library_reference) +{ + AssetList *list = AssetListStorage::lookup_list(*library_reference); + if (!list) { + return false; + } + if (list->needsRefetch()) { + return false; + } + return true; +} + void ED_assetlist_ensure_previews_job(const AssetLibraryReference *library_reference, const bContext *C) { diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 7e9422ff867..b4c8ea6e5eb 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -2525,6 +2525,7 @@ void uiTemplateNodeView(uiLayout *layout, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input); +void uiTemplateNodeAssetMenuItems(uiLayout *layout, struct bContext *C, const char *catalog_path); void uiTemplateTextureUser(uiLayout *layout, struct bContext *C); /** * Button to quickly show texture in Properties Editor texture tab. diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index d7eccbf0b68..ff9e5352d0a 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -29,6 +29,7 @@ set(INC set(SRC add_node_search.cc + add_menu_assets.cc drawnode.cc link_drag_search.cc node_add.cc diff --git a/source/blender/editors/space_node/add_menu_assets.cc b/source/blender/editors/space_node/add_menu_assets.cc new file mode 100644 index 00000000000..4e305ac8af4 --- /dev/null +++ b/source/blender/editors/space_node/add_menu_assets.cc @@ -0,0 +1,297 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_multi_value_map.hh" + +#include "DNA_screen_types.h" +#include "DNA_space_types.h" + +#include "BKE_asset.h" +#include "BKE_asset_catalog.hh" +#include "BKE_asset_library.hh" +#include "BKE_idprop.h" +#include "BKE_screen.h" + +#include "BLT_translation.h" + +#include "RNA_access.h" +#include "RNA_prototypes.h" + +#include "ED_asset.h" + +#include "node_intern.hh" + +namespace blender::ed::space_node { + +static bool node_add_menu_poll(const bContext *C, MenuType * /*mt*/) +{ + return CTX_wm_space_node(C); +} + +struct LibraryAsset { + AssetLibraryReference library_ref; + AssetHandle handle; +}; + +struct LibraryCatalog { + bke::AssetLibrary *library; + const bke::AssetCatalog *catalog; +}; + +struct AssetItemTree { + bke::AssetCatalogTree catalogs; + MultiValueMap assets_per_path; + Map full_catalog_per_tree_item; +}; + +static bool all_loading_finished() +{ + for (const AssetLibraryReference &library : bke::all_valid_asset_library_refs()) { + if (!ED_assetlist_is_loaded(&library)) { + return false; + } + } + return true; +} + +static AssetItemTree build_catalog_tree(const bContext &C, const bNodeTree *node_tree) +{ + if (!node_tree) { + return {}; + } + const Main &bmain = *CTX_data_main(&C); + const Vector all_libraries = bke::all_valid_asset_library_refs(); + + /* Merge catalogs from all libraries to deduplicate menu items. Also store the catalog and + * library for each asset ID in order to use them later when retrieving assets and removing + * empty catalogs. */ + Map id_to_catalog_map; + bke::AssetCatalogTree catalogs_from_all_libraries; + for (const AssetLibraryReference &library_ref : all_libraries) { + if (bke::AssetLibrary *library = BKE_asset_library_load(&bmain, library_ref)) { + if (bke::AssetCatalogTree *tree = library->catalog_service->get_catalog_tree()) { + tree->foreach_item([&](bke::AssetCatalogTreeItem &item) { + const bke::CatalogID &id = item.get_catalog_id(); + bke::AssetCatalog *catalog = library->catalog_service->find_catalog(id); + catalogs_from_all_libraries.insert_item(*catalog); + id_to_catalog_map.add(item.get_catalog_id(), LibraryCatalog{library, catalog}); + }); + } + } + } + + /* Find all the matching node group assets for every catalog path. */ + MultiValueMap assets_per_path; + for (const AssetLibraryReference &library_ref : all_libraries) { + AssetFilterSettings type_filter{}; + type_filter.id_types = FILTER_ID_NT; + + ED_assetlist_storage_fetch(&library_ref, &C); + ED_assetlist_ensure_previews_job(&library_ref, &C); + ED_assetlist_iterate(library_ref, [&](AssetHandle asset) { + if (!ED_asset_filter_matches_asset(&type_filter, &asset)) { + return true; + } + const AssetMetaData &meta_data = *ED_asset_handle_get_metadata(&asset); + const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&meta_data, "type"); + if (tree_type == nullptr || IDP_Int(tree_type) != node_tree->type) { + return true; + } + if (BLI_uuid_is_nil(meta_data.catalog_id)) { + return true; + } + const LibraryCatalog &library_catalog = id_to_catalog_map.lookup(meta_data.catalog_id); + assets_per_path.add(library_catalog.catalog->path, LibraryAsset{library_ref, asset}); + return true; + }); + } + + /* Build the final tree without any of the catalogs that don't have proper node group assets. */ + bke::AssetCatalogTree catalogs_with_node_assets; + catalogs_from_all_libraries.foreach_item([&](bke::AssetCatalogTreeItem &item) { + if (!assets_per_path.lookup(item.catalog_path()).is_empty()) { + const bke::CatalogID &id = item.get_catalog_id(); + const LibraryCatalog &library_catalog = id_to_catalog_map.lookup(id); + bke::AssetCatalog *catalog = library_catalog.library->catalog_service->find_catalog(id); + catalogs_with_node_assets.insert_item(*catalog); + } + }); + + /* Build another map storing full asset paths for each tree item, in order to have stable + * pointers to asset catalog paths to use for context pointers. This is necessary because + * #bke::AssetCatalogTreeItem doesn't store its full path directly. */ + Map full_catalog_per_tree_item; + catalogs_with_node_assets.foreach_item([&](bke::AssetCatalogTreeItem &item) { + full_catalog_per_tree_item.add_new(&item, item.catalog_path()); + }); + + return {std::move(catalogs_with_node_assets), + std::move(assets_per_path), + std::move(full_catalog_per_tree_item)}; +} + +static void node_add_catalog_assets_draw(const bContext *C, Menu *menu) +{ + bScreen &screen = *CTX_wm_screen(C); + const SpaceNode &snode = *CTX_wm_space_node(C); + if (!snode.runtime->assets_for_menu) { + BLI_assert_unreachable(); + return; + } + AssetItemTree &tree = *snode.runtime->assets_for_menu; + const bNodeTree *edit_tree = snode.edittree; + if (!edit_tree) { + return; + } + + const PointerRNA menu_path_ptr = CTX_data_pointer_get(C, "asset_catalog_path"); + if (RNA_pointer_is_null(&menu_path_ptr)) { + return; + } + const bke::AssetCatalogPath &menu_path = *static_cast( + menu_path_ptr.data); + + const Span asset_items = tree.assets_per_path.lookup(menu_path); + bke::AssetCatalogTreeItem *catalog_item = tree.catalogs.find_item(menu_path); + BLI_assert(catalog_item != nullptr); + + if (asset_items.is_empty() && !catalog_item->has_children()) { + return; + } + + uiLayout *layout = menu->layout; + uiItemS(layout); + + for (const LibraryAsset &item : asset_items) { + uiLayout *col = uiLayoutColumn(layout, false); + PointerRNA file{ + &screen.id, &RNA_FileSelectEntry, const_cast(item.handle.file_data)}; + uiLayoutSetContextPointer(col, "active_file", &file); + + PointerRNA library_ptr{&screen.id, + &RNA_AssetLibraryReference, + const_cast(&item.library_ref)}; + uiLayoutSetContextPointer(col, "asset_library_ref", &library_ptr); + + uiItemO(col, ED_asset_handle_get_name(&item.handle), ICON_NONE, "NODE_OT_add_group_asset"); + } + + catalog_item->foreach_child([&](bke::AssetCatalogTreeItem &child_item) { + const bke::AssetCatalogPath &path = tree.full_catalog_per_tree_item.lookup(&child_item); + PointerRNA path_ptr{ + &screen.id, &RNA_AssetCatalogPath, const_cast(&path)}; + uiLayout *col = uiLayoutColumn(layout, false); + uiLayoutSetContextPointer(col, "asset_catalog_path", &path_ptr); + uiItemM(col, "NODE_MT_node_add_catalog_assets", path.name().c_str(), ICON_NONE); + }); +} + +static void add_root_catalogs_draw(const bContext *C, Menu *menu) +{ + bScreen &screen = *CTX_wm_screen(C); + SpaceNode &snode = *CTX_wm_space_node(C); + const bNodeTree *edit_tree = snode.edittree; + uiLayout *layout = menu->layout; + + snode.runtime->assets_for_menu = std::make_shared( + build_catalog_tree(*C, edit_tree)); + + const bool loading_finished = all_loading_finished(); + + AssetItemTree &tree = *snode.runtime->assets_for_menu; + if (tree.catalogs.is_empty() && loading_finished) { + return; + } + + uiItemS(layout); + + if (!loading_finished) { + uiItemL(layout, IFACE_("Loading Asset Libraries"), ICON_INFO); + } + + /* Avoid adding a separate root catalog when the assets have already been added to one of the + * builtin menus. + * TODO: The need to define the builtin menu labels here is completely non-ideal. We don't have + * any UI introspection that can do this though. This can be solved in the near future by + * removing the need to define the add menu completely, instead using a per-node-type path which + * can be merged with catalog tree. + */ + static Set all_builtin_menus = []() { + Set menus; + menus.add_new("Attribute"); + menus.add_new("Color"); + menus.add_new("Curve"); + menus.add_new("Curve Primitives"); + menus.add_new("Curve Topology"); + menus.add_new("Geometry"); + menus.add_new("Input"); + menus.add_new("Instances"); + menus.add_new("Material"); + menus.add_new("Mesh"); + menus.add_new("Mesh Primitives"); + menus.add_new("Mesh Topology"); + menus.add_new("Output"); + menus.add_new("Point"); + menus.add_new("Text"); + menus.add_new("Texture"); + menus.add_new("Utilities"); + menus.add_new("UV"); + menus.add_new("Vector"); + menus.add_new("Volume"); + menus.add_new("Group"); + menus.add_new("Layout"); + return menus; + }(); + + tree.catalogs.foreach_root_item([&](bke::AssetCatalogTreeItem &item) { + if (all_builtin_menus.contains(item.get_name())) { + return; + } + const bke::AssetCatalogPath &path = tree.full_catalog_per_tree_item.lookup(&item); + PointerRNA path_ptr{ + &screen.id, &RNA_AssetCatalogPath, const_cast(&path)}; + uiLayout *col = uiLayoutColumn(layout, false); + uiLayoutSetContextPointer(col, "asset_catalog_path", &path_ptr); + uiItemM(col, "NODE_MT_node_add_catalog_assets", path.name().c_str(), ICON_NONE); + }); +} + +MenuType add_catalog_assets_menu_type() +{ + MenuType type{}; + BLI_strncpy(type.idname, "NODE_MT_node_add_catalog_assets", sizeof(type.idname)); + type.poll = node_add_menu_poll; + type.draw = node_add_catalog_assets_draw; + return type; +} + +MenuType add_root_catalogs_menu_type() +{ + MenuType type{}; + BLI_strncpy(type.idname, "NODE_MT_node_add_root_catalogs", sizeof(type.idname)); + type.poll = node_add_menu_poll; + type.draw = add_root_catalogs_draw; + return type; +} + +} // namespace blender::ed::space_node + +/* Note: This is only necessary because Python can't set an asset catalog path context item. */ +void uiTemplateNodeAssetMenuItems(uiLayout *layout, bContext *C, const char *catalog_path) +{ + using namespace blender; + using namespace blender::ed::space_node; + bScreen &screen = *CTX_wm_screen(C); + SpaceNode &snode = *CTX_wm_space_node(C); + AssetItemTree &tree = *snode.runtime->assets_for_menu; + const bke::AssetCatalogTreeItem *item = tree.catalogs.find_root_item(catalog_path); + if (!item) { + return; + } + const bke::AssetCatalogPath &path = tree.full_catalog_per_tree_item.lookup(item); + PointerRNA path_ptr{ + &screen.id, &RNA_AssetCatalogPath, const_cast(&path)}; + uiItemS(layout); + uiLayout *col = uiLayoutColumn(layout, false); + uiLayoutSetContextPointer(col, "asset_catalog_path", &path_ptr); + uiItemMContents(col, "NODE_MT_node_add_catalog_assets"); +} diff --git a/source/blender/editors/space_node/node_add.cc b/source/blender/editors/space_node/node_add.cc index 07eecff320a..41f70a6d8cf 100644 --- a/source/blender/editors/space_node/node_add.cc +++ b/source/blender/editors/space_node/node_add.cc @@ -30,6 +30,7 @@ #include "DEG_depsgraph_build.h" +#include "ED_asset.h" #include "ED_node.h" /* own include */ #include "ED_render.h" #include "ED_screen.h" @@ -244,38 +245,36 @@ void NODE_OT_add_reroute(wmOperatorType *ot) /** \name Add Node Group Operator * \{ */ -static bNodeTree *node_add_group_get_and_poll_group_node_tree(Main *bmain, - wmOperator *op, - bNodeTree *ntree) +static bool node_group_add_poll(const bNodeTree &node_tree, + const bNodeTree &node_group, + ReportList &reports) { - bNodeTree *node_group = reinterpret_cast( - WM_operator_properties_id_lookup_from_name_or_session_uuid(bmain, op->ptr, ID_NT)); - if (!node_group) { - return nullptr; + if (node_group.type != node_tree.type) { + return false; } const char *disabled_hint = nullptr; - if ((node_group->type != ntree->type) || !nodeGroupPoll(ntree, node_group, &disabled_hint)) { + if (!nodeGroupPoll(&node_tree, &node_group, &disabled_hint)) { if (disabled_hint) { - BKE_reportf(op->reports, + BKE_reportf(&reports, RPT_ERROR, "Can not add node group '%s' to '%s':\n %s", - node_group->id.name + 2, - ntree->id.name + 2, + node_group.id.name + 2, + node_tree.id.name + 2, disabled_hint); } else { - BKE_reportf(op->reports, + BKE_reportf(&reports, RPT_ERROR, "Can not add node group '%s' to '%s'", - node_group->id.name + 2, - ntree->id.name + 2); + node_group.id.name + 2, + node_tree.id.name + 2); } - return nullptr; + return false; } - return node_group; + return true; } static int node_add_group_exec(bContext *C, wmOperator *op) @@ -284,10 +283,14 @@ static int node_add_group_exec(bContext *C, wmOperator *op) SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ntree = snode->edittree; - bNodeTree *node_group = node_add_group_get_and_poll_group_node_tree(bmain, op, ntree); + bNodeTree *node_group = reinterpret_cast( + WM_operator_properties_id_lookup_from_name_or_session_uuid(bmain, op->ptr, ID_NT)); if (!node_group) { return OPERATOR_CANCELLED; } + if (!node_group_add_poll(*ntree, *node_group, *op->reports)) { + return OPERATOR_CANCELLED; + } ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); @@ -320,9 +323,8 @@ static bool node_add_group_poll(bContext *C) } const SpaceNode *snode = CTX_wm_space_node(C); if (snode->edittree->type == NTREE_CUSTOM) { - CTX_wm_operator_poll_msg_set(C, - "This node editor displays a custom (Python defined) node tree. " - "Dropping node groups isn't supported for this"); + CTX_wm_operator_poll_msg_set( + C, "Adding node groups isn't supported for custom (Python defined) node trees"); return false; } return true; @@ -366,6 +368,105 @@ void NODE_OT_add_group(wmOperatorType *ot) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Add Node Group Asset Operator + * \{ */ + +static bool add_node_group_asset(const bContext &C, + const AssetLibraryReference &library_ref, + const AssetHandle asset, + ReportList &reports) +{ + Main &bmain = *CTX_data_main(&C); + SpaceNode &snode = *CTX_wm_space_node(&C); + bNodeTree &edit_tree = *snode.edittree; + + bNodeTree *node_group = reinterpret_cast( + asset::get_local_id_from_asset_or_append_and_reuse(bmain, library_ref, asset)); + if (!node_group) { + return false; + } + if (!node_group_add_poll(edit_tree, *node_group, reports)) { + /* Remove the node group if it was newly appended but can't be added to the tree. */ + id_us_plus(&node_group->id); + BKE_id_free_us(&bmain, node_group); + return false; + } + + ED_preview_kill_jobs(CTX_wm_manager(&C), CTX_data_main(&C)); + + bNode *group_node = add_node( + C, ntreeTypeFind(node_group->idname)->group_idname, snode.runtime->cursor); + if (!group_node) { + BKE_report(&reports, RPT_WARNING, "Could not add node group"); + return false; + } + /* By default, don't show the data-block selector since it's not usually necessary for assets. */ + group_node->flag &= ~NODE_OPTIONS; + + group_node->id = &node_group->id; + id_us_plus(group_node->id); + BKE_ntree_update_tag_node_property(&edit_tree, group_node); + + nodeSetActive(&edit_tree, group_node); + ED_node_tree_propagate_change(&C, &bmain, nullptr); + DEG_relations_tag_update(&bmain); + + return true; +} + +static int node_add_group_asset_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + ARegion ®ion = *CTX_wm_region(C); + SpaceNode &snode = *CTX_wm_space_node(C); + + const AssetLibraryReference *library_ref = CTX_wm_asset_library_ref(C); + if (!library_ref) { + return OPERATOR_CANCELLED; + } + bool is_valid; + const AssetHandle handle = CTX_wm_asset_handle(C, &is_valid); + if (!is_valid) { + return OPERATOR_CANCELLED; + } + + /* Convert mouse coordinates to v2d space. */ + UI_view2d_region_to_view(®ion.v2d, + event->mval[0], + event->mval[1], + &snode.runtime->cursor[0], + &snode.runtime->cursor[1]); + + snode.runtime->cursor /= UI_DPI_FAC; + + if (!add_node_group_asset(*C, *library_ref, handle, *op->reports)) { + return OPERATOR_CANCELLED; + } + + wmOperatorType *ot = WM_operatortype_find("NODE_OT_translate_attach_remove_on_cancel", true); + BLI_assert(ot); + PointerRNA ptr; + WM_operator_properties_create_ptr(&ptr, ot); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, nullptr); + WM_operator_properties_free(&ptr); + + return OPERATOR_FINISHED; +} + +void NODE_OT_add_group_asset(wmOperatorType *ot) +{ + ot->name = "Add Node Group Asset"; + ot->description = "Add a node group asset to the active node tree"; + ot->idname = "NODE_OT_add_group_asset"; + + ot->invoke = node_add_group_asset_invoke; + ot->poll = node_add_group_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Add Node Object Operator * \{ */ @@ -393,7 +494,7 @@ static int node_add_object_exec(bContext *C, wmOperator *op) bNodeSocket *sock = nodeFindSocket(object_node, SOCK_IN, "Object"); if (!sock) { - BKE_report(op->reports, RPT_WARNING, "Could not find node object socket"); + BLI_assert_unreachable(); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_node/node_intern.hh b/source/blender/editors/space_node/node_intern.hh index 1c3026628a6..88be9a52c61 100644 --- a/source/blender/editors/space_node/node_intern.hh +++ b/source/blender/editors/space_node/node_intern.hh @@ -38,6 +38,8 @@ extern const char *node_context_dir[]; namespace blender::ed::space_node { +struct AssetItemTree; + /** Temporary data used in node link drag modal operator. */ struct bNodeLinkDrag { /** Links dragged by the operator. */ @@ -96,6 +98,15 @@ struct SpaceNode_Runtime { /* XXX hack for translate_attach op-macros to pass data from transform op to insert_offset op */ /** Temporary data for node insert offset (in UI called Auto-offset). */ struct NodeInsertOfsData *iofsd; + + /** + * Temporary data for node add menu in order to provide longer-term storage for context pointers. + * Recreated every time the root menu is opened. In the future this will be replaced with an "all + * libraries" cache in the asset system itself. + * + * Stored with a shared pointer so that it can be forward declared. + */ + std::shared_ptr assets_for_menu; }; enum NodeResizeDirection { @@ -253,6 +264,7 @@ bNode *add_static_node(const bContext &C, int type, const float2 &location); void NODE_OT_add_reroute(wmOperatorType *ot); void NODE_OT_add_search(wmOperatorType *ot); void NODE_OT_add_group(wmOperatorType *ot); +void NODE_OT_add_group_asset(wmOperatorType *ot); void NODE_OT_add_object(wmOperatorType *ot); void NODE_OT_add_collection(wmOperatorType *ot); void NODE_OT_add_file(wmOperatorType *ot); @@ -383,4 +395,9 @@ void invoke_node_link_drag_add_menu(bContext &C, void invoke_add_node_search_menu(bContext &C, const float2 &cursor, bool use_transform); +/* add_menu_assets.cc */ + +MenuType add_catalog_assets_menu_type(); +MenuType add_root_catalogs_menu_type(); + } // namespace blender::ed::space_node diff --git a/source/blender/editors/space_node/node_ops.cc b/source/blender/editors/space_node/node_ops.cc index d45c33a3c59..104d1acf3b4 100644 --- a/source/blender/editors/space_node/node_ops.cc +++ b/source/blender/editors/space_node/node_ops.cc @@ -78,6 +78,7 @@ void node_operatortypes() WM_operatortype_append(NODE_OT_add_search); WM_operatortype_append(NODE_OT_add_group); + WM_operatortype_append(NODE_OT_add_group_asset); WM_operatortype_append(NODE_OT_add_object); WM_operatortype_append(NODE_OT_add_collection); WM_operatortype_append(NODE_OT_add_file); diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc index ac49115959c..5754e77399f 100644 --- a/source/blender/editors/space_node/space_node.cc +++ b/source/blender/editors/space_node/space_node.cc @@ -1170,5 +1170,8 @@ void ED_spacetype_node() art->draw = node_toolbar_region_draw; BLI_addhead(&st->regiontypes, art); + WM_menutype_add(MEM_new(__func__, add_catalog_assets_menu_type())); + WM_menutype_add(MEM_new(__func__, add_root_catalogs_menu_type())); + BKE_spacetype_register(st); } diff --git a/source/blender/makesrna/intern/rna_asset.c b/source/blender/makesrna/intern/rna_asset.c index f919cfbeffd..3c7eb3d208f 100644 --- a/source/blender/makesrna/intern/rna_asset.c +++ b/source/blender/makesrna/intern/rna_asset.c @@ -472,6 +472,12 @@ static void rna_def_asset_handle(BlenderRNA *brna) rna_def_asset_handle_api(srna); } +static void rna_def_asset_catalog_path(BlenderRNA *brna) +{ + StructRNA *srna = RNA_def_struct(brna, "AssetCatalogPath", NULL); + RNA_def_struct_ui_text(srna, "Catalog Path", ""); +} + static void rna_def_asset_library_reference(BlenderRNA *brna) { StructRNA *srna = RNA_def_struct(brna, "AssetLibraryReference", NULL); @@ -498,6 +504,7 @@ void RNA_def_asset(BlenderRNA *brna) rna_def_asset_data(brna); rna_def_asset_library_reference(brna); rna_def_asset_handle(brna); + rna_def_asset_catalog_path(brna); RNA_define_animate_sdna(true); } diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index fc68e8421d7..eac29ac5e61 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -1785,6 +1785,10 @@ void RNA_api_ui_layout(StructRNA *srna) parm = RNA_def_pointer(func, "socket", "NodeSocket", "", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + func = RNA_def_function(srna, "template_node_asset_menu_items", "uiTemplateNodeAssetMenuItems"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + parm = RNA_def_string(func, "catalog_path", NULL, 0, "", ""); + func = RNA_def_function(srna, "template_texture_user", "uiTemplateTextureUser"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); -- cgit v1.2.3 From 99e5024e97f1c34697885b1a93935e72c019da5c Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 1 Nov 2022 16:35:23 +0100 Subject: UI: Support refreshing menu popups This allows us to asynchronously load items into the menu, see cf985180551d. All menus spawned from Python using the `wm.call_menu` operator will be affected by this. We could avoid that and only refresh the menu we need to, but it's worth trying to get this to work as a general menu feature. This is a slightly risky change, so keeping an eye open for bugs. --- .../interface/interface_region_menu_popup.cc | 298 +++++++++++++-------- 1 file changed, 192 insertions(+), 106 deletions(-) diff --git a/source/blender/editors/interface/interface_region_menu_popup.cc b/source/blender/editors/interface/interface_region_menu_popup.cc index 569f657a544..0d19390d508 100644 --- a/source/blender/editors/interface/interface_region_menu_popup.cc +++ b/source/blender/editors/interface/interface_region_menu_popup.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include "MEM_guardedalloc.h" @@ -166,28 +167,80 @@ struct uiPopupMenu { uiBut *but; ARegion *butregion; + /* Menu hash is created from this, to keep a memory of recently opened menus. */ + const char *title; + int mx, my; bool popup, slideout; - uiMenuCreateFunc menu_func; - void *menu_arg; + std::function menu_func; }; +/** + * \param title: Optional. If set, it will be used to store recently opened menus so they can be + * opened with the mouse over the last chosen entry again. + */ +static void ui_popup_menu_create_block(bContext *C, + uiPopupMenu *pup, + const char *title, + const char *block_name) +{ + const uiStyle *style = UI_style_get_dpi(); + + pup->block = UI_block_begin(C, nullptr, block_name, UI_EMBOSS_PULLDOWN); + if (!pup->but) { + pup->block->flag |= UI_BLOCK_IS_FLIP | UI_BLOCK_NO_FLIP; + } + if (title && title[0]) { + pup->block->flag |= UI_BLOCK_POPUP_MEMORY; + pup->block->puphash = ui_popup_menu_hash(title); + } + pup->layout = UI_block_layout( + pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); + + /* NOTE: this intentionally differs from the menu & sub-menu default because many operators + * use popups like this to select one of their options - + * where having invoke doesn't make sense. + * When the menu was opened from a button, use invoke still for compatibility. This used to be + * the default and changing now could cause issues. */ + const wmOperatorCallContext opcontext = pup->but ? WM_OP_INVOKE_REGION_WIN : + WM_OP_EXEC_REGION_WIN; + + uiLayoutSetOperatorContext(pup->layout, opcontext); + + if (pup->but) { + if (pup->but->context) { + uiLayoutContextCopy(pup->layout, pup->but->context); + } + } +} + static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, void *arg_pup) { uiPopupMenu *pup = static_cast(arg_pup); - if (pup->menu_func) { - pup->block->handle = handle; - pup->menu_func(C, pup->layout, pup->menu_arg); - pup->block->handle = nullptr; + int minwidth = 0; + + if (!pup->layout) { + ui_popup_menu_create_block(C, pup, pup->title, __func__); + + if (pup->menu_func) { + pup->block->handle = handle; + pup->menu_func(C, pup->layout); + pup->block->handle = nullptr; + } + + if (uiLayoutGetUnitsX(pup->layout) != 0.0f) { + /* Use the minimum width from the layout if it's set. */ + minwidth = uiLayoutGetUnitsX(pup->layout) * UI_UNIT_X; + } + + pup->layout = nullptr; } /* Find block minimum width. */ - int minwidth; - if (uiLayoutGetUnitsX(pup->layout) != 0.0f) { - /* Use the minimum width from the layout if it's set. */ - minwidth = uiLayoutGetUnitsX(pup->layout) * UI_UNIT_X; + if (minwidth) { + /* Skip. */ } else if (pup->but) { /* Minimum width to enforce. */ @@ -236,7 +289,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT); if (pup->popup) { - int offset[2]; + int offset[2] = {0, 0}; uiBut *but_activate = nullptr; UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_NUMSELECT); @@ -244,36 +297,42 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi UI_block_direction_set(block, direction); /* offset the mouse position, possibly based on earlier selection */ - uiBut *bt; - if ((block->flag & UI_BLOCK_POPUP_MEMORY) && (bt = ui_popup_menu_memory_get(block))) { - /* position mouse on last clicked item, at 0.8*width of the - * button, so it doesn't overlap the text too much, also note - * the offset is negative because we are inverse moving the - * block to be under the mouse */ - offset[0] = -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect)); - offset[1] = -(bt->rect.ymin + 0.5f * UI_UNIT_Y); - - if (ui_but_is_editable(bt)) { - but_activate = bt; - } - } - else { - /* position mouse at 0.8*width of the button and below the tile - * on the first item */ - offset[0] = 0; - LISTBASE_FOREACH (uiBut *, but_iter, &block->buttons) { - offset[0] = min_ii(offset[0], - -(but_iter->rect.xmin + 0.8f * BLI_rctf_size_x(&but_iter->rect))); + if (!handle->refresh) { + uiBut *bt; + if ((block->flag & UI_BLOCK_POPUP_MEMORY) && (bt = ui_popup_menu_memory_get(block))) { + /* position mouse on last clicked item, at 0.8*width of the + * button, so it doesn't overlap the text too much, also note + * the offset is negative because we are inverse moving the + * block to be under the mouse */ + offset[0] = -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect)); + offset[1] = -(bt->rect.ymin + 0.5f * UI_UNIT_Y); + + if (ui_but_is_editable(bt)) { + but_activate = bt; + } } + else { + /* position mouse at 0.8*width of the button and below the tile + * on the first item */ + offset[0] = 0; + LISTBASE_FOREACH (uiBut *, but_iter, &block->buttons) { + offset[0] = min_ii(offset[0], + -(but_iter->rect.xmin + 0.8f * BLI_rctf_size_x(&but_iter->rect))); + } - offset[1] = 2.1 * UI_UNIT_Y; + offset[1] = 2.1 * UI_UNIT_Y; - LISTBASE_FOREACH (uiBut *, but_iter, &block->buttons) { - if (ui_but_is_editable(but_iter)) { - but_activate = but_iter; - break; + LISTBASE_FOREACH (uiBut *, but_iter, &block->buttons) { + if (ui_but_is_editable(but_iter)) { + but_activate = but_iter; + break; + } } } + copy_v2_v2_int(handle->prev_bounds_offset, offset); + } + else { + copy_v2_v2_int(offset, handle->prev_bounds_offset); } /* in rare cases this is needed since moving the popup @@ -312,27 +371,35 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi return pup->block; } -uiPopupBlockHandle *ui_popup_menu_create( - bContext *C, ARegion *butregion, uiBut *but, uiMenuCreateFunc menu_func, void *arg) +static void ui_block_free_func_POPUP(void *arg_pup) +{ + uiPopupMenu *pup = static_cast(arg_pup); + MEM_delete(pup); +} + +static uiPopupBlockHandle *ui_popup_menu_create( + bContext *C, + ARegion *butregion, + uiBut *but, + const char *title, + std::function menu_func) { wmWindow *window = CTX_wm_window(C); - const uiStyle *style = UI_style_get_dpi(); - uiPopupMenu *pup = MEM_cnew(__func__); - pup->block = UI_block_begin(C, nullptr, __func__, UI_EMBOSS_PULLDOWN); - pup->block->flag |= UI_BLOCK_NUMSELECT; /* Default menus to numeric-selection. */ - pup->layout = UI_block_layout( - pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); - pup->slideout = but ? ui_block_is_menu(but->block) : false; - pup->but = but; - uiLayoutSetOperatorContext(pup->layout, WM_OP_INVOKE_REGION_WIN); + uiPopupMenu *pup = MEM_new(__func__); + pup->title = title; + /* menu is created from a callback */ + pup->menu_func = menu_func; + if (but) { + pup->slideout = ui_block_is_menu(but->block); + pup->but = but; + } if (!but) { /* no button to start from, means we are a popup */ pup->mx = window->eventstate->xy[0]; pup->my = window->eventstate->xy[1]; pup->popup = true; - pup->block->flag |= UI_BLOCK_NO_FLIP; } /* some enums reversing is strange, currently we have no good way to * reverse some enum's but not others, so reverse all so the first menu @@ -346,17 +413,10 @@ uiPopupBlockHandle *ui_popup_menu_create( pup->block->flag |= UI_BLOCK_NO_FLIP; } #endif - if (but->context) { - uiLayoutContextCopy(pup->layout, but->context); - } } - /* menu is created from a callback */ - pup->menu_func = menu_func; - pup->menu_arg = arg; - uiPopupBlockHandle *handle = ui_popup_block_create( - C, butregion, but, nullptr, ui_block_func_POPUP, pup, nullptr); + C, butregion, but, nullptr, ui_block_func_POPUP, pup, ui_block_free_func_POPUP); if (!but) { handle->popup = true; @@ -365,68 +425,73 @@ uiPopupBlockHandle *ui_popup_menu_create( WM_event_add_mousemove(window); } - MEM_freeN(pup); - return handle; } +uiPopupBlockHandle *ui_popup_menu_create( + bContext *C, ARegion *butregion, uiBut *but, uiMenuCreateFunc menu_func, void *arg) +{ + return ui_popup_menu_create( + C, butregion, but, nullptr, [menu_func, arg](bContext *C, uiLayout *layout) { + menu_func(C, layout, arg); + }); +} + /** \} */ /* -------------------------------------------------------------------- */ /** \name Popup Menu API with begin & end * \{ */ +static void create_title_button(uiLayout *layout, const char *title, int icon) +{ + uiBlock *block = uiLayoutGetBlock(layout); + char titlestr[256]; + + if (icon) { + BLI_snprintf(titlestr, sizeof(titlestr), " %s", title); + uiDefIconTextBut(block, + UI_BTYPE_LABEL, + 0, + icon, + titlestr, + 0, + 0, + 200, + UI_UNIT_Y, + nullptr, + 0.0, + 0.0, + 0, + 0, + ""); + } + else { + uiBut *but = uiDefBut( + block, UI_BTYPE_LABEL, 0, title, 0, 0, 200, UI_UNIT_Y, nullptr, 0.0, 0.0, 0, 0, ""); + but->drawflag = UI_BUT_TEXT_LEFT; + } + + uiItemS(layout); +} + +/* Used to directly create a popup menu that is not refreshed on redraw. */ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C, const char *title, const char *block_name, int icon) { - const uiStyle *style = UI_style_get_dpi(); - uiPopupMenu *pup = MEM_cnew(__func__); + uiPopupMenu *pup = MEM_new(__func__); - pup->block = UI_block_begin(C, nullptr, block_name, UI_EMBOSS_PULLDOWN); - pup->block->flag |= UI_BLOCK_POPUP_MEMORY | UI_BLOCK_IS_FLIP; - pup->block->puphash = ui_popup_menu_hash(title); - pup->layout = UI_block_layout( - pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); + pup->title = title; - /* NOTE: this intentionally differs from the menu & sub-menu default because many operators - * use popups like this to select one of their options - - * where having invoke doesn't make sense */ - uiLayoutSetOperatorContext(pup->layout, WM_OP_EXEC_REGION_WIN); + ui_popup_menu_create_block(C, pup, title, block_name); /* create in advance so we can let buttons point to retval already */ pup->block->handle = MEM_cnew(__func__); - /* create title button */ if (title[0]) { - char titlestr[256]; - - if (icon) { - BLI_snprintf(titlestr, sizeof(titlestr), " %s", title); - uiDefIconTextBut(pup->block, - UI_BTYPE_LABEL, - 0, - icon, - titlestr, - 0, - 0, - 200, - UI_UNIT_Y, - nullptr, - 0.0, - 0.0, - 0, - 0, - ""); - } - else { - uiBut *but = uiDefBut( - pup->block, UI_BTYPE_LABEL, 0, title, 0, 0, 200, UI_UNIT_Y, nullptr, 0.0, 0.0, 0, 0, ""); - but->drawflag = UI_BUT_TEXT_LEFT; - } - - uiItemS(pup->layout); + create_title_button(pup->layout, title, icon); } return pup; @@ -465,7 +530,7 @@ void UI_popup_menu_end(bContext *C, uiPopupMenu *pup) UI_popup_handlers_add(C, &window->modalhandlers, menu, 0); WM_event_add_mousemove(window); - MEM_freeN(pup); + MEM_delete(pup); } bool UI_popup_menu_end_or_cancel(bContext *C, uiPopupMenu *pup) @@ -477,7 +542,7 @@ bool UI_popup_menu_end_or_cancel(bContext *C, uiPopupMenu *pup) UI_block_layout_resolve(pup->block, nullptr, nullptr); MEM_freeN(pup->block->handle); UI_block_free(C, pup->block); - MEM_freeN(pup); + MEM_delete(pup); return false; } @@ -541,6 +606,20 @@ void UI_popup_menu_reports(bContext *C, ReportList *reports) } } +static void ui_popup_menu_create_from_menutype(bContext *C, + MenuType *mt, + const char *title, + const int icon) +{ + uiPopupBlockHandle *handle = ui_popup_menu_create( + C, nullptr, nullptr, title, [mt, title, icon](bContext *C, uiLayout *layout) -> void { + create_title_button(layout, title, icon); + ui_item_menutype_func(C, layout, mt); + }); + + handle->can_refresh = true; +} + int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports) { MenuType *mt = WM_menutype_find(idname, true); @@ -554,14 +633,21 @@ int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports) /* cancel but allow event to pass through, just like operators do */ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); } + /* For now always recreate menus on redraw that were invoked with this function. Maybe we want to + * make that optional somehow. */ + const bool allow_refresh = true; - uiPopupMenu *pup = UI_popup_menu_begin( - C, CTX_IFACE_(mt->translation_context, mt->label), ICON_NONE); - uiLayout *layout = UI_popup_menu_layout(pup); - - UI_menutype_draw(C, mt, layout); - - UI_popup_menu_end(C, pup); + const char *title = CTX_IFACE_(mt->translation_context, mt->label); + if (allow_refresh) { + ui_popup_menu_create_from_menutype(C, mt, title, ICON_NONE); + } + else { + /* If no refresh is needed, create the block directly. */ + uiPopupMenu *pup = UI_popup_menu_begin(C, title, ICON_NONE); + uiLayout *layout = UI_popup_menu_layout(pup); + UI_menutype_draw(C, mt, layout); + UI_popup_menu_end(C, pup); + } return OPERATOR_INTERFACE; } -- cgit v1.2.3 From bcc2656299ad72b224c5f2644518759561c31045 Mon Sep 17 00:00:00 2001 From: Michael Kowalski Date: Tue, 1 Nov 2022 11:55:58 -0400 Subject: USD IO: replace deprecated primvars API. Updated the code to use the UsdGeomPrimvarsAPI class to read and write mesh primvars instead of the now deprecated primvars accessors in UsdGeomImageable. This will be required to build with USD 22.11 in the future, where the deprecated functions have been removed. --- source/blender/io/usd/intern/usd_reader_mesh.cc | 15 +++++++++++---- source/blender/io/usd/intern/usd_writer_mesh.cc | 5 ++++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/source/blender/io/usd/intern/usd_reader_mesh.cc b/source/blender/io/usd/intern/usd_reader_mesh.cc index 01db6baeb5c..8138f38fcad 100644 --- a/source/blender/io/usd/intern/usd_reader_mesh.cc +++ b/source/blender/io/usd/intern/usd_reader_mesh.cc @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -287,11 +288,13 @@ bool USDMeshReader::topology_changed(const Mesh *existing_mesh, const double mot mesh_prim_.GetFaceVertexCountsAttr().Get(&face_counts_, motionSampleTime); mesh_prim_.GetPointsAttr().Get(&positions_, motionSampleTime); + pxr::UsdGeomPrimvarsAPI primvarsAPI(mesh_prim_); + /* TODO(makowalski): Reading normals probably doesn't belong in this function, * as this is not required to determine if the topology has changed. */ /* If 'normals' and 'primvars:normals' are both specified, the latter has precedence. */ - pxr::UsdGeomPrimvar primvar = mesh_prim_.GetPrimvar(usdtokens::normalsPrimvar); + pxr::UsdGeomPrimvar primvar = primvarsAPI.GetPrimvar(usdtokens::normalsPrimvar); if (primvar.HasValue()) { primvar.ComputeFlattened(&normals_, motionSampleTime); normal_interpolation_ = primvar.GetInterpolation(); @@ -355,6 +358,8 @@ void USDMeshReader::read_uvs(Mesh *mesh, const double motionSampleTime, const bo std::vector uv_primvars(ldata->totlayer); + pxr::UsdGeomPrimvarsAPI primvarsAPI(mesh_prim_); + if (has_uvs_) { for (int layer_idx = 0; layer_idx < ldata->totlayer; layer_idx++) { const CustomDataLayer *layer = &ldata->layers[layer_idx]; @@ -385,11 +390,11 @@ void USDMeshReader::read_uvs(Mesh *mesh, const double motionSampleTime, const bo } /* Early out if mesh doesn't have primvar. */ - if (!mesh_prim_.HasPrimvar(uv_token)) { + if (!primvarsAPI.HasPrimvar(uv_token)) { continue; } - if (pxr::UsdGeomPrimvar uv_primvar = mesh_prim_.GetPrimvar(uv_token)) { + if (pxr::UsdGeomPrimvar uv_primvar = primvarsAPI.GetPrimvar(uv_token)) { uv_primvar.ComputeFlattened(&uv_primvars[layer_idx].uvs, motionSampleTime); uv_primvars[layer_idx].interpolation = uv_primvar.GetInterpolation(); } @@ -835,12 +840,14 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh, is_left_handed_ = true; } + pxr::UsdGeomPrimvarsAPI primvarsAPI(mesh_prim_); + std::vector uv_tokens; /* Currently we only handle UV primvars. */ if (read_flag & MOD_MESHSEQ_READ_UV) { - std::vector primvars = mesh_prim_.GetPrimvars(); + std::vector primvars = primvarsAPI.GetPrimvars(); for (pxr::UsdGeomPrimvar p : primvars) { diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc index e949bafe517..e7d79e888e4 100644 --- a/source/blender/io/usd/intern/usd_writer_mesh.cc +++ b/source/blender/io/usd/intern/usd_writer_mesh.cc @@ -4,6 +4,7 @@ #include "usd_hierarchy_iterator.h" #include +#include #include #include @@ -107,6 +108,8 @@ void USDGenericMeshWriter::write_uv_maps(const Mesh *mesh, pxr::UsdGeomMesh usd_ { pxr::UsdTimeCode timecode = get_export_time_code(); + pxr::UsdGeomPrimvarsAPI primvarsAPI(usd_mesh.GetPrim()); + const CustomData *ldata = &mesh->ldata; for (int layer_idx = 0; layer_idx < ldata->totlayer; layer_idx++) { const CustomDataLayer *layer = &ldata->layers[layer_idx]; @@ -119,7 +122,7 @@ void USDGenericMeshWriter::write_uv_maps(const Mesh *mesh, pxr::UsdGeomMesh usd_ * for texture coordinates by naming the UV Map as such, without having to guess which UV Map * is the "standard" one. */ pxr::TfToken primvar_name(pxr::TfMakeValidIdentifier(layer->name)); - pxr::UsdGeomPrimvar uv_coords_primvar = usd_mesh.CreatePrimvar( + pxr::UsdGeomPrimvar uv_coords_primvar = primvarsAPI.CreatePrimvar( primvar_name, pxr::SdfValueTypeNames->TexCoord2fArray, pxr::UsdGeomTokens->faceVarying); MLoopUV *mloopuv = static_cast(layer->data); -- cgit v1.2.3 From 78a7d5cfccdc09293acd97e789d60bfd806910c5 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 1 Nov 2022 17:36:36 +0100 Subject: UI: Support C defined menu types to listen to notifiers Needed to dynamically load assets as menu items, see cf985180551d and 99e5024e97f1. The next commit will add the listener for the node add menu. --- source/blender/blenkernel/BKE_screen.h | 1 + source/blender/editors/include/UI_interface.h | 6 +++--- source/blender/editors/interface/interface.cc | 15 +++++++++++++++ source/blender/editors/interface/interface_intern.h | 10 ++++++++++ source/blender/editors/interface/interface_layout.c | 8 ++++++++ source/blender/editors/interface/views/interface_view.cc | 2 +- source/blender/editors/screen/area.c | 2 +- 7 files changed, 39 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 9a7d2bde810..a86953f35cc 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -385,6 +385,7 @@ typedef struct MenuType { bool (*poll)(const struct bContext *C, struct MenuType *mt); /* draw entirely, view changes should be handled here */ void (*draw)(const struct bContext *C, struct Menu *menu); + void (*listener)(const wmRegionListenerParams *params); /* RNA integration */ ExtensionRNA rna_ext; diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index b4c8ea6e5eb..1098266331f 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -784,6 +784,9 @@ void UI_block_set_search_only(uiBlock *block, bool search_only); * Can be called with C==NULL. */ void UI_block_free(const struct bContext *C, uiBlock *block); + +void UI_block_listen(const uiBlock *block, const struct wmRegionListenerParams *listener_params); + /** * Can be called with C==NULL. */ @@ -3198,9 +3201,6 @@ void UI_interface_tag_script_reload(void); /* Support click-drag motion which presses the button and closes a popover (like a menu). */ #define USE_UI_POPOVER_ONCE -void UI_block_views_listen(const uiBlock *block, - const struct wmRegionListenerParams *listener_params); - bool UI_view_item_is_active(const uiViewItemHandle *item_handle); bool UI_view_item_matches(const uiViewItemHandle *a_handle, const uiViewItemHandle *b_handle); /** diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc index 1f88d25af2b..331d1581db5 100644 --- a/source/blender/editors/interface/interface.cc +++ b/source/blender/editors/interface/interface.cc @@ -3474,6 +3474,7 @@ void UI_block_free(const bContext *C, uiBlock *block) BLI_freelistN(&block->saferct); BLI_freelistN(&block->color_pickers.list); + BLI_freelistN(&block->dynamic_listeners); ui_block_free_button_groups(block); ui_block_free_views(block); @@ -3481,6 +3482,20 @@ void UI_block_free(const bContext *C, uiBlock *block) MEM_freeN(block); } +void UI_block_listen(const uiBlock *block, const wmRegionListenerParams *listener_params) +{ + /* Don't need to let invisible blocks (old blocks from previous redraw) listen. */ + if (!block->active) { + return; + } + + LISTBASE_FOREACH (uiBlockDynamicListener *, listener, &block->dynamic_listeners) { + listener->listener_func(listener_params); + } + + ui_block_views_listen(block, listener_params); +} + void UI_blocklist_update_window_matrix(const bContext *C, const ListBase *lb) { ARegion *region = CTX_wm_region(C); diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 6ef81ad897e..982ac1753e1 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -477,6 +477,12 @@ typedef enum uiButtonGroupFlag { } uiButtonGroupFlag; ENUM_OPERATORS(uiButtonGroupFlag, UI_BUTTON_GROUP_PANEL_HEADER); +typedef struct uiBlockDynamicListener { + struct uiBlockDynamicListener *next, *prev; + + void (*listener_func)(const struct wmRegionListenerParams *params); +} uiBlockDynamicListener; + struct uiBlock { uiBlock *next, *prev; @@ -499,6 +505,8 @@ struct uiBlock { * state that is persistent over redraws (e.g. collapsed tree-view items). */ ListBase views; + ListBase dynamic_listeners; /* #uiBlockDynamicListener */ + char name[UI_MAX_NAME_STR]; float winmat[4][4]; @@ -1540,6 +1548,8 @@ void ui_interface_tag_script_reload_queries(void); /* interface_view.cc */ void ui_block_free_views(struct uiBlock *block); +void ui_block_views_listen(const uiBlock *block, + const struct wmRegionListenerParams *listener_params); uiViewHandle *ui_block_view_find_matching_in_old_block(const uiBlock *new_block, const uiViewHandle *new_view); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 496f72c089a..a456cef7be6 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -5814,6 +5814,14 @@ void UI_menutype_draw(bContext *C, MenuType *mt, struct uiLayout *layout) printf("%s: opening menu \"%s\"\n", __func__, mt->idname); } + if (mt->listener) { + /* Forward the menu type listener to the block we're drawing in. */ + uiBlock *block = uiLayoutGetBlock(layout); + uiBlockDynamicListener *listener = MEM_mallocN(sizeof(*listener), "uiBlockDynamicListener"); + listener->listener_func = mt->listener; + BLI_addtail(&block->dynamic_listeners, listener); + } + if (layout->context) { CTX_store_set(C, layout->context); } diff --git a/source/blender/editors/interface/views/interface_view.cc b/source/blender/editors/interface/views/interface_view.cc index c568a8cab74..71974b4d2f9 100644 --- a/source/blender/editors/interface/views/interface_view.cc +++ b/source/blender/editors/interface/views/interface_view.cc @@ -81,7 +81,7 @@ void ui_block_free_views(uiBlock *block) } } -void UI_block_views_listen(const uiBlock *block, const wmRegionListenerParams *listener_params) +void ui_block_views_listen(const uiBlock *block, const wmRegionListenerParams *listener_params) { ARegion *region = listener_params->region; diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 8db968cbb8a..a62e027ba03 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -147,7 +147,7 @@ void ED_region_do_listen(wmRegionListenerParams *params) } LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { - UI_block_views_listen(block, params); + UI_block_listen(block, params); } LISTBASE_FOREACH (uiList *, list, ®ion->ui_lists) { -- cgit v1.2.3 From 518d7dbebbdce2d5a347c7e53eae216a56f44e2a Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 1 Nov 2022 17:39:26 +0100 Subject: UI/Nodes: Update node add menu as assets get loaded Adds a listener to the node add menu so that it refreshes as assets get loaded asynchronously. Followup to cf985180551d, also see 99e5024e97f1 and the previous commit. --- source/blender/editors/space_node/add_menu_assets.cc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/source/blender/editors/space_node/add_menu_assets.cc b/source/blender/editors/space_node/add_menu_assets.cc index 4e305ac8af4..1ba1d67d854 100644 --- a/source/blender/editors/space_node/add_menu_assets.cc +++ b/source/blender/editors/space_node/add_menu_assets.cc @@ -17,6 +17,7 @@ #include "RNA_prototypes.h" #include "ED_asset.h" +#include "ED_screen.h" #include "node_intern.hh" @@ -27,6 +28,20 @@ static bool node_add_menu_poll(const bContext *C, MenuType * /*mt*/) return CTX_wm_space_node(C); } +static void node_add_menu_assets_listen_fn(const wmRegionListenerParams *params) +{ + const wmNotifier *wmn = params->notifier; + ARegion *region = params->region; + + switch (wmn->category) { + case NC_ASSET: + if (wmn->data == ND_ASSET_LIST_READING) { + ED_region_tag_refresh_ui(region); + } + break; + } +} + struct LibraryAsset { AssetLibraryReference library_ref; AssetHandle handle; @@ -261,6 +276,7 @@ MenuType add_catalog_assets_menu_type() BLI_strncpy(type.idname, "NODE_MT_node_add_catalog_assets", sizeof(type.idname)); type.poll = node_add_menu_poll; type.draw = node_add_catalog_assets_draw; + type.listener = node_add_menu_assets_listen_fn; return type; } @@ -270,6 +286,7 @@ MenuType add_root_catalogs_menu_type() BLI_strncpy(type.idname, "NODE_MT_node_add_root_catalogs", sizeof(type.idname)); type.poll = node_add_menu_poll; type.draw = add_root_catalogs_draw; + type.listener = node_add_menu_assets_listen_fn; return type; } -- cgit v1.2.3 From f66236a827c82bffd9f31ca2a7919e865a0397e0 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 1 Nov 2022 15:34:12 +0100 Subject: Fix T102018: find HIP library also in system library paths on Linux Previously it would use a hardcoded location where the AMD driver installs it, but Linux distributions may use other locations. Now look for both cases. --- extern/hipew/src/hipew.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/hipew/src/hipew.c b/extern/hipew/src/hipew.c index ecf952e266f..7cafe7727f5 100644 --- a/extern/hipew/src/hipew.c +++ b/extern/hipew/src/hipew.c @@ -253,7 +253,7 @@ static int hipewHipInit(void) { /* Default installation path. */ const char *hip_paths[] = {"", NULL}; #else - const char *hip_paths[] = {"/opt/rocm/hip/lib/libamdhip64.so", NULL}; + const char *hip_paths[] = {"libamdhip64.so", "/opt/rocm/hip/lib/libamdhip64.so", NULL}; #endif static int initialized = 0; static int result = 0; -- cgit v1.2.3 From f8699881d6bf1c02586d356b1c816e77e144ad32 Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Tue, 1 Nov 2022 12:46:15 -0600 Subject: CMake/MSVC: Disable ASAN for developer builds ASAN is more often broken than working depending on the MSVC version you have. As it is causing too many support incidents of people that unknowingly turned ASAN on by running `make developer` and running into issues starting blender due to the broken ASAN support in MSVC. This commit changes the default not enable it for MSVC in the developer profile. Devs that still want to enable it can do so though turning WITH_COMPILER_ASAN on in their CMakeCache.txt or by running `make developer asan` --- build_files/cmake/config/blender_developer.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/build_files/cmake/config/blender_developer.cmake b/build_files/cmake/config/blender_developer.cmake index 1f1a100d958..ebc5727a79c 100644 --- a/build_files/cmake/config/blender_developer.cmake +++ b/build_files/cmake/config/blender_developer.cmake @@ -8,7 +8,11 @@ set(WITH_ASSERT_ABORT ON CACHE BOOL "" FORCE) set(WITH_BUILDINFO OFF CACHE BOOL "" FORCE) -set(WITH_COMPILER_ASAN ON CACHE BOOL "" FORCE) +# Sadly ASAN is more often broken than working with MSVC do not enable it in the +# developer profile for now. +if(NOT WIN32) + set(WITH_COMPILER_ASAN ON CACHE BOOL "" FORCE) +endif() set(WITH_CYCLES_NATIVE_ONLY ON CACHE BOOL "" FORCE) set(WITH_DOC_MANPAGE OFF CACHE BOOL "" FORCE) set(WITH_GTESTS ON CACHE BOOL "" FORCE) -- cgit v1.2.3 From 513dfa179f3d7becf2e88da1084741e0c70a8da7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 1 Nov 2022 21:30:02 +1100 Subject: Tests: add BLI_path_parent_dir tests, split BLI_path_normalize tests Also enable a test that was disabled with a fix FIXME comment but works. --- source/blender/blenlib/tests/BLI_path_util_test.cc | 97 ++++++++++++---------- 1 file changed, 51 insertions(+), 46 deletions(-) diff --git a/source/blender/blenlib/tests/BLI_path_util_test.cc b/source/blender/blenlib/tests/BLI_path_util_test.cc index 1241c71cf94..2f0e730129c 100644 --- a/source/blender/blenlib/tests/BLI_path_util_test.cc +++ b/source/blender/blenlib/tests/BLI_path_util_test.cc @@ -13,59 +13,64 @@ /* BLI_path_normalize */ #ifndef _WIN32 -TEST(path_util, Clean) -{ - /* "/./" -> "/" */ - { - char path[FILE_MAX] = "/a/./b/./c/./"; - BLI_path_normalize(nullptr, path); - EXPECT_STREQ("/a/b/c/", path); - } - { - char path[FILE_MAX] = "/./././"; - BLI_path_normalize(nullptr, path); - EXPECT_STREQ("/", path); - } +# define NORMALIZE_WITH_BASEDIR(input, input_base, output) \ + { \ + char path[FILE_MAX] = input; \ + BLI_path_normalize(input_base, path); \ + EXPECT_STREQ(output, path); \ + } \ + ((void)0) - { - char path[FILE_MAX] = "/a/./././b/"; - BLI_path_normalize(nullptr, path); - EXPECT_STREQ("/a/b/", path); - } +# define NORMALIZE(input, output) NORMALIZE_WITH_BASEDIR(input, nullptr, output) - /* "//" -> "/" */ - { - char path[FILE_MAX] = "a////"; - BLI_path_normalize(nullptr, path); - EXPECT_STREQ("a/", path); - } +/* #BLI_path_normalize: "/./" -> "/" */ +TEST(path_util, Clean_Dot) +{ + NORMALIZE("/./", "/"); + NORMALIZE("/a/./b/./c/./", "/a/b/c/"); + NORMALIZE("/./././", "/"); + NORMALIZE("/a/./././b/", "/a/b/"); +} +/* #BLI_path_normalize: "//" -> "/" */ +TEST(path_util, Clean_DoubleSlash) +{ + NORMALIZE("//", "//"); /* Exception, double forward slash. */ + NORMALIZE(".//", "./"); + NORMALIZE("a////", "a/"); + NORMALIZE("./a////", "./a/"); +} +/* #BLI_path_normalize: "foo/bar/../" -> "foo/" */ +TEST(path_util, Clean_Parent) +{ + NORMALIZE("/a/b/c/../../../", "/"); + NORMALIZE("/a/../a/b/../b/c/../c/", "/a/b/c/"); + NORMALIZE_WITH_BASEDIR("//../", "/a/b/c/", "/a/b/"); +} - if (false) /* FIXME */ - { - char path[FILE_MAX] = "./a////"; - BLI_path_normalize(nullptr, path); - EXPECT_STREQ("./a/", path); - } +# undef NORMALIZE_WITH_BASEDIR +# undef NORMALIZE - /* "foo/bar/../" -> "foo/" */ - { - char path[FILE_MAX] = "/a/b/c/../../../"; - BLI_path_normalize(nullptr, path); - EXPECT_STREQ("/", path); - } +#endif /* _WIN32 */ - { - char path[FILE_MAX] = "/a/../a/b/../b/c/../c/"; - BLI_path_normalize(nullptr, path); - EXPECT_STREQ("/a/b/c/", path); - } +/* #BLI_path_parent_dir */ +#ifndef _WIN32 +TEST(path_util, ParentDir) +{ +# define PARENT_DIR(input, output) \ + { \ + char path[FILE_MAX] = input; \ + BLI_path_parent_dir(path); \ + EXPECT_STREQ(output, path); \ + } \ + ((void)0) - { - char path[FILE_MAX] = "//../"; - BLI_path_normalize("/a/b/c/", path); - EXPECT_STREQ("/a/b/", path); - } + PARENT_DIR("/a/b/", "/a/"); + PARENT_DIR("/a/b", "/a/"); + PARENT_DIR("/a", "/"); + PARENT_DIR("/", "/"); + +# undef PARENT_DIR } #endif -- cgit v1.2.3 From 12f4ac170658f82ce85d96873cfb32ec786136ec Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 1 Nov 2022 21:32:46 +1100 Subject: Fix BLI_path_normalize failing with "." and ".." in the path The logic to go up a directory (using "..") ran before stripping "/./" from the path. This caused "/a/b/./../" to result in "/a/b/" instead of "/a/". Now redundant characters are removed before before checking for ".." in paths. Include test to ensure this works as expected. --- source/blender/blenlib/intern/path_util.c | 36 ++++++++++++---------- source/blender/blenlib/tests/BLI_path_util_test.cc | 6 ++++ 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index b16cf8ea161..df18689c74c 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -153,6 +153,19 @@ void BLI_path_normalize(const char *relabase, char *path) */ #ifdef WIN32 + + while ((start = strstr(path, "\\.\\"))) { + eind = start + strlen("\\.\\") - 1; + memmove(start, eind, strlen(eind) + 1); + } + + /* remove two consecutive backslashes, but skip the UNC prefix, + * which needs to be preserved */ + while ((start = strstr(path + BLI_path_unc_prefix_len(path), "\\\\"))) { + eind = start + strlen("\\\\") - 1; + memmove(start, eind, strlen(eind) + 1); + } + while ((start = strstr(path, "\\..\\"))) { eind = start + strlen("\\..\\") - 1; a = start - path - 1; @@ -170,18 +183,18 @@ void BLI_path_normalize(const char *relabase, char *path) } } - while ((start = strstr(path, "\\.\\"))) { - eind = start + strlen("\\.\\") - 1; +#else + + while ((start = strstr(path, "/./"))) { + eind = start + (3 - 1) /* strlen("/./") - 1 */; memmove(start, eind, strlen(eind) + 1); } - /* remove two consecutive backslashes, but skip the UNC prefix, - * which needs to be preserved */ - while ((start = strstr(path + BLI_path_unc_prefix_len(path), "\\\\"))) { - eind = start + strlen("\\\\") - 1; + while ((start = strstr(path, "//"))) { + eind = start + (2 - 1) /* strlen("//") - 1 */; memmove(start, eind, strlen(eind) + 1); } -#else + while ((start = strstr(path, "/../"))) { a = start - path - 1; if (a > 0) { @@ -206,15 +219,6 @@ void BLI_path_normalize(const char *relabase, char *path) } } - while ((start = strstr(path, "/./"))) { - eind = start + (3 - 1) /* strlen("/./") - 1 */; - memmove(start, eind, strlen(eind) + 1); - } - - while ((start = strstr(path, "//"))) { - eind = start + (2 - 1) /* strlen("//") - 1 */; - memmove(start, eind, strlen(eind) + 1); - } #endif } diff --git a/source/blender/blenlib/tests/BLI_path_util_test.cc b/source/blender/blenlib/tests/BLI_path_util_test.cc index 2f0e730129c..51db376e03f 100644 --- a/source/blender/blenlib/tests/BLI_path_util_test.cc +++ b/source/blender/blenlib/tests/BLI_path_util_test.cc @@ -32,6 +32,12 @@ TEST(path_util, Clean_Dot) NORMALIZE("/./././", "/"); NORMALIZE("/a/./././b/", "/a/b/"); } +/* #BLI_path_normalize: complex "/./" -> "/", "//" -> "/", "./path/../" -> "./". */ +TEST(path_util, Clean_Complex) +{ + NORMALIZE("/a/./b/./c/./.././.././", "/a/"); + NORMALIZE("/a//.//b//.//c//.//..//.//..//.//", "/a/"); +} /* #BLI_path_normalize: "//" -> "/" */ TEST(path_util, Clean_DoubleSlash) { -- cgit v1.2.3 From cc6f41f8a53f7f0392afa59e6da8ebc3849fc03c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 1 Nov 2022 22:02:08 +1100 Subject: Fix BLI_path_parent_dir failing on paths ending with ".." The check for BLI_path_normalize having succeeded only checked for a trailing "../" which isn't correct. This caused going up a directory in the file selector to do nothing on directories ending with "..". This also caused an empty path to expand into "../" because BLI_path_extension_check didn't account for this case. Resolve using BLI_path_name_at_index which extracts the last component of the path without having to match the the surrounding slashes. --- source/blender/blenlib/BLI_path_util.h | 2 ++ source/blender/blenlib/intern/path_util.c | 26 +++++++++++++++++----- source/blender/blenlib/tests/BLI_path_util_test.cc | 11 +++++++++ 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 6d411b51f85..1b723ab038d 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -364,6 +364,8 @@ bool BLI_path_make_safe(char *path) ATTR_NONNULL(1); * * Replaces path with the path of its parent directory, returning true if * it was able to find a parent directory within the path. + * + * On success, the resulting path will always have a trailing slash. */ bool BLI_path_parent_dir(char *path) ATTR_NONNULL(); /** diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index df18689c74c..f46c2e65395 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -630,14 +630,28 @@ bool BLI_path_parent_dir(char *path) char tmp[FILE_MAX + 4]; BLI_path_join(tmp, sizeof(tmp), path, parent_dir); - BLI_path_normalize(NULL, tmp); /* does all the work of normalizing the path for us */ - - if (!BLI_path_extension_check(tmp, parent_dir)) { - strcpy(path, tmp); /* We assume the parent directory is always shorter. */ - return true; + /* Does all the work of normalizing the path for us. + * + * NOTE(@campbellbarton): While it's possible strip text after the second last slash, + * this would have to be clever and skip cases like "/./" & multiple slashes. + * Since this ends up solving some of the same problems as #BLI_path_normalize, + * call this function instead of attempting to handle them separately. */ + BLI_path_normalize(NULL, tmp); + + /* Use #BLI_path_name_at_index instead of checking if the strings ends with `parent_dir` + * to ensure the logic isn't confused by: + * - Directory names that happen to end with `..`. + * - When `path` is empty, the contents will be `../` + * which would cause checking for a tailing `/../` fail. + * Extracting the span of the final directory avoids both these issues. */ + int tail_ofs = 0, tail_len = 0; + if (BLI_path_name_at_index(tmp, -1, &tail_ofs, &tail_len) && (tail_len == 2) && + (memcmp(&tmp[tail_ofs], "..", 2) == 0)) { + return false; } - return false; + strcpy(path, tmp); /* We assume the parent directory is always shorter. */ + return true; } bool BLI_path_parent_dir_until_exists(char *dir) diff --git a/source/blender/blenlib/tests/BLI_path_util_test.cc b/source/blender/blenlib/tests/BLI_path_util_test.cc index 51db376e03f..93922b41b23 100644 --- a/source/blender/blenlib/tests/BLI_path_util_test.cc +++ b/source/blender/blenlib/tests/BLI_path_util_test.cc @@ -75,6 +75,17 @@ TEST(path_util, ParentDir) PARENT_DIR("/a/b", "/a/"); PARENT_DIR("/a", "/"); PARENT_DIR("/", "/"); + PARENT_DIR("", ""); + + /* Ensure trailing dots aren't confused with parent path. */ + PARENT_DIR("/.../.../.../", "/.../.../"); + PARENT_DIR("/.../.../...", "/.../.../"); + + PARENT_DIR("/a../b../c../", "/a../b../"); + PARENT_DIR("/a../b../c..", "/a../b../"); + + PARENT_DIR("/a./b./c./", "/a./b./"); + PARENT_DIR("/a./b./c.", "/a./b./"); # undef PARENT_DIR } -- cgit v1.2.3 From 889b3385b54984024e1a2624c1ab3811e4817c53 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 2 Nov 2022 10:14:37 +1100 Subject: Cleanup: spelling in comments --- intern/ghost/intern/GHOST_ContextGLX.cpp | 2 +- intern/ghost/intern/GHOST_ImeWin32.h | 2 +- intern/ghost/intern/GHOST_SystemWayland.cpp | 2 +- intern/guardedalloc/intern/leak_detector.cc | 2 +- source/blender/blenkernel/intern/blender.c | 2 +- source/blender/blenkernel/intern/gpencil_modifier.c | 2 +- source/blender/blenkernel/intern/icons.cc | 2 +- source/blender/blenkernel/intern/ipo.c | 2 +- source/blender/blenkernel/intern/lib_id.c | 2 +- source/blender/blenkernel/intern/nla.c | 2 +- source/blender/blenkernel/intern/particle_system.c | 4 ++-- source/blender/blenkernel/intern/rigidbody.c | 6 +++--- source/blender/blenkernel/intern/softbody.c | 4 ++-- source/blender/blenkernel/intern/unit.c | 2 +- source/blender/python/intern/bpy_gizmo_wrap.h | 2 +- source/blender/python/intern/bpy_operator_wrap.h | 5 +++-- 16 files changed, 22 insertions(+), 21 deletions(-) diff --git a/intern/ghost/intern/GHOST_ContextGLX.cpp b/intern/ghost/intern/GHOST_ContextGLX.cpp index 93708983f37..d9f2df21ee0 100644 --- a/intern/ghost/intern/GHOST_ContextGLX.cpp +++ b/intern/ghost/intern/GHOST_ContextGLX.cpp @@ -140,7 +140,7 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext() /* End Inline GLEW. */ /* -------------------------------------------------------------------- */ #else - /* Important to initialize only glxew (_not_ GLEW), + /* Important to initialize only GLXEW (_not_ GLEW), * since this breaks w/ Mesa's `swrast`, see: T46431. */ glxewInit(); #endif /* USE_GLXEW_INIT_WORKAROUND */ diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h index 85c8ed7b4bd..cb6d8a770cf 100644 --- a/intern/ghost/intern/GHOST_ImeWin32.h +++ b/intern/ghost/intern/GHOST_ImeWin32.h @@ -266,7 +266,7 @@ class GHOST_ImeWin32 { * Parameters * * window_handle [in] (HWND) * Represents the window handle of the caller. - * * caret_rect [in] (const gfx::Rect&) + * * caret_rect [in] (`const gfx::Rect&`) * Represent the rectangle of the input caret. * This rectangle is used for controlling the positions of IME windows. * * complete [in] (bool) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 5afbf5b0b5f..67270d26ed3 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -101,7 +101,7 @@ static const struct GWL_RegistryHandler *gwl_registry_handler_from_interface_slo int interface_slot); /* -------------------------------------------------------------------- */ -/** \name Workaround Compositor Sprsific Bugs +/** \name Workaround Compositor Specific Bugs * \{ */ /** diff --git a/intern/guardedalloc/intern/leak_detector.cc b/intern/guardedalloc/intern/leak_detector.cc index 288d78fd206..5b565b15920 100644 --- a/intern/guardedalloc/intern/leak_detector.cc +++ b/intern/guardedalloc/intern/leak_detector.cc @@ -41,7 +41,7 @@ class MemLeakPrinter { if (fail_on_memleak) { /* There are many other ways to change the exit code to failure here: - * - Make the destructor noexcept(false) and throw an exception. + * - Make the destructor `noexcept(false)` and throw an exception. * - Call exit(EXIT_FAILURE). * - Call terminate(). */ diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 23cf368af01..3598201d906 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -59,7 +59,7 @@ void BKE_blender_free(void) { /* samples are in a global list..., also sets G_MAIN->sound->sample NULL */ - /* Needs to run before main free as wm is still referenced for icons preview jobs. */ + /* Needs to run before main free as window-manager is still referenced for icons preview jobs. */ BKE_studiolight_free(); BKE_blender_globals_clear(); diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index c84ee2e4a56..1ad7aeed41c 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -942,7 +942,7 @@ void BKE_gpencil_modifier_blend_read_data(BlendDataReader *reader, ListBase *lb) BLO_read_data_address(reader, &gpmd->curve_intensity); if (gpmd->curve_intensity) { BKE_curvemapping_blend_read(reader, gpmd->curve_intensity); - /* initialize the curve. Maybe this could be moved to modififer logic */ + /* Initialize the curve. Maybe this could be moved to modifier logic. */ BKE_curvemapping_init(gpmd->curve_intensity); } } diff --git a/source/blender/blenkernel/intern/icons.cc b/source/blender/blenkernel/intern/icons.cc index dc1d23de7e0..7fd0515b52c 100644 --- a/source/blender/blenkernel/intern/icons.cc +++ b/source/blender/blenkernel/intern/icons.cc @@ -530,7 +530,7 @@ void BKE_previewimg_ensure(PreviewImage *prv, const int size) thumb = IMB_thumb_manage(filepath, THB_LARGE, (ThumbSource)source); if (thumb) { - /* PreviewImage assumes premultiplied alhpa... */ + /* #PreviewImage assumes pre-multiplied alpha. */ IMB_premultiply_alpha(thumb); if (do_preview) { diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index bd655caae2b..a21033a8b91 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1147,7 +1147,7 @@ static char *get_rna_access(ID *id, /* 'buf' _must_ be initialized in this block */ /* append preceding bits to path */ - /* NOTE: strings are not escapted and they should be! */ + /* NOTE: strings are not escaped and they should be! */ if ((actname && actname[0]) && (constname && constname[0])) { /* Constraint in Pose-Channel */ char actname_esc[sizeof(((bActionChannel *)NULL)->name) * 2]; diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 158aaa961ce..f60234a684d 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -1612,7 +1612,7 @@ static void library_make_local_copying_check(ID *id, if (!BLI_gset_haskey(done_ids, from_id)) { if (BLI_gset_haskey(loop_tags, from_id)) { /* We are in a 'dependency loop' of IDs, this does not say us anything, skip it. - * Note that this is the situation that can lead to archipelagoes of linked data-blocks + * Note that this is the situation that can lead to archipelagos of linked data-blocks * (since all of them have non-local users, they would all be duplicated, * leading to a loop of unused linked data-blocks that cannot be freed since they all use * each other...). */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 326f239a95a..c0aff204069 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -2055,7 +2055,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt) } /* If block is already in tweak-mode, just leave, but we should report - * that this block is in tweak-mode (as our returncode). */ + * that this block is in tweak-mode (as our return-code). */ if (adt->flag & ADT_NLA_EDIT_ON) { return true; } diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 72733349087..7317318e828 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -1639,7 +1639,7 @@ static void sph_springs_modify(ParticleSystem *psys, float dtime) } } - /* Loop through springs backwaqrds - for efficient delete function */ + /* Loop through springs backwards - for efficient delete function. */ for (i = psys->tot_fluidsprings - 1; i >= 0; i--) { if (psys->fluid_springs[i].delete_flag) { sph_spring_delete(psys, i); @@ -4764,7 +4764,7 @@ void particle_system_update(struct Depsgraph *depsgraph, float cfra; ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); - /* drawdata is outdated after ANY change */ + /* Draw data is outdated after ANY change. */ if (psys->pdd) { psys->pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED; } diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index a67bb8568c3..5e91b23bce3 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -264,13 +264,13 @@ static RigidBodyCon *rigidbody_copy_constraint(const Object *ob, const int UNUSE RigidBodyCon *rbcN = NULL; if (ob->rigidbody_constraint) { - /* just duplicate the whole struct first (to catch all the settings) */ + /* Just duplicate the whole struct first (to catch all the settings). */ rbcN = MEM_dupallocN(ob->rigidbody_constraint); - /* tag object as needing to be verified */ + /* Tag object as needing to be verified. */ rbcN->flag |= RBC_FLAG_NEEDS_VALIDATE; - /* clear out all the fields which need to be revalidated later */ + /* Clear out all the fields which need to be re-validated later. */ rbcN->physics_constraint = NULL; } diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index be033f495c7..4147999bef8 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -318,7 +318,7 @@ static ccd_Mesh *ccd_mesh_make(Object *ob) /* OBBs for idea1 */ pccd_M->mima = MEM_mallocN(sizeof(ccdf_minmax) * pccd_M->tri_num, "ccd_Mesh_Faces_mima"); - /* anyhoo we need to walk the list of faces and find OBB they live in */ + /* Anyhow we need to walk the list of faces and find OBB they live in. */ for (i = 0, mima = pccd_M->mima, vt = pccd_M->tri; i < pccd_M->tri_num; i++, mima++, vt++) { const float *v; @@ -413,7 +413,7 @@ static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M) pccd_M->bbmax[2] = max_ff(pccd_M->bbmax[2], v[2] + hull); } - /* anyhoo we need to walk the list of faces and find OBB they live in */ + /* Anyhow we need to walk the list of faces and find OBB they live in. */ for (i = 0, mima = pccd_M->mima, vt = pccd_M->tri; i < pccd_M->tri_num; i++, mima++, vt++) { const float *v; diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index f7ea4c81fbf..f5badfc9e94 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -715,7 +715,7 @@ static const char *unit_find_str(const char *str, const char *substr, bool case_ /* Weak unicode support!, so "µm" won't match up be replaced by "m" * since non ascii utf8 values will NEVER return true */ isalpha_or_utf8(*BLI_str_find_prev_char_utf8(str_found, str)) == 0) { - /* Next char cannot be alphanum. */ + /* Next char cannot be alpha-numeric. */ int len_name = strlen(substr); if (!isalpha_or_utf8(*(str_found + len_name))) { diff --git a/source/blender/python/intern/bpy_gizmo_wrap.h b/source/blender/python/intern/bpy_gizmo_wrap.h index 6a876747e22..7d5edebed0f 100644 --- a/source/blender/python/intern/bpy_gizmo_wrap.h +++ b/source/blender/python/intern/bpy_gizmo_wrap.h @@ -13,7 +13,7 @@ struct wmGizmoType; extern "C" { #endif -/* exposed to rna/wm api */ +/* Exposed to RNA/WM API. */ void BPY_RNA_gizmo_wrapper(struct wmGizmoType *gzt, void *userdata); void BPY_RNA_gizmogroup_wrapper(struct wmGizmoGroupType *gzgt, void *userdata); diff --git a/source/blender/python/intern/bpy_operator_wrap.h b/source/blender/python/intern/bpy_operator_wrap.h index de3779332da..4b8ceba5f0c 100644 --- a/source/blender/python/intern/bpy_operator_wrap.h +++ b/source/blender/python/intern/bpy_operator_wrap.h @@ -12,10 +12,11 @@ struct wmOperatorType; extern "C" { #endif -/* these are used for operator methods, used by bpy_operator.c */ +/** These are used for operator methods, used by `bpy_operator.c`. */ PyObject *PYOP_wrap_macro_define(PyObject *self, PyObject *args); -/* exposed to rna/wm api */ +/* Exposed to RNA/WM API. */ + /** * Generic function used by all Python defined operators * it's passed as an argument to #WM_operatortype_append_ptr in for operator registration. -- cgit v1.2.3 From 5a90bbf71675651bd74cef435c0724e5b07a544c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 2 Nov 2022 10:18:40 +1100 Subject: Cleanup: format --- release/scripts/startup/bl_ui/node_add_menu.py | 2 ++ source/blender/gpu/vulkan/vk_framebuffer.cc | 2 +- source/blender/gpu/vulkan/vk_query.hh | 4 ++-- source/blender/gpu/vulkan/vk_shader.hh | 31 +++++++++++++------------- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/release/scripts/startup/bl_ui/node_add_menu.py b/release/scripts/startup/bl_ui/node_add_menu.py index d393dc04963..873dbd533a5 100644 --- a/release/scripts/startup/bl_ui/node_add_menu.py +++ b/release/scripts/startup/bl_ui/node_add_menu.py @@ -58,9 +58,11 @@ def draw_node_group_add_menu(context, layout): ops.name = "node_tree" ops.value = "bpy.data.node_groups[%r]" % group.name + def draw_assets_for_catalog(layout, catalog_path): layout.template_node_asset_menu_items(catalog_path=catalog_path) + def draw_root_assets(layout): layout.menu_contents("NODE_MT_node_add_root_catalogs") diff --git a/source/blender/gpu/vulkan/vk_framebuffer.cc b/source/blender/gpu/vulkan/vk_framebuffer.cc index 01a5f7c0f81..48b0685bf38 100644 --- a/source/blender/gpu/vulkan/vk_framebuffer.cc +++ b/source/blender/gpu/vulkan/vk_framebuffer.cc @@ -25,7 +25,7 @@ void VKFrameBuffer::clear(eGPUFrameBufferBits /*buffers*/, { } -void VKFrameBuffer::clear_multi(const float (* /*clear_col*/)[4]) +void VKFrameBuffer::clear_multi(const float (*/*clear_col*/)[4]) { } diff --git a/source/blender/gpu/vulkan/vk_query.hh b/source/blender/gpu/vulkan/vk_query.hh index 7f8f81e2b95..36558ef9549 100644 --- a/source/blender/gpu/vulkan/vk_query.hh +++ b/source/blender/gpu/vulkan/vk_query.hh @@ -15,8 +15,8 @@ class VKQueryPool : public QueryPool { public: void init(GPUQueryType type) override; void begin_query() override; - void end_query() override; - void get_occlusion_result(MutableSpan r_values) override; + void end_query() override; + void get_occlusion_result(MutableSpan r_values) override; }; } // namespace blender::gpu \ No newline at end of file diff --git a/source/blender/gpu/vulkan/vk_shader.hh b/source/blender/gpu/vulkan/vk_shader.hh index 1c09ef407ad..9ab0aca67eb 100644 --- a/source/blender/gpu/vulkan/vk_shader.hh +++ b/source/blender/gpu/vulkan/vk_shader.hh @@ -17,21 +17,22 @@ class VKShader : public Shader { { } - void vertex_shader_from_glsl(MutableSpan sources)override; - void geometry_shader_from_glsl(MutableSpan sources)override; - void fragment_shader_from_glsl(MutableSpan sources)override; - void compute_shader_from_glsl(MutableSpan sources)override; - bool finalize(const shader::ShaderCreateInfo *info = nullptr)override; - - void transform_feedback_names_set(Span name_list, eGPUShaderTFBType geom_type)override; - bool transform_feedback_enable(GPUVertBuf *)override; - void transform_feedback_disable()override; - - void bind()override; - void unbind()override; - - void uniform_float(int location, int comp_len, int array_size, const float *data)override; - void uniform_int(int location, int comp_len, int array_size, const int *data)override; + void vertex_shader_from_glsl(MutableSpan sources) override; + void geometry_shader_from_glsl(MutableSpan sources) override; + void fragment_shader_from_glsl(MutableSpan sources) override; + void compute_shader_from_glsl(MutableSpan sources) override; + bool finalize(const shader::ShaderCreateInfo *info = nullptr) override; + + void transform_feedback_names_set(Span name_list, + eGPUShaderTFBType geom_type) override; + bool transform_feedback_enable(GPUVertBuf *) override; + void transform_feedback_disable() override; + + void bind() override; + void unbind() override; + + void uniform_float(int location, int comp_len, int array_size, const float *data) override; + void uniform_int(int location, int comp_len, int array_size, const int *data) override; std::string resources_declare(const shader::ShaderCreateInfo &info) const override; std::string vertex_interface_declare(const shader::ShaderCreateInfo &info) const override; -- cgit v1.2.3 From db43aa772925d4f6bd311858cd1ee4fe9aebc4e8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 2 Nov 2022 14:07:54 +1100 Subject: Fix T102201: File selector shows "\" before folder names on WIN32 Regression in [0] on WIN32 caused joining paths {"//", "path"} to result in "//\path". This made the file selector show paths with a "\" prefix. Add an exception for WIN32 where an initial path of forward slashes is joined without a back-slash. [0]: 8f7ab1bf46d5e8610b167180b7631ff62e718a08 --- source/blender/blenlib/intern/path_util.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index f46c2e65395..7c08eeedaa2 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1500,6 +1500,27 @@ size_t BLI_path_join_array(char *__restrict dst, return ofs; } +#ifdef WIN32 + /* Special case "//" for relative paths, don't use separator #SEP + * as this has a special meaning on both WIN32 & UNIX. + * Without this check joining `"//", "path"`. results in `"//\path"`. */ + if (ofs != 0) { + size_t i; + for (i = 0; i < ofs; i++) { + if (dst[i] != '/') { + break; + } + } + if (i == ofs) { + /* All slashes, keep them as-is, and join the remaining path array. */ + return path_array_num > 1 ? + BLI_path_join_array( + dst + ofs, dst_len - ofs, &path_array[1], path_array_num - 1) : + ofs; + } + } +#endif + /* Remove trailing slashes, unless there are *only* trailing slashes * (allow `//` or `//some_path` as the first argument). */ bool has_trailing_slash = false; -- cgit v1.2.3 From 52664437fbf8f0c948a30c0cc385e292aa03f5c4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 2 Nov 2022 14:26:26 +1100 Subject: Cleanup: use doxy sections for path tests --- source/blender/blenlib/tests/BLI_path_util_test.cc | 105 +++++++++++++++++---- 1 file changed, 86 insertions(+), 19 deletions(-) diff --git a/source/blender/blenlib/tests/BLI_path_util_test.cc b/source/blender/blenlib/tests/BLI_path_util_test.cc index 93922b41b23..5d64de99ff6 100644 --- a/source/blender/blenlib/tests/BLI_path_util_test.cc +++ b/source/blender/blenlib/tests/BLI_path_util_test.cc @@ -9,9 +9,9 @@ #include "BLI_string.h" /* -------------------------------------------------------------------- */ -/* tests */ +/** \name Tests for: #BLI_path_normalize + * \{ */ -/* BLI_path_normalize */ #ifndef _WIN32 # define NORMALIZE_WITH_BASEDIR(input, input_base, output) \ @@ -57,9 +57,14 @@ TEST(path_util, Clean_Parent) # undef NORMALIZE_WITH_BASEDIR # undef NORMALIZE -#endif /* _WIN32 */ +#endif /* !_WIN32 */ + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Tests for: #BLI_path_parent_dir + * \{ */ -/* #BLI_path_parent_dir */ #ifndef _WIN32 TEST(path_util, ParentDir) { @@ -89,7 +94,13 @@ TEST(path_util, ParentDir) # undef PARENT_DIR } -#endif +#endif /* !_WIN32 */ + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Tests for: #BLI_path_name_at_index + * \{ */ #define AT_INDEX(str_input, index_input, str_expect) \ { \ @@ -113,7 +124,6 @@ TEST(path_util, ParentDir) } \ ((void)0) -/* BLI_path_name_at_index */ TEST(path_util, NameAtIndex_Single) { AT_INDEX("/a", 0, "a"); @@ -227,6 +237,12 @@ TEST(path_util, NameAtIndex_NoneComplexNeg) #undef AT_INDEX +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Tests for: #BLI_path_join + * \{ */ + /* For systems with `/` path separator (non WIN32). */ #define JOIN_FORWARD_SLASH(str_expect, out_size, ...) \ { \ @@ -274,7 +290,6 @@ TEST(path_util, NameAtIndex_NoneComplexNeg) # define JOIN JOIN_FORWARD_SLASH #endif -/* BLI_path_join */ TEST(path_util, JoinNop) { JOIN("", 100, ""); @@ -368,7 +383,12 @@ TEST(path_util, JoinRelativePrefix) #undef JOIN_BACK_SLASH #undef JOIN_FORWARD_SLASH -/* BLI_path_frame */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Tests for: #BLI_path_frame + * \{ */ + TEST(path_util, Frame) { bool ret; @@ -445,7 +465,12 @@ TEST(path_util, Frame) } } -/* BLI_split_dirfile */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Tests for: #BLI_split_dirfile + * \{ */ + TEST(path_util, SplitDirfile) { { @@ -501,6 +526,12 @@ TEST(path_util, SplitDirfile) } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Tests for: #BLI_path_frame_strip + * \{ */ + #define PATH_FRAME_STRIP(input_path, expect_path, expect_ext) \ { \ char path[FILE_MAX]; \ @@ -512,7 +543,6 @@ TEST(path_util, SplitDirfile) } \ ((void)0) -/* BLI_path_frame_strip */ TEST(path_util, PathFrameStrip) { PATH_FRAME_STRIP("", "", ""); @@ -524,6 +554,12 @@ TEST(path_util, PathFrameStrip) } #undef PATH_FRAME_STRIP +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Tests for: #BLI_path_extension_check + * \{ */ + #define PATH_EXTENSION_CHECK(input_path, input_ext, expect_ext) \ { \ const bool ret = BLI_path_extension_check(input_path, input_ext); \ @@ -536,7 +572,6 @@ TEST(path_util, PathFrameStrip) } \ ((void)0) -/* BLI_path_extension_check */ TEST(path_util, PathExtensionCheck) { PATH_EXTENSION_CHECK("a/b/c.exe", ".exe", ".exe"); @@ -562,6 +597,12 @@ TEST(path_util, PathExtensionCheck) } #undef PATH_EXTENSION_CHECK +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Tests for: #BLI_path_frame_check_chars + * \{ */ + #define PATH_FRAME_CHECK_CHARS(input_path, expect_hasChars) \ { \ const bool ret = BLI_path_frame_check_chars(input_path); \ @@ -574,7 +615,6 @@ TEST(path_util, PathExtensionCheck) } \ ((void)0) -/* BLI_path_frame_check_chars */ TEST(path_util, PathFrameCheckChars) { PATH_FRAME_CHECK_CHARS("a#", true); @@ -594,6 +634,12 @@ TEST(path_util, PathFrameCheckChars) } #undef PATH_FRAME_CHECK_CHARS +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Tests for: #BLI_path_frame_range + * \{ */ + #define PATH_FRAME_RANGE(input_path, sta, end, digits, expect_outpath) \ { \ char path[FILE_MAX]; \ @@ -610,7 +656,6 @@ TEST(path_util, PathFrameCheckChars) } \ ((void)0) -/* BLI_path_frame_range */ TEST(path_util, PathFrameRange) { int dummy = -1; @@ -626,6 +671,12 @@ TEST(path_util, PathFrameRange) } #undef PATH_FRAME_RANGE +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Tests for: #BLI_path_frame_get + * \{ */ + #define PATH_FRAME_GET(input_path, expect_frame, expect_numdigits, expect_pathisvalid) \ { \ char path[FILE_MAX]; \ @@ -643,7 +694,6 @@ TEST(path_util, PathFrameRange) } \ ((void)0) -/* BLI_path_frame_get */ TEST(path_util, PathFrameGet) { PATH_FRAME_GET("001.avi", 1, 3, true); @@ -655,7 +705,12 @@ TEST(path_util, PathFrameGet) } #undef PATH_FRAME_GET -/* BLI_path_extension */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Tests for: #BLI_path_extension + * \{ */ + TEST(path_util, PathExtension) { EXPECT_EQ(nullptr, BLI_path_extension("some.def/file")); @@ -669,7 +724,12 @@ TEST(path_util, PathExtension) EXPECT_STREQ(".001", BLI_path_extension("Text.001")); } -/* BLI_path_rel. */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Tests for: #BLI_path_rel + * \{ */ + #ifndef _WIN32 # define PATH_REL(abs_path, ref_path, rel_path) \ @@ -722,9 +782,14 @@ TEST(path_util, PathRelPath) # undef PATH_REL -#endif +#endif /* !_WIN32 */ + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Tests for: #BLI_path_contains + * \{ */ -/* BLI_path_contains */ TEST(path_util, PathContains) { EXPECT_TRUE(BLI_path_contains("/some/path", "/some/path")) << "A path contains itself"; @@ -753,4 +818,6 @@ TEST(path_util, PathContains_Windows_case_insensitive) EXPECT_TRUE(BLI_path_contains("C:\\some\\path", "c:\\SOME\\path\\inside")) << "On Windows path comparison should ignore case"; } -#endif +#endif /* WIN32 */ + +/** \} */ -- cgit v1.2.3 From 7f1e98839a79ef8c5d08b53e01b3d01302a2e419 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 2 Nov 2022 16:15:48 +1100 Subject: Tests: enable path tests for WIN32 Tests for BLI_path_normalize, BLI_path_parent_dir & BLI_path_rel were disabled on WIN32 because of complications with slash direction. Enable these tests using character replacement to manipulate test data. --- source/blender/blenlib/tests/BLI_path_util_test.cc | 191 +++++++++++++-------- 1 file changed, 124 insertions(+), 67 deletions(-) diff --git a/source/blender/blenlib/tests/BLI_path_util_test.cc b/source/blender/blenlib/tests/BLI_path_util_test.cc index 5d64de99ff6..379ff432988 100644 --- a/source/blender/blenlib/tests/BLI_path_util_test.cc +++ b/source/blender/blenlib/tests/BLI_path_util_test.cc @@ -9,20 +9,59 @@ #include "BLI_string.h" /* -------------------------------------------------------------------- */ -/** \name Tests for: #BLI_path_normalize +/** \name Local Utilities * \{ */ -#ifndef _WIN32 +static void str_replace_char_with_relative_exception(char *str, char src, char dst) +{ + /* Always keep "//" or more leading slashes (special meaning). */ + if (src == '/') { + if (str[0] == '/' && str[1] == '/') { + str += 2; + while (*str == '/') { + str++; + } + } + } + BLI_str_replace_char(str, src, dst); +} + +static char *str_replace_char_strdup(const char *str, char src, char dst) +{ + if (str == nullptr) { + return nullptr; + } + char *str_dupe = strdup(str); + BLI_str_replace_char(str_dupe, src, dst); + return str_dupe; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Tests for: #BLI_path_normalize + * \{ */ -# define NORMALIZE_WITH_BASEDIR(input, input_base, output) \ - { \ - char path[FILE_MAX] = input; \ - BLI_path_normalize(input_base, path); \ - EXPECT_STREQ(output, path); \ +#define NORMALIZE_WITH_BASEDIR(input, input_base, output) \ + { \ + char path[FILE_MAX] = input; \ + const char *input_base_test = input_base; \ + if (SEP == '\\') { \ + str_replace_char_with_relative_exception(path, '/', '\\'); \ + input_base_test = str_replace_char_strdup(input_base_test, '/', '\\'); \ } \ - ((void)0) + BLI_path_normalize(input_base_test, path); \ + if (SEP == '\\') { \ + BLI_str_replace_char(path, '\\', '/'); \ + if (input_base_test) { \ + free((void *)input_base_test); \ + } \ + } \ + EXPECT_STREQ(output, path); \ + } \ + ((void)0) -# define NORMALIZE(input, output) NORMALIZE_WITH_BASEDIR(input, nullptr, output) +#define NORMALIZE(input, output) NORMALIZE_WITH_BASEDIR(input, nullptr, output) /* #BLI_path_normalize: "/./" -> "/" */ TEST(path_util, Clean_Dot) @@ -54,10 +93,8 @@ TEST(path_util, Clean_Parent) NORMALIZE_WITH_BASEDIR("//../", "/a/b/c/", "/a/b/"); } -# undef NORMALIZE_WITH_BASEDIR -# undef NORMALIZE - -#endif /* !_WIN32 */ +#undef NORMALIZE_WITH_BASEDIR +#undef NORMALIZE /** \} */ @@ -65,16 +102,21 @@ TEST(path_util, Clean_Parent) /** \name Tests for: #BLI_path_parent_dir * \{ */ -#ifndef _WIN32 TEST(path_util, ParentDir) { -# define PARENT_DIR(input, output) \ - { \ - char path[FILE_MAX] = input; \ - BLI_path_parent_dir(path); \ - EXPECT_STREQ(output, path); \ +#define PARENT_DIR(input, output) \ + { \ + char path[FILE_MAX] = input; \ + if (SEP == '\\') { \ + BLI_str_replace_char(path, '/', '\\'); \ } \ - ((void)0) + BLI_path_parent_dir(path); \ + if (SEP == '\\') { \ + BLI_str_replace_char(path, '\\', '/'); \ + } \ + EXPECT_STREQ(output, path); \ + } \ + ((void)0) PARENT_DIR("/a/b/", "/a/"); PARENT_DIR("/a/b", "/a/"); @@ -92,9 +134,8 @@ TEST(path_util, ParentDir) PARENT_DIR("/a./b./c./", "/a./b./"); PARENT_DIR("/a./b./c.", "/a./b./"); -# undef PARENT_DIR +#undef PARENT_DIR } -#endif /* !_WIN32 */ /** \} */ @@ -730,59 +771,75 @@ TEST(path_util, PathExtension) /** \name Tests for: #BLI_path_rel * \{ */ -#ifndef _WIN32 - -# define PATH_REL(abs_path, ref_path, rel_path) \ - { \ - char path[FILE_MAX]; \ - BLI_strncpy(path, abs_path, sizeof(path)); \ - BLI_path_rel(path, ref_path); \ - EXPECT_STREQ(rel_path, path); \ +#define PATH_REL(abs_path, ref_path, rel_path) \ + { \ + char path[FILE_MAX]; \ + const char *ref_path_test = ref_path; \ + BLI_strncpy(path, abs_path, sizeof(path)); \ + if (SEP == '\\') { \ + BLI_str_replace_char(path, '/', '\\'); \ + ref_path_test = str_replace_char_strdup(ref_path_test, '/', '\\'); \ + } \ + BLI_path_rel(path, ref_path_test); \ + if (SEP == '\\') { \ + BLI_str_replace_char(path, '\\', '/'); \ + free((void *)ref_path_test); \ } \ - void(0) + EXPECT_STREQ(rel_path, path); \ + } \ + void(0) + +#ifdef WIN32 +# define ABS_PREFIX "C:" +#else +# define ABS_PREFIX "" +#endif + +TEST(path_util, PathRelPath_Simple) +{ + PATH_REL(ABS_PREFIX "/foo/bar/blender.blend", ABS_PREFIX "/foo/bar/", "//blender.blend"); +} -TEST(path_util, PathRelPath) +TEST(path_util, PathRelPath_SimpleSubdir) { - PATH_REL("/foo/bar/blender.blend", "/foo/bar/", "//blender.blend"); - PATH_REL("/foo/bar/blender.blend", "/foo/bar", "//bar/blender.blend"); + PATH_REL(ABS_PREFIX "/foo/bar/blender.blend", ABS_PREFIX "/foo/bar", "//bar/blender.blend"); +} - /* Check for potential buffer overflows. */ - { - char abs_path_in[FILE_MAX]; - abs_path_in[0] = '/'; - for (int i = 1; i < FILE_MAX - 1; i++) { - abs_path_in[i] = 'A'; - } - abs_path_in[FILE_MAX - 1] = '\0'; - char abs_path_out[FILE_MAX]; - abs_path_out[0] = '/'; - abs_path_out[1] = '/'; - for (int i = 2; i < FILE_MAX - 1; i++) { - abs_path_out[i] = 'A'; - } - abs_path_out[FILE_MAX - 1] = '\0'; - PATH_REL(abs_path_in, "/", abs_path_out); - - const char *ref_path_in = "/foo/bar/"; - const size_t ref_path_in_len = strlen(ref_path_in); - strcpy(abs_path_in, ref_path_in); - for (int i = ref_path_in_len; i < FILE_MAX - 1; i++) { - abs_path_in[i] = 'A'; - } - abs_path_in[FILE_MAX - 1] = '\0'; - abs_path_out[0] = '/'; - abs_path_out[1] = '/'; - for (int i = 2; i < FILE_MAX - (int(ref_path_in_len) - 1); i++) { - abs_path_out[i] = 'A'; - } - abs_path_out[FILE_MAX - (ref_path_in_len - 1)] = '\0'; - PATH_REL(abs_path_in, ref_path_in, abs_path_out); +TEST(path_util, PathRelPath_BufferOverflowRoot) +{ + char abs_path_in[FILE_MAX]; + const char *abs_prefix = ABS_PREFIX "/"; + for (int i = STRNCPY_RLEN(abs_path_in, abs_prefix); i < FILE_MAX - 1; i++) { + abs_path_in[i] = 'A'; } + abs_path_in[FILE_MAX - 1] = '\0'; + char abs_path_out[FILE_MAX]; + for (int i = STRNCPY_RLEN(abs_path_out, "//"); i < FILE_MAX - 1; i++) { + abs_path_out[i] = 'A'; + } + abs_path_out[FILE_MAX - std::max((strlen(abs_prefix) - 1), size_t(1))] = '\0'; + PATH_REL(abs_path_in, abs_prefix, abs_path_out); } -# undef PATH_REL +TEST(path_util, PathRelPath_BufferOverflowSubdir) +{ + char abs_path_in[FILE_MAX]; + const char *ref_path_in = ABS_PREFIX "/foo/bar/"; + const size_t ref_path_in_len = strlen(ref_path_in); + for (int i = STRNCPY_RLEN(abs_path_in, ref_path_in); i < FILE_MAX - 1; i++) { + abs_path_in[i] = 'A'; + } + abs_path_in[FILE_MAX - 1] = '\0'; + char abs_path_out[FILE_MAX]; + for (int i = STRNCPY_RLEN(abs_path_out, "//"); i < FILE_MAX - (int(ref_path_in_len) - 1); i++) { + abs_path_out[i] = 'A'; + } + abs_path_out[FILE_MAX - std::max((ref_path_in_len - 1), size_t(1))] = '\0'; + PATH_REL(abs_path_in, ref_path_in, abs_path_out); +} -#endif /* !_WIN32 */ +#undef PATH_REL +#undef ABS_PREFIX /** \} */ -- cgit v1.2.3 From 638bf05a23e1ef7dddd3b5d42d9521d8849a4375 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 2 Nov 2022 16:56:37 +1100 Subject: Fix BLI_path_parent_dir returning success with a single period as input While relatively harmless, BLI_path_parent_dir wasn't returning failure when passed in "./" which wouldn't succeed. Instead of adding a ".." and normalizing, normalize the path and remove the last directly. This is simpler than inspecting the resulting path to see if normalize removed it or not. Add additional tests which failed previously. --- source/blender/blenlib/intern/path_util.c | 18 ++++++++++------ source/blender/blenlib/tests/BLI_path_util_test.cc | 25 +++++++++++++++++++--- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 7c08eeedaa2..3a87b39a446 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -626,10 +626,9 @@ bool BLI_path_suffix(char *string, size_t maxlen, const char *suffix, const char bool BLI_path_parent_dir(char *path) { - const char parent_dir[] = {'.', '.', SEP, '\0'}; /* "../" or "..\\" */ - char tmp[FILE_MAX + 4]; + char tmp[FILE_MAX]; - BLI_path_join(tmp, sizeof(tmp), path, parent_dir); + STRNCPY(tmp, path); /* Does all the work of normalizing the path for us. * * NOTE(@campbellbarton): While it's possible strip text after the second last slash, @@ -645,12 +644,19 @@ bool BLI_path_parent_dir(char *path) * which would cause checking for a tailing `/../` fail. * Extracting the span of the final directory avoids both these issues. */ int tail_ofs = 0, tail_len = 0; - if (BLI_path_name_at_index(tmp, -1, &tail_ofs, &tail_len) && (tail_len == 2) && - (memcmp(&tmp[tail_ofs], "..", 2) == 0)) { + if (!BLI_path_name_at_index(tmp, -1, &tail_ofs, &tail_len)) { return false; } + if (tail_len == 1) { + /* Last path is ".", as normalize should remove this, it's safe to assume failure. + * This happens when the input a single period (possibly with slashes before or after). */ + if (tmp[tail_ofs] == '.') { + return false; + } + } - strcpy(path, tmp); /* We assume the parent directory is always shorter. */ + memcpy(path, tmp, tail_ofs); + path[tail_ofs] = '\0'; return true; } diff --git a/source/blender/blenlib/tests/BLI_path_util_test.cc b/source/blender/blenlib/tests/BLI_path_util_test.cc index 379ff432988..293d353efcc 100644 --- a/source/blender/blenlib/tests/BLI_path_util_test.cc +++ b/source/blender/blenlib/tests/BLI_path_util_test.cc @@ -102,8 +102,6 @@ TEST(path_util, Clean_Parent) /** \name Tests for: #BLI_path_parent_dir * \{ */ -TEST(path_util, ParentDir) -{ #define PARENT_DIR(input, output) \ { \ char path[FILE_MAX] = input; \ @@ -118,12 +116,25 @@ TEST(path_util, ParentDir) } \ ((void)0) +TEST(path_util, ParentDir_Simple) +{ PARENT_DIR("/a/b/", "/a/"); PARENT_DIR("/a/b", "/a/"); PARENT_DIR("/a", "/"); +} + +TEST(path_util, ParentDir_NOP) +{ PARENT_DIR("/", "/"); PARENT_DIR("", ""); + PARENT_DIR(".", "."); + PARENT_DIR("./", "./"); + PARENT_DIR(".//", ".//"); + PARENT_DIR("./.", "./."); +} +TEST(path_util, ParentDir_TrailingPeriod) +{ /* Ensure trailing dots aren't confused with parent path. */ PARENT_DIR("/.../.../.../", "/.../.../"); PARENT_DIR("/.../.../...", "/.../.../"); @@ -133,10 +144,18 @@ TEST(path_util, ParentDir) PARENT_DIR("/a./b./c./", "/a./b./"); PARENT_DIR("/a./b./c.", "/a./b./"); +} -#undef PARENT_DIR +TEST(path_util, ParentDir_Complex) +{ + PARENT_DIR("./a/", "./"); + PARENT_DIR("./a", "./"); + PARENT_DIR("../a/", "../"); + PARENT_DIR("../a", "../"); } +#undef PARENT_DIR + /** \} */ /* -------------------------------------------------------------------- */ -- cgit v1.2.3 From 460c9d3d92e9f74254d58c6bb07d7e4fcb53e8b7 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 2 Nov 2022 11:50:42 +0100 Subject: Fix use-after-free in asset library storage destruction Would only appear when more than 4 asset libraries were loaded, because small buffer optimization would hide the issue. --- source/blender/editors/asset/intern/asset_list.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/asset/intern/asset_list.cc b/source/blender/editors/asset/intern/asset_list.cc index 01a6dc46c48..bb72c5cc1bb 100644 --- a/source/blender/editors/asset/intern/asset_list.cc +++ b/source/blender/editors/asset/intern/asset_list.cc @@ -351,7 +351,7 @@ void AssetListStorage::fetch_library(const AssetLibraryReference &library_refere void AssetListStorage::destruct() { - global_storage().~AssetListMap(); + global_storage().clear(); } AssetList *AssetListStorage::lookup_list(const AssetLibraryReference &library_ref) -- cgit v1.2.3 From 5f7ca5462d31ff56f16016d5f9e6a5489b30a05e Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 2 Nov 2022 12:29:01 +0100 Subject: Geometry Nodes: Add index and value inputs to sample curve node As described in T92474 and T91650, this patch adds two features to the sample curve node. First is an index input, to allow choosing the curve to sample for each point. Second is a custom field input, which is evaluated on the control points of the curve and then sampled like the other outputs. There is an "All Curves" option for the old behavior which takes the length of all curves into account. For invalid curve indices, the node outputs zeros (default values). Invalid lengths and factors are clamped. There have been various discussions about splitting the node up more, but this is an intuitive combination of options and will work well enough for current use cases. The node could still be generalized more in the future. Keep in mind that the source field is evaluated on curve control points, not the evaluated points used for sampling. This is necessary so that fields like "Index" work as expected. Differential Revision: https://developer.blender.org/D16147 --- source/blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenloader/intern/versioning_300.cc | 19 ++ source/blender/makesdna/DNA_node_types.h | 4 + source/blender/makesrna/intern/rna_nodetree.c | 18 +- .../nodes/geometry/nodes/node_geo_curve_sample.cc | 336 ++++++++++++++++----- 5 files changed, 309 insertions(+), 70 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 806fff2099e..1a642cf4eb3 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -25,7 +25,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 5 +#define BLENDER_FILE_SUBVERSION 6 /* 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/blenloader/intern/versioning_300.cc b/source/blender/blenloader/intern/versioning_300.cc index a2bd7fd2fd1..65094655cfe 100644 --- a/source/blender/blenloader/intern/versioning_300.cc +++ b/source/blender/blenloader/intern/versioning_300.cc @@ -3653,6 +3653,25 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) } } + if (!MAIN_VERSION_ATLEAST(bmain, 304, 6)) { + LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) { + if (ntree->type != NTREE_GEOMETRY) { + continue; + } + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->type != GEO_NODE_SAMPLE_CURVE) { + continue; + } + static_cast(node->storage)->use_all_curves = true; + static_cast(node->storage)->data_type = CD_PROP_FLOAT; + bNodeSocket *curve_socket = nodeFindSocket(node, SOCK_IN, "Curve"); + BLI_assert(curve_socket != nullptr); + STRNCPY(curve_socket->name, "Curves"); + STRNCPY(curve_socket->identifier, "Curves"); + } + } + } + /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 74714cf7e41..0b7c17d44bb 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1497,6 +1497,10 @@ typedef struct NodeGeometryCurveToPoints { typedef struct NodeGeometryCurveSample { /* GeometryNodeCurveSampleMode. */ uint8_t mode; + int8_t use_all_curves; + /* eCustomDataType. */ + int8_t data_type; + char _pad[1]; } NodeGeometryCurveSample; typedef struct NodeGeometryTransferAttribute { diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 865399df9ef..7457267a83c 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -9442,10 +9442,26 @@ static void def_geo_curve_sample(StructRNA *srna) RNA_def_struct_sdna_from(srna, "NodeGeometryCurveSample", "storage"); - PropertyRNA *prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + PropertyRNA *prop; + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, mode_items); RNA_def_property_ui_text(prop, "Mode", "Method for sampling input"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); + + prop = RNA_def_property(srna, "use_all_curves", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_ui_text(prop, + "All Curves", + "Sample lengths based on the total lengh of all curves, rather than " + "using a length inside each selected curve"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); + + prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_attribute_type_items); + RNA_def_property_enum_funcs( + prop, NULL, NULL, "rna_GeometryNodeAttributeType_type_with_socket_itemf"); + RNA_def_property_enum_default(prop, CD_PROP_FLOAT); + RNA_def_property_ui_text(prop, "Data Type", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } static void def_geo_triangulate(StructRNA *srna) diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc index 27e111822bf..2b732bba889 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ #include "BLI_devirtualize_parameters.hh" +#include "BLI_generic_array.hh" #include "BLI_length_parameterize.hh" #include "BKE_curves.hh" @@ -8,6 +9,8 @@ #include "UI_interface.h" #include "UI_resources.h" +#include "NOD_socket_search_link.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_curve_sample_cc { @@ -16,9 +19,16 @@ NODE_STORAGE_FUNCS(NodeGeometryCurveSample) static void node_declare(NodeDeclarationBuilder &b) { - b.add_input(N_("Curve")) + b.add_input(N_("Curves")) .only_realized_data() .supported_type(GEO_COMPONENT_TYPE_CURVE); + + b.add_input(N_("Value"), "Value_Float").hide_value().supports_field(); + b.add_input(N_("Value"), "Value_Int").hide_value().supports_field(); + b.add_input(N_("Value"), "Value_Vector").hide_value().supports_field(); + b.add_input(N_("Value"), "Value_Color").hide_value().supports_field(); + b.add_input(N_("Value"), "Value_Bool").hide_value().supports_field(); + b.add_input(N_("Factor")) .min(0.0f) .max(1.0f) @@ -30,6 +40,16 @@ static void node_declare(NodeDeclarationBuilder &b) .subtype(PROP_DISTANCE) .supports_field() .make_available([](bNode &node) { node_storage(node).mode = GEO_NODE_CURVE_SAMPLE_LENGTH; }); + b.add_input(N_("Curve Index")).supports_field().make_available([](bNode &node) { + node_storage(node).use_all_curves = false; + }); + + b.add_output(N_("Value"), "Value_Float").dependent_field(); + b.add_output(N_("Value"), "Value_Int").dependent_field(); + b.add_output(N_("Value"), "Value_Vector").dependent_field(); + b.add_output(N_("Value"), "Value_Color").dependent_field(); + b.add_output(N_("Value"), "Value_Bool").dependent_field(); + b.add_output(N_("Position")).dependent_field(); b.add_output(N_("Tangent")).dependent_field(); b.add_output(N_("Normal")).dependent_field(); @@ -37,13 +57,17 @@ static void node_declare(NodeDeclarationBuilder &b) static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) { + uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE); uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); + uiItemR(layout, ptr, "use_all_curves", 0, nullptr, ICON_NONE); } static void node_type_init(bNodeTree * /*tree*/, bNode *node) { NodeGeometryCurveSample *data = MEM_cnew(__func__); - data->mode = GEO_NODE_CURVE_SAMPLE_LENGTH; + data->mode = GEO_NODE_CURVE_SAMPLE_FACTOR; + data->use_all_curves = false; + data->data_type = CD_PROP_FLOAT; node->storage = data; } @@ -51,16 +75,62 @@ static void node_update(bNodeTree *ntree, bNode *node) { const NodeGeometryCurveSample &storage = node_storage(*node); const GeometryNodeCurveSampleMode mode = (GeometryNodeCurveSampleMode)storage.mode; + const eCustomDataType data_type = eCustomDataType(storage.data_type); + + bNodeSocket *in_socket_float = static_cast(node->inputs.first)->next; + bNodeSocket *in_socket_int32 = in_socket_float->next; + bNodeSocket *in_socket_vector = in_socket_int32->next; + bNodeSocket *in_socket_color4f = in_socket_vector->next; + bNodeSocket *in_socket_bool = in_socket_color4f->next; - bNodeSocket *factor = static_cast(node->inputs.first)->next; + bNodeSocket *factor = in_socket_bool->next; bNodeSocket *length = factor->next; + bNodeSocket *curve_index = length->next; nodeSetSocketAvailability(ntree, factor, mode == GEO_NODE_CURVE_SAMPLE_FACTOR); nodeSetSocketAvailability(ntree, length, mode == GEO_NODE_CURVE_SAMPLE_LENGTH); + nodeSetSocketAvailability(ntree, curve_index, !storage.use_all_curves); + + nodeSetSocketAvailability(ntree, in_socket_vector, data_type == CD_PROP_FLOAT3); + nodeSetSocketAvailability(ntree, in_socket_float, data_type == CD_PROP_FLOAT); + nodeSetSocketAvailability(ntree, in_socket_color4f, data_type == CD_PROP_COLOR); + nodeSetSocketAvailability(ntree, in_socket_bool, data_type == CD_PROP_BOOL); + nodeSetSocketAvailability(ntree, in_socket_int32, data_type == CD_PROP_INT32); + + bNodeSocket *out_socket_float = static_cast(node->outputs.first); + bNodeSocket *out_socket_int32 = out_socket_float->next; + bNodeSocket *out_socket_vector = out_socket_int32->next; + bNodeSocket *out_socket_color4f = out_socket_vector->next; + bNodeSocket *out_socket_bool = out_socket_color4f->next; + + nodeSetSocketAvailability(ntree, out_socket_vector, data_type == CD_PROP_FLOAT3); + nodeSetSocketAvailability(ntree, out_socket_float, data_type == CD_PROP_FLOAT); + nodeSetSocketAvailability(ntree, out_socket_color4f, data_type == CD_PROP_COLOR); + nodeSetSocketAvailability(ntree, out_socket_bool, data_type == CD_PROP_BOOL); + nodeSetSocketAvailability(ntree, out_socket_int32, data_type == CD_PROP_INT32); +} + +static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) +{ + const NodeDeclaration &declaration = *params.node_type().fixed_declaration; + search_link_ops_for_declarations(params, declaration.inputs().take_front(4)); + search_link_ops_for_declarations(params, declaration.outputs().take_front(3)); + + const std::optional type = node_data_type_to_custom_data_type( + eNodeSocketDatatype(params.other_socket().type)); + if (type && *type != CD_PROP_STRING) { + /* The input and output sockets have the same name. */ + params.add_item(IFACE_("Value"), [type](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("GeometryNodeSampleCurve"); + node_storage(node).data_type = *type; + params.update_and_connect_available_socket(node, "Value"); + }); + } } static void sample_indices_and_lengths(const Span accumulated_lengths, const Span sample_lengths, + const GeometryNodeCurveSampleMode length_mode, const IndexMask mask, MutableSpan r_segment_indices, MutableSpan r_length_in_segment) @@ -70,10 +140,13 @@ static void sample_indices_and_lengths(const Span accumulated_lengths, mask.to_best_mask_type([&](const auto mask) { for (const int64_t i : mask) { + const float sample_length = length_mode == GEO_NODE_CURVE_SAMPLE_FACTOR ? + sample_lengths[i] * total_length : + sample_lengths[i]; int segment_i; float factor_in_segment; length_parameterize::sample_at_length(accumulated_lengths, - std::clamp(sample_lengths[i], 0.0f, total_length), + std::clamp(sample_length, 0.0f, total_length), segment_i, factor_in_segment, &hint); @@ -89,6 +162,7 @@ static void sample_indices_and_lengths(const Span accumulated_lengths, static void sample_indices_and_factors_to_compressed(const Span accumulated_lengths, const Span sample_lengths, + const GeometryNodeCurveSampleMode length_mode, const IndexMask mask, MutableSpan r_segment_indices, MutableSpan r_factor_in_segment) @@ -96,16 +170,32 @@ static void sample_indices_and_factors_to_compressed(const Span accumulat const float total_length = accumulated_lengths.last(); length_parameterize::SampleSegmentHint hint; - mask.to_best_mask_type([&](const auto mask) { - for (const int64_t i : IndexRange(mask.size())) { - const float length = sample_lengths[mask[i]]; - length_parameterize::sample_at_length(accumulated_lengths, - std::clamp(length, 0.0f, total_length), - r_segment_indices[i], - r_factor_in_segment[i], - &hint); - } - }); + switch (length_mode) { + case GEO_NODE_CURVE_SAMPLE_FACTOR: + mask.to_best_mask_type([&](const auto mask) { + for (const int64_t i : IndexRange(mask.size())) { + const float length = sample_lengths[mask[i]] * total_length; + length_parameterize::sample_at_length(accumulated_lengths, + std::clamp(length, 0.0f, total_length), + r_segment_indices[i], + r_factor_in_segment[i], + &hint); + } + }); + break; + case GEO_NODE_CURVE_SAMPLE_LENGTH: + mask.to_best_mask_type([&](const auto mask) { + for (const int64_t i : IndexRange(mask.size())) { + const float length = sample_lengths[mask[i]]; + length_parameterize::sample_at_length(accumulated_lengths, + std::clamp(length, 0.0f, total_length), + r_segment_indices[i], + r_factor_in_segment[i], + &hint); + } + }); + break; + } } /** @@ -115,10 +205,12 @@ static void sample_indices_and_factors_to_compressed(const Span accumulat class SampleFloatSegmentsFunction : public fn::MultiFunction { private: Array accumulated_lengths_; + GeometryNodeCurveSampleMode length_mode_; public: - SampleFloatSegmentsFunction(Array accumulated_lengths) - : accumulated_lengths_(std::move(accumulated_lengths)) + SampleFloatSegmentsFunction(Array accumulated_lengths, + const GeometryNodeCurveSampleMode length_mode) + : accumulated_lengths_(std::move(accumulated_lengths)), length_mode_(length_mode) { static fn::MFSignature signature = create_signature(); this->set_signature(&signature); @@ -141,7 +233,8 @@ class SampleFloatSegmentsFunction : public fn::MultiFunction { MutableSpan lengths_in_segments = params.uninitialized_single_output( 2, "Length in Curve"); - sample_indices_and_lengths(accumulated_lengths_, lengths, mask, indices, lengths_in_segments); + sample_indices_and_lengths( + accumulated_lengths_, lengths, length_mode_, mask, indices, lengths_in_segments); } }; @@ -153,15 +246,27 @@ class SampleCurveFunction : public fn::MultiFunction { * that the curve is not freed before the function can execute. */ GeometrySet geometry_set_; + GField src_field_; + GeometryNodeCurveSampleMode length_mode_; + + fn::MFSignature signature_; + + std::optional source_context_; + std::unique_ptr source_evaluator_; + const GVArray *source_data_; public: - SampleCurveFunction(GeometrySet geometry_set) : geometry_set_(std::move(geometry_set)) + SampleCurveFunction(GeometrySet geometry_set, + const GeometryNodeCurveSampleMode length_mode, + const GField &src_field) + : geometry_set_(std::move(geometry_set)), src_field_(src_field), length_mode_(length_mode) { - static fn::MFSignature signature = create_signature(); - this->set_signature(&signature); + signature_ = create_signature(); + this->set_signature(&signature_); + this->evaluate_source(); } - static fn::MFSignature create_signature() + fn::MFSignature create_signature() { blender::fn::MFSignatureBuilder signature{"Sample Curve"}; signature.single_input("Curve Index"); @@ -169,6 +274,7 @@ class SampleCurveFunction : public fn::MultiFunction { signature.single_output("Position"); signature.single_output("Tangent"); signature.single_output("Normal"); + signature.single_output("Value", src_field_.cpp_type()); return signature.build(); } @@ -180,6 +286,7 @@ class SampleCurveFunction : public fn::MultiFunction { 3, "Tangent"); MutableSpan sampled_normals = params.uninitialized_single_output_if_required( 4, "Normal"); + GMutableSpan sampled_values = params.uninitialized_single_output_if_required(5, "Value"); auto return_default = [&]() { if (!sampled_positions.is_empty()) { @@ -218,18 +325,40 @@ class SampleCurveFunction : public fn::MultiFunction { Array indices; Array factors; + GArray<> src_original_values(source_data_->type()); + GArray<> src_evaluated_values(source_data_->type()); + + auto fill_invalid = [&](const IndexMask mask) { + if (!sampled_positions.is_empty()) { + sampled_positions.fill_indices(mask, float3(0)); + } + if (!sampled_tangents.is_empty()) { + sampled_tangents.fill_indices(mask, float3(0)); + } + if (!sampled_normals.is_empty()) { + sampled_normals.fill_indices(mask, float3(0)); + } + if (!sampled_values.is_empty()) { + attribute_math::convert_to_static_type(source_data_->type(), [&](auto dummy) { + using T = decltype(dummy); + sampled_values.typed().fill_indices(mask, {}); + }); + } + }; auto sample_curve = [&](const int curve_i, const IndexMask mask) { + const Span accumulated_lengths = curves.evaluated_lengths_for_curve(curve_i, + cyclic[curve_i]); + if (accumulated_lengths.is_empty()) { + fill_invalid(mask); + return; + } /* Store the sampled indices and factors in arrays the size of the mask. * Then, during interpolation, move the results back to the masked indices. */ indices.reinitialize(mask.size()); factors.reinitialize(mask.size()); sample_indices_and_factors_to_compressed( - curves.evaluated_lengths_for_curve(curve_i, cyclic[curve_i]), - lengths, - mask, - indices, - factors); + accumulated_lengths, lengths, length_mode_, mask, indices, factors); const IndexRange evaluated_points = curves.evaluated_points_for_curve(curve_i); if (!sampled_positions.is_empty()) { @@ -254,54 +383,67 @@ class SampleCurveFunction : public fn::MultiFunction { sampled_normals[i] = math::normalize(sampled_normals[i]); } } + if (!sampled_values.is_empty()) { + const IndexRange points = curves.points_for_curve(curve_i); + src_original_values.reinitialize(points.size()); + source_data_->materialize_compressed_to_uninitialized(points, src_original_values.data()); + src_evaluated_values.reinitialize(curves.evaluated_points_for_curve(curve_i).size()); + curves.interpolate_to_evaluated(curve_i, src_original_values, src_evaluated_values); + attribute_math::convert_to_static_type(source_data_->type(), [&](auto dummy) { + using T = decltype(dummy); + const Span src_evaluated_values_typed = src_evaluated_values.as_span().typed(); + MutableSpan sampled_values_typed = sampled_values.typed(); + length_parameterize::interpolate_to_masked( + src_evaluated_values_typed, indices, factors, mask, sampled_values_typed); + }); + } }; - if (curve_indices.is_single()) { - sample_curve(curve_indices.get_internal_single(), mask); + if (const std::optional curve_i = curve_indices.get_if_single()) { + if (curves.curves_range().contains(*curve_i)) { + sample_curve(*curve_i, mask); + } + else { + fill_invalid(mask); + } } else { + Vector invalid_indices; MultiValueMap indices_per_curve; devirtualize_varray(curve_indices, [&](const auto curve_indices) { for (const int64_t i : mask) { - indices_per_curve.add(curve_indices[i], i); + const int curve_i = curve_indices[i]; + if (curves.curves_range().contains(curve_i)) { + indices_per_curve.add(curve_i, i); + } + else { + invalid_indices.append(i); + } } }); for (const int curve_i : indices_per_curve.keys()) { sample_curve(curve_i, IndexMask(indices_per_curve.lookup(curve_i))); } + fill_invalid(IndexMask(invalid_indices)); } } -}; -/** - * Pre-process the lengths or factors used for the sampling, turning factors into lengths, and - * clamping between zero and the total length of the curves. Do this as a separate operation in the - * field tree to make the sampling simpler, and to let the evaluator optimize better. - * - * \todo Use a mutable single input instead when they are supported. - */ -static Field get_length_input_field(GeoNodeExecParams params, - const GeometryNodeCurveSampleMode mode, - const float curves_total_length) -{ - if (mode == GEO_NODE_CURVE_SAMPLE_LENGTH) { - return params.extract_input>("Length"); + private: + void evaluate_source() + { + const Curves &curves_id = *geometry_set_.get_curves_for_read(); + const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); + source_context_.emplace(bke::CurvesFieldContext{curves, ATTR_DOMAIN_POINT}); + source_evaluator_ = std::make_unique(*source_context_, curves.points_num()); + source_evaluator_->add(src_field_); + source_evaluator_->evaluate(); + source_data_ = &source_evaluator_->get_evaluated(0); } - - /* Convert the factor to a length. */ - Field factor_field = params.get_input>("Factor"); - auto clamp_fn = std::make_unique>( - __func__, - [curves_total_length](float factor) { return factor * curves_total_length; }, - fn::CustomMF_presets::AllSpanOrSingle()); - - return Field(FieldOperation::Create(std::move(clamp_fn), {std::move(factor_field)}), 0); -} +}; static Array curve_accumulated_lengths(const bke::CurvesGeometry &curves) { - curves.ensure_evaluated_lengths(); Array curve_lengths(curves.curves_num()); const VArray cyclic = curves.cyclic(); @@ -313,9 +455,56 @@ static Array curve_accumulated_lengths(const bke::CurvesGeometry &curves) return curve_lengths; } +static GField get_input_attribute_field(GeoNodeExecParams ¶ms, const eCustomDataType data_type) +{ + switch (data_type) { + case CD_PROP_FLOAT: + return params.extract_input>("Value_Float"); + case CD_PROP_FLOAT3: + return params.extract_input>("Value_Vector"); + case CD_PROP_COLOR: + return params.extract_input>("Value_Color"); + case CD_PROP_BOOL: + return params.extract_input>("Value_Bool"); + case CD_PROP_INT32: + return params.extract_input>("Value_Int"); + default: + BLI_assert_unreachable(); + } + return {}; +} + +static void output_attribute_field(GeoNodeExecParams ¶ms, GField field) +{ + switch (bke::cpp_type_to_custom_data_type(field.cpp_type())) { + case CD_PROP_FLOAT: { + params.set_output("Value_Float", Field(field)); + break; + } + case CD_PROP_FLOAT3: { + params.set_output("Value_Vector", Field(field)); + break; + } + case CD_PROP_COLOR: { + params.set_output("Value_Color", Field(field)); + break; + } + case CD_PROP_BOOL: { + params.set_output("Value_Bool", Field(field)); + break; + } + case CD_PROP_INT32: { + params.set_output("Value_Int", Field(field)); + break; + } + default: + break; + } +} + static void node_geo_exec(GeoNodeExecParams params) { - GeometrySet geometry_set = params.extract_input("Curve"); + GeometrySet geometry_set = params.extract_input("Curves"); if (!geometry_set.has_curves()) { params.set_default_remaining_outputs(); return; @@ -328,18 +517,18 @@ static void node_geo_exec(GeoNodeExecParams params) return; } - Array curve_lengths = curve_accumulated_lengths(curves); - const float total_length = curve_lengths.last(); - if (total_length == 0.0f) { - params.set_default_remaining_outputs(); - return; - } + curves.ensure_evaluated_lengths(); const NodeGeometryCurveSample &storage = node_storage(params.node()); const GeometryNodeCurveSampleMode mode = (GeometryNodeCurveSampleMode)storage.mode; - Field length_field = get_length_input_field(params, mode, total_length); + const eCustomDataType data_type = eCustomDataType(storage.data_type); - auto sample_fn = std::make_unique(std::move(geometry_set)); + Field length_field = params.extract_input>( + mode == GEO_NODE_CURVE_SAMPLE_FACTOR ? "Factor" : "Length"); + GField src_values_field = get_input_attribute_field(params, data_type); + + auto sample_fn = std::make_unique( + std::move(geometry_set), mode, std::move(src_values_field)); std::shared_ptr sample_op; if (curves.curves_num() == 1) { @@ -347,15 +536,26 @@ static void node_geo_exec(GeoNodeExecParams params) {fn::make_constant_field(0), std::move(length_field)}); } else { - auto index_fn = std::make_unique(std::move(curve_lengths)); - auto index_op = FieldOperation::Create(std::move(index_fn), {std::move(length_field)}); - sample_op = FieldOperation::Create(std::move(sample_fn), - {Field(index_op, 0), Field(index_op, 1)}); + Field curve_index; + Field length_in_curve; + if (storage.use_all_curves) { + auto index_fn = std::make_unique( + curve_accumulated_lengths(curves), mode); + auto index_op = FieldOperation::Create(std::move(index_fn), {std::move(length_field)}); + curve_index = Field(index_op, 0); + length_in_curve = Field(index_op, 1); + } + else { + curve_index = params.extract_input>("Curve Index"); + length_in_curve = std::move(length_field); + } + sample_op = FieldOperation::Create(std::move(sample_fn), {curve_index, length_in_curve}); } params.set_output("Position", Field(sample_op, 0)); params.set_output("Tangent", Field(sample_op, 1)); params.set_output("Normal", Field(sample_op, 2)); + output_attribute_field(params, GField(sample_op, 3)); } } // namespace blender::nodes::node_geo_curve_sample_cc @@ -374,6 +574,6 @@ void register_node_type_geo_curve_sample() node_type_storage( &ntype, "NodeGeometryCurveSample", node_free_standard_storage, node_copy_standard_storage); ntype.draw_buttons = file_ns::node_layout; - + ntype.gather_link_search_ops = file_ns::node_gather_link_searches; nodeRegisterType(&ntype); } -- cgit v1.2.3 From 14e4c96b64f982dae26256be57c848ec134a72e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Csaba=20Boncs=C3=A9r?= Date: Wed, 2 Nov 2022 12:33:09 +0100 Subject: Nodes: Reuse input sockets when creating new node groups **Problem** Currently multiple input sockets are created when a new node group is made from selected nodes. Some of these are linked from the same source. It is not convenient to sort out and remove multiple input sockets that represent the same input. These inputs usually have meaningless names like 'value', 'x', etc. **Solution** Create common input sockets for each link starting from the same input. Move links inside the new group's node tree and reroute it to connect the common input socket to the original nodes. This is done by building up a mapping between the incoming link sources to the input interfaces created for them. The input interfaces are reused by the rest of the links having the same source. This patch also changes the way the input sockets get their names. Output socket names of the group nodes usually are specific and are given consciously. Use the output socket names from group nodes instead of the inputs where the links point to. Differential Revision: https://developer.blender.org/D15802 --- source/blender/blenkernel/BKE_node.h | 5 ++ source/blender/blenkernel/intern/node.cc | 16 +++-- source/blender/editors/space_node/node_group.cc | 93 ++++++++++++++++++++----- 3 files changed, 92 insertions(+), 22 deletions(-) diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index ecf7a556459..6eb9650348a 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -572,6 +572,11 @@ struct bNodeSocket *ntreeInsertSocketInterface(struct bNodeTree *ntree, struct bNodeSocket *ntreeAddSocketInterfaceFromSocket(struct bNodeTree *ntree, struct bNode *from_node, struct bNodeSocket *from_sock); +struct bNodeSocket *ntreeAddSocketInterfaceFromSocketWithName(struct bNodeTree *ntree, + struct bNode *from_node, + struct bNodeSocket *from_sock, + const char *idname, + const char *name); struct bNodeSocket *ntreeInsertSocketInterfaceFromSocket(struct bNodeTree *ntree, struct bNodeSocket *next_sock, struct bNode *from_node, diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 8f8cd02e119..ad9d4e4fcca 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -3381,10 +3381,18 @@ struct bNodeSocket *ntreeAddSocketInterfaceFromSocket(bNodeTree *ntree, bNode *from_node, bNodeSocket *from_sock) { - bNodeSocket *iosock = ntreeAddSocketInterface(ntree, - static_cast(from_sock->in_out), - from_sock->idname, - DATA_(from_sock->name)); + return ntreeAddSocketInterfaceFromSocketWithName( + ntree, from_node, from_sock, from_sock->idname, from_sock->name); +} + +struct bNodeSocket *ntreeAddSocketInterfaceFromSocketWithName(bNodeTree *ntree, + bNode *from_node, + bNodeSocket *from_sock, + const char *idname, + const char *name) +{ + bNodeSocket *iosock = ntreeAddSocketInterface( + ntree, static_cast(from_sock->in_out), idname, DATA_(name)); if (iosock) { if (iosock->typeinfo->interface_from_socket) { iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock); diff --git a/source/blender/editors/space_node/node_group.cc b/source/blender/editors/space_node/node_group.cc index aedceb1d368..329f78860a4 100644 --- a/source/blender/editors/space_node/node_group.cc +++ b/source/blender/editors/space_node/node_group.cc @@ -14,6 +14,7 @@ #include "BLI_linklist.h" #include "BLI_listbase.h" +#include "BLI_map.hh" #include "BLI_math_vec_types.hh" #include "BLI_string.h" #include "BLI_vector.hh" @@ -735,6 +736,74 @@ static int node_get_selected_minmax( return totselect; } +/** + * Redirect a link that are connecting a non-selected node to selected one. + * Create new socket or reuse an existing one that was connected from the same input. + * The output sockets of group nodes usually have consciously given names so they have + * precedence over socket names the link points to. + * + * \param ntree: The node tree that the node group is being created from. + * \param ngroup: The node tree of the new node group. + * \param gnode: The new group node in the original tree. + * \param input_node: The input node of the new node group. + * \param link: The incoming link that needs to be altered. + * \param reusable_sockets: Map for input socket interface lookup. + */ +static void node_group_make_redirect_incoming_link( + bNodeTree &ntree, + bNodeTree *ngroup, + bNode *gnode, + bNode *input_node, + bNodeLink *link, + Map &reusable_sockets) +{ + bNodeSocket *input_socket = reusable_sockets.lookup_default(link->fromsock, nullptr); + if (input_socket) { + /* The incoming link is from a socket that has already been linked to + * a socket interface of the input node. + * Change the source of the link to the previously created socket interface. + * Move the link into the node tree of the new group. */ + link->fromnode = input_node; + link->fromsock = input_socket; + BLI_remlink(&ntree.links, link); + BLI_addtail(&ngroup->links, link); + } + else { + bNode *node_for_typeinfo = nullptr; + bNodeSocket *socket_for_typeinfo = nullptr; + /* Find a socket where typeinfo and name may come from. */ + node_socket_skip_reroutes( + &ntree.links, link->tonode, link->tosock, &node_for_typeinfo, &socket_for_typeinfo); + bNodeSocket *socket_for_naming = socket_for_typeinfo; + + /* Use the name of group node output sockets. */ + if (ELEM(link->fromnode->type, NODE_GROUP_INPUT, NODE_GROUP, NODE_CUSTOM_GROUP)) { + socket_for_naming = link->fromsock; + } + + bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocketWithName(ngroup, + node_for_typeinfo, + socket_for_typeinfo, + socket_for_naming->idname, + socket_for_naming->name); + + /* Update the group node and interface sockets so the new interface socket can be linked. */ + node_group_update(&ntree, gnode); + node_group_input_update(ngroup, input_node); + + /* Create new internal link. */ + bNodeSocket *input_sock = node_group_input_find_socket(input_node, iosock->identifier); + nodeAddLink(ngroup, input_node, input_sock, link->tonode, link->tosock); + + /* Redirect external link. */ + link->tonode = gnode; + link->tosock = node_group_find_input_socket(gnode, iosock->identifier); + + /* Remember which interface socket the link has been redirected to. */ + reusable_sockets.add_new(link->fromsock, input_sock); + } +} + static void node_group_make_insert_selected(const bContext &C, bNodeTree &ntree, bNode *gnode) { Main *bmain = CTX_data_main(&C); @@ -834,6 +903,10 @@ static void node_group_make_insert_selected(const bContext &C, bNodeTree &ntree, output_node->locy = -offsety; /* relink external sockets */ + + /* A map from link sources to input sockets already connected. */ + Map reusable_sockets; + LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree.links) { const bool fromselect = node_group_make_use_node(*link->fromnode, gnode); const bool toselect = node_group_make_use_node(*link->tonode, gnode); @@ -851,24 +924,8 @@ static void node_group_make_insert_selected(const bContext &C, bNodeTree &ntree, continue; } - bNodeSocket *link_sock; - bNode *link_node; - node_socket_skip_reroutes(&ntree.links, link->tonode, link->tosock, &link_node, &link_sock); - bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, link_node, link_sock); - - /* update the group node and interface node sockets, - * so the new interface socket can be linked. - */ - node_group_update(&ntree, gnode); - node_group_input_update(ngroup, input_node); - - /* create new internal link */ - bNodeSocket *input_sock = node_group_input_find_socket(input_node, iosock->identifier); - nodeAddLink(ngroup, input_node, input_sock, link->tonode, link->tosock); - - /* redirect external link */ - link->tonode = gnode; - link->tosock = node_group_find_input_socket(gnode, iosock->identifier); + node_group_make_redirect_incoming_link( + ntree, ngroup, gnode, input_node, link, reusable_sockets); } else if (fromselect && !toselect) { /* Remove hidden links to not create unconnected sockets in the interface. */ -- cgit v1.2.3 From c394f510a5150a177919976b5775783c997b6934 Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Wed, 2 Nov 2022 13:48:20 +0200 Subject: Realtime Compositor: Make vectors four dimensional Currently, the realtime compositor treat vector types as 3D vectors, which is true for most operations. However, some operations deal with vector types as 4D vectors that encode two 2D vectors or one 3D vector with the last component ignored. So this patch expands vector types to include a fourth component that is only sometimes used. Since we already stored vectors in RGBA textures, the necessary changes are straightforward and are mostly concerned with adjusting the Result class. Differential Revision: https://developer.blender.org/D16359 Reviewed By: Clement Foucault --- source/blender/compositor/realtime_compositor/COM_result.hh | 12 +++++++----- .../compositor/realtime_compositor/COM_texture_pool.hh | 4 ++-- .../realtime_compositor/intern/conversion_operation.cc | 8 ++++---- .../intern/input_single_value_operation.cc | 2 +- .../blender/compositor/realtime_compositor/intern/result.cc | 8 ++++---- .../compositor/realtime_compositor/intern/texture_pool.cc | 2 +- 6 files changed, 19 insertions(+), 17 deletions(-) diff --git a/source/blender/compositor/realtime_compositor/COM_result.hh b/source/blender/compositor/realtime_compositor/COM_result.hh index a16d68bb92d..f5ecc4c2112 100644 --- a/source/blender/compositor/realtime_compositor/COM_result.hh +++ b/source/blender/compositor/realtime_compositor/COM_result.hh @@ -14,7 +14,9 @@ namespace blender::realtime_compositor { /* Possible data types that operations can operate on. They either represent the base type of the - * result texture or a single value result. */ + * result texture or a single value result. The color type represents an RGBA color. And the vector + * type represents a generic 4-component vector, which can encode two 2D vectors, one 3D vector + * with the last component ignored, or other dimensional data. */ enum class ResultType : uint8_t { Float, Vector, @@ -85,7 +87,7 @@ class Result { * is a texture. */ union { float float_value_; - float3 vector_value_; + float4 vector_value_; float4 color_value_; }; /* The domain of the result. This only matters if the result was a texture. See the discussion in @@ -157,7 +159,7 @@ class Result { /* If the result is a single value result of type vector, return its vector value. Otherwise, an * uninitialized value is returned. */ - float3 get_vector_value() const; + float4 get_vector_value() const; /* If the result is a single value result of type color, return its color value. Otherwise, an * uninitialized value is returned. */ @@ -167,7 +169,7 @@ class Result { float get_float_value_default(float default_value) const; /* Same as get_vector_value but returns a default value if the result is not a single value. */ - float3 get_vector_value_default(const float3 &default_value) const; + float4 get_vector_value_default(const float4 &default_value) const; /* Same as get_color_value but returns a default value if the result is not a single value. */ float4 get_color_value_default(const float4 &default_value) const; @@ -178,7 +180,7 @@ class Result { /* If the result is a single value result of type vector, set its vector value and upload it to * the texture. Otherwise, an undefined behavior is invoked. */ - void set_vector_value(const float3 &value); + void set_vector_value(const float4 &value); /* If the result is a single value result of type color, set its color value and upload it to the * texture. Otherwise, an undefined behavior is invoked. */ diff --git a/source/blender/compositor/realtime_compositor/COM_texture_pool.hh b/source/blender/compositor/realtime_compositor/COM_texture_pool.hh index cc6641d288f..c68219b0279 100644 --- a/source/blender/compositor/realtime_compositor/COM_texture_pool.hh +++ b/source/blender/compositor/realtime_compositor/COM_texture_pool.hh @@ -60,8 +60,8 @@ class TexturePool { /* Shorthand for acquire with GPU_RGBA16F format. */ GPUTexture *acquire_color(int2 size); - /* Shorthand for acquire with GPU_RGBA16F format. Identical to acquire_color because vectors - * are stored in RGBA textures, due to the limited support for RGB textures. */ + /* Shorthand for acquire with GPU_RGBA16F format. Identical to acquire_color because vectors are + * 4D, and are thus stored in RGBA textures. */ GPUTexture *acquire_vector(int2 size); /* Shorthand for acquire with GPU_R16F format. */ diff --git a/source/blender/compositor/realtime_compositor/intern/conversion_operation.cc b/source/blender/compositor/realtime_compositor/intern/conversion_operation.cc index 3743b9bba87..dd585aedec6 100644 --- a/source/blender/compositor/realtime_compositor/intern/conversion_operation.cc +++ b/source/blender/compositor/realtime_compositor/intern/conversion_operation.cc @@ -96,7 +96,7 @@ ConvertFloatToVectorOperation::ConvertFloatToVectorOperation(Context &context) void ConvertFloatToVectorOperation::execute_single(const Result &input, Result &output) { - output.set_vector_value(float3(input.get_float_value())); + output.set_vector_value(float4(float3(input.get_float_value()), 0.0f)); } GPUShader *ConvertFloatToVectorOperation::get_conversion_shader() const @@ -175,7 +175,7 @@ ConvertColorToVectorOperation::ConvertColorToVectorOperation(Context &context) void ConvertColorToVectorOperation::execute_single(const Result &input, Result &output) { float4 color = input.get_color_value(); - output.set_vector_value(float3(color)); + output.set_vector_value(float4(float3(color), 0.0f)); } GPUShader *ConvertColorToVectorOperation::get_conversion_shader() const @@ -200,7 +200,7 @@ ConvertVectorToFloatOperation::ConvertVectorToFloatOperation(Context &context) void ConvertVectorToFloatOperation::execute_single(const Result &input, Result &output) { - float3 vector = input.get_vector_value(); + float4 vector = input.get_vector_value(); output.set_float_value((vector[0] + vector[1] + vector[2]) / 3.0f); } @@ -226,7 +226,7 @@ ConvertVectorToColorOperation::ConvertVectorToColorOperation(Context &context) void ConvertVectorToColorOperation::execute_single(const Result &input, Result &output) { - output.set_color_value(float4(input.get_vector_value(), 1.0f)); + output.set_color_value(float4(float3(input.get_vector_value()), 1.0f)); } GPUShader *ConvertVectorToColorOperation::get_conversion_shader() const diff --git a/source/blender/compositor/realtime_compositor/intern/input_single_value_operation.cc b/source/blender/compositor/realtime_compositor/intern/input_single_value_operation.cc index b3cc86b5f79..99f7cd90557 100644 --- a/source/blender/compositor/realtime_compositor/intern/input_single_value_operation.cc +++ b/source/blender/compositor/realtime_compositor/intern/input_single_value_operation.cc @@ -38,7 +38,7 @@ void InputSingleValueOperation::execute() break; case ResultType::Vector: result.set_vector_value( - float3(bsocket->default_value_typed()->value)); + float4(float3(bsocket->default_value_typed()->value), 0.0f)); break; case ResultType::Color: result.set_color_value(float4(bsocket->default_value_typed()->value)); diff --git a/source/blender/compositor/realtime_compositor/intern/result.cc b/source/blender/compositor/realtime_compositor/intern/result.cc index 8059367d211..d89f1c86167 100644 --- a/source/blender/compositor/realtime_compositor/intern/result.cc +++ b/source/blender/compositor/realtime_compositor/intern/result.cc @@ -62,7 +62,7 @@ void Result::allocate_invalid() set_float_value(0.0f); break; case ResultType::Vector: - set_vector_value(float3(0.0f)); + set_vector_value(float4(0.0f)); break; case ResultType::Color: set_color_value(float4(0.0f)); @@ -125,7 +125,7 @@ float Result::get_float_value() const return float_value_; } -float3 Result::get_vector_value() const +float4 Result::get_vector_value() const { return vector_value_; } @@ -143,7 +143,7 @@ float Result::get_float_value_default(float default_value) const return default_value; } -float3 Result::get_vector_value_default(const float3 &default_value) const +float4 Result::get_vector_value_default(const float4 &default_value) const { if (is_single_value()) { return get_vector_value(); @@ -165,7 +165,7 @@ void Result::set_float_value(float value) GPU_texture_update(texture_, GPU_DATA_FLOAT, &float_value_); } -void Result::set_vector_value(const float3 &value) +void Result::set_vector_value(const float4 &value) { vector_value_ = value; GPU_texture_update(texture_, GPU_DATA_FLOAT, vector_value_); diff --git a/source/blender/compositor/realtime_compositor/intern/texture_pool.cc b/source/blender/compositor/realtime_compositor/intern/texture_pool.cc index 6bf2041e6ba..4b476574d72 100644 --- a/source/blender/compositor/realtime_compositor/intern/texture_pool.cc +++ b/source/blender/compositor/realtime_compositor/intern/texture_pool.cc @@ -64,7 +64,7 @@ GPUTexture *TexturePool::acquire_color(int2 size) GPUTexture *TexturePool::acquire_vector(int2 size) { - /* Vectors are stored in RGBA textures because RGB textures have limited support. */ + /* Vectors are 4D, and are thus stored in RGBA textures. */ return acquire(size, GPU_RGBA16F); } -- cgit v1.2.3 From bc8b15f1a532b078fcc4072295c442d140cdbc06 Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Wed, 2 Nov 2022 13:55:23 +0200 Subject: Realtime Compositor: Move shaders to compositor module This patch moves the GLSL shaders and their infos to the compositor module as decided by the EEVEE & Viewport module. This is a non functional change. Differential Revision: https://developer.blender.org/D16360 Reviewed By: Clement Foucault --- .../compositor/realtime_compositor/CMakeLists.txt | 125 +++++++++++++++++ .../shaders/compositor_alpha_crop.glsl | 11 ++ .../shaders/compositor_bilateral_blur.glsl | 31 +++++ .../shaders/compositor_blur.glsl | 66 +++++++++ .../shaders/compositor_blur_variable_size.glsl | 71 ++++++++++ .../shaders/compositor_bokeh_image.glsl | 118 ++++++++++++++++ .../shaders/compositor_box_mask.glsl | 27 ++++ .../shaders/compositor_convert.glsl | 8 ++ .../shaders/compositor_despeckle.glsl | 70 ++++++++++ .../shaders/compositor_directional_blur.glsl | 21 +++ .../shaders/compositor_edge_filter.glsl | 31 +++++ .../shaders/compositor_ellipse_mask.glsl | 27 ++++ .../shaders/compositor_filter.glsl | 20 +++ .../shaders/compositor_flip.glsl | 15 ++ .../shaders/compositor_image_crop.glsl | 7 + .../shaders/compositor_morphological_distance.glsl | 24 ++++ .../compositor_morphological_distance_feather.glsl | 101 ++++++++++++++ ...ompositor_morphological_distance_threshold.glsl | 88 ++++++++++++ .../shaders/compositor_morphological_step.glsl | 19 +++ .../shaders/compositor_normalize.glsl | 10 ++ .../shaders/compositor_parallel_reduction.glsl | 98 +++++++++++++ .../compositor_projector_lens_distortion.glsl | 16 +++ .../shaders/compositor_realize_on_domain.glsl | 29 ++++ .../shaders/compositor_screen_lens_distortion.glsl | 151 +++++++++++++++++++++ .../shaders/compositor_set_alpha.glsl | 8 ++ .../shaders/compositor_split_viewer.glsl | 14 ++ .../shaders/compositor_symmetric_blur.glsl | 77 +++++++++++ .../compositor_symmetric_separable_blur.glsl | 53 ++++++++ .../shaders/compositor_tone_map_photoreceptor.glsl | 22 +++ .../shaders/compositor_tone_map_simple.glsl | 26 ++++ .../shaders/infos/compositor_alpha_crop_info.hh | 12 ++ .../infos/compositor_bilateral_blur_info.hh | 13 ++ .../shaders/infos/compositor_blur_info.hh | 14 ++ .../infos/compositor_blur_variable_size_info.hh | 15 ++ .../shaders/infos/compositor_bokeh_image_info.hh | 14 ++ .../shaders/infos/compositor_box_mask_info.hh | 35 +++++ .../shaders/infos/compositor_convert_info.hh | 69 ++++++++++ .../shaders/infos/compositor_despeckle_info.hh | 13 ++ .../infos/compositor_directional_blur_info.hh | 12 ++ .../shaders/infos/compositor_edge_filter_info.hh | 12 ++ .../shaders/infos/compositor_ellipse_mask_info.hh | 35 +++++ .../shaders/infos/compositor_filter_info.hh | 12 ++ .../shaders/infos/compositor_flip_info.hh | 12 ++ .../shaders/infos/compositor_image_crop_info.hh | 11 ++ ...mpositor_morphological_distance_feather_info.hh | 21 +++ .../compositor_morphological_distance_info.hh | 22 +++ ...ositor_morphological_distance_threshold_info.hh | 13 ++ .../infos/compositor_morphological_step_info.hh | 22 +++ .../shaders/infos/compositor_normalize_info.hh | 12 ++ .../infos/compositor_parallel_reduction_info.hh | 149 ++++++++++++++++++++ .../compositor_projector_lens_distortion_info.hh | 11 ++ .../infos/compositor_realize_on_domain_info.hh | 24 ++++ .../compositor_screen_lens_distortion_info.hh | 20 +++ .../shaders/infos/compositor_set_alpha_info.hh | 11 ++ .../shaders/infos/compositor_split_viewer_info.hh | 22 +++ .../infos/compositor_symmetric_blur_info.hh | 13 ++ .../compositor_symmetric_separable_blur_info.hh | 14 ++ .../compositor_tone_map_photoreceptor_info.hh | 16 +++ .../infos/compositor_tone_map_simple_info.hh | 13 ++ .../library/gpu_shader_compositor_alpha_over.glsl | 48 +++++++ .../library/gpu_shader_compositor_blur_common.glsl | 32 +++++ .../gpu_shader_compositor_bright_contrast.glsl | 38 ++++++ .../gpu_shader_compositor_channel_matte.glsl | 52 +++++++ .../gpu_shader_compositor_chroma_matte.glsl | 43 ++++++ .../gpu_shader_compositor_color_balance.glsl | 34 +++++ .../gpu_shader_compositor_color_correction.glsl | 87 ++++++++++++ .../library/gpu_shader_compositor_color_matte.glsl | 27 ++++ .../library/gpu_shader_compositor_color_spill.glsl | 13 ++ .../gpu_shader_compositor_color_to_luminance.glsl | 6 + .../gpu_shader_compositor_difference_matte.glsl | 10 ++ .../gpu_shader_compositor_distance_matte.glsl | 26 ++++ .../library/gpu_shader_compositor_exposure.glsl | 6 + .../library/gpu_shader_compositor_gamma.glsl | 7 + .../library/gpu_shader_compositor_hue_correct.glsl | 39 ++++++ ...gpu_shader_compositor_hue_saturation_value.glsl | 16 +++ .../library/gpu_shader_compositor_invert.glsl | 13 ++ .../gpu_shader_compositor_luminance_matte.glsl | 14 ++ .../library/gpu_shader_compositor_main.glsl | 7 + .../library/gpu_shader_compositor_map_value.glsl | 56 ++++++++ .../library/gpu_shader_compositor_normal.glsl | 9 ++ .../library/gpu_shader_compositor_posterize.glsl | 6 + .../gpu_shader_compositor_separate_combine.glsl | 132 ++++++++++++++++++ .../library/gpu_shader_compositor_set_alpha.glsl | 9 ++ .../gpu_shader_compositor_store_output.glsl | 26 ++++ .../gpu_shader_compositor_texture_utilities.glsl | 35 +++++ .../gpu_shader_compositor_type_conversion.glsl | 29 ++++ source/blender/gpu/CMakeLists.txt | 90 +----------- .../blender/gpu/intern/gpu_shader_create_info.cc | 1 + source/blender/gpu/intern/gpu_shader_dependency.cc | 2 + .../shaders/compositor/compositor_alpha_crop.glsl | 11 -- .../compositor/compositor_bilateral_blur.glsl | 31 ----- .../gpu/shaders/compositor/compositor_blur.glsl | 66 --------- .../compositor/compositor_blur_variable_size.glsl | 71 ---------- .../shaders/compositor/compositor_bokeh_image.glsl | 118 ---------------- .../shaders/compositor/compositor_box_mask.glsl | 27 ---- .../gpu/shaders/compositor/compositor_convert.glsl | 8 -- .../shaders/compositor/compositor_despeckle.glsl | 70 ---------- .../compositor/compositor_directional_blur.glsl | 21 --- .../shaders/compositor/compositor_edge_filter.glsl | 31 ----- .../compositor/compositor_ellipse_mask.glsl | 27 ---- .../gpu/shaders/compositor/compositor_filter.glsl | 20 --- .../gpu/shaders/compositor/compositor_flip.glsl | 15 -- .../shaders/compositor/compositor_image_crop.glsl | 7 - .../compositor_morphological_distance.glsl | 24 ---- .../compositor_morphological_distance_feather.glsl | 101 -------------- ...ompositor_morphological_distance_threshold.glsl | 88 ------------ .../compositor/compositor_morphological_step.glsl | 19 --- .../shaders/compositor/compositor_normalize.glsl | 10 -- .../compositor/compositor_parallel_reduction.glsl | 98 ------------- .../compositor_projector_lens_distortion.glsl | 16 --- .../compositor/compositor_realize_on_domain.glsl | 29 ---- .../compositor_screen_lens_distortion.glsl | 151 --------------------- .../shaders/compositor/compositor_set_alpha.glsl | 8 -- .../compositor/compositor_split_viewer.glsl | 14 -- .../compositor/compositor_symmetric_blur.glsl | 77 ----------- .../compositor_symmetric_separable_blur.glsl | 53 -------- .../compositor_tone_map_photoreceptor.glsl | 22 --- .../compositor/compositor_tone_map_simple.glsl | 26 ---- .../compositor/infos/compositor_alpha_crop_info.hh | 12 -- .../infos/compositor_bilateral_blur_info.hh | 13 -- .../compositor/infos/compositor_blur_info.hh | 14 -- .../infos/compositor_blur_variable_size_info.hh | 15 -- .../infos/compositor_bokeh_image_info.hh | 14 -- .../compositor/infos/compositor_box_mask_info.hh | 35 ----- .../compositor/infos/compositor_convert_info.hh | 69 ---------- .../compositor/infos/compositor_despeckle_info.hh | 13 -- .../infos/compositor_directional_blur_info.hh | 12 -- .../infos/compositor_edge_filter_info.hh | 12 -- .../infos/compositor_ellipse_mask_info.hh | 35 ----- .../compositor/infos/compositor_filter_info.hh | 12 -- .../compositor/infos/compositor_flip_info.hh | 12 -- .../compositor/infos/compositor_image_crop_info.hh | 11 -- ...mpositor_morphological_distance_feather_info.hh | 21 --- .../compositor_morphological_distance_info.hh | 22 --- ...ositor_morphological_distance_threshold_info.hh | 13 -- .../infos/compositor_morphological_step_info.hh | 22 --- .../compositor/infos/compositor_normalize_info.hh | 12 -- .../infos/compositor_parallel_reduction_info.hh | 149 -------------------- .../compositor_projector_lens_distortion_info.hh | 11 -- .../infos/compositor_realize_on_domain_info.hh | 24 ---- .../compositor_screen_lens_distortion_info.hh | 20 --- .../compositor/infos/compositor_set_alpha_info.hh | 11 -- .../infos/compositor_split_viewer_info.hh | 22 --- .../infos/compositor_symmetric_blur_info.hh | 13 -- .../compositor_symmetric_separable_blur_info.hh | 14 -- .../compositor_tone_map_photoreceptor_info.hh | 16 --- .../infos/compositor_tone_map_simple_info.hh | 13 -- .../library/gpu_shader_compositor_alpha_over.glsl | 48 ------- .../library/gpu_shader_compositor_blur_common.glsl | 32 ----- .../gpu_shader_compositor_bright_contrast.glsl | 38 ------ .../gpu_shader_compositor_channel_matte.glsl | 52 ------- .../gpu_shader_compositor_chroma_matte.glsl | 43 ------ .../gpu_shader_compositor_color_balance.glsl | 34 ----- .../gpu_shader_compositor_color_correction.glsl | 87 ------------ .../library/gpu_shader_compositor_color_matte.glsl | 27 ---- .../library/gpu_shader_compositor_color_spill.glsl | 13 -- .../gpu_shader_compositor_color_to_luminance.glsl | 6 - .../gpu_shader_compositor_difference_matte.glsl | 10 -- .../gpu_shader_compositor_distance_matte.glsl | 26 ---- .../library/gpu_shader_compositor_exposure.glsl | 6 - .../library/gpu_shader_compositor_gamma.glsl | 7 - .../library/gpu_shader_compositor_hue_correct.glsl | 39 ------ ...gpu_shader_compositor_hue_saturation_value.glsl | 16 --- .../library/gpu_shader_compositor_invert.glsl | 13 -- .../gpu_shader_compositor_luminance_matte.glsl | 14 -- .../library/gpu_shader_compositor_main.glsl | 7 - .../library/gpu_shader_compositor_map_value.glsl | 56 -------- .../library/gpu_shader_compositor_normal.glsl | 9 -- .../library/gpu_shader_compositor_posterize.glsl | 6 - .../gpu_shader_compositor_separate_combine.glsl | 132 ------------------ .../library/gpu_shader_compositor_set_alpha.glsl | 9 -- .../gpu_shader_compositor_store_output.glsl | 26 ---- .../gpu_shader_compositor_texture_utilities.glsl | 35 ----- .../gpu_shader_compositor_type_conversion.glsl | 29 ---- 174 files changed, 2871 insertions(+), 2829 deletions(-) create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_alpha_crop.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_bilateral_blur.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_blur.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_blur_variable_size.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_bokeh_image.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_box_mask.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_convert.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_despeckle.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_directional_blur.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_edge_filter.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_ellipse_mask.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_filter.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_flip.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_image_crop.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_morphological_distance.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_morphological_distance_feather.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_morphological_distance_threshold.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_morphological_step.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_normalize.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_parallel_reduction.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_projector_lens_distortion.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_realize_on_domain.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_screen_lens_distortion.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_set_alpha.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_split_viewer.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_symmetric_blur.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_symmetric_separable_blur.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_tone_map_photoreceptor.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/compositor_tone_map_simple.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_alpha_crop_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_bilateral_blur_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_blur_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_blur_variable_size_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_bokeh_image_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_box_mask_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_convert_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_despeckle_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_directional_blur_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_edge_filter_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_ellipse_mask_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_filter_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_flip_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_image_crop_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_morphological_distance_feather_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_morphological_distance_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_morphological_distance_threshold_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_morphological_step_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_normalize_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_parallel_reduction_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_projector_lens_distortion_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_realize_on_domain_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_screen_lens_distortion_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_set_alpha_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_split_viewer_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_symmetric_blur_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_symmetric_separable_blur_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_tone_map_photoreceptor_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/infos/compositor_tone_map_simple_info.hh create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_alpha_over.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_blur_common.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_bright_contrast.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_channel_matte.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_chroma_matte.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_balance.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_correction.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_matte.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_spill.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_to_luminance.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_difference_matte.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_distance_matte.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_exposure.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_gamma.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_hue_correct.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_hue_saturation_value.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_invert.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_luminance_matte.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_main.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_map_value.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_normal.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_posterize.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_separate_combine.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_set_alpha.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_store_output.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_texture_utilities.glsl create mode 100644 source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_type_conversion.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_alpha_crop.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_bilateral_blur.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_blur.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_bokeh_image.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_box_mask.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_convert.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_despeckle.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_directional_blur.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_edge_filter.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_ellipse_mask.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_filter.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_flip.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_image_crop.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_morphological_distance.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_morphological_distance_feather.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_morphological_distance_threshold.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_morphological_step.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_normalize.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_parallel_reduction.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_projector_lens_distortion.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_realize_on_domain.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_screen_lens_distortion.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_set_alpha.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_split_viewer.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_symmetric_blur.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_symmetric_separable_blur.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl delete mode 100644 source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_alpha_crop_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_bilateral_blur_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_blur_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_blur_variable_size_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_bokeh_image_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_box_mask_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_convert_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_despeckle_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_directional_blur_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_edge_filter_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_ellipse_mask_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_filter_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_flip_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_image_crop_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_morphological_distance_feather_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_morphological_distance_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_morphological_distance_threshold_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_morphological_step_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_projector_lens_distortion_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_realize_on_domain_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_screen_lens_distortion_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_set_alpha_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_split_viewer_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_symmetric_blur_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_symmetric_separable_blur_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_alpha_over.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_blur_common.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_bright_contrast.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_channel_matte.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_chroma_matte.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_balance.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_correction.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_matte.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_spill.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_to_luminance.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_difference_matte.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_distance_matte.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_exposure.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_gamma.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_hue_correct.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_hue_saturation_value.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_invert.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_luminance_matte.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_main.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_map_value.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_normal.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_posterize.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_separate_combine.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_set_alpha.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_store_output.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_texture_utilities.glsl delete mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_type_conversion.glsl diff --git a/source/blender/compositor/realtime_compositor/CMakeLists.txt b/source/blender/compositor/realtime_compositor/CMakeLists.txt index bab0b5385ec..2402adcadaf 100644 --- a/source/blender/compositor/realtime_compositor/CMakeLists.txt +++ b/source/blender/compositor/realtime_compositor/CMakeLists.txt @@ -68,4 +68,129 @@ set(LIB bf_blenkernel ) +set(GLSL_SRC + shaders/compositor_alpha_crop.glsl + shaders/compositor_bilateral_blur.glsl + shaders/compositor_blur.glsl + shaders/compositor_blur_variable_size.glsl + shaders/compositor_bokeh_image.glsl + shaders/compositor_box_mask.glsl + shaders/compositor_convert.glsl + shaders/compositor_despeckle.glsl + shaders/compositor_directional_blur.glsl + shaders/compositor_edge_filter.glsl + shaders/compositor_ellipse_mask.glsl + shaders/compositor_filter.glsl + shaders/compositor_flip.glsl + shaders/compositor_image_crop.glsl + shaders/compositor_morphological_distance.glsl + shaders/compositor_morphological_distance_feather.glsl + shaders/compositor_morphological_distance_threshold.glsl + shaders/compositor_morphological_step.glsl + shaders/compositor_normalize.glsl + shaders/compositor_parallel_reduction.glsl + shaders/compositor_projector_lens_distortion.glsl + shaders/compositor_realize_on_domain.glsl + shaders/compositor_screen_lens_distortion.glsl + shaders/compositor_set_alpha.glsl + shaders/compositor_split_viewer.glsl + shaders/compositor_symmetric_blur.glsl + shaders/compositor_symmetric_separable_blur.glsl + shaders/compositor_tone_map_photoreceptor.glsl + shaders/compositor_tone_map_simple.glsl + + shaders/library/gpu_shader_compositor_alpha_over.glsl + shaders/library/gpu_shader_compositor_blur_common.glsl + shaders/library/gpu_shader_compositor_bright_contrast.glsl + shaders/library/gpu_shader_compositor_channel_matte.glsl + shaders/library/gpu_shader_compositor_chroma_matte.glsl + shaders/library/gpu_shader_compositor_color_balance.glsl + shaders/library/gpu_shader_compositor_color_correction.glsl + shaders/library/gpu_shader_compositor_color_matte.glsl + shaders/library/gpu_shader_compositor_color_spill.glsl + shaders/library/gpu_shader_compositor_color_to_luminance.glsl + shaders/library/gpu_shader_compositor_difference_matte.glsl + shaders/library/gpu_shader_compositor_distance_matte.glsl + shaders/library/gpu_shader_compositor_exposure.glsl + shaders/library/gpu_shader_compositor_gamma.glsl + shaders/library/gpu_shader_compositor_hue_correct.glsl + shaders/library/gpu_shader_compositor_hue_saturation_value.glsl + shaders/library/gpu_shader_compositor_invert.glsl + shaders/library/gpu_shader_compositor_luminance_matte.glsl + shaders/library/gpu_shader_compositor_main.glsl + shaders/library/gpu_shader_compositor_map_value.glsl + shaders/library/gpu_shader_compositor_normal.glsl + shaders/library/gpu_shader_compositor_posterize.glsl + shaders/library/gpu_shader_compositor_separate_combine.glsl + shaders/library/gpu_shader_compositor_set_alpha.glsl + shaders/library/gpu_shader_compositor_store_output.glsl + shaders/library/gpu_shader_compositor_texture_utilities.glsl + shaders/library/gpu_shader_compositor_type_conversion.glsl +) + +set(GLSL_C) +foreach(GLSL_FILE ${GLSL_SRC}) + data_to_c_simple(${GLSL_FILE} GLSL_C) +endforeach() + +blender_add_lib(bf_compositor_shaders "${GLSL_C}" "" "" "") + +list(APPEND LIB + bf_compositor_shaders +) + +set(GLSL_SOURCE_CONTENT "") +foreach(GLSL_FILE ${GLSL_SRC}) + get_filename_component(GLSL_FILE_NAME ${GLSL_FILE} NAME) + string(REPLACE "." "_" GLSL_FILE_NAME_UNDERSCORES ${GLSL_FILE_NAME}) + string(APPEND GLSL_SOURCE_CONTENT "SHADER_SOURCE\(datatoc_${GLSL_FILE_NAME_UNDERSCORES}, \"${GLSL_FILE_NAME}\", \"${GLSL_FILE}\"\)\n") +endforeach() + +set(glsl_source_list_file "${CMAKE_CURRENT_BINARY_DIR}/glsl_compositor_source_list.h") +file(GENERATE OUTPUT ${glsl_source_list_file} CONTENT "${GLSL_SOURCE_CONTENT}") +list(APPEND SRC ${glsl_source_list_file}) +list(APPEND INC ${CMAKE_CURRENT_BINARY_DIR}) + +target_include_directories(bf_compositor_shaders PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) + +set(SRC_SHADER_CREATE_INFOS + shaders/infos/compositor_alpha_crop_info.hh + shaders/infos/compositor_bilateral_blur_info.hh + shaders/infos/compositor_blur_info.hh + shaders/infos/compositor_blur_variable_size_info.hh + shaders/infos/compositor_bokeh_image_info.hh + shaders/infos/compositor_box_mask_info.hh + shaders/infos/compositor_convert_info.hh + shaders/infos/compositor_despeckle_info.hh + shaders/infos/compositor_directional_blur_info.hh + shaders/infos/compositor_edge_filter_info.hh + shaders/infos/compositor_ellipse_mask_info.hh + shaders/infos/compositor_filter_info.hh + shaders/infos/compositor_flip_info.hh + shaders/infos/compositor_image_crop_info.hh + shaders/infos/compositor_morphological_distance_feather_info.hh + shaders/infos/compositor_morphological_distance_info.hh + shaders/infos/compositor_morphological_distance_threshold_info.hh + shaders/infos/compositor_morphological_step_info.hh + shaders/infos/compositor_normalize_info.hh + shaders/infos/compositor_parallel_reduction_info.hh + shaders/infos/compositor_projector_lens_distortion_info.hh + shaders/infos/compositor_realize_on_domain_info.hh + shaders/infos/compositor_screen_lens_distortion_info.hh + shaders/infos/compositor_set_alpha_info.hh + shaders/infos/compositor_split_viewer_info.hh + shaders/infos/compositor_symmetric_blur_info.hh + shaders/infos/compositor_symmetric_separable_blur_info.hh + shaders/infos/compositor_tone_map_photoreceptor_info.hh + shaders/infos/compositor_tone_map_simple_info.hh +) + +set(SHADER_CREATE_INFOS_CONTENT "") +foreach(DESCRIPTOR_FILE ${SRC_SHADER_CREATE_INFOS}) + string(APPEND SHADER_CREATE_INFOS_CONTENT "#include \"${DESCRIPTOR_FILE}\"\n") +endforeach() + +set(shader_create_info_list_file "${CMAKE_CURRENT_BINARY_DIR}/compositor_shader_create_info_list.hh") +file(GENERATE OUTPUT ${shader_create_info_list_file} CONTENT "${SHADER_CREATE_INFOS_CONTENT}") + blender_add_lib(bf_realtime_compositor "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_alpha_crop.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_alpha_crop.glsl new file mode 100644 index 00000000000..d55c8efd4c6 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_alpha_crop.glsl @@ -0,0 +1,11 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + /* The lower bound is inclusive and upper bound is exclusive. */ + bool is_inside = all(greaterThanEqual(texel, lower_bound)) && all(lessThan(texel, upper_bound)); + /* Write the pixel color if it is inside the cropping region, otherwise, write zero. */ + vec4 color = is_inside ? texture_load(input_tx, texel) : vec4(0.0); + imageStore(output_img, texel, color); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_bilateral_blur.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_bilateral_blur.glsl new file mode 100644 index 00000000000..c7c5ada7a9f --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_bilateral_blur.glsl @@ -0,0 +1,31 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + vec4 center_determinator = texture_load(determinator_tx, texel); + + /* Go over the pixels in the blur window of the specified radius around the center pixel, and for + * pixels whose determinator is close enough to the determinator of the center pixel, accumulate + * their color as well as their weights. */ + float accumulated_weight = 0.0; + vec4 accumulated_color = vec4(0.0); + for (int y = -radius; y <= radius; y++) { + for (int x = -radius; x <= radius; x++) { + vec4 determinator = texture_load(determinator_tx, texel + ivec2(x, y)); + float difference = dot(abs(center_determinator - determinator).rgb, vec3(1.0)); + + if (difference < threshold) { + accumulated_weight += 1.0; + accumulated_color += texture_load(input_tx, texel + ivec2(x, y)); + } + } + } + + /* Write the accumulated color divided by the accumulated weight if any pixel in the window was + * accumulated, otherwise, write a fallback black color. */ + vec4 fallback = vec4(vec3(0.0), 1.0); + vec4 color = (accumulated_weight != 0.0) ? (accumulated_color / accumulated_weight) : fallback; + imageStore(output_img, texel, color); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_blur.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_blur.glsl new file mode 100644 index 00000000000..c7ac620f99b --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_blur.glsl @@ -0,0 +1,66 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +vec4 load_input(ivec2 texel) +{ + vec4 color; + if (extend_bounds) { + /* If bounds are extended, then we treat the input as padded by a radius amount of pixels. So + * we load the input with an offset by the radius amount and fallback to a transparent color if + * it is out of bounds. */ + color = texture_load(input_tx, texel - radius, vec4(0.0)); + } + else { + color = texture_load(input_tx, texel); + } + + return color; +} + +/* Given the texel in the range [-radius, radius] in both axis, load the appropriate weight from + * the weights texture, where the given texel (0, 0) corresponds the center of weights texture. + * Note that we load the weights texture inverted along both directions to maintain the shape of + * the weights if it was not symmetrical. To understand why inversion makes sense, consider a 1D + * weights texture whose right half is all ones and whose left half is all zeros. Further, consider + * that we are blurring a single white pixel on a black background. When computing the value of a + * pixel that is to the right of the white pixel, the white pixel will be in the left region of the + * search window, and consequently, without inversion, a zero will be sampled from the left side of + * the weights texture and result will be zero. However, what we expect is that pixels to the right + * of the white pixel will be white, that is, they should sample a weight of 1 from the right side + * of the weights texture, hence the need for inversion. */ +vec4 load_weight(ivec2 texel) +{ + /* Add the radius to transform the texel into the range [0, radius * 2], with an additional 0.5 + * to sample at the center of the pixels, then divide by the upper bound plus one to transform + * the texel into the normalized range [0, 1] needed to sample the weights sampler. Finally, + * invert the textures coordinates by subtracting from 1 to maintain the shape of the weights as + * mentioned in the function description. */ + return texture(weights_tx, 1.0 - ((texel + vec2(radius + 0.5)) / (radius * 2 + 1))); +} + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + /* The mask input is treated as a boolean. If it is zero, then no blurring happens for this + * pixel. Otherwise, the pixel is blurred normally and the mask value is irrelevant. */ + float mask = texture_load(mask_tx, texel).x; + if (mask == 0.0) { + imageStore(output_img, texel, texture_load(input_tx, texel)); + return; + } + + /* Go over the window of the given radius and accumulate the colors multiplied by their + * respective weights as well as the weights themselves. */ + vec4 accumulated_color = vec4(0.0); + vec4 accumulated_weight = vec4(0.0); + for (int y = -radius; y <= radius; y++) { + for (int x = -radius; x <= radius; x++) { + vec4 weight = load_weight(ivec2(x, y)); + accumulated_color += load_input(texel + ivec2(x, y)) * weight; + accumulated_weight += weight; + } + } + + imageStore(output_img, texel, safe_divide(accumulated_color, accumulated_weight)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_blur_variable_size.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_blur_variable_size.glsl new file mode 100644 index 00000000000..9383bbf9825 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_blur_variable_size.glsl @@ -0,0 +1,71 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +/* Given the texel in the range [-radius, radius] in both axis, load the appropriate weight from + * the weights texture, where the given texel (0, 0) corresponds the center of weights texture. + * Note that we load the weights texture inverted along both directions to maintain the shape of + * the weights if it was not symmetrical. To understand why inversion makes sense, consider a 1D + * weights texture whose right half is all ones and whose left half is all zeros. Further, consider + * that we are blurring a single white pixel on a black background. When computing the value of a + * pixel that is to the right of the white pixel, the white pixel will be in the left region of the + * search window, and consequently, without inversion, a zero will be sampled from the left side of + * the weights texture and result will be zero. However, what we expect is that pixels to the right + * of the white pixel will be white, that is, they should sample a weight of 1 from the right side + * of the weights texture, hence the need for inversion. */ +vec4 load_weight(ivec2 texel, float radius) +{ + /* The center zero texel is always assigned a unit weight regardless of the corresponding weight + * in the weights texture. That's to guarantee that at last the center pixel will be accumulated + * even if the weights texture is zero at its center. */ + if (texel == ivec2(0)) { + return vec4(1.0); + } + + /* Add the radius to transform the texel into the range [0, radius * 2], with an additional 0.5 + * to sample at the center of the pixels, then divide by the upper bound plus one to transform + * the texel into the normalized range [0, 1] needed to sample the weights sampler. Finally, + * invert the textures coordinates by subtracting from 1 to maintain the shape of the weights as + * mentioned in the function description. */ + return texture(weights_tx, 1.0 - ((texel + vec2(radius + 0.5)) / (radius * 2 + 1))); +} + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + /* The mask input is treated as a boolean. If it is zero, then no blurring happens for this + * pixel. Otherwise, the pixel is blurred normally and the mask value is irrelevant. */ + float mask = texture_load(mask_tx, texel).x; + if (mask == 0.0) { + imageStore(output_img, texel, texture_load(input_tx, texel)); + return; + } + + float center_size = texture_load(size_tx, texel).x * base_size; + + /* Go over the window of the given search radius and accumulate the colors multiplied by their + * respective weights as well as the weights themselves, but only if both the size of the center + * pixel and the size of the candidate pixel are less than both the x and y distances of the + * candidate pixel. */ + vec4 accumulated_color = vec4(0.0); + vec4 accumulated_weight = vec4(0.0); + for (int y = -search_radius; y <= search_radius; y++) { + for (int x = -search_radius; x <= search_radius; x++) { + float candidate_size = texture_load(size_tx, texel + ivec2(x, y)).x * base_size; + + /* Skip accumulation if either the x or y distances of the candidate pixel are larger than + * either the center or candidate pixel size. Note that the max and min functions here denote + * "either" in the aforementioned description. */ + float size = min(center_size, candidate_size); + if (max(abs(x), abs(y)) > size) { + continue; + } + + vec4 weight = load_weight(ivec2(x, y), size); + accumulated_color += texture_load(input_tx, texel + ivec2(x, y)) * weight; + accumulated_weight += weight; + } + } + + imageStore(output_img, texel, safe_divide(accumulated_color, accumulated_weight)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_bokeh_image.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_bokeh_image.glsl new file mode 100644 index 00000000000..6e98aa9fe17 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_bokeh_image.glsl @@ -0,0 +1,118 @@ +#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +/* Get the 2D vertex position of the vertex with the given index in the regular polygon + * representing this bokeh. The polygon is rotated by the rotation amount and have a unit + * circumradius. The regular polygon is one whose vertices' exterior angles are given by + * exterior_angle. See the bokeh function for more information. */ +vec2 get_regular_polygon_vertex_position(int vertex_index) +{ + float angle = exterior_angle * vertex_index - rotation; + return vec2(cos(angle), sin(angle)); +} + +/* Find the closest point to the given point on the given line. This assumes the length of the + * given line is not zero. */ +vec2 closest_point_on_line(vec2 point, vec2 line_start, vec2 line_end) +{ + vec2 line_vector = line_end - line_start; + vec2 point_vector = point - line_start; + float line_length_squared = dot(line_vector, line_vector); + float parameter = dot(point_vector, line_vector) / line_length_squared; + return line_start + line_vector * parameter; +} + +/* Compute the value of the bokeh at the given point. The computed bokeh is essentially a regular + * polygon centered in space having the given circumradius. The regular polygon is one whose + * vertices' exterior angles are given by "exterior_angle", which relates to the number of vertices + * n through the equation "exterior angle = 2 pi / n". The regular polygon may additionally morph + * into a shape with the given properties: + * + * - The regular polygon may have a circular hole in its center whose radius is controlled by the + * "catadioptric" value. + * - The regular polygon is rotated by the "rotation" value. + * - The regular polygon can morph into a circle controlled by the "roundness" value, such that it + * becomes a full circle at unit roundness. + * + * The function returns 0 when the point lies inside the regular polygon and 1 otherwise. However, + * at the edges, it returns a narrow band gradient as a form of anti-aliasing. */ +float bokeh(vec2 point, float circumradius) +{ + /* Get the index of the vertex of the regular polygon whose polar angle is maximum but less than + * the polar angle of the given point, taking rotation into account. This essentially finds the + * vertex closest to the given point in the clock-wise direction. */ + float angle = mod(atan(point.y, point.x) + rotation, M_2PI); + int vertex_index = int(angle / exterior_angle); + + /* Compute the shortest distance between the origin and the polygon edge composed from the + * previously selected vertex and the one following it. */ + vec2 first_vertex = get_regular_polygon_vertex_position(vertex_index) * circumradius; + vec2 second_vertex = get_regular_polygon_vertex_position(vertex_index + 1) * circumradius; + vec2 closest_point = closest_point_on_line(point, first_vertex, second_vertex); + float distance_to_edge = length(closest_point); + + /* Mix the distance to the edge with the circumradius, making it tend to the distance to a + * circle when roundness tends to 1. */ + float distance_to_edge_round = mix(distance_to_edge, circumradius, roundness); + + /* The point is outside of the bokeh, so we return 0. */ + float distance = length(point); + if (distance > distance_to_edge_round) { + return 0.0; + } + + /* The point is inside the catadioptric hole and is not part of the bokeh, so we return 0. */ + float catadioptric_distance = distance_to_edge_round * catadioptric; + if (distance < catadioptric_distance) { + return 0.0; + } + + /* The point is very close to the edge of the bokeh, so we return the difference between the + * distance to the edge and the distance as a form of anti-aliasing. */ + if (distance_to_edge_round - distance < 1.0) { + return distance_to_edge_round - distance; + } + + /* The point is very close to the edge of the catadioptric hole, so we return the difference + * between the distance to the hole and the distance as a form of anti-aliasing. */ + if (catadioptric != 0.0 && distance - catadioptric_distance < 1.0) { + return distance - catadioptric_distance; + } + + /* Otherwise, the point is part of the bokeh and we return 1. */ + return 1.0; +} + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + /* Since we need the regular polygon to occupy the entirety of the output image, the circumradius + * of the regular polygon is half the width of the output image. */ + float circumradius = float(imageSize(output_img).x) / 2.0; + + /* Move the texel coordinates such that the regular polygon is centered. */ + vec2 point = vec2(texel) - circumradius; + + /* Each of the color channels of the output image contains a bokeh with a different circumradius. + * The largest one occupies the whole image as stated above, while the other two have circumradii + * that are shifted by an amount that is proportional to the "lens_shift" value. The alpha + * channel of the output is the average of all three values. */ + float min_shift = abs(lens_shift * circumradius); + float min = mix(bokeh(point, circumradius - min_shift), 0.0, min_shift == circumradius); + + float median_shift = min_shift / 2.0; + float median = bokeh(point, circumradius - median_shift); + + float max = bokeh(point, circumradius); + vec4 bokeh = vec4(min, median, max, (max + median + min) / 3.0); + + /* If the lens shift is negative, swap the min and max bokeh values, which are stored in the red + * and blue channels respectively. Note that we take the absolute value of the lens shift above, + * so the sign of the lens shift only controls this swap. */ + if (lens_shift < 0) { + bokeh = bokeh.zyxw; + } + + imageStore(output_img, texel, bokeh); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_box_mask.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_box_mask.glsl new file mode 100644 index 00000000000..fad23f28fde --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_box_mask.glsl @@ -0,0 +1,27 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + vec2 uv = vec2(texel) / vec2(domain_size - ivec2(1)); + uv -= location; + uv.y *= float(domain_size.y) / float(domain_size.x); + uv = mat2(cos_angle, -sin_angle, sin_angle, cos_angle) * uv; + bool is_inside = all(lessThan(abs(uv), size)); + + float base_mask_value = texture_load(base_mask_tx, texel).x; + float value = texture_load(mask_value_tx, texel).x; + +#if defined(CMP_NODE_MASKTYPE_ADD) + float output_mask_value = is_inside ? max(base_mask_value, value) : base_mask_value; +#elif defined(CMP_NODE_MASKTYPE_SUBTRACT) + float output_mask_value = is_inside ? clamp(base_mask_value - value, 0.0, 1.0) : base_mask_value; +#elif defined(CMP_NODE_MASKTYPE_MULTIPLY) + float output_mask_value = is_inside ? base_mask_value * value : 0.0; +#elif defined(CMP_NODE_MASKTYPE_NOT) + float output_mask_value = is_inside ? (base_mask_value > 0.0 ? 0.0 : value) : base_mask_value; +#endif + + imageStore(output_mask_img, texel, vec4(output_mask_value)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_convert.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_convert.glsl new file mode 100644 index 00000000000..044fb057ca5 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_convert.glsl @@ -0,0 +1,8 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + vec4 value = texture_load(input_tx, texel); + imageStore(output_img, texel, CONVERT_EXPRESSION(value)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_despeckle.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_despeckle.glsl new file mode 100644 index 00000000000..e4743d69d17 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_despeckle.glsl @@ -0,0 +1,70 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +/* Returns true if the given color is close enough to the given reference color within the + * threshold supplied by the user, and returns false otherwise. */ +bool is_close(vec4 reference_color, vec4 color) +{ + return all(lessThan(abs(reference_color - color).rgb, vec3(threshold))); +} + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + /* A 3x3 weights kernel whose weights are the inverse of the distance to the center of the + * kernel. So the center weight is zero, the corners weights are (1 / sqrt(2)), and the rest + * of the weights are 1. The total sum of weights is 4 plus quadruple the corner weight. */ + float corner_weight = 1.0 / sqrt(2.0); + float sum_of_weights = 4.0 + corner_weight * 4.0; + mat3 weights = mat3(vec3(corner_weight, 1.0, corner_weight), + vec3(1.0, 0.0, 1.0), + vec3(corner_weight, 1.0, corner_weight)); + + vec4 center_color = texture_load(input_tx, texel); + + /* Go over the pixels in the 3x3 window around the center pixel and compute the total sum of + * their colors multiplied by their weights. Additionally, for pixels whose colors are not close + * enough to the color of the center pixel, accumulate their color as well as their weights. */ + vec4 sum_of_colors = vec4(0); + float accumulated_weight = 0.0; + vec4 accumulated_color = vec4(0); + for (int j = 0; j < 3; j++) { + for (int i = 0; i < 3; i++) { + float weight = weights[j][i]; + vec4 color = texture_load(input_tx, texel + ivec2(i - 1, j - 1)) * weight; + sum_of_colors += color; + if (!is_close(center_color, color)) { + accumulated_color += color; + accumulated_weight += weight; + } + } + } + + /* If the accumulated weight is zero, that means all pixels in the 3x3 window are similar and no + * need to despeckle anything, so write the original center color and return. */ + if (accumulated_weight == 0.0) { + imageStore(output_img, texel, center_color); + return; + } + + /* If the ratio between the accumulated weights and the total sum of weights is not larger than + * the user specified neighbor threshold, then the number of pixels in the neighborhood that are + * not close enough to the center pixel is low, and no need to despeckle anything, so write the + * original center color and return. */ + if (accumulated_weight / sum_of_weights < neighbor_threshold) { + imageStore(output_img, texel, center_color); + return; + } + + /* If the weighted average color of the neighborhood is close enough to the center pixel, then no + * need to despeckle anything, so write the original center color and return. */ + if (is_close(center_color, sum_of_colors / sum_of_weights)) { + imageStore(output_img, texel, center_color); + return; + } + + /* We need to despeckle, so write the mean accumulated color. */ + float factor = texture_load(factor_tx, texel).x; + vec4 mean_color = accumulated_color / accumulated_weight; + imageStore(output_img, texel, mix(center_color, mean_color, factor)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_directional_blur.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_directional_blur.glsl new file mode 100644 index 00000000000..1805cb5a7f5 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_directional_blur.glsl @@ -0,0 +1,21 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + ivec2 input_size = texture_size(input_tx); + + /* Add 0.5 to evaluate the input sampler at the center of the pixel. */ + vec2 coordinates = vec2(texel) + vec2(0.5); + + /* For each iteration, accumulate the input at the normalize coordinates, hence the divide by + * input size, then transform the coordinates for the next iteration. */ + vec4 accumulated_color = vec4(0.0); + for (int i = 0; i < iterations; i++) { + accumulated_color += texture(input_tx, coordinates / input_size); + coordinates = (mat3(inverse_transformation) * vec3(coordinates, 1.0)).xy; + } + + /* Write the accumulated color divided by the number of iterations. */ + imageStore(output_img, texel, accumulated_color / iterations); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_edge_filter.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_edge_filter.glsl new file mode 100644 index 00000000000..67e27c22602 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_edge_filter.glsl @@ -0,0 +1,31 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + /* Compute the dot product between the 3x3 window around the pixel and the edge detection kernel + * in the X direction and Y direction. The Y direction kernel is computed by transposing the + * given X direction kernel. */ + vec3 color_x = vec3(0); + vec3 color_y = vec3(0); + for (int j = 0; j < 3; j++) { + for (int i = 0; i < 3; i++) { + vec3 color = texture_load(input_tx, texel + ivec2(i - 1, j - 1)).rgb; + color_x += color * kernel[j][i]; + color_y += color * kernel[i][j]; + } + } + + /* Compute the channel-wise magnitude of the 2D vector composed from the X and Y edge detection + * filter results. */ + vec3 magnitude = sqrt(color_x * color_x + color_y * color_y); + + /* Mix the channel-wise magnitude with the original color at the center of the kernel using the + * input factor. */ + vec4 color = texture_load(input_tx, texel); + magnitude = mix(color.rgb, magnitude, texture_load(factor_tx, texel).x); + + /* Store the channel-wise magnitude with the original alpha of the input. */ + imageStore(output_img, texel, vec4(magnitude, color.a)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_ellipse_mask.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_ellipse_mask.glsl new file mode 100644 index 00000000000..28f725067e0 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_ellipse_mask.glsl @@ -0,0 +1,27 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + vec2 uv = vec2(texel) / vec2(domain_size - ivec2(1)); + uv -= location; + uv.y *= float(domain_size.y) / float(domain_size.x); + uv = mat2(cos_angle, -sin_angle, sin_angle, cos_angle) * uv; + bool is_inside = length(uv / radius) < 1.0; + + float base_mask_value = texture_load(base_mask_tx, texel).x; + float value = texture_load(mask_value_tx, texel).x; + +#if defined(CMP_NODE_MASKTYPE_ADD) + float output_mask_value = is_inside ? max(base_mask_value, value) : base_mask_value; +#elif defined(CMP_NODE_MASKTYPE_SUBTRACT) + float output_mask_value = is_inside ? clamp(base_mask_value - value, 0.0, 1.0) : base_mask_value; +#elif defined(CMP_NODE_MASKTYPE_MULTIPLY) + float output_mask_value = is_inside ? base_mask_value * value : 0.0; +#elif defined(CMP_NODE_MASKTYPE_NOT) + float output_mask_value = is_inside ? (base_mask_value > 0.0 ? 0.0 : value) : base_mask_value; +#endif + + imageStore(output_mask_img, texel, vec4(output_mask_value)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_filter.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_filter.glsl new file mode 100644 index 00000000000..e501c563dda --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_filter.glsl @@ -0,0 +1,20 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + /* Compute the dot product between the 3x3 window around the pixel and the filter kernel. */ + vec4 color = vec4(0); + for (int j = 0; j < 3; j++) { + for (int i = 0; i < 3; i++) { + color += texture_load(input_tx, texel + ivec2(i - 1, j - 1)) * kernel[j][i]; + } + } + + /* Mix with the original color at the center of the kernel using the input factor. */ + color = mix(texture_load(input_tx, texel), color, texture_load(factor_tx, texel).x); + + /* Store the color making sure it is not negative. */ + imageStore(output_img, texel, max(color, 0.0)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_flip.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_flip.glsl new file mode 100644 index 00000000000..919c454ee63 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_flip.glsl @@ -0,0 +1,15 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + ivec2 size = texture_size(input_tx); + ivec2 flipped_texel = texel; + if (flip_x) { + flipped_texel.x = size.x - texel.x - 1; + } + if (flip_y) { + flipped_texel.y = size.y - texel.y - 1; + } + imageStore(output_img, texel, texture_load(input_tx, flipped_texel)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_image_crop.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_image_crop.glsl new file mode 100644 index 00000000000..f20e033dee4 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_image_crop.glsl @@ -0,0 +1,7 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + imageStore(output_img, texel, texture_load(input_tx, texel + lower_bound)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_morphological_distance.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_morphological_distance.glsl new file mode 100644 index 00000000000..09f896b7a9d --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_morphological_distance.glsl @@ -0,0 +1,24 @@ +#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + /* Find the minimum/maximum value in the circular window of the given radius around the pixel. By + * circular window, we mean that pixels in the window whose distance to the center of window is + * larger than the given radius are skipped and not considered. Consequently, the dilation or + * erosion that take place produces round results as opposed to squarish ones. This is + * essentially a morphological operator with a circular structuring element. The LIMIT value + * should be FLT_MAX if OPERATOR is min and FLT_MIN if OPERATOR is max. */ + float value = LIMIT; + for (int y = -radius; y <= radius; y++) { + for (int x = -radius; x <= radius; x++) { + if (x * x + y * y <= radius * radius) { + value = OPERATOR(value, texture_load(input_tx, texel + ivec2(x, y), vec4(LIMIT)).x); + } + } + } + + imageStore(output_img, texel, vec4(value)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_morphological_distance_feather.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_morphological_distance_feather.glsl new file mode 100644 index 00000000000..acdd8a40342 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_morphological_distance_feather.glsl @@ -0,0 +1,101 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +/* The Morphological Distance Feather operation is a linear combination between the result of two + * operations. The first operation is a Gaussian blur with a radius equivalent to the dilate/erode + * distance, which is straightforward and implemented as a separable filter similar to the blur + * operation. + * + * The second operation is an approximation of a morphological inverse distance operation evaluated + * at a distance falloff function. The result of a morphological inverse distance operation is a + * narrow band distance field that starts at its maximum value at boundaries where a difference in + * values took place and linearly deceases until it reaches zero in the span of a number of pixels + * equivalent to the erode/dilate distance. Additionally, instead of linearly decreasing, the user + * may choose a different falloff which is evaluated at the computed distance. For dilation, the + * distance field decreases outwards, and for erosion, the distance field decreased inwards. + * + * The reason why the result of a Gaussian blur is mixed in with the distance field is because the + * distance field is merely approximated and not accurately computed, the defects of which is more + * apparent away from boundaries and especially at corners where the distance field should take a + * circular shape. That's why the Gaussian blur is mostly mixed only further from boundaries. + * + * The morphological inverse distance operation is approximated using a separable implementation + * and intertwined with the Gaussian blur implementation as follows. A search window of a radius + * equivalent to the dilate/erode distance is applied on the image to find either the minimum or + * maximum pixel value multiplied by its corresponding falloff value in the window. For dilation, + * we try to find the maximum, and for erosion, we try to find the minimum. Additionally, we also + * save the falloff value where the minimum or maximum was found. The found value will be that of + * the narrow band distance field and the saved falloff value will be used as the mixing factor + * with the Gaussian blur. + * + * To make sense of the aforementioned algorithm, assume we are dilating a binary image by 5 pixels + * whose half has a value of 1 and the other half has a value of zero. Consider the following: + * + * - A pixel of value 1 already has the maximum possible value, so its value will remain unchanged + * regardless of its position. + * - A pixel of value 0 that is right at the boundary of the 1's region will have a maximum value + * of around 0.8 depending on the falloff. That's because the search window intersects the 1's + * region, which when multiplied by the falloff gives the first value of the falloff, which is + * larger than the initially zero value computed at the center of the search window. + * - A pixel of value 0 that is 3 pixels away from the boundary will have a maximum value of around + * 0.4 depending on the falloff. That's because the search window intersects the 1's region, + * which when multiplied by the falloff gives the third value of the falloff, which is larger + * than the initially zero value computed at the center of the search window. + * - Finally, a pixel of value 0 that is 6 pixels away from the boundary will have a maximum value + * of 0, because the search window doesn't intersects the 1's region and only spans zero values. + * + * The previous example demonstrates how the distance field naturally arises, and the same goes for + * the erode case, except the minimum value is computed instead. + */ +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + /* A value for accumulating the blur result. */ + float accumulated_value = 0.0; + + /* Compute the contribution of the center pixel to the blur result. */ + float center_value = texture_load(input_tx, texel).x; + accumulated_value += center_value * texture_load(weights_tx, 0).x; + + /* Start with the center value as the maximum/minimum distance and reassign to the true maximum + * or minimum in the search loop below. Additionally, the center falloff is always 1.0, so start + * with that. */ + float limit_distance = center_value; + float limit_distance_falloff = 1.0; + + /* Compute the contributions of the pixels to the right and left, noting that the weights and + * falloffs textures only store the weights and falloffs for the positive half, but since the + * they are both symmetric, the same weights and falloffs are used for the negative half and we + * compute both of their contributions. */ + for (int i = 1; i < texture_size(weights_tx); i++) { + float weight = texture_load(weights_tx, i).x; + float falloff = texture_load(falloffs_tx, i).x; + + /* Loop for two iterations, where s takes the value of -1 and 1, which is used as the sign + * needed to evaluated the positive and negative sides as explain above. */ + for (int s = -1; s < 2; s += 2) { + /* Compute the contribution of the pixel to the blur result. */ + float value = texture_load(input_tx, texel + ivec2(s * i, 0)).x; + accumulated_value += value * weight; + + /* The distance is computed such that its highest value is the pixel value itself, so + * multiply the distance falloff by the pixel value. */ + float falloff_distance = value * falloff; + + /* Find either the maximum or the minimum for the dilate and erode cases respectively. */ + if (COMPARE(falloff_distance, limit_distance)) { + limit_distance = falloff_distance; + limit_distance_falloff = falloff; + } + } + } + + /* Mix between the limit distance and the blurred accumulated value such that the limit distance + * is used for pixels closer to the boundary and the blurred value is used for pixels away from + * the boundary. */ + float value = mix(accumulated_value, limit_distance, limit_distance_falloff); + + /* Write the value using the transposed texel. See the execute_distance_feather_horizontal_pass + * method for more information on the rational behind this. */ + imageStore(output_img, texel.yx, vec4(value)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_morphological_distance_threshold.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_morphological_distance_threshold.glsl new file mode 100644 index 00000000000..e6625e7419f --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_morphological_distance_threshold.glsl @@ -0,0 +1,88 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +/* The Morphological Distance Threshold operation is effectively three consecutive operations + * implemented as a single operation. The three operations are as follows: + * + * .-----------. .--------------. .----------------. + * | Threshold |-->| Dilate/Erode |-->| Distance Inset | + * '-----------' '--------------' '----------------' + * + * The threshold operation just converts the input into a binary image, where the pixel is 1 if it + * is larger than 0.5 and 0 otherwise. Pixels that are 1 in the output of the threshold operation + * are said to be masked. The dilate/erode operation is a dilate or erode morphological operation + * with a circular structuring element depending on the sign of the distance, where it is a dilate + * operation if the distance is positive and an erode operation otherwise. This is equivalent to + * the Morphological Distance operation, see its implementation for more information. Finally, the + * distance inset is an operation that converts the binary image into a narrow band distance field. + * That is, pixels that are unmasked will remain 0, while pixels that are masked will start from + * zero at the boundary of the masked region and linearly increase until reaching 1 in the span of + * a number pixels given by the inset value. + * + * As a performance optimization, the dilate/erode operation is omitted and its effective result is + * achieved by slightly adjusting the distance inset operation. The base distance inset operation + * works by computing the signed distance from the current center pixel to the nearest pixel with a + * different value. Since our image is a binary image, that means that if the pixel is masked, we + * compute the signed distance to the nearest unmasked pixel, and if the pixel unmasked, we compute + * the signed distance to the nearest masked pixel. The distance is positive if the pixel is masked + * and negative otherwise. The distance is then normalized by dividing by the given inset value and + * clamped to the [0, 1] range. Since distances larger than the inset value are eventually clamped, + * the distance search window is limited to a radius equivalent to the inset value. + * + * To archive the effective result of the omitted dilate/erode operation, we adjust the distance + * inset operation as follows. First, we increase the radius of the distance search window by the + * radius of the dilate/erode operation. Then we adjust the resulting narrow band signed distance + * field as follows. + * + * For the erode case, we merely subtract the erode distance, which makes the outermost erode + * distance number of pixels zero due to clamping, consequently achieving the result of the erode, + * while retaining the needed inset because we increased the distance search window by the same + * amount we subtracted. + * + * Similarly, for the dilate case, we add the dilate distance, which makes the dilate distance + * number of pixels just outside of the masked region positive and part of the narrow band distance + * field, consequently achieving the result of the dilate, while at the same time, the innermost + * dilate distance number of pixels become 1 due to clamping, retaining the needed inset because we + * increased the distance search window by the same amount we added. + * + * Since the erode/dilate distance is already signed appropriately as described before, we just add + * it in both cases. */ +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + /* Apply a threshold operation on the center pixel, where the threshold is currently hard-coded + * at 0.5. The pixels with values larger than the threshold are said to be masked. */ + bool is_center_masked = texture_load(input_tx, texel).x > 0.5; + + /* Since the distance search window will access pixels outside of the bounds of the image, we use + * a texture loader with a fallback value. And since we don't want those values to affect the + * result, the fallback value is chosen such that the inner condition fails, which is when the + * sampled pixel and the center pixel are the same, so choose a fallback that will be considered + * masked if the center pixel is masked and unmasked otherwise. */ + vec4 fallback = vec4(is_center_masked ? 1.0 : 0.0); + + /* Since the distance search window is limited to the given radius, the maximum possible squared + * distance to the center is double the squared radius. */ + int minimum_squared_distance = radius * radius * 2; + + /* Find the squared distance to the nearest different pixel in the search window of the given + * radius. */ + for (int y = -radius; y <= radius; y++) { + for (int x = -radius; x <= radius; x++) { + bool is_sample_masked = texture_load(input_tx, texel + ivec2(x, y), fallback).x > 0.5; + if (is_center_masked != is_sample_masked) { + minimum_squared_distance = min(minimum_squared_distance, x * x + y * y); + } + } + } + + /* Compute the actual distance from the squared distance and assign it an appropriate sign + * depending on whether it lies in a masked region or not. */ + float signed_minimum_distance = sqrt(minimum_squared_distance) * (is_center_masked ? 1.0 : -1.0); + + /* Add the erode/dilate distance and divide by the inset amount as described in the discussion, + * then clamp to the [0, 1] range. */ + float value = clamp((signed_minimum_distance + distance) / inset, 0.0, 1.0); + + imageStore(output_img, texel, vec4(value)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_morphological_step.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_morphological_step.glsl new file mode 100644 index 00000000000..6992bc2afa5 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_morphological_step.glsl @@ -0,0 +1,19 @@ +#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + /* Find the minimum/maximum value in the window of the given radius around the pixel. This is + * essentially a morphological operator with a square structuring element. The LIMIT value should + * be FLT_MAX if OPERATOR is min and FLT_MIN if OPERATOR is max. */ + float value = LIMIT; + for (int i = -radius; i <= radius; i++) { + value = OPERATOR(value, texture_load(input_tx, texel + ivec2(i, 0), vec4(LIMIT)).x); + } + + /* Write the value using the transposed texel. See the execute_step_horizontal_pass method for + * more information on the rational behind this. */ + imageStore(output_img, texel.yx, vec4(value)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_normalize.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_normalize.glsl new file mode 100644 index 00000000000..53dfeb01730 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_normalize.glsl @@ -0,0 +1,10 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + float value = texture_load(input_tx, texel).x; + float normalized_value = (value - minimum) * scale; + float clamped_value = clamp(normalized_value, 0.0, 1.0); + imageStore(output_img, texel, vec4(clamped_value)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_parallel_reduction.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_parallel_reduction.glsl new file mode 100644 index 00000000000..f6f84aa24c1 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_parallel_reduction.glsl @@ -0,0 +1,98 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +/* This shader reduces the given texture into a smaller texture of a size equal to the number of + * work groups. In particular, each work group reduces its contents into a single value and writes + * that value to a single pixel in the output image. The shader can be dispatched multiple times to + * eventually reduce the image into a single pixel. + * + * The shader works by loading the whole data of each work group into a linear array, then it + * reduces the second half of the array onto the first half of the array, then it reduces the + * second quarter of the array onto the first quarter or the array, and so on until only one + * element remains. The following figure illustrates the process for sum reduction on 8 elements. + * + * .---. .---. .---. .---. .---. .---. .---. .---. + * | 0 | | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | | 7 | Original data. + * '---' '---' '---' '---' '---' '---' '---' '---' + * |.____|_____|_____|_____| | | | + * || |.____|_____|___________| | | + * || || |.____|_________________| | + * || || || |.______________________| <--First reduction. Stride = 4. + * || || || || + * .---. .---. .---. .----. + * | 4 | | 6 | | 8 | | 10 | <--Data after first reduction. + * '---' '---' '---' '----' + * |.____|_____| | + * || |.__________| <--Second reduction. Stride = 2. + * || || + * .----. .----. + * | 12 | | 16 | <--Data after second reduction. + * '----' '----' + * |.____| + * || <--Third reduction. Stride = 1. + * .----. + * | 28 | + * '----' <--Data after third reduction. + * + * + * The shader is generic enough to implement many types of reductions. This is done by using macros + * that the developer should define to implement a certain reduction operation. Those include, + * TYPE, IDENTITY, INITIALIZE, LOAD, and REDUCE. See the implementation below for more information + * as well as the compositor_parallel_reduction_info.hh for example reductions operations. */ + +/* Doing the reduction in shared memory is faster, so create a shared array where the whole data + * of the work group will be loaded and reduced. The 2D structure of the work group is irrelevant + * for reduction, so we just load the data in a 1D array to simplify reduction. The developer is + * expected to define the TYPE macro to be a float or a vec4, depending on the type of data being + * reduced. */ +const uint reduction_size = gl_WorkGroupSize.x * gl_WorkGroupSize.y; +shared TYPE reduction_data[reduction_size]; + +void main() +{ + /* Load the data from the texture, while returning IDENTITY for out of bound coordinates. The + * developer is expected to define the IDENTITY macro to be a vec4 that does not affect the + * output of the reduction. For instance, sum reductions have an identity of vec4(0.0), while + * max value reductions have an identity of vec4(FLT_MIN). */ + vec4 value = texture_load(input_tx, ivec2(gl_GlobalInvocationID.xy), IDENTITY); + + /* Initialize the shared array given the previously loaded value. This step can be different + * depending on whether this is the initial reduction pass or a latter one. Indeed, the input + * texture for the initial reduction is the source texture itself, while the input texture to a + * latter reduction pass is an intermediate texture after one or more reductions have happened. + * This is significant because the data being reduced might be computed from the original data + * and different from it, for instance, when summing the luminance of an image, the original data + * is a vec4 color, while the reduced data is a float luminance value. So for the initial + * reduction pass, the luminance will be computed from the color, reduced, then stored into an + * intermediate float texture. On the other hand, for latter reduction passes, the luminance will + * be loaded directly and reduced without extra processing. So the developer is expected to + * define the INITIALIZE and LOAD macros to be expressions that derive the needed value from the + * loaded value for the initial reduction pass and latter ones respectively. */ + reduction_data[gl_LocalInvocationIndex] = is_initial_reduction ? INITIALIZE(value) : LOAD(value); + + /* Reduce the reduction data by half on every iteration until only one element remains. See the + * above figure for an intuitive understanding of the stride value. */ + for (uint stride = reduction_size / 2; stride > 0; stride /= 2) { + barrier(); + + /* Only the threads up to the current stride should be active as can be seen in the diagram + * above. */ + if (gl_LocalInvocationIndex >= stride) { + continue; + } + + /* Reduce each two elements that are stride apart, writing the result to the element with the + * lower index, as can be seen in the diagram above. The developer is expected to define the + * REDUCE macro to be a commutative and associative binary operator suitable for parallel + * reduction. */ + reduction_data[gl_LocalInvocationIndex] = REDUCE( + reduction_data[gl_LocalInvocationIndex], reduction_data[gl_LocalInvocationIndex + stride]); + } + + /* Finally, the result of the reduction is available as the first element in the reduction data, + * write it to the pixel corresponding to the work group, making sure only the one thread writes + * it. */ + barrier(); + if (gl_LocalInvocationIndex == 0) { + imageStore(output_img, ivec2(gl_WorkGroupID.xy), vec4(reduction_data[0])); + } +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_projector_lens_distortion.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_projector_lens_distortion.glsl new file mode 100644 index 00000000000..ab44dac93e6 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_projector_lens_distortion.glsl @@ -0,0 +1,16 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + /* Get the normalized coordinates of the pixel centers. */ + vec2 normalized_texel = (vec2(texel) + vec2(0.5)) / vec2(texture_size(input_tx)); + + /* Sample the red and blue channels shifted by the dispersion amount. */ + const float red = texture(input_tx, normalized_texel + vec2(dispersion, 0.0)).r; + const float green = texture_load(input_tx, texel).g; + const float blue = texture(input_tx, normalized_texel - vec2(dispersion, 0.0)).b; + + imageStore(output_img, texel, vec4(red, green, blue, 1.0)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_realize_on_domain.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_realize_on_domain.glsl new file mode 100644 index 00000000000..b8561e5f059 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_realize_on_domain.glsl @@ -0,0 +1,29 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + /* Add 0.5 to evaluate the input sampler at the center of the pixel. */ + vec2 coordinates = vec2(texel) + vec2(0.5); + + /* Transform the input image by transforming the domain coordinates with the inverse of input + * image's transformation. The inverse transformation is an affine matrix and thus the + * coordinates should be in homogeneous coordinates. */ + coordinates = (mat3(inverse_transformation) * vec3(coordinates, 1.0)).xy; + + /* Since an input image with an identity transformation is supposed to be centered in the domain, + * we subtract the offset between the lower left corners of the input image and the domain, which + * is half the difference between their sizes, because the difference in size is on both sides of + * the centered image. Additionally, we floor the offset to retain the 0.5 offset added above in + * case the difference in sizes was odd. */ + ivec2 domain_size = imageSize(domain_img); + ivec2 input_size = texture_size(input_tx); + vec2 offset = floor((domain_size - input_size) / 2.0); + + /* Subtract the offset and divide by the input image size to get the relevant coordinates into + * the sampler's expected [0, 1] range. */ + vec2 normalized_coordinates = (coordinates - offset) / input_size; + + imageStore(domain_img, texel, texture(input_tx, normalized_coordinates)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_screen_lens_distortion.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_screen_lens_distortion.glsl new file mode 100644 index 00000000000..dc572ea5aaf --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_screen_lens_distortion.glsl @@ -0,0 +1,151 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_hash.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +/* A model that approximates lens distortion parameterized by a distortion parameter and dependent + * on the squared distance to the center of the image. The distorted pixel is then computed as the + * scalar multiplication of the pixel coordinates with the value returned by this model. See the + * compute_distorted_uv function for more details. */ +float compute_distortion_scale(float distortion, float distance_squared) +{ + return 1.0 / (1.0 + sqrt(max(0.0, 1.0 - distortion * distance_squared))); +} + +/* A vectorized version of compute_distortion_scale that is applied on the chromatic distortion + * parameters passed to the shader. */ +vec3 compute_chromatic_distortion_scale(float distance_squared) +{ + return 1.0 / (1.0 + sqrt(max(vec3(0.0), 1.0 - chromatic_distortion * distance_squared))); +} + +/* Compute the image coordinates after distortion by the given distortion scale computed by the + * compute_distortion_scale function. Note that the function expects centered normalized UV + * coordinates but outputs non-centered image coordinates. */ +vec2 compute_distorted_uv(vec2 uv, float scale) +{ + return (uv * scale + 0.5) * texture_size(input_tx) - 0.5; +} + +/* Compute the number of integration steps that should be used to approximate the distorted pixel + * using a heuristic, see the compute_number_of_steps function for more details. The numbers of + * steps is proportional to the number of pixels spanned by the distortion amount. For jitter + * distortion, the square root of the distortion amount plus 1 is used with a minimum of 2 steps. + * For non-jitter distortion, the distortion amount plus 1 is used as the number of steps */ +int compute_number_of_integration_steps_heuristic(float distortion) +{ +#if defined(JITTER) + return distortion < 4.0 ? 2 : int(sqrt(distortion + 1.0)); +#else + return int(distortion + 1.0); +#endif +} + +/* Compute the number of integration steps that should be used to compute each channel of the + * distorted pixel. Each of the channels are distorted by their respective chromatic distortion + * amount, then the amount of distortion between each two consecutive channels is computed, this + * amount is then used to heuristically infer the number of needed integration steps, see the + * integrate_distortion function for more information. */ +ivec3 compute_number_of_integration_steps(vec2 uv, float distance_squared) +{ + /* Distort each channel by its respective chromatic distortion amount. */ + vec3 distortion_scale = compute_chromatic_distortion_scale(distance_squared); + vec2 distorted_uv_red = compute_distorted_uv(uv, distortion_scale.r); + vec2 distorted_uv_green = compute_distorted_uv(uv, distortion_scale.g); + vec2 distorted_uv_blue = compute_distorted_uv(uv, distortion_scale.b); + + /* Infer the number of needed integration steps to compute the distorted red channel starting + * from the green channel. */ + float distortion_red = distance(distorted_uv_red, distorted_uv_green); + int steps_red = compute_number_of_integration_steps_heuristic(distortion_red); + + /* Infer the number of needed integration steps to compute the distorted blue channel starting + * from the green channel. */ + float distortion_blue = distance(distorted_uv_green, distorted_uv_blue); + int steps_blue = compute_number_of_integration_steps_heuristic(distortion_blue); + + /* The number of integration steps used to compute the green channel is the sum of both the red + * and the blue channel steps because it is computed once with each of them. */ + return ivec3(steps_red, steps_red + steps_blue, steps_blue); +} + +/* Returns a random jitter amount, which is essentially a random value in the [0, 1] range. If + * jitter is not enabled, return a constant 0.5 value instead. */ +float get_jitter(int seed) +{ +#if defined(JITTER) + return hash_uint3_to_float(gl_GlobalInvocationID.x, gl_GlobalInvocationID.y, seed); +#else + return 0.5; +#endif +} + +/* Each color channel may have a different distortion with the guarantee that the red will have the + * lowest distortion while the blue will have the highest one. If each channel is distorted + * independently, the image will look disintegrated, with each channel seemingly merely shifted. + * Consequently, the distorted pixels needs to be computed by integrating along the path of change + * of distortion starting from one channel to another. For instance, to compute the distorted red + * from the distorted green, we accumulate the color of the distorted pixel starting from the + * distortion of the red, taking small steps until we reach the distortion of the green. The pixel + * color is weighted such that it is maximum at the start distortion and zero at the end distortion + * in an arithmetic progression. The integration steps can be augmented with random values to + * simulate lens jitter. Finally, it should be noted that this function integrates both the start + * and end channels in reverse directions for more efficient computation. */ +vec3 integrate_distortion(int start, int end, float distance_squared, vec2 uv, int steps) +{ + vec3 accumulated_color = vec3(0.0); + float distortion_amount = chromatic_distortion[end] - chromatic_distortion[start]; + for (int i = 0; i < steps; i++) { + /* The increment will be in the [0, 1) range across iterations. */ + float increment = (i + get_jitter(i)) / steps; + float distortion = chromatic_distortion[start] + increment * distortion_amount; + float distortion_scale = compute_distortion_scale(distortion, distance_squared); + + /* Sample the color at the distorted coordinates and accumulate it weighted by the increment + * value for both the start and end channels. */ + vec2 distorted_uv = compute_distorted_uv(uv, distortion_scale); + vec4 color = texture(input_tx, distorted_uv / texture_size(input_tx)); + accumulated_color[start] += (1.0 - increment) * color[start]; + accumulated_color[end] += increment * color[end]; + } + return accumulated_color; +} + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + /* Compute the UV image coordinates in the range [-1, 1] as well as the squared distance to the + * center of the image, which is at (0, 0) in the UV coordinates. */ + vec2 center = texture_size(input_tx) / 2.0; + vec2 uv = scale * (texel + 0.5 - center) / center; + float distance_squared = dot(uv, uv); + + /* If any of the color channels will get distorted outside of the screen beyond what is possible, + * write a zero transparent color and return. */ + if (any(greaterThan(chromatic_distortion * distance_squared, vec3(1.0)))) { + imageStore(output_img, texel, vec4(0.0)); + return; + } + + /* Compute the number of integration steps that should be used to compute each channel of the + * distorted pixel. */ + ivec3 number_of_steps = compute_number_of_integration_steps(uv, distance_squared); + + /* Integrate the distortion of the red and green, then the green and blue channels. That means + * the green will be integrated twice, but this is accounted for in the number of steps which the + * color will later be divided by. See the compute_number_of_integration_steps function for more + * details. */ + vec3 color = vec3(0.0); + color += integrate_distortion(0, 1, distance_squared, uv, number_of_steps.r); + color += integrate_distortion(1, 2, distance_squared, uv, number_of_steps.b); + + /* The integration above performed weighted accumulation, and thus the color needs to be divided + * by the sum of the weights. Assuming no jitter, the weights are generated as an arithmetic + * progression starting from (0.5 / n) to ((n - 0.5) / n) for n terms. The sum of an arithmetic + * progression can be computed as (n * (start + end) / 2), which when subsisting the start and + * end reduces to (n / 2). So the color should be multiplied by 2 / n. The jitter sequence + * approximately sums to the same value because it is a uniform random value whose mean value is + * 0.5, so the expression doesn't change regardless of jitter. */ + color *= 2.0 / vec3(number_of_steps); + + imageStore(output_img, texel, vec4(color, 1.0)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_set_alpha.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_set_alpha.glsl new file mode 100644 index 00000000000..7dd40581790 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_set_alpha.glsl @@ -0,0 +1,8 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + vec4 color = vec4(texture_load(image_tx, texel).rgb, texture_load(alpha_tx, texel).x); + imageStore(output_img, texel, color); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_split_viewer.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_split_viewer.glsl new file mode 100644 index 00000000000..866b9045da2 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_split_viewer.glsl @@ -0,0 +1,14 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); +#if defined(SPLIT_HORIZONTAL) + bool condition = (view_size.x * split_ratio) < texel.x; +#elif defined(SPLIT_VERTICAL) + bool condition = (view_size.y * split_ratio) < texel.y; +#endif + vec4 color = condition ? texture_load(first_image_tx, texel) : + texture_load(second_image_tx, texel); + imageStore(output_img, texel, color); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_symmetric_blur.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_symmetric_blur.glsl new file mode 100644 index 00000000000..df08991a35c --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_symmetric_blur.glsl @@ -0,0 +1,77 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_blur_common.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +vec4 load_input(ivec2 texel) +{ + vec4 color; + if (extend_bounds) { + /* If bounds are extended, then we treat the input as padded by a radius amount of pixels. So + * we load the input with an offset by the radius amount and fallback to a transparent color if + * it is out of bounds. Notice that we subtract 1 because the weights texture have an extra + * center weight, see the SymmetricBlurWeights for more information. */ + ivec2 blur_size = texture_size(weights_tx) - 1; + color = texture_load(input_tx, texel - blur_size, vec4(0.0)); + } + else { + color = texture_load(input_tx, texel); + } + + if (gamma_correct) { + color = gamma_correct_blur_input(color); + } + + return color; +} + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + vec4 accumulated_color = vec4(0.0); + + /* First, compute the contribution of the center pixel. */ + vec4 center_color = load_input(texel); + accumulated_color += center_color * texture_load(weights_tx, ivec2(0)).x; + + ivec2 weights_size = texture_size(weights_tx); + + /* Then, compute the contributions of the pixels along the x axis of the filter, noting that the + * weights texture only stores the weights for the positive half, but since the filter is + * symmetric, the same weight is used for the negative half and we add both of their + * contributions. */ + for (int x = 1; x < weights_size.x; x++) { + float weight = texture_load(weights_tx, ivec2(x, 0)).x; + accumulated_color += load_input(texel + ivec2(x, 0)) * weight; + accumulated_color += load_input(texel + ivec2(-x, 0)) * weight; + } + + /* Then, compute the contributions of the pixels along the y axis of the filter, noting that the + * weights texture only stores the weights for the positive half, but since the filter is + * symmetric, the same weight is used for the negative half and we add both of their + * contributions. */ + for (int y = 1; y < weights_size.y; y++) { + float weight = texture_load(weights_tx, ivec2(0, y)).x; + accumulated_color += load_input(texel + ivec2(0, y)) * weight; + accumulated_color += load_input(texel + ivec2(0, -y)) * weight; + } + + /* Finally, compute the contributions of the pixels in the four quadrants of the filter, noting + * that the weights texture only stores the weights for the upper right quadrant, but since the + * filter is symmetric, the same weight is used for the rest of the quadrants and we add all four + * of their contributions. */ + for (int y = 1; y < weights_size.y; y++) { + for (int x = 1; x < weights_size.x; x++) { + float weight = texture_load(weights_tx, ivec2(x, y)).x; + accumulated_color += load_input(texel + ivec2(x, y)) * weight; + accumulated_color += load_input(texel + ivec2(-x, y)) * weight; + accumulated_color += load_input(texel + ivec2(x, -y)) * weight; + accumulated_color += load_input(texel + ivec2(-x, -y)) * weight; + } + } + + if (gamma_correct) { + accumulated_color = gamma_uncorrect_blur_output(accumulated_color); + } + + imageStore(output_img, texel, accumulated_color); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_symmetric_separable_blur.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_symmetric_separable_blur.glsl new file mode 100644 index 00000000000..ab0c7baa787 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_symmetric_separable_blur.glsl @@ -0,0 +1,53 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_blur_common.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +vec4 load_input(ivec2 texel) +{ + vec4 color; + if (extend_bounds) { + /* If bounds are extended, then we treat the input as padded by a radius amount of pixels. So + * we load the input with an offset by the radius amount and fallback to a transparent color if + * it is out of bounds. Notice that we subtract 1 because the weights texture have an extra + * center weight, see the SymmetricSeparableBlurWeights for more information. */ + int blur_size = texture_size(weights_tx) - 1; + color = texture_load(input_tx, texel - ivec2(blur_size, 0), vec4(0.0)); + } + else { + color = texture_load(input_tx, texel); + } + + if (gamma_correct_input) { + color = gamma_correct_blur_input(color); + } + + return color; +} + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + vec4 accumulated_color = vec4(0.0); + + /* First, compute the contribution of the center pixel. */ + vec4 center_color = load_input(texel); + accumulated_color += center_color * texture_load(weights_tx, 0).x; + + /* Then, compute the contributions of the pixel to the right and left, noting that the + * weights texture only stores the weights for the positive half, but since the filter is + * symmetric, the same weight is used for the negative half and we add both of their + * contributions. */ + for (int i = 1; i < texture_size(weights_tx); i++) { + float weight = texture_load(weights_tx, i).x; + accumulated_color += load_input(texel + ivec2(i, 0)) * weight; + accumulated_color += load_input(texel + ivec2(-i, 0)) * weight; + } + + if (gamma_uncorrect_output) { + accumulated_color = gamma_uncorrect_blur_output(accumulated_color); + } + + /* Write the color using the transposed texel. See the execute_separable_blur_horizontal_pass + * method for more information on the rational behind this. */ + imageStore(output_img, texel.yx, accumulated_color); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_tone_map_photoreceptor.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_tone_map_photoreceptor.glsl new file mode 100644 index 00000000000..167006585ca --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_tone_map_photoreceptor.glsl @@ -0,0 +1,22 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +/* Tone mapping based on equation (1) and the trilinear interpolation between equations (6) and (7) + * from Reinhard, Erik, and Kate Devlin. "Dynamic range reduction inspired by photoreceptor + * physiology." IEEE transactions on visualization and computer graphics 11.1 (2005): 13-24. */ +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + vec4 input_color = texture_load(input_tx, texel); + float input_luminance = dot(input_color.rgb, luminance_coefficients); + + /* Trilinear interpolation between equations (6) and (7) from Reinhard's 2005 paper. */ + vec4 local_adaptation_level = mix(vec4(input_luminance), input_color, chromatic_adaptation); + vec4 adaptation_level = mix(global_adaptation_level, local_adaptation_level, light_adaptation); + + /* Equation (1) from Reinhard's 2005 paper, assuming Vmax is 1. */ + vec4 semi_saturation = pow(intensity * adaptation_level, vec4(contrast)); + vec4 tone_mapped_color = input_color / (input_color + semi_saturation); + + imageStore(output_img, texel, vec4(tone_mapped_color.rgb, input_color.a)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_tone_map_simple.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_tone_map_simple.glsl new file mode 100644 index 00000000000..ce42d021dd1 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_tone_map_simple.glsl @@ -0,0 +1,26 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl) + +/* Tone mapping based on equation (3) from Reinhard, Erik, et al. "Photographic tone reproduction + * for digital images." Proceedings of the 29th annual conference on Computer graphics and + * interactive techniques. 2002. */ +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + vec4 input_color = texture_load(input_tx, texel); + + /* Equation (2) from Reinhard's 2002 paper. */ + vec4 scaled_color = input_color * luminance_scale; + + /* Equation (3) from Reinhard's 2002 paper, but with the 1 replaced with the blend factor for + * more flexibility. See ToneMapOperation::compute_luminance_scale_blend_factor. */ + vec4 denominator = luminance_scale_blend_factor + scaled_color; + vec4 tone_mapped_color = safe_divide(scaled_color, denominator); + + if (inverse_gamma != 0.0) { + tone_mapped_color = pow(max(tone_mapped_color, vec4(0.0)), vec4(inverse_gamma)); + } + + imageStore(output_img, texel, vec4(tone_mapped_color.rgb, input_color.a)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_alpha_crop_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_alpha_crop_info.hh new file mode 100644 index 00000000000..11f2f329cd8 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_alpha_crop_info.hh @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_alpha_crop) + .local_group_size(16, 16) + .push_constant(Type::IVEC2, "lower_bound") + .push_constant(Type::IVEC2, "upper_bound") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_alpha_crop.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_bilateral_blur_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_bilateral_blur_info.hh new file mode 100644 index 00000000000..301cd6acd9e --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_bilateral_blur_info.hh @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_bilateral_blur) + .local_group_size(16, 16) + .push_constant(Type::INT, "radius") + .push_constant(Type::FLOAT, "threshold") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .sampler(1, ImageType::FLOAT_2D, "determinator_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_bilateral_blur.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_blur_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_blur_info.hh new file mode 100644 index 00000000000..36b772aa486 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_blur_info.hh @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_blur) + .local_group_size(16, 16) + .push_constant(Type::INT, "radius") + .push_constant(Type::BOOL, "extend_bounds") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .sampler(1, ImageType::FLOAT_2D, "weights_tx") + .sampler(2, ImageType::FLOAT_2D, "mask_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_blur.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_blur_variable_size_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_blur_variable_size_info.hh new file mode 100644 index 00000000000..05b6385fd1e --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_blur_variable_size_info.hh @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_blur_variable_size) + .local_group_size(16, 16) + .push_constant(Type::FLOAT, "base_size") + .push_constant(Type::INT, "search_radius") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .sampler(1, ImageType::FLOAT_2D, "weights_tx") + .sampler(2, ImageType::FLOAT_2D, "size_tx") + .sampler(3, ImageType::FLOAT_2D, "mask_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_blur_variable_size.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_bokeh_image_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_bokeh_image_info.hh new file mode 100644 index 00000000000..3541de53070 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_bokeh_image_info.hh @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_bokeh_image) + .local_group_size(16, 16) + .push_constant(Type::FLOAT, "exterior_angle") + .push_constant(Type::FLOAT, "rotation") + .push_constant(Type::FLOAT, "roundness") + .push_constant(Type::FLOAT, "catadioptric") + .push_constant(Type::FLOAT, "lens_shift") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_bokeh_image.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_box_mask_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_box_mask_info.hh new file mode 100644 index 00000000000..ecb253bbab1 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_box_mask_info.hh @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_box_mask_shared) + .local_group_size(16, 16) + .push_constant(Type::IVEC2, "domain_size") + .push_constant(Type::VEC2, "location") + .push_constant(Type::VEC2, "size") + .push_constant(Type::FLOAT, "cos_angle") + .push_constant(Type::FLOAT, "sin_angle") + .sampler(0, ImageType::FLOAT_2D, "base_mask_tx") + .sampler(1, ImageType::FLOAT_2D, "mask_value_tx") + .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_mask_img") + .compute_source("compositor_box_mask.glsl"); + +GPU_SHADER_CREATE_INFO(compositor_box_mask_add) + .additional_info("compositor_box_mask_shared") + .define("CMP_NODE_MASKTYPE_ADD") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_box_mask_subtract) + .additional_info("compositor_box_mask_shared") + .define("CMP_NODE_MASKTYPE_SUBTRACT") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_box_mask_multiply) + .additional_info("compositor_box_mask_shared") + .define("CMP_NODE_MASKTYPE_MULTIPLY") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_box_mask_not) + .additional_info("compositor_box_mask_shared") + .define("CMP_NODE_MASKTYPE_NOT") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_convert_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_convert_info.hh new file mode 100644 index 00000000000..35e60056736 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_convert_info.hh @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_convert_shared) + .local_group_size(16, 16) + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .typedef_source("gpu_shader_compositor_type_conversion.glsl") + .compute_source("compositor_convert.glsl"); + +GPU_SHADER_CREATE_INFO(compositor_convert_float_to_vector) + .additional_info("compositor_convert_shared") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .define("CONVERT_EXPRESSION(value)", "vec4(vec3_from_float(value.x), 0.0)") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_convert_float_to_color) + .additional_info("compositor_convert_shared") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .define("CONVERT_EXPRESSION(value)", "vec4_from_float(value.x)") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_convert_color_to_float) + .additional_info("compositor_convert_shared") + .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .define("CONVERT_EXPRESSION(value)", "vec4(float_from_vec4(value), vec3(0.0))") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_convert_color_to_vector) + .additional_info("compositor_convert_shared") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .define("CONVERT_EXPRESSION(value)", "vec4(vec3_from_vec4(value), 0.0)") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_convert_vector_to_float) + .additional_info("compositor_convert_shared") + .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .define("CONVERT_EXPRESSION(value)", "vec4(float_from_vec3(value.xyz), vec3(0.0))") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_convert_vector_to_color) + .additional_info("compositor_convert_shared") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .define("CONVERT_EXPRESSION(value)", "vec4_from_vec3(value.xyz)") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_extract_alpha_from_color) + .additional_info("compositor_convert_shared") + .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .define("CONVERT_EXPRESSION(value)", "vec4(value.a, vec3(0.0))") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_convert_color_to_half_color) + .additional_info("compositor_convert_shared") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .define("CONVERT_EXPRESSION(value)", "value") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_convert_float_to_half_float) + .additional_info("compositor_convert_shared") + .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .define("CONVERT_EXPRESSION(value)", "vec4(value.r, vec3(0.0))") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_convert_color_to_opaque) + .additional_info("compositor_convert_shared") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .define("CONVERT_EXPRESSION(value)", "vec4(value.rgb, 1.0)") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_despeckle_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_despeckle_info.hh new file mode 100644 index 00000000000..df86c3a8258 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_despeckle_info.hh @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_despeckle) + .local_group_size(16, 16) + .push_constant(Type::FLOAT, "threshold") + .push_constant(Type::FLOAT, "neighbor_threshold") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .sampler(1, ImageType::FLOAT_2D, "factor_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_despeckle.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_directional_blur_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_directional_blur_info.hh new file mode 100644 index 00000000000..bb9199dcd26 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_directional_blur_info.hh @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_directional_blur) + .local_group_size(16, 16) + .push_constant(Type::INT, "iterations") + .push_constant(Type::MAT4, "inverse_transformation") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_directional_blur.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_edge_filter_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_edge_filter_info.hh new file mode 100644 index 00000000000..916ec62bdba --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_edge_filter_info.hh @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_edge_filter) + .local_group_size(16, 16) + .push_constant(Type::MAT4, "kernel") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .sampler(1, ImageType::FLOAT_2D, "factor_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_edge_filter.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_ellipse_mask_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_ellipse_mask_info.hh new file mode 100644 index 00000000000..52db91c94e5 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_ellipse_mask_info.hh @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_ellipse_mask_shared) + .local_group_size(16, 16) + .push_constant(Type::IVEC2, "domain_size") + .push_constant(Type::VEC2, "location") + .push_constant(Type::VEC2, "radius") + .push_constant(Type::FLOAT, "cos_angle") + .push_constant(Type::FLOAT, "sin_angle") + .sampler(0, ImageType::FLOAT_2D, "base_mask_tx") + .sampler(1, ImageType::FLOAT_2D, "mask_value_tx") + .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_mask_img") + .compute_source("compositor_ellipse_mask.glsl"); + +GPU_SHADER_CREATE_INFO(compositor_ellipse_mask_add) + .additional_info("compositor_ellipse_mask_shared") + .define("CMP_NODE_MASKTYPE_ADD") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_ellipse_mask_subtract) + .additional_info("compositor_ellipse_mask_shared") + .define("CMP_NODE_MASKTYPE_SUBTRACT") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_ellipse_mask_multiply) + .additional_info("compositor_ellipse_mask_shared") + .define("CMP_NODE_MASKTYPE_MULTIPLY") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_ellipse_mask_not) + .additional_info("compositor_ellipse_mask_shared") + .define("CMP_NODE_MASKTYPE_NOT") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_filter_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_filter_info.hh new file mode 100644 index 00000000000..9d565cf4b8a --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_filter_info.hh @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_filter) + .local_group_size(16, 16) + .push_constant(Type::MAT4, "kernel") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .sampler(1, ImageType::FLOAT_2D, "factor_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_filter.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_flip_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_flip_info.hh new file mode 100644 index 00000000000..db831518cb7 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_flip_info.hh @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_flip) + .local_group_size(16, 16) + .push_constant(Type::BOOL, "flip_x") + .push_constant(Type::BOOL, "flip_y") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_flip.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_image_crop_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_image_crop_info.hh new file mode 100644 index 00000000000..e7736744c40 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_image_crop_info.hh @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_image_crop) + .local_group_size(16, 16) + .push_constant(Type::IVEC2, "lower_bound") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_image_crop.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_morphological_distance_feather_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_morphological_distance_feather_info.hh new file mode 100644 index 00000000000..9f17f60129d --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_morphological_distance_feather_info.hh @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_morphological_distance_feather_shared) + .local_group_size(16, 16) + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .sampler(1, ImageType::FLOAT_1D, "weights_tx") + .sampler(2, ImageType::FLOAT_1D, "falloffs_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_morphological_distance_feather.glsl"); + +GPU_SHADER_CREATE_INFO(compositor_morphological_distance_feather_dilate) + .additional_info("compositor_morphological_distance_feather_shared") + .define("COMPARE(x, y)", "x > y") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_morphological_distance_feather_erode) + .additional_info("compositor_morphological_distance_feather_shared") + .define("COMPARE(x, y)", "x < y") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_morphological_distance_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_morphological_distance_info.hh new file mode 100644 index 00000000000..fc960e119e5 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_morphological_distance_info.hh @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_morphological_distance_shared) + .local_group_size(16, 16) + .push_constant(Type::INT, "radius") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_morphological_distance.glsl"); + +GPU_SHADER_CREATE_INFO(compositor_morphological_distance_dilate) + .additional_info("compositor_morphological_distance_shared") + .define("OPERATOR(a, b)", "max(a, b)") + .define("LIMIT", "FLT_MIN") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_morphological_distance_erode) + .additional_info("compositor_morphological_distance_shared") + .define("OPERATOR(a, b)", "min(a, b)") + .define("LIMIT", "FLT_MAX") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_morphological_distance_threshold_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_morphological_distance_threshold_info.hh new file mode 100644 index 00000000000..b1d64f61b80 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_morphological_distance_threshold_info.hh @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_morphological_distance_threshold) + .local_group_size(16, 16) + .push_constant(Type::INT, "radius") + .push_constant(Type::INT, "distance") + .push_constant(Type::FLOAT, "inset") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_morphological_distance_threshold.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_morphological_step_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_morphological_step_info.hh new file mode 100644 index 00000000000..e97ffd9feea --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_morphological_step_info.hh @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_morphological_step_shared) + .local_group_size(16, 16) + .push_constant(Type::INT, "radius") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_morphological_step.glsl"); + +GPU_SHADER_CREATE_INFO(compositor_morphological_step_dilate) + .additional_info("compositor_morphological_step_shared") + .define("OPERATOR(a, b)", "max(a, b)") + .define("LIMIT", "FLT_MIN") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_morphological_step_erode) + .additional_info("compositor_morphological_step_shared") + .define("OPERATOR(a, b)", "min(a, b)") + .define("LIMIT", "FLT_MAX") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_normalize_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_normalize_info.hh new file mode 100644 index 00000000000..02fdc424014 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_normalize_info.hh @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_normalize) + .local_group_size(16, 16) + .push_constant(Type::FLOAT, "minimum") + .push_constant(Type::FLOAT, "scale") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_normalize.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_parallel_reduction_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_parallel_reduction_info.hh new file mode 100644 index 00000000000..e2252b14758 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_parallel_reduction_info.hh @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_parallel_reduction_shared) + .local_group_size(16, 16) + .push_constant(Type::BOOL, "is_initial_reduction") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .compute_source("compositor_parallel_reduction.glsl"); + +/* -------------------------------------------------------------------- + * Sum Reductions. + */ + +GPU_SHADER_CREATE_INFO(compositor_sum_shared) + .additional_info("compositor_parallel_reduction_shared") + .define("IDENTITY", "vec4(0.0)") + .define("REDUCE(lhs, rhs)", "lhs + rhs"); + +GPU_SHADER_CREATE_INFO(compositor_sum_float_shared) + .additional_info("compositor_sum_shared") + .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .define("TYPE", "float") + .define("LOAD(value)", "value.x"); + +GPU_SHADER_CREATE_INFO(compositor_sum_red) + .additional_info("compositor_sum_float_shared") + .define("INITIALIZE(value)", "value.r") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_sum_green) + .additional_info("compositor_sum_float_shared") + .define("INITIALIZE(value)", "value.g") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_sum_blue) + .additional_info("compositor_sum_float_shared") + .define("INITIALIZE(value)", "value.b") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_sum_luminance) + .additional_info("compositor_sum_float_shared") + .push_constant(Type::VEC3, "luminance_coefficients") + .define("INITIALIZE(value)", "dot(value.rgb, luminance_coefficients)") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_sum_log_luminance) + .additional_info("compositor_sum_float_shared") + .push_constant(Type::VEC3, "luminance_coefficients") + .define("INITIALIZE(value)", "log(max(dot(value.rgb, luminance_coefficients), 1e-5))") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_sum_color) + .additional_info("compositor_sum_shared") + .image(0, GPU_RGBA32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .define("TYPE", "vec4") + .define("INITIALIZE(value)", "value") + .define("LOAD(value)", "value") + .do_static_compilation(true); + +/* -------------------------------------------------------------------- + * Sum Of Squared Difference Reductions. + */ + +GPU_SHADER_CREATE_INFO(compositor_sum_squared_difference_float_shared) + .additional_info("compositor_parallel_reduction_shared") + .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .push_constant(Type::FLOAT, "subtrahend") + .define("TYPE", "float") + .define("IDENTITY", "vec4(subtrahend)") + .define("LOAD(value)", "value.x") + .define("REDUCE(lhs, rhs)", "lhs + rhs"); + +GPU_SHADER_CREATE_INFO(compositor_sum_red_squared_difference) + .additional_info("compositor_sum_squared_difference_float_shared") + .define("INITIALIZE(value)", "pow(value.r - subtrahend, 2.0)") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_sum_green_squared_difference) + .additional_info("compositor_sum_squared_difference_float_shared") + .define("INITIALIZE(value)", "pow(value.g - subtrahend, 2.0)") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_sum_blue_squared_difference) + .additional_info("compositor_sum_squared_difference_float_shared") + .define("INITIALIZE(value)", "pow(value.b - subtrahend, 2.0)") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_sum_luminance_squared_difference) + .additional_info("compositor_sum_squared_difference_float_shared") + .push_constant(Type::VEC3, "luminance_coefficients") + .define("INITIALIZE(value)", "pow(dot(value.rgb, luminance_coefficients) - subtrahend, 2.0)") + .do_static_compilation(true); + +/* -------------------------------------------------------------------- + * Maximum Reductions. + */ + +GPU_SHADER_CREATE_INFO(compositor_maximum_luminance) + .additional_info("compositor_parallel_reduction_shared") + .typedef_source("common_math_lib.glsl") + .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .push_constant(Type::VEC3, "luminance_coefficients") + .define("TYPE", "float") + .define("IDENTITY", "vec4(FLT_MIN)") + .define("INITIALIZE(value)", "dot(value.rgb, luminance_coefficients)") + .define("LOAD(value)", "value.x") + .define("REDUCE(lhs, rhs)", "max(lhs, rhs)") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_maximum_float_in_range) + .additional_info("compositor_parallel_reduction_shared") + .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .push_constant(Type::FLOAT, "lower_bound") + .push_constant(Type::FLOAT, "upper_bound") + .define("TYPE", "float") + .define("IDENTITY", "vec4(lower_bound)") + .define("INITIALIZE(v)", "((v.x <= upper_bound) && (v.x >= lower_bound)) ? v.x : lower_bound") + .define("LOAD(value)", "value.x") + .define("REDUCE(lhs, rhs)", "((rhs > lhs) && (rhs <= upper_bound)) ? rhs : lhs") + .do_static_compilation(true); + +/* -------------------------------------------------------------------- + * Minimum Reductions. + */ + +GPU_SHADER_CREATE_INFO(compositor_minimum_luminance) + .additional_info("compositor_parallel_reduction_shared") + .typedef_source("common_math_lib.glsl") + .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .push_constant(Type::VEC3, "luminance_coefficients") + .define("TYPE", "float") + .define("IDENTITY", "vec4(FLT_MAX)") + .define("INITIALIZE(value)", "dot(value.rgb, luminance_coefficients)") + .define("LOAD(value)", "value.x") + .define("REDUCE(lhs, rhs)", "min(lhs, rhs)") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_minimum_float_in_range) + .additional_info("compositor_parallel_reduction_shared") + .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .push_constant(Type::FLOAT, "lower_bound") + .push_constant(Type::FLOAT, "upper_bound") + .define("TYPE", "float") + .define("IDENTITY", "vec4(upper_bound)") + .define("INITIALIZE(v)", "((v.x <= upper_bound) && (v.x >= lower_bound)) ? v.x : upper_bound") + .define("LOAD(value)", "value.x") + .define("REDUCE(lhs, rhs)", "((rhs < lhs) && (rhs >= lower_bound)) ? rhs : lhs") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_projector_lens_distortion_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_projector_lens_distortion_info.hh new file mode 100644 index 00000000000..98fe1731703 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_projector_lens_distortion_info.hh @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_projector_lens_distortion) + .local_group_size(16, 16) + .push_constant(Type::FLOAT, "dispersion") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_projector_lens_distortion.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_realize_on_domain_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_realize_on_domain_info.hh new file mode 100644 index 00000000000..4528649ae98 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_realize_on_domain_info.hh @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_realize_on_domain_shared) + .local_group_size(16, 16) + .push_constant(Type::MAT4, "inverse_transformation") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .compute_source("compositor_realize_on_domain.glsl"); + +GPU_SHADER_CREATE_INFO(compositor_realize_on_domain_color) + .additional_info("compositor_realize_on_domain_shared") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "domain_img") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_realize_on_domain_vector) + .additional_info("compositor_realize_on_domain_shared") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "domain_img") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_realize_on_domain_float) + .additional_info("compositor_realize_on_domain_shared") + .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "domain_img") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_screen_lens_distortion_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_screen_lens_distortion_info.hh new file mode 100644 index 00000000000..c42f2b328d4 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_screen_lens_distortion_info.hh @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_screen_lens_distortion_shared) + .local_group_size(16, 16) + .push_constant(Type::VEC3, "chromatic_distortion") + .push_constant(Type::FLOAT, "scale") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_screen_lens_distortion.glsl"); + +GPU_SHADER_CREATE_INFO(compositor_screen_lens_distortion) + .additional_info("compositor_screen_lens_distortion_shared") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_screen_lens_distortion_jitter) + .additional_info("compositor_screen_lens_distortion_shared") + .define("JITTER") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_set_alpha_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_set_alpha_info.hh new file mode 100644 index 00000000000..ca28194e921 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_set_alpha_info.hh @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_set_alpha) + .local_group_size(16, 16) + .sampler(0, ImageType::FLOAT_2D, "image_tx") + .sampler(1, ImageType::FLOAT_2D, "alpha_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_set_alpha.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_split_viewer_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_split_viewer_info.hh new file mode 100644 index 00000000000..d5793b0ce59 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_split_viewer_info.hh @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_split_viewer_shared) + .local_group_size(16, 16) + .push_constant(Type::FLOAT, "split_ratio") + .push_constant(Type::IVEC2, "view_size") + .sampler(0, ImageType::FLOAT_2D, "first_image_tx") + .sampler(1, ImageType::FLOAT_2D, "second_image_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_split_viewer.glsl"); + +GPU_SHADER_CREATE_INFO(compositor_split_viewer_horizontal) + .additional_info("compositor_split_viewer_shared") + .define("SPLIT_HORIZONTAL") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_split_viewer_vertical) + .additional_info("compositor_split_viewer_shared") + .define("SPLIT_VERTICAL") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_symmetric_blur_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_symmetric_blur_info.hh new file mode 100644 index 00000000000..8ba2b4e04ef --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_symmetric_blur_info.hh @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_symmetric_blur) + .local_group_size(16, 16) + .push_constant(Type::BOOL, "extend_bounds") + .push_constant(Type::BOOL, "gamma_correct") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .sampler(1, ImageType::FLOAT_2D, "weights_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_symmetric_blur.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_symmetric_separable_blur_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_symmetric_separable_blur_info.hh new file mode 100644 index 00000000000..57247dba4b8 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_symmetric_separable_blur_info.hh @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_symmetric_separable_blur) + .local_group_size(16, 16) + .push_constant(Type::BOOL, "extend_bounds") + .push_constant(Type::BOOL, "gamma_correct_input") + .push_constant(Type::BOOL, "gamma_uncorrect_output") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .sampler(1, ImageType::FLOAT_1D, "weights_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_symmetric_separable_blur.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_tone_map_photoreceptor_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_tone_map_photoreceptor_info.hh new file mode 100644 index 00000000000..a460c9d58a6 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_tone_map_photoreceptor_info.hh @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_tone_map_photoreceptor) + .local_group_size(16, 16) + .push_constant(Type::VEC4, "global_adaptation_level") + .push_constant(Type::FLOAT, "contrast") + .push_constant(Type::FLOAT, "intensity") + .push_constant(Type::FLOAT, "chromatic_adaptation") + .push_constant(Type::FLOAT, "light_adaptation") + .push_constant(Type::VEC3, "luminance_coefficients") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_tone_map_photoreceptor.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_tone_map_simple_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_tone_map_simple_info.hh new file mode 100644 index 00000000000..2b220af9460 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_tone_map_simple_info.hh @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_tone_map_simple) + .local_group_size(16, 16) + .push_constant(Type::FLOAT, "luminance_scale") + .push_constant(Type::FLOAT, "luminance_scale_blend_factor") + .push_constant(Type::FLOAT, "inverse_gamma") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_tone_map_simple.glsl") + .do_static_compilation(true); diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_alpha_over.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_alpha_over.glsl new file mode 100644 index 00000000000..8e3e033147f --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_alpha_over.glsl @@ -0,0 +1,48 @@ +void node_composite_alpha_over_mixed( + float factor, vec4 color, vec4 over_color, float premultiply_factor, out vec4 result) +{ + if (over_color.a <= 0.0) { + result = color; + } + else if (factor == 1.0 && over_color.a >= 1.0) { + result = over_color; + } + else { + float add_factor = 1.0 - premultiply_factor + over_color.a * premultiply_factor; + float premultiplier = factor * add_factor; + float multiplier = 1.0 - factor * over_color.a; + + result = multiplier * color + vec2(premultiplier, factor).xxxy * over_color; + } +} + +void node_composite_alpha_over_key(float factor, vec4 color, vec4 over_color, out vec4 result) +{ + if (over_color.a <= 0.0) { + result = color; + } + else if (factor == 1.0 && over_color.a >= 1.0) { + result = over_color; + } + else { + result = mix(color, vec4(over_color.rgb, 1.0), factor * over_color.a); + } +} + +void node_composite_alpha_over_premultiply(float factor, + vec4 color, + vec4 over_color, + out vec4 result) +{ + if (over_color.a < 0.0) { + result = color; + } + else if (factor == 1.0 && over_color.a >= 1.0) { + result = over_color; + } + else { + float multiplier = 1.0 - factor * over_color.a; + + result = multiplier * color + factor * over_color; + } +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_blur_common.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_blur_common.glsl new file mode 100644 index 00000000000..e404c03bbb0 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_blur_common.glsl @@ -0,0 +1,32 @@ +/* Preprocess the input of the blur filter by squaring it in its alpha straight form, assuming the + * given color is alpha premultiplied. */ +vec4 gamma_correct_blur_input(vec4 color) +{ + /* Unpremultiply alpha. */ + color.rgb /= color.a > 0.0 ? color.a : 1.0; + + /* Square color channel if it is positive, otherwise zero it. */ + color.rgb *= mix(color.rgb, vec3(0.0), lessThan(color.rgb, vec3(0.0))); + + /* Premultiply alpha to undo previous alpha unpremultiplication. */ + color.rgb *= color.a > 0.0 ? color.a : 1.0; + + return color; +} + +/* Postprocess the output of the blur filter by taking its square root it in its alpha straight + * form, assuming the given color is alpha premultiplied. This essential undoes the processing done + * by the gamma_correct_blur_input function. */ +vec4 gamma_uncorrect_blur_output(vec4 color) +{ + /* Unpremultiply alpha. */ + color.rgb /= color.a > 0.0 ? color.a : 1.0; + + /* Take the square root of the color channel if it is positive, otherwise zero it. */ + color.rgb = mix(sqrt(color.rgb), vec3(0.0), lessThan(color.rgb, vec3(0.0))); + + /* Premultiply alpha to undo previous alpha unpremultiplication. */ + color.rgb *= color.a > 0.0 ? color.a : 1.0; + + return color; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_bright_contrast.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_bright_contrast.glsl new file mode 100644 index 00000000000..ce71b4fd8a4 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_bright_contrast.glsl @@ -0,0 +1,38 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +/* The algorithm is by Werner D. Streidt + * (http://visca.com/ffactory/archives/5-99/msg00021.html) + * Extracted of OpenCV demhist.c + */ + +#define FLT_EPSILON 1.192092896e-07F + +void node_composite_bright_contrast( + vec4 color, float brightness, float contrast, const float use_premultiply, out vec4 result) +{ + brightness /= 100.0; + float delta = contrast / 200.0; + + float multiplier, offset; + if (contrast > 0.0) { + multiplier = 1.0 - delta * 2.0; + multiplier = 1.0 / max(multiplier, FLT_EPSILON); + offset = multiplier * (brightness - delta); + } + else { + delta *= -1.0; + multiplier = max(1.0 - delta * 2.0, 0.0); + offset = multiplier * brightness + delta; + } + + if (use_premultiply != 0.0) { + color_alpha_unpremultiply(color, color); + } + + result.rgb = color.rgb * multiplier + offset; + result.a = color.a; + + if (use_premultiply != 0.0) { + color_alpha_premultiply(result, result); + } +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_channel_matte.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_channel_matte.glsl new file mode 100644 index 00000000000..f2dcc9543f2 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_channel_matte.glsl @@ -0,0 +1,52 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +#define CMP_NODE_CHANNEL_MATTE_CS_RGB 1.0 +#define CMP_NODE_CHANNEL_MATTE_CS_HSV 2.0 +#define CMP_NODE_CHANNEL_MATTE_CS_YUV 3.0 +#define CMP_NODE_CHANNEL_MATTE_CS_YCC 4.0 + +void node_composite_channel_matte(vec4 color, + const float color_space, + const float matte_channel, + const vec2 limit_channels, + float max_limit, + float min_limit, + out vec4 result, + out float matte) +{ + vec4 channels; + if (color_space == CMP_NODE_CHANNEL_MATTE_CS_HSV) { + rgb_to_hsv(color, channels); + } + else if (color_space == CMP_NODE_CHANNEL_MATTE_CS_YUV) { + rgba_to_yuva_itu_709(color, channels); + } + else if (color_space == CMP_NODE_CHANNEL_MATTE_CS_YCC) { + rgba_to_ycca_itu_709(color, channels); + } + else { + channels = color; + } + + float matte_value = channels[int(matte_channel)]; + float limit_value = max(channels[int(limit_channels.x)], channels[int(limit_channels.y)]); + + float alpha = 1.0 - (matte_value - limit_value); + if (alpha > max_limit) { + alpha = color.a; + } + else if (alpha < min_limit) { + alpha = 0.0; + } + else { + alpha = (alpha - min_limit) / (max_limit - min_limit); + } + + matte = min(alpha, color.a); + result = color * matte; +} + +#undef CMP_NODE_CHANNEL_MATTE_CS_RGB +#undef CMP_NODE_CHANNEL_MATTE_CS_HSV +#undef CMP_NODE_CHANNEL_MATTE_CS_YUV +#undef CMP_NODE_CHANNEL_MATTE_CS_YCC diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_chroma_matte.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_chroma_matte.glsl new file mode 100644 index 00000000000..5d6bea0c9db --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_chroma_matte.glsl @@ -0,0 +1,43 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +/* Algorithm from the book Video Demystified. Chapter 7. Chroma Keying. */ +void node_composite_chroma_matte(vec4 color, + vec4 key, + float acceptance, + float cutoff, + float falloff, + out vec4 result, + out float matte) +{ + vec4 color_ycca; + rgba_to_ycca_itu_709(color, color_ycca); + vec4 key_ycca; + rgba_to_ycca_itu_709(key, key_ycca); + + /* Normalize the CrCb components into the [-1, 1] range. */ + vec2 color_cc = color_ycca.yz * 2.0 - 1.0; + vec2 key_cc = key_ycca.yz * 2.0 - 1.0; + + /* Rotate the color onto the space of the key such that x axis of the color space passes through + * the key color. */ + color_cc = vector_to_rotation_matrix(key_cc * vec2(1.0, -1.0)) * color_cc; + + /* Compute foreground key. If positive, the value is in the [0, 1] range. */ + float foreground_key = color_cc.x - (abs(color_cc.y) / acceptance); + + /* Negative foreground key values retain the original alpha. Positive values are scaled by the + * falloff, while colors that make an angle less than the cutoff angle get a zero alpha. */ + float alpha = color.a; + if (foreground_key > 0.0) { + alpha = 1.0 - (foreground_key / falloff); + + if (abs(atan(color_cc.y, color_cc.x)) < (cutoff / 2.0)) { + alpha = 0.0; + } + } + + /* Compute output. */ + matte = min(alpha, color.a); + result = color * matte; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_balance.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_balance.glsl new file mode 100644 index 00000000000..bffb94cdedb --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_balance.glsl @@ -0,0 +1,34 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +void node_composite_color_balance_lgg( + float factor, vec4 color, vec3 lift, vec3 gamma, vec3 gain, out vec4 result) +{ + lift = 2.0 - lift; + vec3 srgb_color = linear_rgb_to_srgb(color.rgb); + vec3 lift_balanced = ((srgb_color - 1.0) * lift) + 1.0; + + vec3 gain_balanced = lift_balanced * gain; + gain_balanced = max(gain_balanced, vec3(0.0)); + + vec3 linear_color = srgb_to_linear_rgb(gain_balanced); + gamma = mix(gamma, vec3(1e-6), equal(gamma, vec3(0.0))); + vec3 gamma_balanced = pow(linear_color, 1.0 / gamma); + + result.rgb = mix(color.rgb, gamma_balanced, min(factor, 1.0)); + result.a = color.a; +} + +void node_composite_color_balance_asc_cdl(float factor, + vec4 color, + vec3 offset, + vec3 power, + vec3 slope, + float offset_basis, + out vec4 result) +{ + offset += offset_basis; + vec3 balanced = color.rgb * slope + offset; + balanced = pow(max(balanced, vec3(0.0)), power); + result.rgb = mix(color.rgb, balanced, min(factor, 1.0)); + result.a = color.a; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_correction.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_correction.glsl new file mode 100644 index 00000000000..9b4858f03be --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_correction.glsl @@ -0,0 +1,87 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +void node_composite_color_correction(vec4 color, + float mask, + const vec3 enabled_channels, + float start_midtones, + float end_midtones, + float master_saturation, + float master_contrast, + float master_gamma, + float master_gain, + float master_lift, + float shadows_saturation, + float shadows_contrast, + float shadows_gamma, + float shadows_gain, + float shadows_lift, + float midtones_saturation, + float midtones_contrast, + float midtones_gamma, + float midtones_gain, + float midtones_lift, + float highlights_saturation, + float highlights_contrast, + float highlights_gamma, + float highlights_gain, + float highlights_lift, + const vec3 luminance_coefficients, + out vec4 result) +{ + const float margin = 0.10; + const float margin_divider = 0.5 / margin; + float level = (color.r + color.g + color.b) / 3.0; + float level_shadows = 0.0; + float level_midtones = 0.0; + float level_highlights = 0.0; + if (level < (start_midtones - margin)) { + level_shadows = 1.0; + } + else if (level < (start_midtones + margin)) { + level_midtones = ((level - start_midtones) * margin_divider) + 0.5; + level_shadows = 1.0 - level_midtones; + } + else if (level < (end_midtones - margin)) { + level_midtones = 1.0; + } + else if (level < (end_midtones + margin)) { + level_highlights = ((level - end_midtones) * margin_divider) + 0.5; + level_midtones = 1.0 - level_highlights; + } + else { + level_highlights = 1.0; + } + + float contrast = level_shadows * shadows_contrast; + contrast += level_midtones * midtones_contrast; + contrast += level_highlights * highlights_contrast; + contrast *= master_contrast; + float saturation = level_shadows * shadows_saturation; + saturation += level_midtones * midtones_saturation; + saturation += level_highlights * highlights_saturation; + saturation *= master_saturation; + float gamma = level_shadows * shadows_gamma; + gamma += level_midtones * midtones_gamma; + gamma += level_highlights * highlights_gamma; + gamma *= master_gamma; + float gain = level_shadows * shadows_gain; + gain += level_midtones * midtones_gain; + gain += level_highlights * highlights_gain; + gain *= master_gain; + float lift = level_shadows * shadows_lift; + lift += level_midtones * midtones_lift; + lift += level_highlights * highlights_lift; + lift += master_lift; + + float inverse_gamma = 1.0 / gamma; + float luma = get_luminance(color.rgb, luminance_coefficients); + + vec3 corrected = luma + saturation * (color.rgb - luma); + corrected = 0.5 + (corrected - 0.5) * contrast; + corrected = fallback_pow(corrected * gain + lift, inverse_gamma, corrected); + corrected = mix(color.rgb, corrected, min(mask, 1.0)); + + result.rgb = mix(corrected, color.rgb, equal(enabled_channels, vec3(0.0))); + result.a = color.a; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_matte.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_matte.glsl new file mode 100644 index 00000000000..038471bc1bc --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_matte.glsl @@ -0,0 +1,27 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +void node_composite_color_matte(vec4 color, + vec4 key, + float hue_epsilon, + float saturation_epsilon, + float value_epsilon, + out vec4 result, + out float matte) + +{ + vec4 color_hsva; + rgb_to_hsv(color, color_hsva); + vec4 key_hsva; + rgb_to_hsv(key, key_hsva); + + bool is_within_saturation = distance(color_hsva.y, key_hsva.y) < saturation_epsilon; + bool is_within_value = distance(color_hsva.z, key_hsva.z) < value_epsilon; + bool is_within_hue = distance(color_hsva.x, key_hsva.x) < hue_epsilon; + /* Hue wraps around, so check the distance around the boundary. */ + float min_hue = min(color_hsva.x, key_hsva.x); + float max_hue = max(color_hsva.x, key_hsva.x); + is_within_hue = is_within_hue || ((min_hue + (1.0 - max_hue)) < hue_epsilon); + + matte = (is_within_hue && is_within_saturation && is_within_value) ? 0.0 : color.a; + result = color * matte; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_spill.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_spill.glsl new file mode 100644 index 00000000000..0adad53ad80 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_spill.glsl @@ -0,0 +1,13 @@ +void node_composite_color_spill(vec4 color, + float factor, + const float spill_channel, + vec3 spill_scale, + const vec2 limit_channels, + float limit_scale, + out vec4 result) +{ + float average_limit = (color[int(limit_channels.x)] + color[int(limit_channels.y)]) / 2.0; + float map = factor * color[int(spill_channel)] - limit_scale * average_limit; + result.rgb = map > 0.0 ? color.rgb + spill_scale * map : color.rgb; + result.a = color.a; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_to_luminance.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_to_luminance.glsl new file mode 100644 index 00000000000..bcdd625bd4f --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_color_to_luminance.glsl @@ -0,0 +1,6 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +void color_to_luminance(vec4 color, const vec3 luminance_coefficients, out float result) +{ + result = get_luminance(color.rgb, luminance_coefficients); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_difference_matte.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_difference_matte.glsl new file mode 100644 index 00000000000..d769cadce3c --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_difference_matte.glsl @@ -0,0 +1,10 @@ +void node_composite_difference_matte( + vec4 color, vec4 key, float tolerance, float falloff, out vec4 result, out float matte) +{ + vec4 difference = abs(color - key); + float average_difference = (difference.r + difference.g + difference.b) / 3.0; + bool is_opaque = average_difference > tolerance + falloff; + float alpha = is_opaque ? color.a : (max(0.0, average_difference - tolerance) / falloff); + matte = min(alpha, color.a); + result = color * matte; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_distance_matte.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_distance_matte.glsl new file mode 100644 index 00000000000..9beed66826c --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_distance_matte.glsl @@ -0,0 +1,26 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +void node_composite_distance_matte_rgba( + vec4 color, vec4 key, float tolerance, float falloff, out vec4 result, out float matte) +{ + float difference = distance(color.rgb, key.rgb); + bool is_opaque = difference > tolerance + falloff; + float alpha = is_opaque ? color.a : max(0.0, difference - tolerance) / falloff; + matte = min(alpha, color.a); + result = color * matte; +} + +void node_composite_distance_matte_ycca( + vec4 color, vec4 key, float tolerance, float falloff, out vec4 result, out float matte) +{ + vec4 color_ycca; + rgba_to_ycca_itu_709(color, color_ycca); + vec4 key_ycca; + rgba_to_ycca_itu_709(key, key_ycca); + + float difference = distance(color_ycca.yz, key_ycca.yz); + bool is_opaque = difference > tolerance + falloff; + float alpha = is_opaque ? color.a : max(0.0, difference - tolerance) / falloff; + matte = min(alpha, color.a); + result = color * matte; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_exposure.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_exposure.glsl new file mode 100644 index 00000000000..f246635a91e --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_exposure.glsl @@ -0,0 +1,6 @@ +void node_composite_exposure(vec4 color, float exposure, out vec4 result) +{ + float multiplier = exp2(exposure); + result.rgb = color.rgb * multiplier; + result.a = color.a; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_gamma.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_gamma.glsl new file mode 100644 index 00000000000..53070d4b0e2 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_gamma.glsl @@ -0,0 +1,7 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl) + +void node_composite_gamma(vec4 color, float gamma, out vec4 result) +{ + result.rgb = fallback_pow(color.rgb, gamma, color.rgb); + result.a = color.a; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_hue_correct.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_hue_correct.glsl new file mode 100644 index 00000000000..99eb125cdf2 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_hue_correct.glsl @@ -0,0 +1,39 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +/* Curve maps are stored in sampler objects that are evaluated in the [0, 1] range, so normalize + * parameters accordingly. */ +#define NORMALIZE_PARAMETER(parameter, minimum, range) ((parameter - minimum) * range) + +void node_composite_hue_correct(float factor, + vec4 color, + sampler1DArray curve_map, + const float layer, + vec3 minimums, + vec3 range_dividers, + out vec4 result) +{ + vec4 hsv; + rgb_to_hsv(color, hsv); + + /* First, adjust the hue channel on its own, since corrections in the saturation and value + * channels depends on the new value of the hue, not its original value. A curve map value of 0.5 + * means no change in hue, so adjust the value to get an identity at 0.5. Since the identity of + * addition is 0, we subtract 0.5 (0.5 - 0.5 = 0). */ + const float hue_parameter = NORMALIZE_PARAMETER(hsv.x, minimums.x, range_dividers.x); + hsv.x += texture(curve_map, vec2(hue_parameter, layer)).x - 0.5; + + /* Second, adjust the saturation and value based on the new value of the hue. A curve map value + * of 0.5 means no change in hue, so adjust the value to get an identity at 0.5. Since the + * identity of duplication is 1, we multiply by 2 (0.5 * 2 = 1). */ + vec2 parameters = NORMALIZE_PARAMETER(hsv.x, minimums.yz, range_dividers.yz); + hsv.y *= texture(curve_map, vec2(parameters.x, layer)).y * 2.0; + hsv.z *= texture(curve_map, vec2(parameters.y, layer)).z * 2.0; + + /* Sanitize the new hue and saturation values. */ + hsv.x = fract(hsv.x); + hsv.y = clamp(hsv.y, 0.0, 1.0); + + hsv_to_rgb(hsv, result); + + result = mix(color, result, factor); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_hue_saturation_value.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_hue_saturation_value.glsl new file mode 100644 index 00000000000..dd5eb33d318 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_hue_saturation_value.glsl @@ -0,0 +1,16 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +void node_composite_hue_saturation_value( + vec4 color, float hue, float saturation, float value, float factor, out vec4 result) +{ + vec4 hsv; + rgb_to_hsv(color, hsv); + + hsv.x = fract(hsv.x + hue + 0.5); + hsv.y = clamp(hsv.y * saturation, 0.0, 1.0); + hsv.z = hsv.z * value; + + hsv_to_rgb(hsv, result); + + result = mix(color, result, factor); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_invert.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_invert.glsl new file mode 100644 index 00000000000..59be746da7f --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_invert.glsl @@ -0,0 +1,13 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +void node_composite_invert(float fac, vec4 color, float do_rgb, float do_alpha, out vec4 result) +{ + result = color; + if (do_rgb != 0.0) { + result.rgb = 1.0 - result.rgb; + } + if (do_alpha != 0.0) { + result.a = 1.0 - result.a; + } + result = mix(color, result, fac); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_luminance_matte.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_luminance_matte.glsl new file mode 100644 index 00000000000..3647ac583fe --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_luminance_matte.glsl @@ -0,0 +1,14 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +void node_composite_luminance_matte(vec4 color, + float high, + float low, + const vec3 luminance_coefficients, + out vec4 result, + out float matte) +{ + float luminance = get_luminance(color.rgb, luminance_coefficients); + float alpha = clamp(0.0, 1.0, (luminance - low) / (high - low)); + matte = min(alpha, color.a); + result = color * matte; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_main.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_main.glsl new file mode 100644 index 00000000000..27624223dbc --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_main.glsl @@ -0,0 +1,7 @@ +/* The compute shader that will be dispatched by the compositor ShaderOperation. It just calls the + * evaluate function that will be dynamically generated and appended to this shader in the + * ShaderOperation::generate_code method. */ +void main() +{ + evaluate(); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_map_value.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_map_value.glsl new file mode 100644 index 00000000000..20874b4ef44 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_map_value.glsl @@ -0,0 +1,56 @@ +/* An arbitrary value determined by Blender. */ +#define BLENDER_ZMAX 10000.0 + +void node_composite_map_range(float value, + float from_min, + float from_max, + float to_min, + float to_max, + const float should_clamp, + out float result) +{ + if (abs(from_max - from_min) < 1e-6) { + result = 0.0; + } + else { + if (value >= -BLENDER_ZMAX && value <= BLENDER_ZMAX) { + result = (value - from_min) / (from_max - from_min); + result = to_min + result * (to_max - to_min); + } + else if (value > BLENDER_ZMAX) { + result = to_max; + } + else { + result = to_min; + } + + if (should_clamp != 0.0) { + if (to_max > to_min) { + result = clamp(result, to_min, to_max); + } + else { + result = clamp(result, to_max, to_min); + } + } + } +} + +void node_composite_map_value(float value, + float offset, + float size, + const float use_min, + float min, + const float use_max, + float max, + out float result) +{ + result = (value + offset) * size; + + if (use_min != 0.0 && result < min) { + result = min; + } + + if (use_max != 0.0 && result > max) { + result = max; + } +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_normal.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_normal.glsl new file mode 100644 index 00000000000..a2e3b6c4aaa --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_normal.glsl @@ -0,0 +1,9 @@ +void node_composite_normal(vec3 input_vector, + vec3 input_normal, + out vec3 result_normal, + out float result_dot) +{ + vec3 normal = normalize(input_normal); + result_normal = normal; + result_dot = -dot(input_vector, normal); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_posterize.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_posterize.glsl new file mode 100644 index 00000000000..ee8ae234abe --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_posterize.glsl @@ -0,0 +1,6 @@ +void node_composite_posterize(vec4 color, float steps, out vec4 result) +{ + steps = clamp(steps, 2.0, 1024.0); + result = floor(color * steps) / steps; + result.a = color.a; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_separate_combine.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_separate_combine.glsl new file mode 100644 index 00000000000..d72d2260394 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_separate_combine.glsl @@ -0,0 +1,132 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) + +/* ** Combine/Separate XYZ ** */ + +void node_composite_combine_xyz(float x, float y, float z, out vec3 vector) +{ + vector = vec3(x, y, z); +} + +void node_composite_separate_xyz(vec3 vector, out float x, out float y, out float z) +{ + x = vector.x; + y = vector.y; + z = vector.z; +} + +/* ** Combine/Separate RGBA ** */ + +void node_composite_combine_rgba(float r, float g, float b, float a, out vec4 color) +{ + color = vec4(r, g, b, a); +} + +void node_composite_separate_rgba(vec4 color, out float r, out float g, out float b, out float a) +{ + r = color.r; + g = color.g; + b = color.b; + a = color.a; +} + +/* ** Combine/Separate HSVA ** */ + +void node_composite_combine_hsva(float h, float s, float v, float a, out vec4 color) +{ + hsv_to_rgb(vec4(h, s, v, a), color); +} + +void node_composite_separate_hsva(vec4 color, out float h, out float s, out float v, out float a) +{ + vec4 hsva; + rgb_to_hsv(color, hsva); + h = hsva.x; + s = hsva.y; + v = hsva.z; + a = hsva.a; +} + +/* ** Combine/Separate HSLA ** */ + +void node_composite_combine_hsla(float h, float s, float l, float a, out vec4 color) +{ + hsl_to_rgb(vec4(h, s, l, a), color); +} + +void node_composite_separate_hsla(vec4 color, out float h, out float s, out float l, out float a) +{ + vec4 hsla; + rgb_to_hsl(color, hsla); + h = hsla.x; + s = hsla.y; + l = hsla.z; + a = hsla.a; +} + +/* ** Combine/Separate YCCA ** */ + +void node_composite_combine_ycca_itu_601(float y, float cb, float cr, float a, out vec4 color) +{ + ycca_to_rgba_itu_601(vec4(y, cb, cr, a), color); +} + +void node_composite_combine_ycca_itu_709(float y, float cb, float cr, float a, out vec4 color) +{ + ycca_to_rgba_itu_709(vec4(y, cb, cr, a), color); +} + +void node_composite_combine_ycca_jpeg(float y, float cb, float cr, float a, out vec4 color) +{ + ycca_to_rgba_jpeg(vec4(y, cb, cr, a), color); +} + +void node_composite_separate_ycca_itu_601( + vec4 color, out float y, out float cb, out float cr, out float a) +{ + vec4 ycca; + rgba_to_ycca_itu_601(color, ycca); + y = ycca.x; + cb = ycca.y; + cr = ycca.z; + a = ycca.a; +} + +void node_composite_separate_ycca_itu_709( + vec4 color, out float y, out float cb, out float cr, out float a) +{ + vec4 ycca; + rgba_to_ycca_itu_709(color, ycca); + y = ycca.x; + cb = ycca.y; + cr = ycca.z; + a = ycca.a; +} + +void node_composite_separate_ycca_jpeg( + vec4 color, out float y, out float cb, out float cr, out float a) +{ + vec4 ycca; + rgba_to_ycca_jpeg(color, ycca); + y = ycca.x; + cb = ycca.y; + cr = ycca.z; + a = ycca.a; +} + +/* ** Combine/Separate YUVA ** */ + +void node_composite_combine_yuva_itu_709(float y, float u, float v, float a, out vec4 color) +{ + yuva_to_rgba_itu_709(vec4(y, u, v, a), color); +} + +void node_composite_separate_yuva_itu_709( + vec4 color, out float y, out float u, out float v, out float a) +{ + vec4 yuva; + rgba_to_yuva_itu_709(color, yuva); + y = yuva.x; + u = yuva.y; + v = yuva.z; + a = yuva.a; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_set_alpha.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_set_alpha.glsl new file mode 100644 index 00000000000..95380d1ed0f --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_set_alpha.glsl @@ -0,0 +1,9 @@ +void node_composite_set_alpha_apply(vec4 color, float alpha, out vec4 result) +{ + result = color * alpha; +} + +void node_composite_set_alpha_replace(vec4 color, float alpha, out vec4 result) +{ + result = vec4(color.rgb, alpha); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_store_output.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_store_output.glsl new file mode 100644 index 00000000000..7fba26907b5 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_store_output.glsl @@ -0,0 +1,26 @@ +/* The following functions are called to store the given value in the output identified by the + * given ID. The ID is an unsigned integer that is encoded in a float, so floatBitsToUint is called + * to get the actual identifier. The functions have an output value as their last argument that is + * used to establish an output link that is then used to track the nodes that contribute to the + * output of the compositor node tree. + * + * The store_[float|vector|color] functions are dynamically generated in + * ShaderOperation::generate_code_for_outputs. */ + +void node_compositor_store_output_float(const float id, float value, out float out_value) +{ + store_float(floatBitsToUint(id), value); + out_value = value; +} + +void node_compositor_store_output_vector(const float id, vec3 vector, out vec3 out_vector) +{ + store_vector(floatBitsToUint(id), vector); + out_vector = vector; +} + +void node_compositor_store_output_color(const float id, vec4 color, out vec4 out_color) +{ + store_color(floatBitsToUint(id), color); + out_color = color; +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_texture_utilities.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_texture_utilities.glsl new file mode 100644 index 00000000000..128fc6aeaf5 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_texture_utilities.glsl @@ -0,0 +1,35 @@ +/* A shorthand for 1D textureSize with a zero LOD. */ +int texture_size(sampler1D sampler) +{ + return textureSize(sampler, 0); +} + +/* A shorthand for 1D texelFetch with zero LOD and bounded access clamped to border. */ +vec4 texture_load(sampler1D sampler, int x) +{ + const int texture_bound = texture_size(sampler) - 1; + return texelFetch(sampler, clamp(x, 0, texture_bound), 0); +} + +/* A shorthand for 2D textureSize with a zero LOD. */ +ivec2 texture_size(sampler2D sampler) +{ + return textureSize(sampler, 0); +} + +/* A shorthand for 2D texelFetch with zero LOD and bounded access clamped to border. */ +vec4 texture_load(sampler2D sampler, ivec2 texel) +{ + const ivec2 texture_bounds = texture_size(sampler) - ivec2(1); + return texelFetch(sampler, clamp(texel, ivec2(0), texture_bounds), 0); +} + +/* A shorthand for 2D texelFetch with zero LOD and a fallback value for out-of-bound access. */ +vec4 texture_load(sampler2D sampler, ivec2 texel, vec4 fallback) +{ + const ivec2 texture_bounds = texture_size(sampler) - ivec2(1); + if (any(lessThan(texel, ivec2(0))) || any(greaterThan(texel, texture_bounds))) { + return fallback; + } + return texelFetch(sampler, texel, 0); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_type_conversion.glsl b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_type_conversion.glsl new file mode 100644 index 00000000000..75c76fd7341 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/library/gpu_shader_compositor_type_conversion.glsl @@ -0,0 +1,29 @@ +float float_from_vec4(vec4 vector) +{ + return dot(vector.rgb, vec3(1.0)) / 3.0; +} + +float float_from_vec3(vec3 vector) +{ + return dot(vector, vec3(1.0)) / 3.0; +} + +vec3 vec3_from_vec4(vec4 vector) +{ + return vector.rgb; +} + +vec3 vec3_from_float(float value) +{ + return vec3(value); +} + +vec4 vec4_from_vec3(vec3 vector) +{ + return vec4(vector, 1.0); +} + +vec4 vec4_from_float(float value) +{ + return vec4(vec3(value), 1.0); +} diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index bfbbf1be225..8da17720339 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -27,6 +27,7 @@ set(INC ../editors/include # For *_info.hh includes. + ../compositor/realtime_compositor ../draw/engines/eevee_next ../draw/intern @@ -366,64 +367,6 @@ set(GLSL_SRC shaders/common/gpu_shader_common_math_utils.glsl shaders/common/gpu_shader_common_mix_rgb.glsl - shaders/compositor/compositor_alpha_crop.glsl - shaders/compositor/compositor_bilateral_blur.glsl - shaders/compositor/compositor_blur.glsl - shaders/compositor/compositor_blur_variable_size.glsl - shaders/compositor/compositor_bokeh_image.glsl - shaders/compositor/compositor_box_mask.glsl - shaders/compositor/compositor_convert.glsl - shaders/compositor/compositor_despeckle.glsl - shaders/compositor/compositor_directional_blur.glsl - shaders/compositor/compositor_edge_filter.glsl - shaders/compositor/compositor_ellipse_mask.glsl - shaders/compositor/compositor_filter.glsl - shaders/compositor/compositor_flip.glsl - shaders/compositor/compositor_image_crop.glsl - shaders/compositor/compositor_morphological_distance.glsl - shaders/compositor/compositor_morphological_distance_feather.glsl - shaders/compositor/compositor_morphological_distance_threshold.glsl - shaders/compositor/compositor_morphological_step.glsl - shaders/compositor/compositor_normalize.glsl - shaders/compositor/compositor_parallel_reduction.glsl - shaders/compositor/compositor_projector_lens_distortion.glsl - shaders/compositor/compositor_realize_on_domain.glsl - shaders/compositor/compositor_screen_lens_distortion.glsl - shaders/compositor/compositor_set_alpha.glsl - shaders/compositor/compositor_split_viewer.glsl - shaders/compositor/compositor_symmetric_blur.glsl - shaders/compositor/compositor_symmetric_separable_blur.glsl - shaders/compositor/compositor_tone_map_photoreceptor.glsl - shaders/compositor/compositor_tone_map_simple.glsl - - shaders/compositor/library/gpu_shader_compositor_alpha_over.glsl - shaders/compositor/library/gpu_shader_compositor_blur_common.glsl - shaders/compositor/library/gpu_shader_compositor_bright_contrast.glsl - shaders/compositor/library/gpu_shader_compositor_channel_matte.glsl - shaders/compositor/library/gpu_shader_compositor_chroma_matte.glsl - shaders/compositor/library/gpu_shader_compositor_color_balance.glsl - shaders/compositor/library/gpu_shader_compositor_color_correction.glsl - shaders/compositor/library/gpu_shader_compositor_color_matte.glsl - shaders/compositor/library/gpu_shader_compositor_color_spill.glsl - shaders/compositor/library/gpu_shader_compositor_color_to_luminance.glsl - shaders/compositor/library/gpu_shader_compositor_difference_matte.glsl - shaders/compositor/library/gpu_shader_compositor_distance_matte.glsl - shaders/compositor/library/gpu_shader_compositor_exposure.glsl - shaders/compositor/library/gpu_shader_compositor_gamma.glsl - shaders/compositor/library/gpu_shader_compositor_hue_correct.glsl - shaders/compositor/library/gpu_shader_compositor_hue_saturation_value.glsl - shaders/compositor/library/gpu_shader_compositor_invert.glsl - shaders/compositor/library/gpu_shader_compositor_luminance_matte.glsl - shaders/compositor/library/gpu_shader_compositor_main.glsl - shaders/compositor/library/gpu_shader_compositor_map_value.glsl - shaders/compositor/library/gpu_shader_compositor_normal.glsl - shaders/compositor/library/gpu_shader_compositor_posterize.glsl - shaders/compositor/library/gpu_shader_compositor_separate_combine.glsl - shaders/compositor/library/gpu_shader_compositor_set_alpha.glsl - shaders/compositor/library/gpu_shader_compositor_store_output.glsl - shaders/compositor/library/gpu_shader_compositor_texture_utilities.glsl - shaders/compositor/library/gpu_shader_compositor_type_conversion.glsl - shaders/material/gpu_shader_material_add_shader.glsl shaders/material/gpu_shader_material_ambient_occlusion.glsl shaders/material/gpu_shader_material_anisotropic.glsl @@ -651,36 +594,6 @@ set(SRC_SHADER_CREATE_INFOS shaders/infos/gpu_shader_simple_lighting_info.hh shaders/infos/gpu_shader_text_info.hh shaders/infos/gpu_srgb_to_framebuffer_space_info.hh - - shaders/compositor/infos/compositor_alpha_crop_info.hh - shaders/compositor/infos/compositor_bilateral_blur_info.hh - shaders/compositor/infos/compositor_blur_info.hh - shaders/compositor/infos/compositor_blur_variable_size_info.hh - shaders/compositor/infos/compositor_bokeh_image_info.hh - shaders/compositor/infos/compositor_box_mask_info.hh - shaders/compositor/infos/compositor_convert_info.hh - shaders/compositor/infos/compositor_despeckle_info.hh - shaders/compositor/infos/compositor_directional_blur_info.hh - shaders/compositor/infos/compositor_edge_filter_info.hh - shaders/compositor/infos/compositor_ellipse_mask_info.hh - shaders/compositor/infos/compositor_filter_info.hh - shaders/compositor/infos/compositor_flip_info.hh - shaders/compositor/infos/compositor_image_crop_info.hh - shaders/compositor/infos/compositor_morphological_distance_feather_info.hh - shaders/compositor/infos/compositor_morphological_distance_info.hh - shaders/compositor/infos/compositor_morphological_distance_threshold_info.hh - shaders/compositor/infos/compositor_morphological_step_info.hh - shaders/compositor/infos/compositor_normalize_info.hh - shaders/compositor/infos/compositor_parallel_reduction_info.hh - shaders/compositor/infos/compositor_projector_lens_distortion_info.hh - shaders/compositor/infos/compositor_realize_on_domain_info.hh - shaders/compositor/infos/compositor_screen_lens_distortion_info.hh - shaders/compositor/infos/compositor_set_alpha_info.hh - shaders/compositor/infos/compositor_split_viewer_info.hh - shaders/compositor/infos/compositor_symmetric_blur_info.hh - shaders/compositor/infos/compositor_symmetric_separable_blur_info.hh - shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh - shaders/compositor/infos/compositor_tone_map_simple_info.hh ) set(SRC_SHADER_CREATE_INFOS_MTL @@ -715,6 +628,7 @@ endif() blender_add_lib(bf_gpu "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") target_link_libraries(bf_gpu PUBLIC + bf_compositor_shaders bf_draw_shaders bf_gpu_shaders ) diff --git a/source/blender/gpu/intern/gpu_shader_create_info.cc b/source/blender/gpu/intern/gpu_shader_create_info.cc index ff7aa65f03f..ebbddccbe47 100644 --- a/source/blender/gpu/intern/gpu_shader_create_info.cc +++ b/source/blender/gpu/intern/gpu_shader_create_info.cc @@ -284,6 +284,7 @@ void gpu_shader_create_info_init() _info /* Declare, register and construct the infos. */ +#include "compositor_shader_create_info_list.hh" #include "gpu_shader_create_info_list.hh" /* Baked shader data appended to create infos. */ diff --git a/source/blender/gpu/intern/gpu_shader_dependency.cc b/source/blender/gpu/intern/gpu_shader_dependency.cc index be53ee5d945..7d5b8c891b9 100644 --- a/source/blender/gpu/intern/gpu_shader_dependency.cc +++ b/source/blender/gpu/intern/gpu_shader_dependency.cc @@ -24,6 +24,7 @@ extern "C" { #define SHADER_SOURCE(datatoc, filename, filepath) extern char datatoc[]; +#include "glsl_compositor_source_list.h" #include "glsl_draw_source_list.h" #include "glsl_gpu_source_list.h" #ifdef WITH_OCIO @@ -845,6 +846,7 @@ void gpu_shader_dependency_init() #define SHADER_SOURCE(datatoc, filename, filepath) \ g_sources->add_new(filename, new GPUSource(filepath, filename, datatoc, g_functions)); +#include "glsl_compositor_source_list.h" #include "glsl_draw_source_list.h" #include "glsl_gpu_source_list.h" #ifdef WITH_OCIO diff --git a/source/blender/gpu/shaders/compositor/compositor_alpha_crop.glsl b/source/blender/gpu/shaders/compositor/compositor_alpha_crop.glsl deleted file mode 100644 index d55c8efd4c6..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_alpha_crop.glsl +++ /dev/null @@ -1,11 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - /* The lower bound is inclusive and upper bound is exclusive. */ - bool is_inside = all(greaterThanEqual(texel, lower_bound)) && all(lessThan(texel, upper_bound)); - /* Write the pixel color if it is inside the cropping region, otherwise, write zero. */ - vec4 color = is_inside ? texture_load(input_tx, texel) : vec4(0.0); - imageStore(output_img, texel, color); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_bilateral_blur.glsl b/source/blender/gpu/shaders/compositor/compositor_bilateral_blur.glsl deleted file mode 100644 index c7c5ada7a9f..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_bilateral_blur.glsl +++ /dev/null @@ -1,31 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - vec4 center_determinator = texture_load(determinator_tx, texel); - - /* Go over the pixels in the blur window of the specified radius around the center pixel, and for - * pixels whose determinator is close enough to the determinator of the center pixel, accumulate - * their color as well as their weights. */ - float accumulated_weight = 0.0; - vec4 accumulated_color = vec4(0.0); - for (int y = -radius; y <= radius; y++) { - for (int x = -radius; x <= radius; x++) { - vec4 determinator = texture_load(determinator_tx, texel + ivec2(x, y)); - float difference = dot(abs(center_determinator - determinator).rgb, vec3(1.0)); - - if (difference < threshold) { - accumulated_weight += 1.0; - accumulated_color += texture_load(input_tx, texel + ivec2(x, y)); - } - } - } - - /* Write the accumulated color divided by the accumulated weight if any pixel in the window was - * accumulated, otherwise, write a fallback black color. */ - vec4 fallback = vec4(vec3(0.0), 1.0); - vec4 color = (accumulated_weight != 0.0) ? (accumulated_color / accumulated_weight) : fallback; - imageStore(output_img, texel, color); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_blur.glsl b/source/blender/gpu/shaders/compositor/compositor_blur.glsl deleted file mode 100644 index c7ac620f99b..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_blur.glsl +++ /dev/null @@ -1,66 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl) -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -vec4 load_input(ivec2 texel) -{ - vec4 color; - if (extend_bounds) { - /* If bounds are extended, then we treat the input as padded by a radius amount of pixels. So - * we load the input with an offset by the radius amount and fallback to a transparent color if - * it is out of bounds. */ - color = texture_load(input_tx, texel - radius, vec4(0.0)); - } - else { - color = texture_load(input_tx, texel); - } - - return color; -} - -/* Given the texel in the range [-radius, radius] in both axis, load the appropriate weight from - * the weights texture, where the given texel (0, 0) corresponds the center of weights texture. - * Note that we load the weights texture inverted along both directions to maintain the shape of - * the weights if it was not symmetrical. To understand why inversion makes sense, consider a 1D - * weights texture whose right half is all ones and whose left half is all zeros. Further, consider - * that we are blurring a single white pixel on a black background. When computing the value of a - * pixel that is to the right of the white pixel, the white pixel will be in the left region of the - * search window, and consequently, without inversion, a zero will be sampled from the left side of - * the weights texture and result will be zero. However, what we expect is that pixels to the right - * of the white pixel will be white, that is, they should sample a weight of 1 from the right side - * of the weights texture, hence the need for inversion. */ -vec4 load_weight(ivec2 texel) -{ - /* Add the radius to transform the texel into the range [0, radius * 2], with an additional 0.5 - * to sample at the center of the pixels, then divide by the upper bound plus one to transform - * the texel into the normalized range [0, 1] needed to sample the weights sampler. Finally, - * invert the textures coordinates by subtracting from 1 to maintain the shape of the weights as - * mentioned in the function description. */ - return texture(weights_tx, 1.0 - ((texel + vec2(radius + 0.5)) / (radius * 2 + 1))); -} - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - /* The mask input is treated as a boolean. If it is zero, then no blurring happens for this - * pixel. Otherwise, the pixel is blurred normally and the mask value is irrelevant. */ - float mask = texture_load(mask_tx, texel).x; - if (mask == 0.0) { - imageStore(output_img, texel, texture_load(input_tx, texel)); - return; - } - - /* Go over the window of the given radius and accumulate the colors multiplied by their - * respective weights as well as the weights themselves. */ - vec4 accumulated_color = vec4(0.0); - vec4 accumulated_weight = vec4(0.0); - for (int y = -radius; y <= radius; y++) { - for (int x = -radius; x <= radius; x++) { - vec4 weight = load_weight(ivec2(x, y)); - accumulated_color += load_input(texel + ivec2(x, y)) * weight; - accumulated_weight += weight; - } - } - - imageStore(output_img, texel, safe_divide(accumulated_color, accumulated_weight)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl b/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl deleted file mode 100644 index 9383bbf9825..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl +++ /dev/null @@ -1,71 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl) -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -/* Given the texel in the range [-radius, radius] in both axis, load the appropriate weight from - * the weights texture, where the given texel (0, 0) corresponds the center of weights texture. - * Note that we load the weights texture inverted along both directions to maintain the shape of - * the weights if it was not symmetrical. To understand why inversion makes sense, consider a 1D - * weights texture whose right half is all ones and whose left half is all zeros. Further, consider - * that we are blurring a single white pixel on a black background. When computing the value of a - * pixel that is to the right of the white pixel, the white pixel will be in the left region of the - * search window, and consequently, without inversion, a zero will be sampled from the left side of - * the weights texture and result will be zero. However, what we expect is that pixels to the right - * of the white pixel will be white, that is, they should sample a weight of 1 from the right side - * of the weights texture, hence the need for inversion. */ -vec4 load_weight(ivec2 texel, float radius) -{ - /* The center zero texel is always assigned a unit weight regardless of the corresponding weight - * in the weights texture. That's to guarantee that at last the center pixel will be accumulated - * even if the weights texture is zero at its center. */ - if (texel == ivec2(0)) { - return vec4(1.0); - } - - /* Add the radius to transform the texel into the range [0, radius * 2], with an additional 0.5 - * to sample at the center of the pixels, then divide by the upper bound plus one to transform - * the texel into the normalized range [0, 1] needed to sample the weights sampler. Finally, - * invert the textures coordinates by subtracting from 1 to maintain the shape of the weights as - * mentioned in the function description. */ - return texture(weights_tx, 1.0 - ((texel + vec2(radius + 0.5)) / (radius * 2 + 1))); -} - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - /* The mask input is treated as a boolean. If it is zero, then no blurring happens for this - * pixel. Otherwise, the pixel is blurred normally and the mask value is irrelevant. */ - float mask = texture_load(mask_tx, texel).x; - if (mask == 0.0) { - imageStore(output_img, texel, texture_load(input_tx, texel)); - return; - } - - float center_size = texture_load(size_tx, texel).x * base_size; - - /* Go over the window of the given search radius and accumulate the colors multiplied by their - * respective weights as well as the weights themselves, but only if both the size of the center - * pixel and the size of the candidate pixel are less than both the x and y distances of the - * candidate pixel. */ - vec4 accumulated_color = vec4(0.0); - vec4 accumulated_weight = vec4(0.0); - for (int y = -search_radius; y <= search_radius; y++) { - for (int x = -search_radius; x <= search_radius; x++) { - float candidate_size = texture_load(size_tx, texel + ivec2(x, y)).x * base_size; - - /* Skip accumulation if either the x or y distances of the candidate pixel are larger than - * either the center or candidate pixel size. Note that the max and min functions here denote - * "either" in the aforementioned description. */ - float size = min(center_size, candidate_size); - if (max(abs(x), abs(y)) > size) { - continue; - } - - vec4 weight = load_weight(ivec2(x, y), size); - accumulated_color += texture_load(input_tx, texel + ivec2(x, y)) * weight; - accumulated_weight += weight; - } - } - - imageStore(output_img, texel, safe_divide(accumulated_color, accumulated_weight)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_bokeh_image.glsl b/source/blender/gpu/shaders/compositor/compositor_bokeh_image.glsl deleted file mode 100644 index 6e98aa9fe17..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_bokeh_image.glsl +++ /dev/null @@ -1,118 +0,0 @@ -#pragma BLENDER_REQUIRE(common_math_lib.glsl) -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -/* Get the 2D vertex position of the vertex with the given index in the regular polygon - * representing this bokeh. The polygon is rotated by the rotation amount and have a unit - * circumradius. The regular polygon is one whose vertices' exterior angles are given by - * exterior_angle. See the bokeh function for more information. */ -vec2 get_regular_polygon_vertex_position(int vertex_index) -{ - float angle = exterior_angle * vertex_index - rotation; - return vec2(cos(angle), sin(angle)); -} - -/* Find the closest point to the given point on the given line. This assumes the length of the - * given line is not zero. */ -vec2 closest_point_on_line(vec2 point, vec2 line_start, vec2 line_end) -{ - vec2 line_vector = line_end - line_start; - vec2 point_vector = point - line_start; - float line_length_squared = dot(line_vector, line_vector); - float parameter = dot(point_vector, line_vector) / line_length_squared; - return line_start + line_vector * parameter; -} - -/* Compute the value of the bokeh at the given point. The computed bokeh is essentially a regular - * polygon centered in space having the given circumradius. The regular polygon is one whose - * vertices' exterior angles are given by "exterior_angle", which relates to the number of vertices - * n through the equation "exterior angle = 2 pi / n". The regular polygon may additionally morph - * into a shape with the given properties: - * - * - The regular polygon may have a circular hole in its center whose radius is controlled by the - * "catadioptric" value. - * - The regular polygon is rotated by the "rotation" value. - * - The regular polygon can morph into a circle controlled by the "roundness" value, such that it - * becomes a full circle at unit roundness. - * - * The function returns 0 when the point lies inside the regular polygon and 1 otherwise. However, - * at the edges, it returns a narrow band gradient as a form of anti-aliasing. */ -float bokeh(vec2 point, float circumradius) -{ - /* Get the index of the vertex of the regular polygon whose polar angle is maximum but less than - * the polar angle of the given point, taking rotation into account. This essentially finds the - * vertex closest to the given point in the clock-wise direction. */ - float angle = mod(atan(point.y, point.x) + rotation, M_2PI); - int vertex_index = int(angle / exterior_angle); - - /* Compute the shortest distance between the origin and the polygon edge composed from the - * previously selected vertex and the one following it. */ - vec2 first_vertex = get_regular_polygon_vertex_position(vertex_index) * circumradius; - vec2 second_vertex = get_regular_polygon_vertex_position(vertex_index + 1) * circumradius; - vec2 closest_point = closest_point_on_line(point, first_vertex, second_vertex); - float distance_to_edge = length(closest_point); - - /* Mix the distance to the edge with the circumradius, making it tend to the distance to a - * circle when roundness tends to 1. */ - float distance_to_edge_round = mix(distance_to_edge, circumradius, roundness); - - /* The point is outside of the bokeh, so we return 0. */ - float distance = length(point); - if (distance > distance_to_edge_round) { - return 0.0; - } - - /* The point is inside the catadioptric hole and is not part of the bokeh, so we return 0. */ - float catadioptric_distance = distance_to_edge_round * catadioptric; - if (distance < catadioptric_distance) { - return 0.0; - } - - /* The point is very close to the edge of the bokeh, so we return the difference between the - * distance to the edge and the distance as a form of anti-aliasing. */ - if (distance_to_edge_round - distance < 1.0) { - return distance_to_edge_round - distance; - } - - /* The point is very close to the edge of the catadioptric hole, so we return the difference - * between the distance to the hole and the distance as a form of anti-aliasing. */ - if (catadioptric != 0.0 && distance - catadioptric_distance < 1.0) { - return distance - catadioptric_distance; - } - - /* Otherwise, the point is part of the bokeh and we return 1. */ - return 1.0; -} - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - /* Since we need the regular polygon to occupy the entirety of the output image, the circumradius - * of the regular polygon is half the width of the output image. */ - float circumradius = float(imageSize(output_img).x) / 2.0; - - /* Move the texel coordinates such that the regular polygon is centered. */ - vec2 point = vec2(texel) - circumradius; - - /* Each of the color channels of the output image contains a bokeh with a different circumradius. - * The largest one occupies the whole image as stated above, while the other two have circumradii - * that are shifted by an amount that is proportional to the "lens_shift" value. The alpha - * channel of the output is the average of all three values. */ - float min_shift = abs(lens_shift * circumradius); - float min = mix(bokeh(point, circumradius - min_shift), 0.0, min_shift == circumradius); - - float median_shift = min_shift / 2.0; - float median = bokeh(point, circumradius - median_shift); - - float max = bokeh(point, circumradius); - vec4 bokeh = vec4(min, median, max, (max + median + min) / 3.0); - - /* If the lens shift is negative, swap the min and max bokeh values, which are stored in the red - * and blue channels respectively. Note that we take the absolute value of the lens shift above, - * so the sign of the lens shift only controls this swap. */ - if (lens_shift < 0) { - bokeh = bokeh.zyxw; - } - - imageStore(output_img, texel, bokeh); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_box_mask.glsl b/source/blender/gpu/shaders/compositor/compositor_box_mask.glsl deleted file mode 100644 index fad23f28fde..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_box_mask.glsl +++ /dev/null @@ -1,27 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - vec2 uv = vec2(texel) / vec2(domain_size - ivec2(1)); - uv -= location; - uv.y *= float(domain_size.y) / float(domain_size.x); - uv = mat2(cos_angle, -sin_angle, sin_angle, cos_angle) * uv; - bool is_inside = all(lessThan(abs(uv), size)); - - float base_mask_value = texture_load(base_mask_tx, texel).x; - float value = texture_load(mask_value_tx, texel).x; - -#if defined(CMP_NODE_MASKTYPE_ADD) - float output_mask_value = is_inside ? max(base_mask_value, value) : base_mask_value; -#elif defined(CMP_NODE_MASKTYPE_SUBTRACT) - float output_mask_value = is_inside ? clamp(base_mask_value - value, 0.0, 1.0) : base_mask_value; -#elif defined(CMP_NODE_MASKTYPE_MULTIPLY) - float output_mask_value = is_inside ? base_mask_value * value : 0.0; -#elif defined(CMP_NODE_MASKTYPE_NOT) - float output_mask_value = is_inside ? (base_mask_value > 0.0 ? 0.0 : value) : base_mask_value; -#endif - - imageStore(output_mask_img, texel, vec4(output_mask_value)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_convert.glsl b/source/blender/gpu/shaders/compositor/compositor_convert.glsl deleted file mode 100644 index 044fb057ca5..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_convert.glsl +++ /dev/null @@ -1,8 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - vec4 value = texture_load(input_tx, texel); - imageStore(output_img, texel, CONVERT_EXPRESSION(value)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_despeckle.glsl b/source/blender/gpu/shaders/compositor/compositor_despeckle.glsl deleted file mode 100644 index e4743d69d17..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_despeckle.glsl +++ /dev/null @@ -1,70 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -/* Returns true if the given color is close enough to the given reference color within the - * threshold supplied by the user, and returns false otherwise. */ -bool is_close(vec4 reference_color, vec4 color) -{ - return all(lessThan(abs(reference_color - color).rgb, vec3(threshold))); -} - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - /* A 3x3 weights kernel whose weights are the inverse of the distance to the center of the - * kernel. So the center weight is zero, the corners weights are (1 / sqrt(2)), and the rest - * of the weights are 1. The total sum of weights is 4 plus quadruple the corner weight. */ - float corner_weight = 1.0 / sqrt(2.0); - float sum_of_weights = 4.0 + corner_weight * 4.0; - mat3 weights = mat3(vec3(corner_weight, 1.0, corner_weight), - vec3(1.0, 0.0, 1.0), - vec3(corner_weight, 1.0, corner_weight)); - - vec4 center_color = texture_load(input_tx, texel); - - /* Go over the pixels in the 3x3 window around the center pixel and compute the total sum of - * their colors multiplied by their weights. Additionally, for pixels whose colors are not close - * enough to the color of the center pixel, accumulate their color as well as their weights. */ - vec4 sum_of_colors = vec4(0); - float accumulated_weight = 0.0; - vec4 accumulated_color = vec4(0); - for (int j = 0; j < 3; j++) { - for (int i = 0; i < 3; i++) { - float weight = weights[j][i]; - vec4 color = texture_load(input_tx, texel + ivec2(i - 1, j - 1)) * weight; - sum_of_colors += color; - if (!is_close(center_color, color)) { - accumulated_color += color; - accumulated_weight += weight; - } - } - } - - /* If the accumulated weight is zero, that means all pixels in the 3x3 window are similar and no - * need to despeckle anything, so write the original center color and return. */ - if (accumulated_weight == 0.0) { - imageStore(output_img, texel, center_color); - return; - } - - /* If the ratio between the accumulated weights and the total sum of weights is not larger than - * the user specified neighbor threshold, then the number of pixels in the neighborhood that are - * not close enough to the center pixel is low, and no need to despeckle anything, so write the - * original center color and return. */ - if (accumulated_weight / sum_of_weights < neighbor_threshold) { - imageStore(output_img, texel, center_color); - return; - } - - /* If the weighted average color of the neighborhood is close enough to the center pixel, then no - * need to despeckle anything, so write the original center color and return. */ - if (is_close(center_color, sum_of_colors / sum_of_weights)) { - imageStore(output_img, texel, center_color); - return; - } - - /* We need to despeckle, so write the mean accumulated color. */ - float factor = texture_load(factor_tx, texel).x; - vec4 mean_color = accumulated_color / accumulated_weight; - imageStore(output_img, texel, mix(center_color, mean_color, factor)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_directional_blur.glsl b/source/blender/gpu/shaders/compositor/compositor_directional_blur.glsl deleted file mode 100644 index 1805cb5a7f5..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_directional_blur.glsl +++ /dev/null @@ -1,21 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - ivec2 input_size = texture_size(input_tx); - - /* Add 0.5 to evaluate the input sampler at the center of the pixel. */ - vec2 coordinates = vec2(texel) + vec2(0.5); - - /* For each iteration, accumulate the input at the normalize coordinates, hence the divide by - * input size, then transform the coordinates for the next iteration. */ - vec4 accumulated_color = vec4(0.0); - for (int i = 0; i < iterations; i++) { - accumulated_color += texture(input_tx, coordinates / input_size); - coordinates = (mat3(inverse_transformation) * vec3(coordinates, 1.0)).xy; - } - - /* Write the accumulated color divided by the number of iterations. */ - imageStore(output_img, texel, accumulated_color / iterations); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_edge_filter.glsl b/source/blender/gpu/shaders/compositor/compositor_edge_filter.glsl deleted file mode 100644 index 67e27c22602..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_edge_filter.glsl +++ /dev/null @@ -1,31 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - /* Compute the dot product between the 3x3 window around the pixel and the edge detection kernel - * in the X direction and Y direction. The Y direction kernel is computed by transposing the - * given X direction kernel. */ - vec3 color_x = vec3(0); - vec3 color_y = vec3(0); - for (int j = 0; j < 3; j++) { - for (int i = 0; i < 3; i++) { - vec3 color = texture_load(input_tx, texel + ivec2(i - 1, j - 1)).rgb; - color_x += color * kernel[j][i]; - color_y += color * kernel[i][j]; - } - } - - /* Compute the channel-wise magnitude of the 2D vector composed from the X and Y edge detection - * filter results. */ - vec3 magnitude = sqrt(color_x * color_x + color_y * color_y); - - /* Mix the channel-wise magnitude with the original color at the center of the kernel using the - * input factor. */ - vec4 color = texture_load(input_tx, texel); - magnitude = mix(color.rgb, magnitude, texture_load(factor_tx, texel).x); - - /* Store the channel-wise magnitude with the original alpha of the input. */ - imageStore(output_img, texel, vec4(magnitude, color.a)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_ellipse_mask.glsl b/source/blender/gpu/shaders/compositor/compositor_ellipse_mask.glsl deleted file mode 100644 index 28f725067e0..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_ellipse_mask.glsl +++ /dev/null @@ -1,27 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - vec2 uv = vec2(texel) / vec2(domain_size - ivec2(1)); - uv -= location; - uv.y *= float(domain_size.y) / float(domain_size.x); - uv = mat2(cos_angle, -sin_angle, sin_angle, cos_angle) * uv; - bool is_inside = length(uv / radius) < 1.0; - - float base_mask_value = texture_load(base_mask_tx, texel).x; - float value = texture_load(mask_value_tx, texel).x; - -#if defined(CMP_NODE_MASKTYPE_ADD) - float output_mask_value = is_inside ? max(base_mask_value, value) : base_mask_value; -#elif defined(CMP_NODE_MASKTYPE_SUBTRACT) - float output_mask_value = is_inside ? clamp(base_mask_value - value, 0.0, 1.0) : base_mask_value; -#elif defined(CMP_NODE_MASKTYPE_MULTIPLY) - float output_mask_value = is_inside ? base_mask_value * value : 0.0; -#elif defined(CMP_NODE_MASKTYPE_NOT) - float output_mask_value = is_inside ? (base_mask_value > 0.0 ? 0.0 : value) : base_mask_value; -#endif - - imageStore(output_mask_img, texel, vec4(output_mask_value)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_filter.glsl b/source/blender/gpu/shaders/compositor/compositor_filter.glsl deleted file mode 100644 index e501c563dda..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_filter.glsl +++ /dev/null @@ -1,20 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - /* Compute the dot product between the 3x3 window around the pixel and the filter kernel. */ - vec4 color = vec4(0); - for (int j = 0; j < 3; j++) { - for (int i = 0; i < 3; i++) { - color += texture_load(input_tx, texel + ivec2(i - 1, j - 1)) * kernel[j][i]; - } - } - - /* Mix with the original color at the center of the kernel using the input factor. */ - color = mix(texture_load(input_tx, texel), color, texture_load(factor_tx, texel).x); - - /* Store the color making sure it is not negative. */ - imageStore(output_img, texel, max(color, 0.0)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_flip.glsl b/source/blender/gpu/shaders/compositor/compositor_flip.glsl deleted file mode 100644 index 919c454ee63..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_flip.glsl +++ /dev/null @@ -1,15 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - ivec2 size = texture_size(input_tx); - ivec2 flipped_texel = texel; - if (flip_x) { - flipped_texel.x = size.x - texel.x - 1; - } - if (flip_y) { - flipped_texel.y = size.y - texel.y - 1; - } - imageStore(output_img, texel, texture_load(input_tx, flipped_texel)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_image_crop.glsl b/source/blender/gpu/shaders/compositor/compositor_image_crop.glsl deleted file mode 100644 index f20e033dee4..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_image_crop.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - imageStore(output_img, texel, texture_load(input_tx, texel + lower_bound)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_morphological_distance.glsl b/source/blender/gpu/shaders/compositor/compositor_morphological_distance.glsl deleted file mode 100644 index 09f896b7a9d..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_morphological_distance.glsl +++ /dev/null @@ -1,24 +0,0 @@ -#pragma BLENDER_REQUIRE(common_math_lib.glsl) -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - /* Find the minimum/maximum value in the circular window of the given radius around the pixel. By - * circular window, we mean that pixels in the window whose distance to the center of window is - * larger than the given radius are skipped and not considered. Consequently, the dilation or - * erosion that take place produces round results as opposed to squarish ones. This is - * essentially a morphological operator with a circular structuring element. The LIMIT value - * should be FLT_MAX if OPERATOR is min and FLT_MIN if OPERATOR is max. */ - float value = LIMIT; - for (int y = -radius; y <= radius; y++) { - for (int x = -radius; x <= radius; x++) { - if (x * x + y * y <= radius * radius) { - value = OPERATOR(value, texture_load(input_tx, texel + ivec2(x, y), vec4(LIMIT)).x); - } - } - } - - imageStore(output_img, texel, vec4(value)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_morphological_distance_feather.glsl b/source/blender/gpu/shaders/compositor/compositor_morphological_distance_feather.glsl deleted file mode 100644 index acdd8a40342..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_morphological_distance_feather.glsl +++ /dev/null @@ -1,101 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -/* The Morphological Distance Feather operation is a linear combination between the result of two - * operations. The first operation is a Gaussian blur with a radius equivalent to the dilate/erode - * distance, which is straightforward and implemented as a separable filter similar to the blur - * operation. - * - * The second operation is an approximation of a morphological inverse distance operation evaluated - * at a distance falloff function. The result of a morphological inverse distance operation is a - * narrow band distance field that starts at its maximum value at boundaries where a difference in - * values took place and linearly deceases until it reaches zero in the span of a number of pixels - * equivalent to the erode/dilate distance. Additionally, instead of linearly decreasing, the user - * may choose a different falloff which is evaluated at the computed distance. For dilation, the - * distance field decreases outwards, and for erosion, the distance field decreased inwards. - * - * The reason why the result of a Gaussian blur is mixed in with the distance field is because the - * distance field is merely approximated and not accurately computed, the defects of which is more - * apparent away from boundaries and especially at corners where the distance field should take a - * circular shape. That's why the Gaussian blur is mostly mixed only further from boundaries. - * - * The morphological inverse distance operation is approximated using a separable implementation - * and intertwined with the Gaussian blur implementation as follows. A search window of a radius - * equivalent to the dilate/erode distance is applied on the image to find either the minimum or - * maximum pixel value multiplied by its corresponding falloff value in the window. For dilation, - * we try to find the maximum, and for erosion, we try to find the minimum. Additionally, we also - * save the falloff value where the minimum or maximum was found. The found value will be that of - * the narrow band distance field and the saved falloff value will be used as the mixing factor - * with the Gaussian blur. - * - * To make sense of the aforementioned algorithm, assume we are dilating a binary image by 5 pixels - * whose half has a value of 1 and the other half has a value of zero. Consider the following: - * - * - A pixel of value 1 already has the maximum possible value, so its value will remain unchanged - * regardless of its position. - * - A pixel of value 0 that is right at the boundary of the 1's region will have a maximum value - * of around 0.8 depending on the falloff. That's because the search window intersects the 1's - * region, which when multiplied by the falloff gives the first value of the falloff, which is - * larger than the initially zero value computed at the center of the search window. - * - A pixel of value 0 that is 3 pixels away from the boundary will have a maximum value of around - * 0.4 depending on the falloff. That's because the search window intersects the 1's region, - * which when multiplied by the falloff gives the third value of the falloff, which is larger - * than the initially zero value computed at the center of the search window. - * - Finally, a pixel of value 0 that is 6 pixels away from the boundary will have a maximum value - * of 0, because the search window doesn't intersects the 1's region and only spans zero values. - * - * The previous example demonstrates how the distance field naturally arises, and the same goes for - * the erode case, except the minimum value is computed instead. - */ -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - /* A value for accumulating the blur result. */ - float accumulated_value = 0.0; - - /* Compute the contribution of the center pixel to the blur result. */ - float center_value = texture_load(input_tx, texel).x; - accumulated_value += center_value * texture_load(weights_tx, 0).x; - - /* Start with the center value as the maximum/minimum distance and reassign to the true maximum - * or minimum in the search loop below. Additionally, the center falloff is always 1.0, so start - * with that. */ - float limit_distance = center_value; - float limit_distance_falloff = 1.0; - - /* Compute the contributions of the pixels to the right and left, noting that the weights and - * falloffs textures only store the weights and falloffs for the positive half, but since the - * they are both symmetric, the same weights and falloffs are used for the negative half and we - * compute both of their contributions. */ - for (int i = 1; i < texture_size(weights_tx); i++) { - float weight = texture_load(weights_tx, i).x; - float falloff = texture_load(falloffs_tx, i).x; - - /* Loop for two iterations, where s takes the value of -1 and 1, which is used as the sign - * needed to evaluated the positive and negative sides as explain above. */ - for (int s = -1; s < 2; s += 2) { - /* Compute the contribution of the pixel to the blur result. */ - float value = texture_load(input_tx, texel + ivec2(s * i, 0)).x; - accumulated_value += value * weight; - - /* The distance is computed such that its highest value is the pixel value itself, so - * multiply the distance falloff by the pixel value. */ - float falloff_distance = value * falloff; - - /* Find either the maximum or the minimum for the dilate and erode cases respectively. */ - if (COMPARE(falloff_distance, limit_distance)) { - limit_distance = falloff_distance; - limit_distance_falloff = falloff; - } - } - } - - /* Mix between the limit distance and the blurred accumulated value such that the limit distance - * is used for pixels closer to the boundary and the blurred value is used for pixels away from - * the boundary. */ - float value = mix(accumulated_value, limit_distance, limit_distance_falloff); - - /* Write the value using the transposed texel. See the execute_distance_feather_horizontal_pass - * method for more information on the rational behind this. */ - imageStore(output_img, texel.yx, vec4(value)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_morphological_distance_threshold.glsl b/source/blender/gpu/shaders/compositor/compositor_morphological_distance_threshold.glsl deleted file mode 100644 index e6625e7419f..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_morphological_distance_threshold.glsl +++ /dev/null @@ -1,88 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -/* The Morphological Distance Threshold operation is effectively three consecutive operations - * implemented as a single operation. The three operations are as follows: - * - * .-----------. .--------------. .----------------. - * | Threshold |-->| Dilate/Erode |-->| Distance Inset | - * '-----------' '--------------' '----------------' - * - * The threshold operation just converts the input into a binary image, where the pixel is 1 if it - * is larger than 0.5 and 0 otherwise. Pixels that are 1 in the output of the threshold operation - * are said to be masked. The dilate/erode operation is a dilate or erode morphological operation - * with a circular structuring element depending on the sign of the distance, where it is a dilate - * operation if the distance is positive and an erode operation otherwise. This is equivalent to - * the Morphological Distance operation, see its implementation for more information. Finally, the - * distance inset is an operation that converts the binary image into a narrow band distance field. - * That is, pixels that are unmasked will remain 0, while pixels that are masked will start from - * zero at the boundary of the masked region and linearly increase until reaching 1 in the span of - * a number pixels given by the inset value. - * - * As a performance optimization, the dilate/erode operation is omitted and its effective result is - * achieved by slightly adjusting the distance inset operation. The base distance inset operation - * works by computing the signed distance from the current center pixel to the nearest pixel with a - * different value. Since our image is a binary image, that means that if the pixel is masked, we - * compute the signed distance to the nearest unmasked pixel, and if the pixel unmasked, we compute - * the signed distance to the nearest masked pixel. The distance is positive if the pixel is masked - * and negative otherwise. The distance is then normalized by dividing by the given inset value and - * clamped to the [0, 1] range. Since distances larger than the inset value are eventually clamped, - * the distance search window is limited to a radius equivalent to the inset value. - * - * To archive the effective result of the omitted dilate/erode operation, we adjust the distance - * inset operation as follows. First, we increase the radius of the distance search window by the - * radius of the dilate/erode operation. Then we adjust the resulting narrow band signed distance - * field as follows. - * - * For the erode case, we merely subtract the erode distance, which makes the outermost erode - * distance number of pixels zero due to clamping, consequently achieving the result of the erode, - * while retaining the needed inset because we increased the distance search window by the same - * amount we subtracted. - * - * Similarly, for the dilate case, we add the dilate distance, which makes the dilate distance - * number of pixels just outside of the masked region positive and part of the narrow band distance - * field, consequently achieving the result of the dilate, while at the same time, the innermost - * dilate distance number of pixels become 1 due to clamping, retaining the needed inset because we - * increased the distance search window by the same amount we added. - * - * Since the erode/dilate distance is already signed appropriately as described before, we just add - * it in both cases. */ -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - /* Apply a threshold operation on the center pixel, where the threshold is currently hard-coded - * at 0.5. The pixels with values larger than the threshold are said to be masked. */ - bool is_center_masked = texture_load(input_tx, texel).x > 0.5; - - /* Since the distance search window will access pixels outside of the bounds of the image, we use - * a texture loader with a fallback value. And since we don't want those values to affect the - * result, the fallback value is chosen such that the inner condition fails, which is when the - * sampled pixel and the center pixel are the same, so choose a fallback that will be considered - * masked if the center pixel is masked and unmasked otherwise. */ - vec4 fallback = vec4(is_center_masked ? 1.0 : 0.0); - - /* Since the distance search window is limited to the given radius, the maximum possible squared - * distance to the center is double the squared radius. */ - int minimum_squared_distance = radius * radius * 2; - - /* Find the squared distance to the nearest different pixel in the search window of the given - * radius. */ - for (int y = -radius; y <= radius; y++) { - for (int x = -radius; x <= radius; x++) { - bool is_sample_masked = texture_load(input_tx, texel + ivec2(x, y), fallback).x > 0.5; - if (is_center_masked != is_sample_masked) { - minimum_squared_distance = min(minimum_squared_distance, x * x + y * y); - } - } - } - - /* Compute the actual distance from the squared distance and assign it an appropriate sign - * depending on whether it lies in a masked region or not. */ - float signed_minimum_distance = sqrt(minimum_squared_distance) * (is_center_masked ? 1.0 : -1.0); - - /* Add the erode/dilate distance and divide by the inset amount as described in the discussion, - * then clamp to the [0, 1] range. */ - float value = clamp((signed_minimum_distance + distance) / inset, 0.0, 1.0); - - imageStore(output_img, texel, vec4(value)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_morphological_step.glsl b/source/blender/gpu/shaders/compositor/compositor_morphological_step.glsl deleted file mode 100644 index 6992bc2afa5..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_morphological_step.glsl +++ /dev/null @@ -1,19 +0,0 @@ -#pragma BLENDER_REQUIRE(common_math_lib.glsl) -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - /* Find the minimum/maximum value in the window of the given radius around the pixel. This is - * essentially a morphological operator with a square structuring element. The LIMIT value should - * be FLT_MAX if OPERATOR is min and FLT_MIN if OPERATOR is max. */ - float value = LIMIT; - for (int i = -radius; i <= radius; i++) { - value = OPERATOR(value, texture_load(input_tx, texel + ivec2(i, 0), vec4(LIMIT)).x); - } - - /* Write the value using the transposed texel. See the execute_step_horizontal_pass method for - * more information on the rational behind this. */ - imageStore(output_img, texel.yx, vec4(value)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_normalize.glsl b/source/blender/gpu/shaders/compositor/compositor_normalize.glsl deleted file mode 100644 index 53dfeb01730..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_normalize.glsl +++ /dev/null @@ -1,10 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - float value = texture_load(input_tx, texel).x; - float normalized_value = (value - minimum) * scale; - float clamped_value = clamp(normalized_value, 0.0, 1.0); - imageStore(output_img, texel, vec4(clamped_value)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_parallel_reduction.glsl b/source/blender/gpu/shaders/compositor/compositor_parallel_reduction.glsl deleted file mode 100644 index f6f84aa24c1..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_parallel_reduction.glsl +++ /dev/null @@ -1,98 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -/* This shader reduces the given texture into a smaller texture of a size equal to the number of - * work groups. In particular, each work group reduces its contents into a single value and writes - * that value to a single pixel in the output image. The shader can be dispatched multiple times to - * eventually reduce the image into a single pixel. - * - * The shader works by loading the whole data of each work group into a linear array, then it - * reduces the second half of the array onto the first half of the array, then it reduces the - * second quarter of the array onto the first quarter or the array, and so on until only one - * element remains. The following figure illustrates the process for sum reduction on 8 elements. - * - * .---. .---. .---. .---. .---. .---. .---. .---. - * | 0 | | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | | 7 | Original data. - * '---' '---' '---' '---' '---' '---' '---' '---' - * |.____|_____|_____|_____| | | | - * || |.____|_____|___________| | | - * || || |.____|_________________| | - * || || || |.______________________| <--First reduction. Stride = 4. - * || || || || - * .---. .---. .---. .----. - * | 4 | | 6 | | 8 | | 10 | <--Data after first reduction. - * '---' '---' '---' '----' - * |.____|_____| | - * || |.__________| <--Second reduction. Stride = 2. - * || || - * .----. .----. - * | 12 | | 16 | <--Data after second reduction. - * '----' '----' - * |.____| - * || <--Third reduction. Stride = 1. - * .----. - * | 28 | - * '----' <--Data after third reduction. - * - * - * The shader is generic enough to implement many types of reductions. This is done by using macros - * that the developer should define to implement a certain reduction operation. Those include, - * TYPE, IDENTITY, INITIALIZE, LOAD, and REDUCE. See the implementation below for more information - * as well as the compositor_parallel_reduction_info.hh for example reductions operations. */ - -/* Doing the reduction in shared memory is faster, so create a shared array where the whole data - * of the work group will be loaded and reduced. The 2D structure of the work group is irrelevant - * for reduction, so we just load the data in a 1D array to simplify reduction. The developer is - * expected to define the TYPE macro to be a float or a vec4, depending on the type of data being - * reduced. */ -const uint reduction_size = gl_WorkGroupSize.x * gl_WorkGroupSize.y; -shared TYPE reduction_data[reduction_size]; - -void main() -{ - /* Load the data from the texture, while returning IDENTITY for out of bound coordinates. The - * developer is expected to define the IDENTITY macro to be a vec4 that does not affect the - * output of the reduction. For instance, sum reductions have an identity of vec4(0.0), while - * max value reductions have an identity of vec4(FLT_MIN). */ - vec4 value = texture_load(input_tx, ivec2(gl_GlobalInvocationID.xy), IDENTITY); - - /* Initialize the shared array given the previously loaded value. This step can be different - * depending on whether this is the initial reduction pass or a latter one. Indeed, the input - * texture for the initial reduction is the source texture itself, while the input texture to a - * latter reduction pass is an intermediate texture after one or more reductions have happened. - * This is significant because the data being reduced might be computed from the original data - * and different from it, for instance, when summing the luminance of an image, the original data - * is a vec4 color, while the reduced data is a float luminance value. So for the initial - * reduction pass, the luminance will be computed from the color, reduced, then stored into an - * intermediate float texture. On the other hand, for latter reduction passes, the luminance will - * be loaded directly and reduced without extra processing. So the developer is expected to - * define the INITIALIZE and LOAD macros to be expressions that derive the needed value from the - * loaded value for the initial reduction pass and latter ones respectively. */ - reduction_data[gl_LocalInvocationIndex] = is_initial_reduction ? INITIALIZE(value) : LOAD(value); - - /* Reduce the reduction data by half on every iteration until only one element remains. See the - * above figure for an intuitive understanding of the stride value. */ - for (uint stride = reduction_size / 2; stride > 0; stride /= 2) { - barrier(); - - /* Only the threads up to the current stride should be active as can be seen in the diagram - * above. */ - if (gl_LocalInvocationIndex >= stride) { - continue; - } - - /* Reduce each two elements that are stride apart, writing the result to the element with the - * lower index, as can be seen in the diagram above. The developer is expected to define the - * REDUCE macro to be a commutative and associative binary operator suitable for parallel - * reduction. */ - reduction_data[gl_LocalInvocationIndex] = REDUCE( - reduction_data[gl_LocalInvocationIndex], reduction_data[gl_LocalInvocationIndex + stride]); - } - - /* Finally, the result of the reduction is available as the first element in the reduction data, - * write it to the pixel corresponding to the work group, making sure only the one thread writes - * it. */ - barrier(); - if (gl_LocalInvocationIndex == 0) { - imageStore(output_img, ivec2(gl_WorkGroupID.xy), vec4(reduction_data[0])); - } -} diff --git a/source/blender/gpu/shaders/compositor/compositor_projector_lens_distortion.glsl b/source/blender/gpu/shaders/compositor/compositor_projector_lens_distortion.glsl deleted file mode 100644 index ab44dac93e6..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_projector_lens_distortion.glsl +++ /dev/null @@ -1,16 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - /* Get the normalized coordinates of the pixel centers. */ - vec2 normalized_texel = (vec2(texel) + vec2(0.5)) / vec2(texture_size(input_tx)); - - /* Sample the red and blue channels shifted by the dispersion amount. */ - const float red = texture(input_tx, normalized_texel + vec2(dispersion, 0.0)).r; - const float green = texture_load(input_tx, texel).g; - const float blue = texture(input_tx, normalized_texel - vec2(dispersion, 0.0)).b; - - imageStore(output_img, texel, vec4(red, green, blue, 1.0)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_realize_on_domain.glsl b/source/blender/gpu/shaders/compositor/compositor_realize_on_domain.glsl deleted file mode 100644 index b8561e5f059..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_realize_on_domain.glsl +++ /dev/null @@ -1,29 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - /* Add 0.5 to evaluate the input sampler at the center of the pixel. */ - vec2 coordinates = vec2(texel) + vec2(0.5); - - /* Transform the input image by transforming the domain coordinates with the inverse of input - * image's transformation. The inverse transformation is an affine matrix and thus the - * coordinates should be in homogeneous coordinates. */ - coordinates = (mat3(inverse_transformation) * vec3(coordinates, 1.0)).xy; - - /* Since an input image with an identity transformation is supposed to be centered in the domain, - * we subtract the offset between the lower left corners of the input image and the domain, which - * is half the difference between their sizes, because the difference in size is on both sides of - * the centered image. Additionally, we floor the offset to retain the 0.5 offset added above in - * case the difference in sizes was odd. */ - ivec2 domain_size = imageSize(domain_img); - ivec2 input_size = texture_size(input_tx); - vec2 offset = floor((domain_size - input_size) / 2.0); - - /* Subtract the offset and divide by the input image size to get the relevant coordinates into - * the sampler's expected [0, 1] range. */ - vec2 normalized_coordinates = (coordinates - offset) / input_size; - - imageStore(domain_img, texel, texture(input_tx, normalized_coordinates)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_screen_lens_distortion.glsl b/source/blender/gpu/shaders/compositor/compositor_screen_lens_distortion.glsl deleted file mode 100644 index dc572ea5aaf..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_screen_lens_distortion.glsl +++ /dev/null @@ -1,151 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_common_hash.glsl) -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -/* A model that approximates lens distortion parameterized by a distortion parameter and dependent - * on the squared distance to the center of the image. The distorted pixel is then computed as the - * scalar multiplication of the pixel coordinates with the value returned by this model. See the - * compute_distorted_uv function for more details. */ -float compute_distortion_scale(float distortion, float distance_squared) -{ - return 1.0 / (1.0 + sqrt(max(0.0, 1.0 - distortion * distance_squared))); -} - -/* A vectorized version of compute_distortion_scale that is applied on the chromatic distortion - * parameters passed to the shader. */ -vec3 compute_chromatic_distortion_scale(float distance_squared) -{ - return 1.0 / (1.0 + sqrt(max(vec3(0.0), 1.0 - chromatic_distortion * distance_squared))); -} - -/* Compute the image coordinates after distortion by the given distortion scale computed by the - * compute_distortion_scale function. Note that the function expects centered normalized UV - * coordinates but outputs non-centered image coordinates. */ -vec2 compute_distorted_uv(vec2 uv, float scale) -{ - return (uv * scale + 0.5) * texture_size(input_tx) - 0.5; -} - -/* Compute the number of integration steps that should be used to approximate the distorted pixel - * using a heuristic, see the compute_number_of_steps function for more details. The numbers of - * steps is proportional to the number of pixels spanned by the distortion amount. For jitter - * distortion, the square root of the distortion amount plus 1 is used with a minimum of 2 steps. - * For non-jitter distortion, the distortion amount plus 1 is used as the number of steps */ -int compute_number_of_integration_steps_heuristic(float distortion) -{ -#if defined(JITTER) - return distortion < 4.0 ? 2 : int(sqrt(distortion + 1.0)); -#else - return int(distortion + 1.0); -#endif -} - -/* Compute the number of integration steps that should be used to compute each channel of the - * distorted pixel. Each of the channels are distorted by their respective chromatic distortion - * amount, then the amount of distortion between each two consecutive channels is computed, this - * amount is then used to heuristically infer the number of needed integration steps, see the - * integrate_distortion function for more information. */ -ivec3 compute_number_of_integration_steps(vec2 uv, float distance_squared) -{ - /* Distort each channel by its respective chromatic distortion amount. */ - vec3 distortion_scale = compute_chromatic_distortion_scale(distance_squared); - vec2 distorted_uv_red = compute_distorted_uv(uv, distortion_scale.r); - vec2 distorted_uv_green = compute_distorted_uv(uv, distortion_scale.g); - vec2 distorted_uv_blue = compute_distorted_uv(uv, distortion_scale.b); - - /* Infer the number of needed integration steps to compute the distorted red channel starting - * from the green channel. */ - float distortion_red = distance(distorted_uv_red, distorted_uv_green); - int steps_red = compute_number_of_integration_steps_heuristic(distortion_red); - - /* Infer the number of needed integration steps to compute the distorted blue channel starting - * from the green channel. */ - float distortion_blue = distance(distorted_uv_green, distorted_uv_blue); - int steps_blue = compute_number_of_integration_steps_heuristic(distortion_blue); - - /* The number of integration steps used to compute the green channel is the sum of both the red - * and the blue channel steps because it is computed once with each of them. */ - return ivec3(steps_red, steps_red + steps_blue, steps_blue); -} - -/* Returns a random jitter amount, which is essentially a random value in the [0, 1] range. If - * jitter is not enabled, return a constant 0.5 value instead. */ -float get_jitter(int seed) -{ -#if defined(JITTER) - return hash_uint3_to_float(gl_GlobalInvocationID.x, gl_GlobalInvocationID.y, seed); -#else - return 0.5; -#endif -} - -/* Each color channel may have a different distortion with the guarantee that the red will have the - * lowest distortion while the blue will have the highest one. If each channel is distorted - * independently, the image will look disintegrated, with each channel seemingly merely shifted. - * Consequently, the distorted pixels needs to be computed by integrating along the path of change - * of distortion starting from one channel to another. For instance, to compute the distorted red - * from the distorted green, we accumulate the color of the distorted pixel starting from the - * distortion of the red, taking small steps until we reach the distortion of the green. The pixel - * color is weighted such that it is maximum at the start distortion and zero at the end distortion - * in an arithmetic progression. The integration steps can be augmented with random values to - * simulate lens jitter. Finally, it should be noted that this function integrates both the start - * and end channels in reverse directions for more efficient computation. */ -vec3 integrate_distortion(int start, int end, float distance_squared, vec2 uv, int steps) -{ - vec3 accumulated_color = vec3(0.0); - float distortion_amount = chromatic_distortion[end] - chromatic_distortion[start]; - for (int i = 0; i < steps; i++) { - /* The increment will be in the [0, 1) range across iterations. */ - float increment = (i + get_jitter(i)) / steps; - float distortion = chromatic_distortion[start] + increment * distortion_amount; - float distortion_scale = compute_distortion_scale(distortion, distance_squared); - - /* Sample the color at the distorted coordinates and accumulate it weighted by the increment - * value for both the start and end channels. */ - vec2 distorted_uv = compute_distorted_uv(uv, distortion_scale); - vec4 color = texture(input_tx, distorted_uv / texture_size(input_tx)); - accumulated_color[start] += (1.0 - increment) * color[start]; - accumulated_color[end] += increment * color[end]; - } - return accumulated_color; -} - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - /* Compute the UV image coordinates in the range [-1, 1] as well as the squared distance to the - * center of the image, which is at (0, 0) in the UV coordinates. */ - vec2 center = texture_size(input_tx) / 2.0; - vec2 uv = scale * (texel + 0.5 - center) / center; - float distance_squared = dot(uv, uv); - - /* If any of the color channels will get distorted outside of the screen beyond what is possible, - * write a zero transparent color and return. */ - if (any(greaterThan(chromatic_distortion * distance_squared, vec3(1.0)))) { - imageStore(output_img, texel, vec4(0.0)); - return; - } - - /* Compute the number of integration steps that should be used to compute each channel of the - * distorted pixel. */ - ivec3 number_of_steps = compute_number_of_integration_steps(uv, distance_squared); - - /* Integrate the distortion of the red and green, then the green and blue channels. That means - * the green will be integrated twice, but this is accounted for in the number of steps which the - * color will later be divided by. See the compute_number_of_integration_steps function for more - * details. */ - vec3 color = vec3(0.0); - color += integrate_distortion(0, 1, distance_squared, uv, number_of_steps.r); - color += integrate_distortion(1, 2, distance_squared, uv, number_of_steps.b); - - /* The integration above performed weighted accumulation, and thus the color needs to be divided - * by the sum of the weights. Assuming no jitter, the weights are generated as an arithmetic - * progression starting from (0.5 / n) to ((n - 0.5) / n) for n terms. The sum of an arithmetic - * progression can be computed as (n * (start + end) / 2), which when subsisting the start and - * end reduces to (n / 2). So the color should be multiplied by 2 / n. The jitter sequence - * approximately sums to the same value because it is a uniform random value whose mean value is - * 0.5, so the expression doesn't change regardless of jitter. */ - color *= 2.0 / vec3(number_of_steps); - - imageStore(output_img, texel, vec4(color, 1.0)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_set_alpha.glsl b/source/blender/gpu/shaders/compositor/compositor_set_alpha.glsl deleted file mode 100644 index 7dd40581790..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_set_alpha.glsl +++ /dev/null @@ -1,8 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - vec4 color = vec4(texture_load(image_tx, texel).rgb, texture_load(alpha_tx, texel).x); - imageStore(output_img, texel, color); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_split_viewer.glsl b/source/blender/gpu/shaders/compositor/compositor_split_viewer.glsl deleted file mode 100644 index 866b9045da2..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_split_viewer.glsl +++ /dev/null @@ -1,14 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); -#if defined(SPLIT_HORIZONTAL) - bool condition = (view_size.x * split_ratio) < texel.x; -#elif defined(SPLIT_VERTICAL) - bool condition = (view_size.y * split_ratio) < texel.y; -#endif - vec4 color = condition ? texture_load(first_image_tx, texel) : - texture_load(second_image_tx, texel); - imageStore(output_img, texel, color); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_symmetric_blur.glsl b/source/blender/gpu/shaders/compositor/compositor_symmetric_blur.glsl deleted file mode 100644 index df08991a35c..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_symmetric_blur.glsl +++ /dev/null @@ -1,77 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_blur_common.glsl) -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -vec4 load_input(ivec2 texel) -{ - vec4 color; - if (extend_bounds) { - /* If bounds are extended, then we treat the input as padded by a radius amount of pixels. So - * we load the input with an offset by the radius amount and fallback to a transparent color if - * it is out of bounds. Notice that we subtract 1 because the weights texture have an extra - * center weight, see the SymmetricBlurWeights for more information. */ - ivec2 blur_size = texture_size(weights_tx) - 1; - color = texture_load(input_tx, texel - blur_size, vec4(0.0)); - } - else { - color = texture_load(input_tx, texel); - } - - if (gamma_correct) { - color = gamma_correct_blur_input(color); - } - - return color; -} - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - vec4 accumulated_color = vec4(0.0); - - /* First, compute the contribution of the center pixel. */ - vec4 center_color = load_input(texel); - accumulated_color += center_color * texture_load(weights_tx, ivec2(0)).x; - - ivec2 weights_size = texture_size(weights_tx); - - /* Then, compute the contributions of the pixels along the x axis of the filter, noting that the - * weights texture only stores the weights for the positive half, but since the filter is - * symmetric, the same weight is used for the negative half and we add both of their - * contributions. */ - for (int x = 1; x < weights_size.x; x++) { - float weight = texture_load(weights_tx, ivec2(x, 0)).x; - accumulated_color += load_input(texel + ivec2(x, 0)) * weight; - accumulated_color += load_input(texel + ivec2(-x, 0)) * weight; - } - - /* Then, compute the contributions of the pixels along the y axis of the filter, noting that the - * weights texture only stores the weights for the positive half, but since the filter is - * symmetric, the same weight is used for the negative half and we add both of their - * contributions. */ - for (int y = 1; y < weights_size.y; y++) { - float weight = texture_load(weights_tx, ivec2(0, y)).x; - accumulated_color += load_input(texel + ivec2(0, y)) * weight; - accumulated_color += load_input(texel + ivec2(0, -y)) * weight; - } - - /* Finally, compute the contributions of the pixels in the four quadrants of the filter, noting - * that the weights texture only stores the weights for the upper right quadrant, but since the - * filter is symmetric, the same weight is used for the rest of the quadrants and we add all four - * of their contributions. */ - for (int y = 1; y < weights_size.y; y++) { - for (int x = 1; x < weights_size.x; x++) { - float weight = texture_load(weights_tx, ivec2(x, y)).x; - accumulated_color += load_input(texel + ivec2(x, y)) * weight; - accumulated_color += load_input(texel + ivec2(-x, y)) * weight; - accumulated_color += load_input(texel + ivec2(x, -y)) * weight; - accumulated_color += load_input(texel + ivec2(-x, -y)) * weight; - } - } - - if (gamma_correct) { - accumulated_color = gamma_uncorrect_blur_output(accumulated_color); - } - - imageStore(output_img, texel, accumulated_color); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_symmetric_separable_blur.glsl b/source/blender/gpu/shaders/compositor/compositor_symmetric_separable_blur.glsl deleted file mode 100644 index ab0c7baa787..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_symmetric_separable_blur.glsl +++ /dev/null @@ -1,53 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_blur_common.glsl) -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -vec4 load_input(ivec2 texel) -{ - vec4 color; - if (extend_bounds) { - /* If bounds are extended, then we treat the input as padded by a radius amount of pixels. So - * we load the input with an offset by the radius amount and fallback to a transparent color if - * it is out of bounds. Notice that we subtract 1 because the weights texture have an extra - * center weight, see the SymmetricSeparableBlurWeights for more information. */ - int blur_size = texture_size(weights_tx) - 1; - color = texture_load(input_tx, texel - ivec2(blur_size, 0), vec4(0.0)); - } - else { - color = texture_load(input_tx, texel); - } - - if (gamma_correct_input) { - color = gamma_correct_blur_input(color); - } - - return color; -} - -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - vec4 accumulated_color = vec4(0.0); - - /* First, compute the contribution of the center pixel. */ - vec4 center_color = load_input(texel); - accumulated_color += center_color * texture_load(weights_tx, 0).x; - - /* Then, compute the contributions of the pixel to the right and left, noting that the - * weights texture only stores the weights for the positive half, but since the filter is - * symmetric, the same weight is used for the negative half and we add both of their - * contributions. */ - for (int i = 1; i < texture_size(weights_tx); i++) { - float weight = texture_load(weights_tx, i).x; - accumulated_color += load_input(texel + ivec2(i, 0)) * weight; - accumulated_color += load_input(texel + ivec2(-i, 0)) * weight; - } - - if (gamma_uncorrect_output) { - accumulated_color = gamma_uncorrect_blur_output(accumulated_color); - } - - /* Write the color using the transposed texel. See the execute_separable_blur_horizontal_pass - * method for more information on the rational behind this. */ - imageStore(output_img, texel.yx, accumulated_color); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl b/source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl deleted file mode 100644 index 167006585ca..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl +++ /dev/null @@ -1,22 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) - -/* Tone mapping based on equation (1) and the trilinear interpolation between equations (6) and (7) - * from Reinhard, Erik, and Kate Devlin. "Dynamic range reduction inspired by photoreceptor - * physiology." IEEE transactions on visualization and computer graphics 11.1 (2005): 13-24. */ -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - vec4 input_color = texture_load(input_tx, texel); - float input_luminance = dot(input_color.rgb, luminance_coefficients); - - /* Trilinear interpolation between equations (6) and (7) from Reinhard's 2005 paper. */ - vec4 local_adaptation_level = mix(vec4(input_luminance), input_color, chromatic_adaptation); - vec4 adaptation_level = mix(global_adaptation_level, local_adaptation_level, light_adaptation); - - /* Equation (1) from Reinhard's 2005 paper, assuming Vmax is 1. */ - vec4 semi_saturation = pow(intensity * adaptation_level, vec4(contrast)); - vec4 tone_mapped_color = input_color / (input_color + semi_saturation); - - imageStore(output_img, texel, vec4(tone_mapped_color.rgb, input_color.a)); -} diff --git a/source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl b/source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl deleted file mode 100644 index ce42d021dd1..00000000000 --- a/source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl +++ /dev/null @@ -1,26 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) -#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl) - -/* Tone mapping based on equation (3) from Reinhard, Erik, et al. "Photographic tone reproduction - * for digital images." Proceedings of the 29th annual conference on Computer graphics and - * interactive techniques. 2002. */ -void main() -{ - ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - - vec4 input_color = texture_load(input_tx, texel); - - /* Equation (2) from Reinhard's 2002 paper. */ - vec4 scaled_color = input_color * luminance_scale; - - /* Equation (3) from Reinhard's 2002 paper, but with the 1 replaced with the blend factor for - * more flexibility. See ToneMapOperation::compute_luminance_scale_blend_factor. */ - vec4 denominator = luminance_scale_blend_factor + scaled_color; - vec4 tone_mapped_color = safe_divide(scaled_color, denominator); - - if (inverse_gamma != 0.0) { - tone_mapped_color = pow(max(tone_mapped_color, vec4(0.0)), vec4(inverse_gamma)); - } - - imageStore(output_img, texel, vec4(tone_mapped_color.rgb, input_color.a)); -} diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_alpha_crop_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_alpha_crop_info.hh deleted file mode 100644 index 11f2f329cd8..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_alpha_crop_info.hh +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_alpha_crop) - .local_group_size(16, 16) - .push_constant(Type::IVEC2, "lower_bound") - .push_constant(Type::IVEC2, "upper_bound") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_alpha_crop.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_bilateral_blur_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_bilateral_blur_info.hh deleted file mode 100644 index 301cd6acd9e..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_bilateral_blur_info.hh +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_bilateral_blur) - .local_group_size(16, 16) - .push_constant(Type::INT, "radius") - .push_constant(Type::FLOAT, "threshold") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .sampler(1, ImageType::FLOAT_2D, "determinator_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_bilateral_blur.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_blur_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_blur_info.hh deleted file mode 100644 index 36b772aa486..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_blur_info.hh +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_blur) - .local_group_size(16, 16) - .push_constant(Type::INT, "radius") - .push_constant(Type::BOOL, "extend_bounds") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .sampler(1, ImageType::FLOAT_2D, "weights_tx") - .sampler(2, ImageType::FLOAT_2D, "mask_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_blur.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_blur_variable_size_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_blur_variable_size_info.hh deleted file mode 100644 index 05b6385fd1e..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_blur_variable_size_info.hh +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_blur_variable_size) - .local_group_size(16, 16) - .push_constant(Type::FLOAT, "base_size") - .push_constant(Type::INT, "search_radius") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .sampler(1, ImageType::FLOAT_2D, "weights_tx") - .sampler(2, ImageType::FLOAT_2D, "size_tx") - .sampler(3, ImageType::FLOAT_2D, "mask_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_blur_variable_size.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_bokeh_image_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_bokeh_image_info.hh deleted file mode 100644 index 3541de53070..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_bokeh_image_info.hh +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_bokeh_image) - .local_group_size(16, 16) - .push_constant(Type::FLOAT, "exterior_angle") - .push_constant(Type::FLOAT, "rotation") - .push_constant(Type::FLOAT, "roundness") - .push_constant(Type::FLOAT, "catadioptric") - .push_constant(Type::FLOAT, "lens_shift") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_bokeh_image.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_box_mask_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_box_mask_info.hh deleted file mode 100644 index ecb253bbab1..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_box_mask_info.hh +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_box_mask_shared) - .local_group_size(16, 16) - .push_constant(Type::IVEC2, "domain_size") - .push_constant(Type::VEC2, "location") - .push_constant(Type::VEC2, "size") - .push_constant(Type::FLOAT, "cos_angle") - .push_constant(Type::FLOAT, "sin_angle") - .sampler(0, ImageType::FLOAT_2D, "base_mask_tx") - .sampler(1, ImageType::FLOAT_2D, "mask_value_tx") - .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_mask_img") - .compute_source("compositor_box_mask.glsl"); - -GPU_SHADER_CREATE_INFO(compositor_box_mask_add) - .additional_info("compositor_box_mask_shared") - .define("CMP_NODE_MASKTYPE_ADD") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_box_mask_subtract) - .additional_info("compositor_box_mask_shared") - .define("CMP_NODE_MASKTYPE_SUBTRACT") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_box_mask_multiply) - .additional_info("compositor_box_mask_shared") - .define("CMP_NODE_MASKTYPE_MULTIPLY") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_box_mask_not) - .additional_info("compositor_box_mask_shared") - .define("CMP_NODE_MASKTYPE_NOT") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_convert_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_convert_info.hh deleted file mode 100644 index 35e60056736..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_convert_info.hh +++ /dev/null @@ -1,69 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_convert_shared) - .local_group_size(16, 16) - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .typedef_source("gpu_shader_compositor_type_conversion.glsl") - .compute_source("compositor_convert.glsl"); - -GPU_SHADER_CREATE_INFO(compositor_convert_float_to_vector) - .additional_info("compositor_convert_shared") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .define("CONVERT_EXPRESSION(value)", "vec4(vec3_from_float(value.x), 0.0)") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_convert_float_to_color) - .additional_info("compositor_convert_shared") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .define("CONVERT_EXPRESSION(value)", "vec4_from_float(value.x)") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_convert_color_to_float) - .additional_info("compositor_convert_shared") - .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .define("CONVERT_EXPRESSION(value)", "vec4(float_from_vec4(value), vec3(0.0))") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_convert_color_to_vector) - .additional_info("compositor_convert_shared") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .define("CONVERT_EXPRESSION(value)", "vec4(vec3_from_vec4(value), 0.0)") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_convert_vector_to_float) - .additional_info("compositor_convert_shared") - .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .define("CONVERT_EXPRESSION(value)", "vec4(float_from_vec3(value.xyz), vec3(0.0))") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_convert_vector_to_color) - .additional_info("compositor_convert_shared") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .define("CONVERT_EXPRESSION(value)", "vec4_from_vec3(value.xyz)") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_extract_alpha_from_color) - .additional_info("compositor_convert_shared") - .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .define("CONVERT_EXPRESSION(value)", "vec4(value.a, vec3(0.0))") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_convert_color_to_half_color) - .additional_info("compositor_convert_shared") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .define("CONVERT_EXPRESSION(value)", "value") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_convert_float_to_half_float) - .additional_info("compositor_convert_shared") - .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .define("CONVERT_EXPRESSION(value)", "vec4(value.r, vec3(0.0))") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_convert_color_to_opaque) - .additional_info("compositor_convert_shared") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .define("CONVERT_EXPRESSION(value)", "vec4(value.rgb, 1.0)") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_despeckle_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_despeckle_info.hh deleted file mode 100644 index df86c3a8258..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_despeckle_info.hh +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_despeckle) - .local_group_size(16, 16) - .push_constant(Type::FLOAT, "threshold") - .push_constant(Type::FLOAT, "neighbor_threshold") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .sampler(1, ImageType::FLOAT_2D, "factor_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_despeckle.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_directional_blur_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_directional_blur_info.hh deleted file mode 100644 index bb9199dcd26..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_directional_blur_info.hh +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_directional_blur) - .local_group_size(16, 16) - .push_constant(Type::INT, "iterations") - .push_constant(Type::MAT4, "inverse_transformation") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_directional_blur.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_edge_filter_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_edge_filter_info.hh deleted file mode 100644 index 916ec62bdba..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_edge_filter_info.hh +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_edge_filter) - .local_group_size(16, 16) - .push_constant(Type::MAT4, "kernel") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .sampler(1, ImageType::FLOAT_2D, "factor_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_edge_filter.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_ellipse_mask_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_ellipse_mask_info.hh deleted file mode 100644 index 52db91c94e5..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_ellipse_mask_info.hh +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_ellipse_mask_shared) - .local_group_size(16, 16) - .push_constant(Type::IVEC2, "domain_size") - .push_constant(Type::VEC2, "location") - .push_constant(Type::VEC2, "radius") - .push_constant(Type::FLOAT, "cos_angle") - .push_constant(Type::FLOAT, "sin_angle") - .sampler(0, ImageType::FLOAT_2D, "base_mask_tx") - .sampler(1, ImageType::FLOAT_2D, "mask_value_tx") - .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_mask_img") - .compute_source("compositor_ellipse_mask.glsl"); - -GPU_SHADER_CREATE_INFO(compositor_ellipse_mask_add) - .additional_info("compositor_ellipse_mask_shared") - .define("CMP_NODE_MASKTYPE_ADD") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_ellipse_mask_subtract) - .additional_info("compositor_ellipse_mask_shared") - .define("CMP_NODE_MASKTYPE_SUBTRACT") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_ellipse_mask_multiply) - .additional_info("compositor_ellipse_mask_shared") - .define("CMP_NODE_MASKTYPE_MULTIPLY") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_ellipse_mask_not) - .additional_info("compositor_ellipse_mask_shared") - .define("CMP_NODE_MASKTYPE_NOT") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_filter_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_filter_info.hh deleted file mode 100644 index 9d565cf4b8a..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_filter_info.hh +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_filter) - .local_group_size(16, 16) - .push_constant(Type::MAT4, "kernel") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .sampler(1, ImageType::FLOAT_2D, "factor_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_filter.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_flip_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_flip_info.hh deleted file mode 100644 index db831518cb7..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_flip_info.hh +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_flip) - .local_group_size(16, 16) - .push_constant(Type::BOOL, "flip_x") - .push_constant(Type::BOOL, "flip_y") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_flip.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_image_crop_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_image_crop_info.hh deleted file mode 100644 index e7736744c40..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_image_crop_info.hh +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_image_crop) - .local_group_size(16, 16) - .push_constant(Type::IVEC2, "lower_bound") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_image_crop.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_morphological_distance_feather_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_morphological_distance_feather_info.hh deleted file mode 100644 index 9f17f60129d..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_morphological_distance_feather_info.hh +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_morphological_distance_feather_shared) - .local_group_size(16, 16) - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .sampler(1, ImageType::FLOAT_1D, "weights_tx") - .sampler(2, ImageType::FLOAT_1D, "falloffs_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_morphological_distance_feather.glsl"); - -GPU_SHADER_CREATE_INFO(compositor_morphological_distance_feather_dilate) - .additional_info("compositor_morphological_distance_feather_shared") - .define("COMPARE(x, y)", "x > y") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_morphological_distance_feather_erode) - .additional_info("compositor_morphological_distance_feather_shared") - .define("COMPARE(x, y)", "x < y") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_morphological_distance_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_morphological_distance_info.hh deleted file mode 100644 index fc960e119e5..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_morphological_distance_info.hh +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_morphological_distance_shared) - .local_group_size(16, 16) - .push_constant(Type::INT, "radius") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_morphological_distance.glsl"); - -GPU_SHADER_CREATE_INFO(compositor_morphological_distance_dilate) - .additional_info("compositor_morphological_distance_shared") - .define("OPERATOR(a, b)", "max(a, b)") - .define("LIMIT", "FLT_MIN") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_morphological_distance_erode) - .additional_info("compositor_morphological_distance_shared") - .define("OPERATOR(a, b)", "min(a, b)") - .define("LIMIT", "FLT_MAX") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_morphological_distance_threshold_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_morphological_distance_threshold_info.hh deleted file mode 100644 index b1d64f61b80..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_morphological_distance_threshold_info.hh +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_morphological_distance_threshold) - .local_group_size(16, 16) - .push_constant(Type::INT, "radius") - .push_constant(Type::INT, "distance") - .push_constant(Type::FLOAT, "inset") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_morphological_distance_threshold.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_morphological_step_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_morphological_step_info.hh deleted file mode 100644 index e97ffd9feea..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_morphological_step_info.hh +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_morphological_step_shared) - .local_group_size(16, 16) - .push_constant(Type::INT, "radius") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_morphological_step.glsl"); - -GPU_SHADER_CREATE_INFO(compositor_morphological_step_dilate) - .additional_info("compositor_morphological_step_shared") - .define("OPERATOR(a, b)", "max(a, b)") - .define("LIMIT", "FLT_MIN") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_morphological_step_erode) - .additional_info("compositor_morphological_step_shared") - .define("OPERATOR(a, b)", "min(a, b)") - .define("LIMIT", "FLT_MAX") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh deleted file mode 100644 index 02fdc424014..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_normalize) - .local_group_size(16, 16) - .push_constant(Type::FLOAT, "minimum") - .push_constant(Type::FLOAT, "scale") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_normalize.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh deleted file mode 100644 index e2252b14758..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh +++ /dev/null @@ -1,149 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_parallel_reduction_shared) - .local_group_size(16, 16) - .push_constant(Type::BOOL, "is_initial_reduction") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .compute_source("compositor_parallel_reduction.glsl"); - -/* -------------------------------------------------------------------- - * Sum Reductions. - */ - -GPU_SHADER_CREATE_INFO(compositor_sum_shared) - .additional_info("compositor_parallel_reduction_shared") - .define("IDENTITY", "vec4(0.0)") - .define("REDUCE(lhs, rhs)", "lhs + rhs"); - -GPU_SHADER_CREATE_INFO(compositor_sum_float_shared) - .additional_info("compositor_sum_shared") - .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .define("TYPE", "float") - .define("LOAD(value)", "value.x"); - -GPU_SHADER_CREATE_INFO(compositor_sum_red) - .additional_info("compositor_sum_float_shared") - .define("INITIALIZE(value)", "value.r") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_sum_green) - .additional_info("compositor_sum_float_shared") - .define("INITIALIZE(value)", "value.g") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_sum_blue) - .additional_info("compositor_sum_float_shared") - .define("INITIALIZE(value)", "value.b") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_sum_luminance) - .additional_info("compositor_sum_float_shared") - .push_constant(Type::VEC3, "luminance_coefficients") - .define("INITIALIZE(value)", "dot(value.rgb, luminance_coefficients)") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_sum_log_luminance) - .additional_info("compositor_sum_float_shared") - .push_constant(Type::VEC3, "luminance_coefficients") - .define("INITIALIZE(value)", "log(max(dot(value.rgb, luminance_coefficients), 1e-5))") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_sum_color) - .additional_info("compositor_sum_shared") - .image(0, GPU_RGBA32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .define("TYPE", "vec4") - .define("INITIALIZE(value)", "value") - .define("LOAD(value)", "value") - .do_static_compilation(true); - -/* -------------------------------------------------------------------- - * Sum Of Squared Difference Reductions. - */ - -GPU_SHADER_CREATE_INFO(compositor_sum_squared_difference_float_shared) - .additional_info("compositor_parallel_reduction_shared") - .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .push_constant(Type::FLOAT, "subtrahend") - .define("TYPE", "float") - .define("IDENTITY", "vec4(subtrahend)") - .define("LOAD(value)", "value.x") - .define("REDUCE(lhs, rhs)", "lhs + rhs"); - -GPU_SHADER_CREATE_INFO(compositor_sum_red_squared_difference) - .additional_info("compositor_sum_squared_difference_float_shared") - .define("INITIALIZE(value)", "pow(value.r - subtrahend, 2.0)") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_sum_green_squared_difference) - .additional_info("compositor_sum_squared_difference_float_shared") - .define("INITIALIZE(value)", "pow(value.g - subtrahend, 2.0)") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_sum_blue_squared_difference) - .additional_info("compositor_sum_squared_difference_float_shared") - .define("INITIALIZE(value)", "pow(value.b - subtrahend, 2.0)") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_sum_luminance_squared_difference) - .additional_info("compositor_sum_squared_difference_float_shared") - .push_constant(Type::VEC3, "luminance_coefficients") - .define("INITIALIZE(value)", "pow(dot(value.rgb, luminance_coefficients) - subtrahend, 2.0)") - .do_static_compilation(true); - -/* -------------------------------------------------------------------- - * Maximum Reductions. - */ - -GPU_SHADER_CREATE_INFO(compositor_maximum_luminance) - .additional_info("compositor_parallel_reduction_shared") - .typedef_source("common_math_lib.glsl") - .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .push_constant(Type::VEC3, "luminance_coefficients") - .define("TYPE", "float") - .define("IDENTITY", "vec4(FLT_MIN)") - .define("INITIALIZE(value)", "dot(value.rgb, luminance_coefficients)") - .define("LOAD(value)", "value.x") - .define("REDUCE(lhs, rhs)", "max(lhs, rhs)") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_maximum_float_in_range) - .additional_info("compositor_parallel_reduction_shared") - .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .push_constant(Type::FLOAT, "lower_bound") - .push_constant(Type::FLOAT, "upper_bound") - .define("TYPE", "float") - .define("IDENTITY", "vec4(lower_bound)") - .define("INITIALIZE(v)", "((v.x <= upper_bound) && (v.x >= lower_bound)) ? v.x : lower_bound") - .define("LOAD(value)", "value.x") - .define("REDUCE(lhs, rhs)", "((rhs > lhs) && (rhs <= upper_bound)) ? rhs : lhs") - .do_static_compilation(true); - -/* -------------------------------------------------------------------- - * Minimum Reductions. - */ - -GPU_SHADER_CREATE_INFO(compositor_minimum_luminance) - .additional_info("compositor_parallel_reduction_shared") - .typedef_source("common_math_lib.glsl") - .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .push_constant(Type::VEC3, "luminance_coefficients") - .define("TYPE", "float") - .define("IDENTITY", "vec4(FLT_MAX)") - .define("INITIALIZE(value)", "dot(value.rgb, luminance_coefficients)") - .define("LOAD(value)", "value.x") - .define("REDUCE(lhs, rhs)", "min(lhs, rhs)") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_minimum_float_in_range) - .additional_info("compositor_parallel_reduction_shared") - .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .push_constant(Type::FLOAT, "lower_bound") - .push_constant(Type::FLOAT, "upper_bound") - .define("TYPE", "float") - .define("IDENTITY", "vec4(upper_bound)") - .define("INITIALIZE(v)", "((v.x <= upper_bound) && (v.x >= lower_bound)) ? v.x : upper_bound") - .define("LOAD(value)", "value.x") - .define("REDUCE(lhs, rhs)", "((rhs < lhs) && (rhs >= lower_bound)) ? rhs : lhs") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_projector_lens_distortion_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_projector_lens_distortion_info.hh deleted file mode 100644 index 98fe1731703..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_projector_lens_distortion_info.hh +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_projector_lens_distortion) - .local_group_size(16, 16) - .push_constant(Type::FLOAT, "dispersion") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_projector_lens_distortion.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_realize_on_domain_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_realize_on_domain_info.hh deleted file mode 100644 index 4528649ae98..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_realize_on_domain_info.hh +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_realize_on_domain_shared) - .local_group_size(16, 16) - .push_constant(Type::MAT4, "inverse_transformation") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .compute_source("compositor_realize_on_domain.glsl"); - -GPU_SHADER_CREATE_INFO(compositor_realize_on_domain_color) - .additional_info("compositor_realize_on_domain_shared") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "domain_img") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_realize_on_domain_vector) - .additional_info("compositor_realize_on_domain_shared") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "domain_img") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_realize_on_domain_float) - .additional_info("compositor_realize_on_domain_shared") - .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "domain_img") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_screen_lens_distortion_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_screen_lens_distortion_info.hh deleted file mode 100644 index c42f2b328d4..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_screen_lens_distortion_info.hh +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_screen_lens_distortion_shared) - .local_group_size(16, 16) - .push_constant(Type::VEC3, "chromatic_distortion") - .push_constant(Type::FLOAT, "scale") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_screen_lens_distortion.glsl"); - -GPU_SHADER_CREATE_INFO(compositor_screen_lens_distortion) - .additional_info("compositor_screen_lens_distortion_shared") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_screen_lens_distortion_jitter) - .additional_info("compositor_screen_lens_distortion_shared") - .define("JITTER") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_set_alpha_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_set_alpha_info.hh deleted file mode 100644 index ca28194e921..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_set_alpha_info.hh +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_set_alpha) - .local_group_size(16, 16) - .sampler(0, ImageType::FLOAT_2D, "image_tx") - .sampler(1, ImageType::FLOAT_2D, "alpha_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_set_alpha.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_split_viewer_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_split_viewer_info.hh deleted file mode 100644 index d5793b0ce59..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_split_viewer_info.hh +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_split_viewer_shared) - .local_group_size(16, 16) - .push_constant(Type::FLOAT, "split_ratio") - .push_constant(Type::IVEC2, "view_size") - .sampler(0, ImageType::FLOAT_2D, "first_image_tx") - .sampler(1, ImageType::FLOAT_2D, "second_image_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_split_viewer.glsl"); - -GPU_SHADER_CREATE_INFO(compositor_split_viewer_horizontal) - .additional_info("compositor_split_viewer_shared") - .define("SPLIT_HORIZONTAL") - .do_static_compilation(true); - -GPU_SHADER_CREATE_INFO(compositor_split_viewer_vertical) - .additional_info("compositor_split_viewer_shared") - .define("SPLIT_VERTICAL") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_symmetric_blur_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_symmetric_blur_info.hh deleted file mode 100644 index 8ba2b4e04ef..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_symmetric_blur_info.hh +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_symmetric_blur) - .local_group_size(16, 16) - .push_constant(Type::BOOL, "extend_bounds") - .push_constant(Type::BOOL, "gamma_correct") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .sampler(1, ImageType::FLOAT_2D, "weights_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_symmetric_blur.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_symmetric_separable_blur_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_symmetric_separable_blur_info.hh deleted file mode 100644 index 57247dba4b8..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_symmetric_separable_blur_info.hh +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_symmetric_separable_blur) - .local_group_size(16, 16) - .push_constant(Type::BOOL, "extend_bounds") - .push_constant(Type::BOOL, "gamma_correct_input") - .push_constant(Type::BOOL, "gamma_uncorrect_output") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .sampler(1, ImageType::FLOAT_1D, "weights_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_symmetric_separable_blur.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh deleted file mode 100644 index a460c9d58a6..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_tone_map_photoreceptor) - .local_group_size(16, 16) - .push_constant(Type::VEC4, "global_adaptation_level") - .push_constant(Type::FLOAT, "contrast") - .push_constant(Type::FLOAT, "intensity") - .push_constant(Type::FLOAT, "chromatic_adaptation") - .push_constant(Type::FLOAT, "light_adaptation") - .push_constant(Type::VEC3, "luminance_coefficients") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_tone_map_photoreceptor.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh deleted file mode 100644 index 2b220af9460..00000000000 --- a/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "gpu_shader_create_info.hh" - -GPU_SHADER_CREATE_INFO(compositor_tone_map_simple) - .local_group_size(16, 16) - .push_constant(Type::FLOAT, "luminance_scale") - .push_constant(Type::FLOAT, "luminance_scale_blend_factor") - .push_constant(Type::FLOAT, "inverse_gamma") - .sampler(0, ImageType::FLOAT_2D, "input_tx") - .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_tone_map_simple.glsl") - .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_alpha_over.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_alpha_over.glsl deleted file mode 100644 index 8e3e033147f..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_alpha_over.glsl +++ /dev/null @@ -1,48 +0,0 @@ -void node_composite_alpha_over_mixed( - float factor, vec4 color, vec4 over_color, float premultiply_factor, out vec4 result) -{ - if (over_color.a <= 0.0) { - result = color; - } - else if (factor == 1.0 && over_color.a >= 1.0) { - result = over_color; - } - else { - float add_factor = 1.0 - premultiply_factor + over_color.a * premultiply_factor; - float premultiplier = factor * add_factor; - float multiplier = 1.0 - factor * over_color.a; - - result = multiplier * color + vec2(premultiplier, factor).xxxy * over_color; - } -} - -void node_composite_alpha_over_key(float factor, vec4 color, vec4 over_color, out vec4 result) -{ - if (over_color.a <= 0.0) { - result = color; - } - else if (factor == 1.0 && over_color.a >= 1.0) { - result = over_color; - } - else { - result = mix(color, vec4(over_color.rgb, 1.0), factor * over_color.a); - } -} - -void node_composite_alpha_over_premultiply(float factor, - vec4 color, - vec4 over_color, - out vec4 result) -{ - if (over_color.a < 0.0) { - result = color; - } - else if (factor == 1.0 && over_color.a >= 1.0) { - result = over_color; - } - else { - float multiplier = 1.0 - factor * over_color.a; - - result = multiplier * color + factor * over_color; - } -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_blur_common.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_blur_common.glsl deleted file mode 100644 index e404c03bbb0..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_blur_common.glsl +++ /dev/null @@ -1,32 +0,0 @@ -/* Preprocess the input of the blur filter by squaring it in its alpha straight form, assuming the - * given color is alpha premultiplied. */ -vec4 gamma_correct_blur_input(vec4 color) -{ - /* Unpremultiply alpha. */ - color.rgb /= color.a > 0.0 ? color.a : 1.0; - - /* Square color channel if it is positive, otherwise zero it. */ - color.rgb *= mix(color.rgb, vec3(0.0), lessThan(color.rgb, vec3(0.0))); - - /* Premultiply alpha to undo previous alpha unpremultiplication. */ - color.rgb *= color.a > 0.0 ? color.a : 1.0; - - return color; -} - -/* Postprocess the output of the blur filter by taking its square root it in its alpha straight - * form, assuming the given color is alpha premultiplied. This essential undoes the processing done - * by the gamma_correct_blur_input function. */ -vec4 gamma_uncorrect_blur_output(vec4 color) -{ - /* Unpremultiply alpha. */ - color.rgb /= color.a > 0.0 ? color.a : 1.0; - - /* Take the square root of the color channel if it is positive, otherwise zero it. */ - color.rgb = mix(sqrt(color.rgb), vec3(0.0), lessThan(color.rgb, vec3(0.0))); - - /* Premultiply alpha to undo previous alpha unpremultiplication. */ - color.rgb *= color.a > 0.0 ? color.a : 1.0; - - return color; -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_bright_contrast.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_bright_contrast.glsl deleted file mode 100644 index ce71b4fd8a4..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_bright_contrast.glsl +++ /dev/null @@ -1,38 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) - -/* The algorithm is by Werner D. Streidt - * (http://visca.com/ffactory/archives/5-99/msg00021.html) - * Extracted of OpenCV demhist.c - */ - -#define FLT_EPSILON 1.192092896e-07F - -void node_composite_bright_contrast( - vec4 color, float brightness, float contrast, const float use_premultiply, out vec4 result) -{ - brightness /= 100.0; - float delta = contrast / 200.0; - - float multiplier, offset; - if (contrast > 0.0) { - multiplier = 1.0 - delta * 2.0; - multiplier = 1.0 / max(multiplier, FLT_EPSILON); - offset = multiplier * (brightness - delta); - } - else { - delta *= -1.0; - multiplier = max(1.0 - delta * 2.0, 0.0); - offset = multiplier * brightness + delta; - } - - if (use_premultiply != 0.0) { - color_alpha_unpremultiply(color, color); - } - - result.rgb = color.rgb * multiplier + offset; - result.a = color.a; - - if (use_premultiply != 0.0) { - color_alpha_premultiply(result, result); - } -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_channel_matte.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_channel_matte.glsl deleted file mode 100644 index f2dcc9543f2..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_channel_matte.glsl +++ /dev/null @@ -1,52 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) - -#define CMP_NODE_CHANNEL_MATTE_CS_RGB 1.0 -#define CMP_NODE_CHANNEL_MATTE_CS_HSV 2.0 -#define CMP_NODE_CHANNEL_MATTE_CS_YUV 3.0 -#define CMP_NODE_CHANNEL_MATTE_CS_YCC 4.0 - -void node_composite_channel_matte(vec4 color, - const float color_space, - const float matte_channel, - const vec2 limit_channels, - float max_limit, - float min_limit, - out vec4 result, - out float matte) -{ - vec4 channels; - if (color_space == CMP_NODE_CHANNEL_MATTE_CS_HSV) { - rgb_to_hsv(color, channels); - } - else if (color_space == CMP_NODE_CHANNEL_MATTE_CS_YUV) { - rgba_to_yuva_itu_709(color, channels); - } - else if (color_space == CMP_NODE_CHANNEL_MATTE_CS_YCC) { - rgba_to_ycca_itu_709(color, channels); - } - else { - channels = color; - } - - float matte_value = channels[int(matte_channel)]; - float limit_value = max(channels[int(limit_channels.x)], channels[int(limit_channels.y)]); - - float alpha = 1.0 - (matte_value - limit_value); - if (alpha > max_limit) { - alpha = color.a; - } - else if (alpha < min_limit) { - alpha = 0.0; - } - else { - alpha = (alpha - min_limit) / (max_limit - min_limit); - } - - matte = min(alpha, color.a); - result = color * matte; -} - -#undef CMP_NODE_CHANNEL_MATTE_CS_RGB -#undef CMP_NODE_CHANNEL_MATTE_CS_HSV -#undef CMP_NODE_CHANNEL_MATTE_CS_YUV -#undef CMP_NODE_CHANNEL_MATTE_CS_YCC diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_chroma_matte.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_chroma_matte.glsl deleted file mode 100644 index 5d6bea0c9db..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_chroma_matte.glsl +++ /dev/null @@ -1,43 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl) -#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) - -/* Algorithm from the book Video Demystified. Chapter 7. Chroma Keying. */ -void node_composite_chroma_matte(vec4 color, - vec4 key, - float acceptance, - float cutoff, - float falloff, - out vec4 result, - out float matte) -{ - vec4 color_ycca; - rgba_to_ycca_itu_709(color, color_ycca); - vec4 key_ycca; - rgba_to_ycca_itu_709(key, key_ycca); - - /* Normalize the CrCb components into the [-1, 1] range. */ - vec2 color_cc = color_ycca.yz * 2.0 - 1.0; - vec2 key_cc = key_ycca.yz * 2.0 - 1.0; - - /* Rotate the color onto the space of the key such that x axis of the color space passes through - * the key color. */ - color_cc = vector_to_rotation_matrix(key_cc * vec2(1.0, -1.0)) * color_cc; - - /* Compute foreground key. If positive, the value is in the [0, 1] range. */ - float foreground_key = color_cc.x - (abs(color_cc.y) / acceptance); - - /* Negative foreground key values retain the original alpha. Positive values are scaled by the - * falloff, while colors that make an angle less than the cutoff angle get a zero alpha. */ - float alpha = color.a; - if (foreground_key > 0.0) { - alpha = 1.0 - (foreground_key / falloff); - - if (abs(atan(color_cc.y, color_cc.x)) < (cutoff / 2.0)) { - alpha = 0.0; - } - } - - /* Compute output. */ - matte = min(alpha, color.a); - result = color * matte; -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_balance.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_balance.glsl deleted file mode 100644 index bffb94cdedb..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_balance.glsl +++ /dev/null @@ -1,34 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) - -void node_composite_color_balance_lgg( - float factor, vec4 color, vec3 lift, vec3 gamma, vec3 gain, out vec4 result) -{ - lift = 2.0 - lift; - vec3 srgb_color = linear_rgb_to_srgb(color.rgb); - vec3 lift_balanced = ((srgb_color - 1.0) * lift) + 1.0; - - vec3 gain_balanced = lift_balanced * gain; - gain_balanced = max(gain_balanced, vec3(0.0)); - - vec3 linear_color = srgb_to_linear_rgb(gain_balanced); - gamma = mix(gamma, vec3(1e-6), equal(gamma, vec3(0.0))); - vec3 gamma_balanced = pow(linear_color, 1.0 / gamma); - - result.rgb = mix(color.rgb, gamma_balanced, min(factor, 1.0)); - result.a = color.a; -} - -void node_composite_color_balance_asc_cdl(float factor, - vec4 color, - vec3 offset, - vec3 power, - vec3 slope, - float offset_basis, - out vec4 result) -{ - offset += offset_basis; - vec3 balanced = color.rgb * slope + offset; - balanced = pow(max(balanced, vec3(0.0)), power); - result.rgb = mix(color.rgb, balanced, min(factor, 1.0)); - result.a = color.a; -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_correction.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_correction.glsl deleted file mode 100644 index 9b4858f03be..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_correction.glsl +++ /dev/null @@ -1,87 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl) -#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) - -void node_composite_color_correction(vec4 color, - float mask, - const vec3 enabled_channels, - float start_midtones, - float end_midtones, - float master_saturation, - float master_contrast, - float master_gamma, - float master_gain, - float master_lift, - float shadows_saturation, - float shadows_contrast, - float shadows_gamma, - float shadows_gain, - float shadows_lift, - float midtones_saturation, - float midtones_contrast, - float midtones_gamma, - float midtones_gain, - float midtones_lift, - float highlights_saturation, - float highlights_contrast, - float highlights_gamma, - float highlights_gain, - float highlights_lift, - const vec3 luminance_coefficients, - out vec4 result) -{ - const float margin = 0.10; - const float margin_divider = 0.5 / margin; - float level = (color.r + color.g + color.b) / 3.0; - float level_shadows = 0.0; - float level_midtones = 0.0; - float level_highlights = 0.0; - if (level < (start_midtones - margin)) { - level_shadows = 1.0; - } - else if (level < (start_midtones + margin)) { - level_midtones = ((level - start_midtones) * margin_divider) + 0.5; - level_shadows = 1.0 - level_midtones; - } - else if (level < (end_midtones - margin)) { - level_midtones = 1.0; - } - else if (level < (end_midtones + margin)) { - level_highlights = ((level - end_midtones) * margin_divider) + 0.5; - level_midtones = 1.0 - level_highlights; - } - else { - level_highlights = 1.0; - } - - float contrast = level_shadows * shadows_contrast; - contrast += level_midtones * midtones_contrast; - contrast += level_highlights * highlights_contrast; - contrast *= master_contrast; - float saturation = level_shadows * shadows_saturation; - saturation += level_midtones * midtones_saturation; - saturation += level_highlights * highlights_saturation; - saturation *= master_saturation; - float gamma = level_shadows * shadows_gamma; - gamma += level_midtones * midtones_gamma; - gamma += level_highlights * highlights_gamma; - gamma *= master_gamma; - float gain = level_shadows * shadows_gain; - gain += level_midtones * midtones_gain; - gain += level_highlights * highlights_gain; - gain *= master_gain; - float lift = level_shadows * shadows_lift; - lift += level_midtones * midtones_lift; - lift += level_highlights * highlights_lift; - lift += master_lift; - - float inverse_gamma = 1.0 / gamma; - float luma = get_luminance(color.rgb, luminance_coefficients); - - vec3 corrected = luma + saturation * (color.rgb - luma); - corrected = 0.5 + (corrected - 0.5) * contrast; - corrected = fallback_pow(corrected * gain + lift, inverse_gamma, corrected); - corrected = mix(color.rgb, corrected, min(mask, 1.0)); - - result.rgb = mix(corrected, color.rgb, equal(enabled_channels, vec3(0.0))); - result.a = color.a; -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_matte.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_matte.glsl deleted file mode 100644 index 038471bc1bc..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_matte.glsl +++ /dev/null @@ -1,27 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) - -void node_composite_color_matte(vec4 color, - vec4 key, - float hue_epsilon, - float saturation_epsilon, - float value_epsilon, - out vec4 result, - out float matte) - -{ - vec4 color_hsva; - rgb_to_hsv(color, color_hsva); - vec4 key_hsva; - rgb_to_hsv(key, key_hsva); - - bool is_within_saturation = distance(color_hsva.y, key_hsva.y) < saturation_epsilon; - bool is_within_value = distance(color_hsva.z, key_hsva.z) < value_epsilon; - bool is_within_hue = distance(color_hsva.x, key_hsva.x) < hue_epsilon; - /* Hue wraps around, so check the distance around the boundary. */ - float min_hue = min(color_hsva.x, key_hsva.x); - float max_hue = max(color_hsva.x, key_hsva.x); - is_within_hue = is_within_hue || ((min_hue + (1.0 - max_hue)) < hue_epsilon); - - matte = (is_within_hue && is_within_saturation && is_within_value) ? 0.0 : color.a; - result = color * matte; -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_spill.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_spill.glsl deleted file mode 100644 index 0adad53ad80..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_spill.glsl +++ /dev/null @@ -1,13 +0,0 @@ -void node_composite_color_spill(vec4 color, - float factor, - const float spill_channel, - vec3 spill_scale, - const vec2 limit_channels, - float limit_scale, - out vec4 result) -{ - float average_limit = (color[int(limit_channels.x)] + color[int(limit_channels.y)]) / 2.0; - float map = factor * color[int(spill_channel)] - limit_scale * average_limit; - result.rgb = map > 0.0 ? color.rgb + spill_scale * map : color.rgb; - result.a = color.a; -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_to_luminance.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_to_luminance.glsl deleted file mode 100644 index bcdd625bd4f..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_color_to_luminance.glsl +++ /dev/null @@ -1,6 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) - -void color_to_luminance(vec4 color, const vec3 luminance_coefficients, out float result) -{ - result = get_luminance(color.rgb, luminance_coefficients); -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_difference_matte.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_difference_matte.glsl deleted file mode 100644 index d769cadce3c..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_difference_matte.glsl +++ /dev/null @@ -1,10 +0,0 @@ -void node_composite_difference_matte( - vec4 color, vec4 key, float tolerance, float falloff, out vec4 result, out float matte) -{ - vec4 difference = abs(color - key); - float average_difference = (difference.r + difference.g + difference.b) / 3.0; - bool is_opaque = average_difference > tolerance + falloff; - float alpha = is_opaque ? color.a : (max(0.0, average_difference - tolerance) / falloff); - matte = min(alpha, color.a); - result = color * matte; -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_distance_matte.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_distance_matte.glsl deleted file mode 100644 index 9beed66826c..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_distance_matte.glsl +++ /dev/null @@ -1,26 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) - -void node_composite_distance_matte_rgba( - vec4 color, vec4 key, float tolerance, float falloff, out vec4 result, out float matte) -{ - float difference = distance(color.rgb, key.rgb); - bool is_opaque = difference > tolerance + falloff; - float alpha = is_opaque ? color.a : max(0.0, difference - tolerance) / falloff; - matte = min(alpha, color.a); - result = color * matte; -} - -void node_composite_distance_matte_ycca( - vec4 color, vec4 key, float tolerance, float falloff, out vec4 result, out float matte) -{ - vec4 color_ycca; - rgba_to_ycca_itu_709(color, color_ycca); - vec4 key_ycca; - rgba_to_ycca_itu_709(key, key_ycca); - - float difference = distance(color_ycca.yz, key_ycca.yz); - bool is_opaque = difference > tolerance + falloff; - float alpha = is_opaque ? color.a : max(0.0, difference - tolerance) / falloff; - matte = min(alpha, color.a); - result = color * matte; -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_exposure.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_exposure.glsl deleted file mode 100644 index f246635a91e..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_exposure.glsl +++ /dev/null @@ -1,6 +0,0 @@ -void node_composite_exposure(vec4 color, float exposure, out vec4 result) -{ - float multiplier = exp2(exposure); - result.rgb = color.rgb * multiplier; - result.a = color.a; -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_gamma.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_gamma.glsl deleted file mode 100644 index 53070d4b0e2..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_gamma.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl) - -void node_composite_gamma(vec4 color, float gamma, out vec4 result) -{ - result.rgb = fallback_pow(color.rgb, gamma, color.rgb); - result.a = color.a; -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_hue_correct.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_hue_correct.glsl deleted file mode 100644 index 99eb125cdf2..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_hue_correct.glsl +++ /dev/null @@ -1,39 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) - -/* Curve maps are stored in sampler objects that are evaluated in the [0, 1] range, so normalize - * parameters accordingly. */ -#define NORMALIZE_PARAMETER(parameter, minimum, range) ((parameter - minimum) * range) - -void node_composite_hue_correct(float factor, - vec4 color, - sampler1DArray curve_map, - const float layer, - vec3 minimums, - vec3 range_dividers, - out vec4 result) -{ - vec4 hsv; - rgb_to_hsv(color, hsv); - - /* First, adjust the hue channel on its own, since corrections in the saturation and value - * channels depends on the new value of the hue, not its original value. A curve map value of 0.5 - * means no change in hue, so adjust the value to get an identity at 0.5. Since the identity of - * addition is 0, we subtract 0.5 (0.5 - 0.5 = 0). */ - const float hue_parameter = NORMALIZE_PARAMETER(hsv.x, minimums.x, range_dividers.x); - hsv.x += texture(curve_map, vec2(hue_parameter, layer)).x - 0.5; - - /* Second, adjust the saturation and value based on the new value of the hue. A curve map value - * of 0.5 means no change in hue, so adjust the value to get an identity at 0.5. Since the - * identity of duplication is 1, we multiply by 2 (0.5 * 2 = 1). */ - vec2 parameters = NORMALIZE_PARAMETER(hsv.x, minimums.yz, range_dividers.yz); - hsv.y *= texture(curve_map, vec2(parameters.x, layer)).y * 2.0; - hsv.z *= texture(curve_map, vec2(parameters.y, layer)).z * 2.0; - - /* Sanitize the new hue and saturation values. */ - hsv.x = fract(hsv.x); - hsv.y = clamp(hsv.y, 0.0, 1.0); - - hsv_to_rgb(hsv, result); - - result = mix(color, result, factor); -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_hue_saturation_value.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_hue_saturation_value.glsl deleted file mode 100644 index dd5eb33d318..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_hue_saturation_value.glsl +++ /dev/null @@ -1,16 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) - -void node_composite_hue_saturation_value( - vec4 color, float hue, float saturation, float value, float factor, out vec4 result) -{ - vec4 hsv; - rgb_to_hsv(color, hsv); - - hsv.x = fract(hsv.x + hue + 0.5); - hsv.y = clamp(hsv.y * saturation, 0.0, 1.0); - hsv.z = hsv.z * value; - - hsv_to_rgb(hsv, result); - - result = mix(color, result, factor); -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_invert.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_invert.glsl deleted file mode 100644 index 59be746da7f..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_invert.glsl +++ /dev/null @@ -1,13 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) - -void node_composite_invert(float fac, vec4 color, float do_rgb, float do_alpha, out vec4 result) -{ - result = color; - if (do_rgb != 0.0) { - result.rgb = 1.0 - result.rgb; - } - if (do_alpha != 0.0) { - result.a = 1.0 - result.a; - } - result = mix(color, result, fac); -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_luminance_matte.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_luminance_matte.glsl deleted file mode 100644 index 3647ac583fe..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_luminance_matte.glsl +++ /dev/null @@ -1,14 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) - -void node_composite_luminance_matte(vec4 color, - float high, - float low, - const vec3 luminance_coefficients, - out vec4 result, - out float matte) -{ - float luminance = get_luminance(color.rgb, luminance_coefficients); - float alpha = clamp(0.0, 1.0, (luminance - low) / (high - low)); - matte = min(alpha, color.a); - result = color * matte; -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_main.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_main.glsl deleted file mode 100644 index 27624223dbc..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_main.glsl +++ /dev/null @@ -1,7 +0,0 @@ -/* The compute shader that will be dispatched by the compositor ShaderOperation. It just calls the - * evaluate function that will be dynamically generated and appended to this shader in the - * ShaderOperation::generate_code method. */ -void main() -{ - evaluate(); -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_map_value.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_map_value.glsl deleted file mode 100644 index 20874b4ef44..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_map_value.glsl +++ /dev/null @@ -1,56 +0,0 @@ -/* An arbitrary value determined by Blender. */ -#define BLENDER_ZMAX 10000.0 - -void node_composite_map_range(float value, - float from_min, - float from_max, - float to_min, - float to_max, - const float should_clamp, - out float result) -{ - if (abs(from_max - from_min) < 1e-6) { - result = 0.0; - } - else { - if (value >= -BLENDER_ZMAX && value <= BLENDER_ZMAX) { - result = (value - from_min) / (from_max - from_min); - result = to_min + result * (to_max - to_min); - } - else if (value > BLENDER_ZMAX) { - result = to_max; - } - else { - result = to_min; - } - - if (should_clamp != 0.0) { - if (to_max > to_min) { - result = clamp(result, to_min, to_max); - } - else { - result = clamp(result, to_max, to_min); - } - } - } -} - -void node_composite_map_value(float value, - float offset, - float size, - const float use_min, - float min, - const float use_max, - float max, - out float result) -{ - result = (value + offset) * size; - - if (use_min != 0.0 && result < min) { - result = min; - } - - if (use_max != 0.0 && result > max) { - result = max; - } -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_normal.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_normal.glsl deleted file mode 100644 index a2e3b6c4aaa..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_normal.glsl +++ /dev/null @@ -1,9 +0,0 @@ -void node_composite_normal(vec3 input_vector, - vec3 input_normal, - out vec3 result_normal, - out float result_dot) -{ - vec3 normal = normalize(input_normal); - result_normal = normal; - result_dot = -dot(input_vector, normal); -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_posterize.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_posterize.glsl deleted file mode 100644 index ee8ae234abe..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_posterize.glsl +++ /dev/null @@ -1,6 +0,0 @@ -void node_composite_posterize(vec4 color, float steps, out vec4 result) -{ - steps = clamp(steps, 2.0, 1024.0); - result = floor(color * steps) / steps; - result.a = color.a; -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_separate_combine.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_separate_combine.glsl deleted file mode 100644 index d72d2260394..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_separate_combine.glsl +++ /dev/null @@ -1,132 +0,0 @@ -#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl) - -/* ** Combine/Separate XYZ ** */ - -void node_composite_combine_xyz(float x, float y, float z, out vec3 vector) -{ - vector = vec3(x, y, z); -} - -void node_composite_separate_xyz(vec3 vector, out float x, out float y, out float z) -{ - x = vector.x; - y = vector.y; - z = vector.z; -} - -/* ** Combine/Separate RGBA ** */ - -void node_composite_combine_rgba(float r, float g, float b, float a, out vec4 color) -{ - color = vec4(r, g, b, a); -} - -void node_composite_separate_rgba(vec4 color, out float r, out float g, out float b, out float a) -{ - r = color.r; - g = color.g; - b = color.b; - a = color.a; -} - -/* ** Combine/Separate HSVA ** */ - -void node_composite_combine_hsva(float h, float s, float v, float a, out vec4 color) -{ - hsv_to_rgb(vec4(h, s, v, a), color); -} - -void node_composite_separate_hsva(vec4 color, out float h, out float s, out float v, out float a) -{ - vec4 hsva; - rgb_to_hsv(color, hsva); - h = hsva.x; - s = hsva.y; - v = hsva.z; - a = hsva.a; -} - -/* ** Combine/Separate HSLA ** */ - -void node_composite_combine_hsla(float h, float s, float l, float a, out vec4 color) -{ - hsl_to_rgb(vec4(h, s, l, a), color); -} - -void node_composite_separate_hsla(vec4 color, out float h, out float s, out float l, out float a) -{ - vec4 hsla; - rgb_to_hsl(color, hsla); - h = hsla.x; - s = hsla.y; - l = hsla.z; - a = hsla.a; -} - -/* ** Combine/Separate YCCA ** */ - -void node_composite_combine_ycca_itu_601(float y, float cb, float cr, float a, out vec4 color) -{ - ycca_to_rgba_itu_601(vec4(y, cb, cr, a), color); -} - -void node_composite_combine_ycca_itu_709(float y, float cb, float cr, float a, out vec4 color) -{ - ycca_to_rgba_itu_709(vec4(y, cb, cr, a), color); -} - -void node_composite_combine_ycca_jpeg(float y, float cb, float cr, float a, out vec4 color) -{ - ycca_to_rgba_jpeg(vec4(y, cb, cr, a), color); -} - -void node_composite_separate_ycca_itu_601( - vec4 color, out float y, out float cb, out float cr, out float a) -{ - vec4 ycca; - rgba_to_ycca_itu_601(color, ycca); - y = ycca.x; - cb = ycca.y; - cr = ycca.z; - a = ycca.a; -} - -void node_composite_separate_ycca_itu_709( - vec4 color, out float y, out float cb, out float cr, out float a) -{ - vec4 ycca; - rgba_to_ycca_itu_709(color, ycca); - y = ycca.x; - cb = ycca.y; - cr = ycca.z; - a = ycca.a; -} - -void node_composite_separate_ycca_jpeg( - vec4 color, out float y, out float cb, out float cr, out float a) -{ - vec4 ycca; - rgba_to_ycca_jpeg(color, ycca); - y = ycca.x; - cb = ycca.y; - cr = ycca.z; - a = ycca.a; -} - -/* ** Combine/Separate YUVA ** */ - -void node_composite_combine_yuva_itu_709(float y, float u, float v, float a, out vec4 color) -{ - yuva_to_rgba_itu_709(vec4(y, u, v, a), color); -} - -void node_composite_separate_yuva_itu_709( - vec4 color, out float y, out float u, out float v, out float a) -{ - vec4 yuva; - rgba_to_yuva_itu_709(color, yuva); - y = yuva.x; - u = yuva.y; - v = yuva.z; - a = yuva.a; -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_set_alpha.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_set_alpha.glsl deleted file mode 100644 index 95380d1ed0f..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_set_alpha.glsl +++ /dev/null @@ -1,9 +0,0 @@ -void node_composite_set_alpha_apply(vec4 color, float alpha, out vec4 result) -{ - result = color * alpha; -} - -void node_composite_set_alpha_replace(vec4 color, float alpha, out vec4 result) -{ - result = vec4(color.rgb, alpha); -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_store_output.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_store_output.glsl deleted file mode 100644 index 7fba26907b5..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_store_output.glsl +++ /dev/null @@ -1,26 +0,0 @@ -/* The following functions are called to store the given value in the output identified by the - * given ID. The ID is an unsigned integer that is encoded in a float, so floatBitsToUint is called - * to get the actual identifier. The functions have an output value as their last argument that is - * used to establish an output link that is then used to track the nodes that contribute to the - * output of the compositor node tree. - * - * The store_[float|vector|color] functions are dynamically generated in - * ShaderOperation::generate_code_for_outputs. */ - -void node_compositor_store_output_float(const float id, float value, out float out_value) -{ - store_float(floatBitsToUint(id), value); - out_value = value; -} - -void node_compositor_store_output_vector(const float id, vec3 vector, out vec3 out_vector) -{ - store_vector(floatBitsToUint(id), vector); - out_vector = vector; -} - -void node_compositor_store_output_color(const float id, vec4 color, out vec4 out_color) -{ - store_color(floatBitsToUint(id), color); - out_color = color; -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_texture_utilities.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_texture_utilities.glsl deleted file mode 100644 index 128fc6aeaf5..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_texture_utilities.glsl +++ /dev/null @@ -1,35 +0,0 @@ -/* A shorthand for 1D textureSize with a zero LOD. */ -int texture_size(sampler1D sampler) -{ - return textureSize(sampler, 0); -} - -/* A shorthand for 1D texelFetch with zero LOD and bounded access clamped to border. */ -vec4 texture_load(sampler1D sampler, int x) -{ - const int texture_bound = texture_size(sampler) - 1; - return texelFetch(sampler, clamp(x, 0, texture_bound), 0); -} - -/* A shorthand for 2D textureSize with a zero LOD. */ -ivec2 texture_size(sampler2D sampler) -{ - return textureSize(sampler, 0); -} - -/* A shorthand for 2D texelFetch with zero LOD and bounded access clamped to border. */ -vec4 texture_load(sampler2D sampler, ivec2 texel) -{ - const ivec2 texture_bounds = texture_size(sampler) - ivec2(1); - return texelFetch(sampler, clamp(texel, ivec2(0), texture_bounds), 0); -} - -/* A shorthand for 2D texelFetch with zero LOD and a fallback value for out-of-bound access. */ -vec4 texture_load(sampler2D sampler, ivec2 texel, vec4 fallback) -{ - const ivec2 texture_bounds = texture_size(sampler) - ivec2(1); - if (any(lessThan(texel, ivec2(0))) || any(greaterThan(texel, texture_bounds))) { - return fallback; - } - return texelFetch(sampler, texel, 0); -} diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_type_conversion.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_type_conversion.glsl deleted file mode 100644 index 75c76fd7341..00000000000 --- a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_type_conversion.glsl +++ /dev/null @@ -1,29 +0,0 @@ -float float_from_vec4(vec4 vector) -{ - return dot(vector.rgb, vec3(1.0)) / 3.0; -} - -float float_from_vec3(vec3 vector) -{ - return dot(vector, vec3(1.0)) / 3.0; -} - -vec3 vec3_from_vec4(vec4 vector) -{ - return vector.rgb; -} - -vec3 vec3_from_float(float value) -{ - return vec3(value); -} - -vec4 vec4_from_vec3(vec3 vector) -{ - return vec4(vector, 1.0); -} - -vec4 vec4_from_float(float value) -{ - return vec4(vec3(value), 1.0); -} -- cgit v1.2.3 From 0fc958a174192b2b25c4187c170ec4a394dc308a Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 2 Nov 2022 13:59:25 +0100 Subject: Fix: Crash adding rest positions to empty mesh The position attribute might not exist when the mesh is empty, which may be another problem, but there is no need to count on it here. --- source/blender/blenkernel/intern/DerivedMesh.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 11ef2b08df4..97ff45e93ce 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -747,7 +747,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, MutableAttributeAccessor attributes = mesh_final->attributes_for_write(); SpanAttributeWriter rest_positions = attributes.lookup_or_add_for_write_only_span("rest_position", ATTR_DOMAIN_POINT); - if (rest_positions) { + if (rest_positions && attributes.domain_size(ATTR_DOMAIN_POINT) > 0) { attributes.lookup("position").materialize(rest_positions.span); rest_positions.finish(); } -- cgit v1.2.3 From 38c7fd36ff7a6eb4522a688d38faa086a6313ae6 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 2 Nov 2022 14:41:49 +0100 Subject: Refactor: Rename Object->imat to Object->world_to_object The goal is to improve clarity and readability, without introducing big design changes. Follows the recent obmat to object_to_world refactor: the similar naming is used, and it is a run-time only rename, meaning, there is no affect on .blend files. This patch does not touch the redundant inversions. Those can be removed in almost (if not all) cases, but it would be the best to do it as a separate change. Differential Revision: https://developer.blender.org/D16367 --- source/blender/blenkernel/intern/armature.c | 2 +- source/blender/blenkernel/intern/armature_update.c | 6 ++--- source/blender/blenkernel/intern/cloth.c | 4 ++-- source/blender/blenkernel/intern/constraint.c | 2 +- source/blender/blenkernel/intern/effect.c | 2 +- source/blender/blenkernel/intern/fluid.c | 4 ++-- source/blender/blenkernel/intern/gpencil.c | 4 ++-- source/blender/blenkernel/intern/object.cc | 12 +++++----- source/blender/blenkernel/intern/object_dupli.cc | 27 +++++++++++----------- source/blender/blenkernel/intern/object_update.cc | 4 ++-- source/blender/blenkernel/intern/particle.c | 6 ++--- source/blender/blenkernel/intern/particle_system.c | 4 ++-- source/blender/blenkernel/intern/softbody.c | 5 ++-- .../depsgraph/intern/depsgraph_query_iter.cc | 2 +- .../draw/engines/gpencil/gpencil_draw_data.c | 2 +- .../draw/engines/workbench/workbench_shadow.c | 3 ++- .../blender/draw/intern/draw_cache_impl_gpencil.cc | 2 +- source/blender/draw/intern/draw_manager_data.cc | 2 +- source/blender/draw/intern/draw_manager_text.cc | 4 ++-- source/blender/draw/intern/draw_resource.hh | 2 +- source/blender/editors/armature/armature_add.c | 4 ++-- source/blender/editors/armature/armature_edit.c | 16 ++++++------- source/blender/editors/curve/editcurve.c | 4 ++-- source/blender/editors/curve/editcurve_paint.c | 8 +++---- .../blender/editors/gpencil/gpencil_sculpt_paint.c | 6 ++--- source/blender/editors/mesh/editmesh_add_gizmo.c | 4 ++-- source/blender/editors/mesh/editmesh_extrude.c | 14 +++++------ source/blender/editors/mesh/editmesh_polybuild.c | 18 +++++++-------- .../blender/editors/mesh/editmesh_preselect_elem.c | 4 ++-- .../blender/editors/mesh/editmesh_select_similar.c | 14 +++++------ source/blender/editors/mesh/editmesh_tools.c | 4 ++-- source/blender/editors/mesh/editmesh_utils.c | 2 +- source/blender/editors/object/object_hook.c | 12 +++++----- source/blender/editors/object/object_remesh.cc | 4 ++-- source/blender/editors/object/object_transform.cc | 12 +++++----- source/blender/editors/physics/particle_edit.c | 20 ++++++++-------- source/blender/editors/sculpt_paint/paint_mask.c | 8 +++---- source/blender/editors/sculpt_paint/paint_stroke.c | 5 ++-- .../blender/editors/sculpt_paint/paint_vertex.cc | 4 ++-- source/blender/editors/sculpt_paint/sculpt.c | 18 +++++++-------- .../editors/sculpt_paint/sculpt_filter_mesh.c | 4 ++-- .../blender/editors/space_view3d/view3d_buttons.c | 6 ++--- source/blender/editors/space_view3d/view3d_snap.c | 10 ++++---- .../editors/transform/transform_convert_particle.c | 2 +- .../blender/editors/transform/transform_gizmo_3d.c | 16 ++++++------- .../editors/transform/transform_mode_vert_slide.c | 4 ++-- source/blender/editors/uvedit/uvedit_unwrap_ops.c | 4 ++-- .../gpencil_modifiers/intern/MOD_gpencilhook.c | 4 ++-- .../gpencil_modifiers/intern/MOD_gpenciltint.c | 2 +- .../io/alembic/exporter/abc_writer_points.cc | 2 +- .../io/alembic/intern/abc_axis_conversion.cc | 4 ++-- source/blender/makesdna/DNA_object_types.h | 10 ++------ source/blender/makesdna/intern/dna_rename_defs.h | 1 + source/blender/modifiers/intern/MOD_cast.c | 8 +++---- source/blender/modifiers/intern/MOD_hook.c | 4 ++-- .../blender/modifiers/intern/MOD_mesh_to_volume.cc | 2 +- .../modifiers/intern/MOD_volume_displace.cc | 3 ++- .../blender/modifiers/intern/MOD_volume_to_mesh.cc | 2 +- source/blender/modifiers/intern/MOD_wave.cc | 4 ++-- .../geometry/nodes/node_geo_collection_info.cc | 6 ++--- .../nodes/geometry/nodes/node_geo_object_info.cc | 2 +- .../nodes/shader/nodes/node_shader_tex_coord.cc | 2 +- .../blender/render/intern/texture_pointdensity.c | 6 ++--- 63 files changed, 194 insertions(+), 194 deletions(-) diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 0f8bf0e9928..e433c26cc54 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -2569,7 +2569,7 @@ void BKE_pose_where_is(struct Depsgraph *depsgraph, Scene *scene, Object *ob) } } else { - invert_m4_m4(ob->imat, ob->object_to_world); /* imat is needed */ + invert_m4_m4(ob->world_to_object, ob->object_to_world); /* world_to_object is needed */ /* 1. clear flags */ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index b9f46118c0d..5f749472b2d 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -253,7 +253,7 @@ static void apply_curve_transform( } /* Convert the position to pose-space. */ - mul_m4_v3(ob->imat, r_vec); + mul_m4_v3(ob->world_to_object, r_vec); /* Set the new radius (it should be the average value). */ *r_radius = (radius + *r_radius) / 2; @@ -818,8 +818,8 @@ void BKE_pose_eval_init(struct Depsgraph *depsgraph, Scene *UNUSED(scene), Objec BLI_assert(object->pose != NULL); BLI_assert((object->pose->flag & POSE_RECALC) == 0); - /* imat is needed for solvers. */ - invert_m4_m4(object->imat, object->object_to_world); + /* world_to_object is needed for solvers. */ + invert_m4_m4(object->world_to_object, object->object_to_world); /* clear flags */ for (bPoseChannel *pchan = pose->chanbase.first; pchan != NULL; pchan = pchan->next) { diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 910869bbc72..88ba50fe901 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -581,11 +581,11 @@ static void cloth_to_object(Object *ob, ClothModifierData *clmd, float (*vertexC if (clmd->clothObject) { /* Inverse matrix is not up to date. */ - invert_m4_m4(ob->imat, ob->object_to_world); + invert_m4_m4(ob->world_to_object, ob->object_to_world); for (i = 0; i < cloth->mvert_num; i++) { copy_v3_v3(vertexCos[i], cloth->verts[i].x); - mul_m4_v3(ob->imat, vertexCos[i]); /* cloth is in global coords */ + mul_m4_v3(ob->world_to_object, vertexCos[i]); /* cloth is in global coords */ } } } diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 1f288aef5ad..bcc4ad0cb55 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -227,7 +227,7 @@ void BKE_constraints_clear_evalob(bConstraintOb *cob) /* cob->ob or cob->pchan might not exist */ if (cob->ob && cob->pchan) { /* copy new pose-matrix back to owner */ - mul_m4_m4m4(cob->pchan->pose_mat, cob->ob->imat, cob->matrix); + mul_m4_m4m4(cob->pchan->pose_mat, cob->ob->world_to_object, cob->matrix); /* copy inverse of delta back to owner */ invert_m4_m4(cob->pchan->constinv, delta); diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 983e4b3c6e6..c2ae4efbde8 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -875,7 +875,7 @@ static void do_texture_effector(EffectorCache *eff, copy_v3_v3(tex_co, point->loc); if (eff->pd->flag & PFIELD_TEX_OBJECT) { - mul_m4_v3(eff->ob->imat, tex_co); + mul_m4_v3(eff->ob->world_to_object, tex_co); if (eff->pd->flag & PFIELD_TEX_2D) { tex_co[2] = 0.0f; diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index b0e99e10acc..a3d2d73678c 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -3495,12 +3495,12 @@ static Mesh *create_smoke_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obje /* Calculate required shift to match domain's global position * it was originally simulated at (if object moves without manta step). */ - invert_m4_m4(ob->imat, ob->object_to_world); + invert_m4_m4(ob->world_to_object, ob->object_to_world); mul_m4_v3(ob->object_to_world, ob_loc); mul_m4_v3(fds->obmat, ob_cache_loc); sub_v3_v3v3(fds->obj_shift_f, ob_cache_loc, ob_loc); /* Convert shift to local space and apply to vertices. */ - mul_mat3_m4_v3(ob->imat, fds->obj_shift_f); + mul_mat3_m4_v3(ob->world_to_object, fds->obj_shift_f); /* Apply shift to vertices. */ for (int i = 0; i < num_verts; i++) { add_v3_v3(mverts[i].co, fds->obj_shift_f); diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 666142e3a54..5409bf61274 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -2771,12 +2771,12 @@ void BKE_gpencil_update_layer_transforms(const Depsgraph *depsgraph, Object *ob) Object *ob_parent = DEG_get_evaluated_object(depsgraph, gpl->parent); /* calculate new matrix */ if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { - mul_m4_m4m4(cur_mat, ob->imat, ob_parent->object_to_world); + mul_m4_m4m4(cur_mat, ob->world_to_object, ob_parent->object_to_world); } else if (gpl->partype == PARBONE) { bPoseChannel *pchan = BKE_pose_channel_find_name(ob_parent->pose, gpl->parsubstr); if (pchan != NULL) { - mul_m4_series(cur_mat, ob->imat, ob_parent->object_to_world, pchan->pose_mat); + mul_m4_series(cur_mat, ob->world_to_object, ob_parent->object_to_world, pchan->pose_mat); } else { unit_m4(cur_mat); diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc index 53e6d47860f..6d1b7caeea6 100644 --- a/source/blender/blenkernel/intern/object.cc +++ b/source/blender/blenkernel/intern/object.cc @@ -1336,8 +1336,8 @@ void BKE_object_modifier_hook_reset(Object *ob, HookModifierData *hmd) mul_m4_m4m4(hmd->parentinv, imat, ob->object_to_world); } else { - invert_m4_m4(hmd->object->imat, hmd->object->object_to_world); - mul_m4_m4m4(hmd->parentinv, hmd->object->imat, ob->object_to_world); + invert_m4_m4(hmd->object->world_to_object, hmd->object->object_to_world); + mul_m4_m4m4(hmd->parentinv, hmd->object->world_to_object, ob->object_to_world); } } } @@ -1361,8 +1361,8 @@ void BKE_object_modifier_gpencil_hook_reset(Object *ob, HookGpencilModifierData mul_m4_m4m4(hmd->parentinv, imat, ob->object_to_world); } else { - invert_m4_m4(hmd->object->imat, hmd->object->object_to_world); - mul_m4_m4m4(hmd->parentinv, hmd->object->imat, ob->object_to_world); + invert_m4_m4(hmd->object->world_to_object, hmd->object->object_to_world); + mul_m4_m4m4(hmd->parentinv, hmd->object->world_to_object, ob->object_to_world); } } @@ -4241,7 +4241,7 @@ void *BKE_object_tfm_backup(Object *ob) copy_m4_m4(obtfm->obmat, ob->object_to_world); copy_m4_m4(obtfm->parentinv, ob->parentinv); copy_m4_m4(obtfm->constinv, ob->constinv); - copy_m4_m4(obtfm->imat, ob->imat); + copy_m4_m4(obtfm->imat, ob->world_to_object); return (void *)obtfm; } @@ -4264,7 +4264,7 @@ void BKE_object_tfm_restore(Object *ob, void *obtfm_pt) copy_m4_m4(ob->object_to_world, obtfm->obmat); copy_m4_m4(ob->parentinv, obtfm->parentinv); copy_m4_m4(ob->constinv, obtfm->constinv); - copy_m4_m4(ob->imat, obtfm->imat); + copy_m4_m4(ob->world_to_object, obtfm->imat); } /** \} */ diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index d029d307d6e..a41f7c8bce4 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -589,7 +589,7 @@ static DupliObject *vertex_dupli(const DupliContext *ctx, /* Space matrix is constructed by removing `obmat` transform, * this yields the world-space transform for recursive duplis. */ - mul_m4_m4m4(space_mat, obmat, inst_ob->imat); + mul_m4_m4m4(space_mat, obmat, inst_ob->world_to_object); DupliObject *dob = make_dupli(ctx, inst_ob, obmat, index); @@ -609,10 +609,10 @@ static void make_child_duplis_verts_from_mesh(const DupliContext *ctx, const MVert *mvert = vdd->mvert; const int totvert = vdd->totvert; - invert_m4_m4(inst_ob->imat, inst_ob->object_to_world); + invert_m4_m4(inst_ob->world_to_object, inst_ob->object_to_world); /* Relative transform from parent to child space. */ float child_imat[4][4]; - mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->object_to_world); + mul_m4_m4m4(child_imat, inst_ob->world_to_object, ctx->object->object_to_world); for (int i = 0; i < totvert; i++) { DupliObject *dob = vertex_dupli( @@ -631,10 +631,10 @@ static void make_child_duplis_verts_from_editmesh(const DupliContext *ctx, BMEditMesh *em = vdd->em; const bool use_rotation = vdd->params.use_rotation; - invert_m4_m4(inst_ob->imat, inst_ob->object_to_world); + invert_m4_m4(inst_ob->world_to_object, inst_ob->object_to_world); /* Relative transform from parent to child space. */ float child_imat[4][4]; - mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->object_to_world); + mul_m4_m4m4(child_imat, inst_ob->world_to_object, ctx->object->object_to_world); BMVert *v; BMIter iter; @@ -920,7 +920,7 @@ static void make_duplis_geometry_set_impl(const DupliContext *ctx, make_dupli(ctx_for_instance, &object, matrix, id, &geometry_set, i); float space_matrix[4][4]; - mul_m4_m4m4(space_matrix, instance_offset_matrices[i].values, object.imat); + mul_m4_m4m4(space_matrix, instance_offset_matrices[i].values, object.world_to_object); mul_m4_m4_pre(space_matrix, parent_transform); make_recursive_duplis(ctx_for_instance, &object, space_matrix, id, &geometry_set, i); break; @@ -1097,7 +1097,7 @@ static DupliObject *face_dupli(const DupliContext *ctx, /* Space matrix is constructed by removing `obmat` transform, * this yields the world-space transform for recursive duplis. */ - mul_m4_m4m4(space_mat, obmat, inst_ob->imat); + mul_m4_m4m4(space_mat, obmat, inst_ob->world_to_object); DupliObject *dob = make_dupli(ctx, inst_ob, obmat, index); @@ -1177,9 +1177,9 @@ static void make_child_duplis_faces_from_mesh(const DupliContext *ctx, float child_imat[4][4]; - invert_m4_m4(inst_ob->imat, inst_ob->object_to_world); + invert_m4_m4(inst_ob->world_to_object, inst_ob->object_to_world); /* Relative transform from parent to child space. */ - mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->object_to_world); + mul_m4_m4m4(child_imat, inst_ob->world_to_object, ctx->object->object_to_world); const float scale_fac = ctx->object->instance_faces_scale; for (a = 0, mp = mpoly; a < totface; a++, mp++) { @@ -1217,9 +1217,9 @@ static void make_child_duplis_faces_from_editmesh(const DupliContext *ctx, BLI_assert((vert_coords == nullptr) || (em->bm->elem_index_dirty & BM_VERT) == 0); - invert_m4_m4(inst_ob->imat, inst_ob->object_to_world); + invert_m4_m4(inst_ob->world_to_object, inst_ob->object_to_world); /* Relative transform from parent to child space. */ - mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->object_to_world); + mul_m4_m4m4(child_imat, inst_ob->world_to_object, ctx->object->object_to_world); const float scale_fac = ctx->object->instance_faces_scale; BM_ITER_MESH_INDEX (f, &iter, em->bm, BM_FACES_OF_MESH, a) { @@ -1348,8 +1348,9 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem sim.ob = par; sim.psys = psys; sim.psmd = psys_get_modifier(par, psys); - /* Make sure emitter `imat` is in global coordinates instead of render view coordinates. */ - invert_m4_m4(par->imat, par->object_to_world); + /* Make sure emitter `world_to_object` is in global coordinates instead of render view + * coordinates. */ + invert_m4_m4(par->world_to_object, par->object_to_world); /* First check for loops (particle system object used as dupli-object). */ if (part->ren_as == PART_DRAW_OB) { diff --git a/source/blender/blenkernel/intern/object_update.cc b/source/blender/blenkernel/intern/object_update.cc index 7ea13bfcc84..106c9594718 100644 --- a/source/blender/blenkernel/intern/object_update.cc +++ b/source/blender/blenkernel/intern/object_update.cc @@ -121,7 +121,7 @@ void BKE_object_eval_transform_final(Depsgraph *depsgraph, Object *ob) DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob); /* Make sure inverse matrix is always up to date. This way users of it * do not need to worry about recalculating it. */ - invert_m4_m4_safe(ob->imat, ob->object_to_world); + invert_m4_m4_safe(ob->world_to_object, ob->object_to_world); /* Set negative scale flag in object. */ if (is_negative_m4(ob->object_to_world)) { ob->transflag |= OB_NEG_SCALE; @@ -258,7 +258,7 @@ void BKE_object_sync_to_original(Depsgraph *depsgraph, Object *object) object_orig->base_flag = object->base_flag; /* Transformation flags. */ copy_m4_m4(object_orig->object_to_world, object->object_to_world); - copy_m4_m4(object_orig->imat, object->imat); + copy_m4_m4(object_orig->world_to_object, object->world_to_object); copy_m4_m4(object_orig->constinv, object->constinv); object_orig->transflag = object->transflag; object_orig->flag = object->flag; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index f111e2dde17..4a0a09bcf56 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -4290,7 +4290,7 @@ static void get_cpa_texture(Mesh *mesh, case TEXCO_OBJECT: copy_v3_v3(texvec, par->state.co); if (mtex->object) { - mul_m4_v3(mtex->object->imat, texvec); + mul_m4_v3(mtex->object->world_to_object, texvec); } break; case TEXCO_UV: @@ -4378,7 +4378,7 @@ void psys_get_texture( case TEXCO_OBJECT: copy_v3_v3(texvec, pa->state.co); if (mtex->object) { - mul_m4_v3(mtex->object->imat, texvec); + mul_m4_v3(mtex->object->world_to_object, texvec); } break; case TEXCO_UV: @@ -5170,7 +5170,7 @@ void psys_get_dupli_path_transform(ParticleSimulationData *sim, } if (psys->part->rotmode == PART_ROT_VEL) { - transpose_m3_m4(nmat, ob->imat); + transpose_m3_m4(nmat, ob->world_to_object); mul_m3_v3(nmat, nor); normalize_v3(nor); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 7317318e828..72094f8cf04 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -3555,7 +3555,7 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra)) HairKey *key, *root; PARTICLE_P; - invert_m4_m4(ob->imat, ob->object_to_world); + invert_m4_m4(ob->world_to_object, ob->object_to_world); psys->lattice_deform_data = psys_create_lattice_deform_data(sim); @@ -3577,7 +3577,7 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra)) /* convert from global to geometry space */ copy_v3_v3(key->co, pa->state.co); - mul_m4_v3(ob->imat, key->co); + mul_m4_v3(ob->world_to_object, key->co); if (pa->totkey) { sub_v3_v3(key->co, root->co); diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 4147999bef8..efe423ccfc5 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -3073,12 +3073,13 @@ static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts, SB_estimate_transform(ob, sb->lcom, sb->lrot, sb->lscale); } /* Inverse matrix is not up to date. */ - invert_m4_m4(ob->imat, ob->object_to_world); + invert_m4_m4(ob->world_to_object, ob->object_to_world); for (a = 0; a < numVerts; a++, bp++) { copy_v3_v3(vertexCos[a], bp->pos); if (local == 0) { - mul_m4_v3(ob->imat, vertexCos[a]); /* softbody is in global coords, baked optionally not */ + mul_m4_v3(ob->world_to_object, + vertexCos[a]); /* softbody is in global coords, baked optionally not */ } } } diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index 11998860ef3..34df9a537e1 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -192,7 +192,7 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data) SET_FLAG_FROM_TEST(data->temp_dupli_object.transflag, is_neg_scale, OB_NEG_SCALE); copy_m4_m4(data->temp_dupli_object.object_to_world, dob->mat); - invert_m4_m4(data->temp_dupli_object.imat, data->temp_dupli_object.object_to_world); + invert_m4_m4(data->temp_dupli_object.world_to_object, data->temp_dupli_object.object_to_world); data->next_object = &data->temp_dupli_object; BLI_assert(deg::deg_validate_copy_on_write_datablock(&data->temp_dupli_object.id)); return true; diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_data.c b/source/blender/draw/engines/gpencil/gpencil_draw_data.c index 07b72c97875..1ebf3982a12 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_data.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_data.c @@ -380,7 +380,7 @@ void gpencil_light_pool_populate(GPENCIL_LightPool *lightpool, Object *ob) float(*mat)[4] = (float(*)[4])gp_light->right; if (la->type == LA_SPOT) { - copy_m4_m4(mat, ob->imat); + copy_m4_m4(mat, ob->world_to_object); gp_light->type = GP_LIGHT_TYPE_SPOT; gp_light->spot_size = cosf(la->spotsize * 0.5f); gp_light->spot_blend = (1.0f - gp_light->spot_size) * la->spotblend; diff --git a/source/blender/draw/engines/workbench/workbench_shadow.c b/source/blender/draw/engines/workbench/workbench_shadow.c index eb4d546648a..211c0e27418 100644 --- a/source/blender/draw/engines/workbench/workbench_shadow.c +++ b/source/blender/draw/engines/workbench/workbench_shadow.c @@ -307,7 +307,8 @@ void workbench_shadow_cache_populate(WORKBENCH_Data *data, Object *ob, const boo NULL); if (workbench_shadow_object_cast_visible_shadow(wpd, ob, engine_object_data)) { - mul_v3_mat3_m4v3(engine_object_data->shadow_dir, ob->imat, wpd->shadow_direction_ws); + mul_v3_mat3_m4v3( + engine_object_data->shadow_dir, ob->world_to_object, wpd->shadow_direction_ws); DRWShadingGroup *grp; bool use_shadow_pass_technique = !workbench_shadow_camera_in_object_shadow( diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.cc b/source/blender/draw/intern/draw_cache_impl_gpencil.cc index 3d6d2631186..6860fae744b 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.cc +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.cc @@ -612,7 +612,7 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_fill) for (int i = 0; i < vert_len; i++) { ED_gpencil_tpoint_to_point(region, origin, &tpoints[i], &gps->points[i]); - mul_m4_v3(ob->imat, &gps->points[i].x); + mul_m4_v3(ob->world_to_object, &gps->points[i].x); bGPDspoint *pt = &gps->points[i]; copy_v4_v4(pt->vert_color, tpoints[i].vert_color); } diff --git a/source/blender/draw/intern/draw_manager_data.cc b/source/blender/draw/intern/draw_manager_data.cc index 4aa27e2288c..29b1493ec5e 100644 --- a/source/blender/draw/intern/draw_manager_data.cc +++ b/source/blender/draw/intern/draw_manager_data.cc @@ -678,7 +678,7 @@ BLI_INLINE void drw_call_matrix_init(DRWObjectMatrix *ob_mats, Object *ob, float { copy_m4_m4(ob_mats->model, obmat); if (ob) { - copy_m4_m4(ob_mats->modelinverse, ob->imat); + copy_m4_m4(ob_mats->modelinverse, ob->world_to_object); } else { /* WATCH: Can be costly. */ diff --git a/source/blender/draw/intern/draw_manager_text.cc b/source/blender/draw/intern/draw_manager_text.cc index 239f6fcca73..1244c46e166 100644 --- a/source/blender/draw/intern/draw_manager_text.cc +++ b/source/blender/draw/intern/draw_manager_text.cc @@ -385,8 +385,8 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region, } if (do_global) { - mul_mat3_m4_v3(ob->imat, no_a); - mul_mat3_m4_v3(ob->imat, no_b); + mul_mat3_m4_v3(ob->world_to_object, no_a); + mul_mat3_m4_v3(ob->world_to_object, no_b); normalize_v3(no_a); normalize_v3(no_b); } diff --git a/source/blender/draw/intern/draw_resource.hh b/source/blender/draw/intern/draw_resource.hh index b116d7fe183..b8a0dbb8fa9 100644 --- a/source/blender/draw/intern/draw_resource.hh +++ b/source/blender/draw/intern/draw_resource.hh @@ -32,7 +32,7 @@ inline void ObjectMatrices::sync(const Object &object) { model = object.object_to_world; - model_inverse = object.imat; + model_inverse = object.world_to_object; } inline void ObjectMatrices::sync(const float4x4 &model_matrix) diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index fbdb375b8a6..806da5ee286 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -1569,8 +1569,8 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op) copy_v3_v3(curs, CTX_data_scene(C)->cursor.location); /* Get inverse point for head and orientation for tail */ - invert_m4_m4(obedit->imat, obedit->object_to_world); - mul_m4_v3(obedit->imat, curs); + invert_m4_m4(obedit->world_to_object, obedit->object_to_world); + mul_m4_v3(obedit->world_to_object, curs); if (rv3d && (U.flag & USER_ADD_VIEWALIGNED)) { copy_m3_m4(obmat, rv3d->viewmat); diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c index 810279f1b6c..780e2fae00e 100644 --- a/source/blender/editors/armature/armature_edit.c +++ b/source/blender/editors/armature/armature_edit.c @@ -113,8 +113,8 @@ void ED_armature_origin_set( /* Find the center-point. */ if (centermode == 2) { copy_v3_v3(cent, cursor); - invert_m4_m4(ob->imat, ob->object_to_world); - mul_m4_v3(ob->imat, cent); + invert_m4_m4(ob->world_to_object, ob->object_to_world); + mul_m4_v3(ob->world_to_object, cent); } else { if (around == V3D_AROUND_CENTER_BOUNDS) { @@ -289,9 +289,9 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op) float cursor_local[3]; const View3DCursor *cursor = &scene->cursor; - invert_m4_m4(ob->imat, ob->object_to_world); + invert_m4_m4(ob->world_to_object, ob->object_to_world); copy_v3_v3(cursor_local, cursor->location); - mul_m4_v3(ob->imat, cursor_local); + mul_m4_v3(ob->world_to_object, cursor_local); /* cursor */ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { @@ -730,8 +730,8 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op) ebp = points.first; /* Get points - cursor (tail) */ - invert_m4_m4(obedit->imat, obedit->object_to_world); - mul_v3_m4v3(curs, obedit->imat, scene->cursor.location); + invert_m4_m4(obedit->world_to_object, obedit->object_to_world); + mul_v3_m4v3(curs, obedit->world_to_object, scene->cursor.location); /* Create a bone */ newbone = add_points_bone(obedit, ebp->vec, curs); @@ -767,8 +767,8 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op) float dist_sq_a, dist_sq_b; /* get cursor location */ - invert_m4_m4(obedit->imat, obedit->object_to_world); - mul_v3_m4v3(curs, obedit->imat, scene->cursor.location); + invert_m4_m4(obedit->world_to_object, obedit->object_to_world); + mul_v3_m4v3(curs, obedit->world_to_object, scene->cursor.location); /* get distances */ dist_sq_a = len_squared_v3v3(ebp_a->vec, curs); diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 2b6cce25bb7..f9377503630 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -5095,8 +5095,8 @@ static int spin_exec(bContext *C, wmOperator *op) continue; } - invert_m4_m4(obedit->imat, obedit->object_to_world); - mul_m4_v3(obedit->imat, cent); + invert_m4_m4(obedit->world_to_object, obedit->object_to_world); + mul_m4_v3(obedit->world_to_object, cent); if (!ed_editnurb_spin(viewmat, v3d, obedit, axis, cent)) { count_failed += 1; diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c index 1e91e2f48fc..af3d439dd2e 100644 --- a/source/blender/editors/curve/editcurve_paint.c +++ b/source/blender/editors/curve/editcurve_paint.c @@ -245,7 +245,7 @@ static bool stroke_elem_project_fallback(const struct CurveDrawData *cdd, cdd->vc.v3d, cdd->vc.region, location_fallback_depth, mval_fl, r_location_world); zero_v3(r_normal_local); } - mul_v3_m4v3(r_location_local, cdd->vc.obedit->imat, r_location_world); + mul_v3_m4v3(r_location_local, cdd->vc.obedit->world_to_object, r_location_world); if (!is_zero_v3(r_normal_world)) { copy_v3_v3(r_normal_local, r_normal_world); @@ -304,7 +304,7 @@ static void curve_draw_stroke_from_operator_elem(wmOperator *op, PointerRNA *ite RNA_float_get_array(itemptr, "mouse", selem->mval); RNA_float_get_array(itemptr, "location", selem->location_world); - mul_v3_m4v3(selem->location_local, cdd->vc.obedit->imat, selem->location_world); + mul_v3_m4v3(selem->location_local, cdd->vc.obedit->world_to_object, selem->location_world); selem->pressure = RNA_float_get(itemptr, "pressure"); } @@ -445,7 +445,7 @@ static void curve_draw_event_add(wmOperator *op, const wmEvent *event) struct CurveDrawData *cdd = op->customdata; Object *obedit = cdd->vc.obedit; - invert_m4_m4(obedit->imat, obedit->object_to_world); + invert_m4_m4(obedit->world_to_object, obedit->object_to_world); struct StrokeElem *selem = BLI_mempool_calloc(cdd->stroke_elem_pool); @@ -758,7 +758,7 @@ static int curve_draw_exec(bContext *C, wmOperator *op) int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool); const bool is_3d = (cu->flag & CU_3D) != 0; - invert_m4_m4(obedit->imat, obedit->object_to_world); + invert_m4_m4(obedit->world_to_object, obedit->object_to_world); if (BLI_mempool_len(cdd->stroke_elem_pool) == 0) { curve_draw_stroke_from_operator(op); diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index 515bdeb6188..37c1524c2ff 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -691,7 +691,7 @@ static bool gpencil_brush_pinch_apply(tGP_BrushEditData *gso, /* 3) Translate back to original space, with the shrinkage applied */ add_v3_v3v3(fpt, gso->dvec, vec); - mul_v3_m4v3(&pt->x, gso->object->imat, fpt); + mul_v3_m4v3(&pt->x, gso->object->world_to_object, fpt); /* compute lock axis */ gpencil_sculpt_compute_lock_axis(gso, pt, save_pt); @@ -748,7 +748,7 @@ static bool gpencil_brush_twist_apply(tGP_BrushEditData *gso, * (center is stored in dvec) */ mul_m3_v3(rmat, vec); add_v3_v3v3(fpt, vec, gso->dvec); /* restore */ - mul_v3_m4v3(&pt->x, gso->object->imat, fpt); + mul_v3_m4v3(&pt->x, gso->object->world_to_object, fpt); /* compute lock axis */ gpencil_sculpt_compute_lock_axis(gso, pt, save_pt); @@ -1041,7 +1041,7 @@ static void gpencil_brush_clone_add(bContext *C, tGP_BrushEditData *gso) /* assume that the delta can just be applied, and then everything works */ add_v3_v3(&pt->x, delta); - mul_m4_v3(gso->object->imat, &pt->x); + mul_m4_v3(gso->object->world_to_object, &pt->x); } /* Store ref for later */ diff --git a/source/blender/editors/mesh/editmesh_add_gizmo.c b/source/blender/editors/mesh/editmesh_add_gizmo.c index ad900c997f8..03c6104bb0d 100644 --- a/source/blender/editors/mesh/editmesh_add_gizmo.c +++ b/source/blender/editors/mesh/editmesh_add_gizmo.c @@ -316,8 +316,8 @@ static int add_primitive_cube_gizmo_exec(bContext *C, wmOperator *op) PropertyRNA *prop_matrix = RNA_struct_find_property(op->ptr, "matrix"); if (RNA_property_is_set(op->ptr, prop_matrix)) { RNA_property_float_get_array(op->ptr, prop_matrix, &matrix[0][0]); - invert_m4_m4(obedit->imat, obedit->object_to_world); - mul_m4_m4m4(matrix, obedit->imat, matrix); + invert_m4_m4(obedit->world_to_object, obedit->object_to_world); + mul_m4_m4m4(matrix, obedit->world_to_object, matrix); } else { /* For the first update the widget may not set the matrix. */ diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 9df3a521cfa..88bcefc5cc8 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -761,11 +761,11 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w continue; } - invert_m4_m4(vc.obedit->imat, vc.obedit->object_to_world); + invert_m4_m4(vc.obedit->world_to_object, vc.obedit->object_to_world); ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); float local_center[3]; - mul_v3_m4v3(local_center, vc.obedit->imat, center); + mul_v3_m4v3(local_center, vc.obedit->world_to_object, center); /* call extrude? */ if (verts_len != 0) { @@ -810,11 +810,11 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w float view_vec[3], cross[3]; /* convert the 2D normal into 3D */ - mul_mat3_m4_v3(vc.rv3d->viewinv, nor); /* World-space. */ - mul_mat3_m4_v3(vc.obedit->imat, nor); /* Local-space. */ + mul_mat3_m4_v3(vc.rv3d->viewinv, nor); /* World-space. */ + mul_mat3_m4_v3(vc.obedit->world_to_object, nor); /* Local-space. */ /* correct the normal to be aligned on the view plane */ - mul_v3_mat3_m4v3(view_vec, vc.obedit->imat, vc.rv3d->viewinv[2]); + mul_v3_mat3_m4v3(view_vec, vc.obedit->world_to_object, vc.rv3d->viewinv[2]); cross_v3_v3v3(cross, nor, view_vec); cross_v3_v3v3(nor, view_vec, cross); normalize_v3(nor); @@ -825,7 +825,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w mul_m4_v3(vc.obedit->object_to_world, ofs); /* view space */ ED_view3d_win_to_3d_int(vc.v3d, vc.region, ofs, event->mval, ofs); - mul_m4_v3(vc.obedit->imat, ofs); /* back in object space */ + mul_m4_v3(vc.obedit->world_to_object, ofs); /* back in object space */ sub_v3_v3(ofs, local_center); @@ -876,7 +876,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w copy_v3_v3(local_center, cursor); ED_view3d_win_to_3d_int(vc.v3d, vc.region, local_center, event->mval, local_center); - mul_m4_v3(vc.obedit->imat, local_center); /* back in object space */ + mul_m4_v3(vc.obedit->world_to_object, local_center); /* back in object space */ EDBM_op_init(vc.em, &bmop, op, "create_vert co=%v", local_center); BMO_op_exec(vc.em->bm, &bmop); diff --git a/source/blender/editors/mesh/editmesh_polybuild.c b/source/blender/editors/mesh/editmesh_polybuild.c index 63e37b18827..cfd07a6ff35 100644 --- a/source/blender/editors/mesh/editmesh_polybuild.c +++ b/source/blender/editors/mesh/editmesh_polybuild.c @@ -124,7 +124,7 @@ static int edbm_polybuild_transform_at_cursor_invoke(bContext *C, BMEditMesh *em = vc.em; BMesh *bm = em->bm; - invert_m4_m4(vc.obedit->imat, vc.obedit->object_to_world); + invert_m4_m4(vc.obedit->world_to_object, vc.obedit->object_to_world); ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); if (!ele_act) { @@ -192,7 +192,7 @@ static int edbm_polybuild_delete_at_cursor_invoke(bContext *C, BMEditMesh *em = vc.em; BMesh *bm = em->bm; - invert_m4_m4(vc.obedit->imat, vc.obedit->object_to_world); + invert_m4_m4(vc.obedit->world_to_object, vc.obedit->object_to_world); ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); if (!ele_act) { @@ -286,7 +286,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con BMEditMesh *em = vc.em; BMesh *bm = em->bm; - invert_m4_m4(vc.obedit->imat, vc.obedit->object_to_world); + invert_m4_m4(vc.obedit->world_to_object, vc.obedit->object_to_world); ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX); @@ -296,7 +296,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con copy_v3_v3(center, vc.scene->cursor.location); mul_v3_m4v3(center, vc.obedit->object_to_world, center); ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center); - mul_m4_v3(vc.obedit->imat, center); + mul_m4_v3(vc.obedit->world_to_object, center); BMVert *v_new = BM_vert_create(bm, center, NULL, BM_CREATE_NOP); edbm_flag_disable_all_multi(vc.scene, vc.view_layer, vc.v3d, BM_ELEM_SELECT); @@ -311,7 +311,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con mid_v3_v3v3(center, e_act->v1->co, e_act->v2->co); mul_m4_v3(vc.obedit->object_to_world, center); ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center); - mul_m4_v3(vc.obedit->imat, center); + mul_m4_v3(vc.obedit->world_to_object, center); if (f_reference->len == 3 && RNA_boolean_get(op->ptr, "create_quads")) { const float fac = line_point_factor_v3(center, e_act->v1->co, e_act->v2->co); BMVert *v_new = BM_edge_split(bm, e_act, e_act->v1, NULL, CLAMPIS(fac, 0.0f, 1.0f)); @@ -366,7 +366,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con mul_v3_m4v3(center, vc.obedit->object_to_world, v_act->co); ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center); - mul_m4_v3(vc.obedit->imat, center); + mul_m4_v3(vc.obedit->world_to_object, center); BMVert *v_quad[4]; v_quad[0] = v_act; @@ -388,7 +388,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con /* Just add edge */ mul_m4_v3(vc.obedit->object_to_world, center); ED_view3d_win_to_3d_int(vc.v3d, vc.region, v_act->co, event->mval, center); - mul_m4_v3(vc.obedit->imat, center); + mul_m4_v3(vc.obedit->world_to_object, center); BMVert *v_new = BM_vert_create(bm, center, NULL, BM_CREATE_NOP); @@ -464,7 +464,7 @@ static int edbm_polybuild_split_at_cursor_invoke(bContext *C, BMEditMesh *em = vc.em; BMesh *bm = em->bm; - invert_m4_m4(vc.obedit->imat, vc.obedit->object_to_world); + invert_m4_m4(vc.obedit->world_to_object, vc.obedit->object_to_world); ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX); @@ -477,7 +477,7 @@ static int edbm_polybuild_split_at_cursor_invoke(bContext *C, mid_v3_v3v3(center, e_act->v1->co, e_act->v2->co); mul_m4_v3(vc.obedit->object_to_world, center); ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center); - mul_m4_v3(vc.obedit->imat, center); + mul_m4_v3(vc.obedit->world_to_object, center); const float fac = line_point_factor_v3(center, e_act->v1->co, e_act->v2->co); BMVert *v_new = BM_edge_split(bm, e_act, e_act->v1, NULL, CLAMPIS(fac, 0.0f, 1.0f)); diff --git a/source/blender/editors/mesh/editmesh_preselect_elem.c b/source/blender/editors/mesh/editmesh_preselect_elem.c index 732f39e4123..5d8ce7cae44 100644 --- a/source/blender/editors/mesh/editmesh_preselect_elem.c +++ b/source/blender/editors/mesh/editmesh_preselect_elem.c @@ -245,7 +245,7 @@ static void view3d_preselect_update_preview_triangle_from_vert(struct EditMesh_P if (e_pair[1] != NULL) { mul_v3_m4v3(center, vc->obedit->object_to_world, v_act->co); ED_view3d_win_to_3d_int(vc->v3d, vc->region, center, mval, center); - mul_m4_v3(vc->obedit->imat, center); + mul_m4_v3(vc->obedit->world_to_object, center); psel->preview_tris = MEM_mallocN(sizeof(*psel->preview_tris) * 2, __func__); psel->preview_lines = MEM_mallocN(sizeof(*psel->preview_lines) * 4, __func__); @@ -313,7 +313,7 @@ static void view3d_preselect_update_preview_triangle_from_edge(struct EditMesh_P mid_v3_v3v3(center, eed->v1->co, eed->v2->co); mul_m4_v3(vc->obedit->object_to_world, center); ED_view3d_win_to_3d_int(vc->v3d, vc->region, center, mval, center); - mul_m4_v3(vc->obedit->imat, center); + mul_m4_v3(vc->obedit->world_to_object, center); copy_v3_v3(psel->preview_tris[0][0], eed->v1->co); copy_v3_v3(psel->preview_tris[0][1], eed->v2->co); diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c index 9469639718f..d9721db326a 100644 --- a/source/blender/editors/mesh/editmesh_select_similar.c +++ b/source/blender/editors/mesh/editmesh_select_similar.c @@ -135,7 +135,7 @@ static void face_to_plane(const Object *ob, BMFace *face, float r_plane[4]) { float normal[3], co[3]; copy_v3_v3(normal, face->no); - mul_transposed_mat3_m4_v3(ob->imat, normal); + mul_transposed_mat3_m4_v3(ob->world_to_object, normal); normalize_v3(normal); mul_v3_m4v3(co, ob->object_to_world, BM_FACE_FIRST_LOOP(face)->v->co); plane_from_point_normal_v3(r_plane, co, normal); @@ -206,7 +206,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op) BMEditMesh *em = BKE_editmesh_from_object(ob); BMesh *bm = em->bm; Material ***material_array = NULL; - invert_m4_m4(ob->imat, ob->object_to_world); + invert_m4_m4(ob->world_to_object, ob->object_to_world); int custom_data_offset = 0; if (bm->totfacesel == 0) { @@ -269,7 +269,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op) case SIMFACE_NORMAL: { float normal[3]; copy_v3_v3(normal, face->no); - mul_transposed_mat3_m4_v3(ob->imat, normal); + mul_transposed_mat3_m4_v3(ob->world_to_object, normal); normalize_v3(normal); BLI_kdtree_3d_insert(tree_3d, tree_index++, normal); break; @@ -414,7 +414,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op) case SIMFACE_NORMAL: { float normal[3]; copy_v3_v3(normal, face->no); - mul_transposed_mat3_m4_v3(ob->imat, normal); + mul_transposed_mat3_m4_v3(ob->world_to_object, normal); normalize_v3(normal); /* We are treating the normals as coordinates, the "nearest" one will @@ -1028,7 +1028,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) BLI_bitmap *defbase_selected = NULL; int defbase_len = 0; - invert_m4_m4(ob->imat, ob->object_to_world); + invert_m4_m4(ob->world_to_object, ob->object_to_world); if (bm->totvertsel == 0) { continue; @@ -1067,7 +1067,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) case SIMVERT_NORMAL: { float normal[3]; copy_v3_v3(normal, vert->no); - mul_transposed_mat3_m4_v3(ob->imat, normal); + mul_transposed_mat3_m4_v3(ob->world_to_object, normal); normalize_v3(normal); BLI_kdtree_3d_insert(tree_3d, normal_tree_index++, normal); @@ -1217,7 +1217,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) case SIMVERT_NORMAL: { float normal[3]; copy_v3_v3(normal, vert->no); - mul_transposed_mat3_m4_v3(ob->imat, normal); + mul_transposed_mat3_m4_v3(ob->world_to_object, normal); normalize_v3(normal); /* We are treating the normals as coordinates, the "nearest" one will diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 9f5c0d74ced..8b29472f687 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -3356,8 +3356,8 @@ static bool merge_target(BMEditMesh *em, if (use_cursor) { vco = scene->cursor.location; copy_v3_v3(co, vco); - invert_m4_m4(ob->imat, ob->object_to_world); - mul_m4_v3(ob->imat, co); + invert_m4_m4(ob->world_to_object, ob->object_to_world); + mul_m4_v3(ob->world_to_object, co); } else { float fac; diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 10acfc96ca8..f6ffbec094e 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -1942,7 +1942,7 @@ void EDBM_project_snap_verts( NULL, co_proj, NULL)) { - mul_v3_m4v3(eve->co, obedit->imat, co_proj); + mul_v3_m4v3(eve->co, obedit->world_to_object, co_proj); } } } diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 63093692e43..d52c7f0b8d4 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -556,13 +556,13 @@ static int add_hook_object(const bContext *C, unit_m4(pose_mat); - invert_m4_m4(obedit->imat, obedit->object_to_world); + invert_m4_m4(obedit->world_to_object, obedit->object_to_world); if (mode == OBJECT_ADDHOOK_NEWOB) { /* pass */ } else { /* may overwrite with pose-bone location, below */ - mul_v3_m4v3(cent, obedit->imat, ob->object_to_world[3]); + mul_v3_m4v3(cent, obedit->world_to_object, ob->object_to_world[3]); } if (mode == OBJECT_ADDHOOK_SELOB_BONE) { @@ -577,7 +577,7 @@ static int add_hook_object(const bContext *C, if (LIKELY(pchan_act)) { invert_m4_m4(pose_mat, pchan_act->pose_mat); mul_v3_m4v3(cent, ob->object_to_world, pchan_act->pose_mat[3]); - mul_v3_m4v3(cent, obedit->imat, cent); + mul_v3_m4v3(cent, obedit->world_to_object, cent); } } else { @@ -588,16 +588,16 @@ static int add_hook_object(const bContext *C, copy_v3_v3(hmd->cent, cent); /* matrix calculus */ - /* vert x (obmat x hook->imat) x hook->object_to_world x ob->imat */ + /* vert x (obmat x hook->world_to_object) x hook->object_to_world x ob->world_to_object */ /* (parentinv ) */ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); BKE_object_transform_copy(object_eval, ob); BKE_object_where_is_calc(depsgraph, scene_eval, object_eval); - invert_m4_m4(object_eval->imat, object_eval->object_to_world); + invert_m4_m4(object_eval->world_to_object, object_eval->object_to_world); /* apparently this call goes from right to left... */ - mul_m4_series(hmd->parentinv, pose_mat, object_eval->imat, obedit->object_to_world); + mul_m4_series(hmd->parentinv, pose_mat, object_eval->world_to_object, obedit->object_to_world); DEG_relations_tag_update(bmain); diff --git a/source/blender/editors/object/object_remesh.cc b/source/blender/editors/object/object_remesh.cc index c653610d6fe..69fa84aa260 100644 --- a/source/blender/editors/object/object_remesh.cc +++ b/source/blender/editors/object/object_remesh.cc @@ -494,10 +494,10 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev float view_normal[3] = {0.0f, 0.0f, 1.0f}; /* Calculate the view normal. */ - invert_m4_m4(active_object->imat, active_object->object_to_world); + invert_m4_m4(active_object->world_to_object, active_object->object_to_world); copy_m3_m4(mat, rv3d->viewinv); mul_m3_v3(mat, view_normal); - copy_m3_m4(mat, active_object->imat); + copy_m3_m4(mat, active_object->world_to_object); mul_m3_v3(mat, view_normal); normalize_v3(view_normal); diff --git a/source/blender/editors/object/object_transform.cc b/source/blender/editors/object/object_transform.cc index a863e9ac324..0c2aca8b97b 100644 --- a/source/blender/editors/object/object_transform.cc +++ b/source/blender/editors/object/object_transform.cc @@ -1274,8 +1274,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) if (centermode == ORIGIN_TO_CURSOR) { copy_v3_v3(cent, cursor); - invert_m4_m4(obedit->imat, obedit->object_to_world); - mul_m4_v3(obedit->imat, cent); + invert_m4_m4(obedit->world_to_object, obedit->object_to_world); + mul_m4_v3(obedit->world_to_object, cent); } else { if (around == V3D_AROUND_CENTER_BOUNDS) { @@ -1342,8 +1342,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) if (centermode == ORIGIN_TO_CURSOR) { copy_v3_v3(cent, cursor); - invert_m4_m4(ob->imat, ob->object_to_world); - mul_m4_v3(ob->imat, cent); + invert_m4_m4(ob->world_to_object, ob->object_to_world); + mul_m4_v3(ob->world_to_object, cent); } if (ob->data == nullptr) { @@ -1363,8 +1363,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) INIT_MINMAX(min, max); BKE_object_minmax_dupli(depsgraph, scene, ob, min, max, true); mid_v3_v3v3(cent, min, max); - invert_m4_m4(ob->imat, ob->object_to_world); - mul_m4_v3(ob->imat, cent); + invert_m4_m4(ob->world_to_object, ob->object_to_world); + mul_m4_v3(ob->world_to_object, cent); } add_v3_v3(ob->instance_collection->instance_offset, cent); diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 6dc3860fdf2..22295c260e2 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -3920,8 +3920,8 @@ static void brush_puff(PEData *data, int point_index, float mouse_distance) mul_m4_v3(mat, co); /* Use `kco` as the object space version of world-space `co`, - * `ob->imat` is set before calling. */ - mul_v3_m4v3(kco, data->ob->imat, co); + * `ob->world_to_object` is set before calling. */ + mul_v3_m4v3(kco, data->ob->world_to_object, co); point_index = BLI_kdtree_3d_find_nearest(edit->emitter_field, kco, NULL); if (point_index == -1) { @@ -4010,8 +4010,8 @@ static void brush_puff(PEData *data, int point_index, float mouse_distance) mul_m4_v3(mat, oco); /* Use `kco` as the object space version of world-space `co`, - * `ob->imat` is set before calling. */ - mul_v3_m4v3(kco, data->ob->imat, oco); + * `ob->world_to_object` is set before calling. */ + mul_v3_m4v3(kco, data->ob->world_to_object, oco); point_index = BLI_kdtree_3d_find_nearest(edit->emitter_field, kco, NULL); if (point_index != -1) { @@ -4797,7 +4797,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) data.combfac = 1.0f - data.combfac; } - invert_m4_m4(ob->imat, ob->object_to_world); + invert_m4_m4(ob->world_to_object, ob->object_to_world); ED_view3d_win_to_delta(region, xy_delta, bedit->zfac, vec); data.dvec = vec; @@ -4865,7 +4865,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) } data.invert = (brush->invert ^ flip); - invert_m4_m4(ob->imat, ob->object_to_world); + invert_m4_m4(ob->world_to_object, ob->object_to_world); foreach_mouse_hit_point(&data, brush_puff, selected); } @@ -4895,7 +4895,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) data.smoothfac = brush->strength; - invert_m4_m4(ob->imat, ob->object_to_world); + invert_m4_m4(ob->world_to_object, ob->object_to_world); foreach_mouse_hit_key(&data, brush_smooth_get, selected); @@ -5112,7 +5112,7 @@ static bool shape_cut_test_point(PEData *data, ParticleEditSettings *pset, Parti userdata.num_hits = 0; float co_shape[3]; - mul_v3_m4v3(co_shape, pset->shape_object->imat, key->co); + mul_v3_m4v3(co_shape, pset->shape_object->world_to_object, key->co); BLI_bvhtree_ray_cast_all( shape_bvh->tree, co_shape, dir, 0.0f, BVH_RAYCAST_DIST_MAX, point_inside_bvh_cb, &userdata); @@ -5153,8 +5153,8 @@ static void shape_cut(PEData *data, int pa_index) float dir_shape[3]; float len_shape; - mul_v3_m4v3(co_curr_shape, pset->shape_object->imat, key->co); - mul_v3_m4v3(co_next_shape, pset->shape_object->imat, (key + 1)->co); + mul_v3_m4v3(co_curr_shape, pset->shape_object->world_to_object, key->co); + mul_v3_m4v3(co_next_shape, pset->shape_object->world_to_object, (key + 1)->co); sub_v3_v3v3(dir_shape, co_next_shape, co_curr_shape); len_shape = normalize_v3(dir_shape); diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index c3e3109ac87..ce7db91571c 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -348,7 +348,7 @@ static void sculpt_gesture_context_init_common(bContext *C, copy_m3_m4(mat, sgcontext->vc.rv3d->viewinv); mul_m3_v3(mat, view_dir); normalize_v3_v3(sgcontext->world_space_view_normal, view_dir); - copy_m3_m4(mat, ob->imat); + copy_m3_m4(mat, ob->world_to_object); mul_m3_v3(mat, view_dir); normalize_v3_v3(sgcontext->true_view_normal, view_dir); @@ -460,12 +460,12 @@ static void sculpt_gesture_line_plane_from_tri(float *r_plane, { float normal[3]; normal_tri_v3(normal, p1, p2, p3); - mul_v3_mat3_m4v3(normal, sgcontext->vc.obact->imat, normal); + mul_v3_mat3_m4v3(normal, sgcontext->vc.obact->world_to_object, normal); if (flip) { mul_v3_fl(normal, -1.0f); } float plane_point_object_space[3]; - mul_v3_m4v3(plane_point_object_space, sgcontext->vc.obact->imat, p1); + mul_v3_m4v3(plane_point_object_space, sgcontext->vc.obact->world_to_object, p1); plane_from_point_normal_v3(r_plane, plane_point_object_space, normal); } @@ -1134,7 +1134,7 @@ static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontex sculpt_gesture_trim_shape_origin_normal_get(sgcontext, shape_origin, shape_normal); plane_from_point_normal_v3(shape_plane, shape_origin, shape_normal); - const float(*ob_imat)[4] = vc->obact->imat; + const float(*ob_imat)[4] = vc->obact->world_to_object; /* Write vertices coordinates for the front face. */ MVert *verts = BKE_mesh_verts_for_write(trim_operation->mesh); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index a70924b0626..97f5bd77d47 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -681,8 +681,9 @@ static float paint_space_stroke_spacing(bContext *C, if (paint_stroke_use_scene_spacing(brush, mode)) { if (!BKE_brush_use_locked_size(scene, brush)) { float last_object_space_position[3]; - mul_v3_m4v3( - last_object_space_position, stroke->vc.obact->imat, stroke->last_world_space_position); + mul_v3_m4v3(last_object_space_position, + stroke->vc.obact->world_to_object, + stroke->last_world_space_position); size_clamp = paint_calc_object_space_radius(&stroke->vc, last_object_space_position, size); } else { diff --git a/source/blender/editors/sculpt_paint/paint_vertex.cc b/source/blender/editors/sculpt_paint/paint_vertex.cc index ac5ad62c91f..8e790ac435e 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex.cc @@ -1647,10 +1647,10 @@ static void vwpaint_update_cache_invariants( /* cache projection matrix */ ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat); - invert_m4_m4(ob->imat, ob->object_to_world); + invert_m4_m4(ob->world_to_object, ob->object_to_world); copy_m3_m4(mat, cache->vc->rv3d->viewinv); mul_m3_v3(mat, view_dir); - copy_m3_m4(mat, ob->imat); + copy_m3_m4(mat, ob->world_to_object); mul_m3_v3(mat, view_dir); normalize_v3_v3(cache->true_view_normal, view_dir); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 24c6f1b0c3d..3477285814e 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -2773,14 +2773,14 @@ static void calc_local_y(ViewContext *vc, const float center[3], float y[3]) float loc[3]; const float xy_delta[2] = {0.0f, 1.0f}; - mul_v3_m4v3(loc, ob->imat, center); + mul_v3_m4v3(loc, ob->world_to_object, center); const float zfac = ED_view3d_calc_zfac(vc->rv3d, loc); ED_view3d_win_to_delta(vc->region, xy_delta, zfac, y); normalize_v3(y); add_v3_v3(y, ob->loc); - mul_m4_v3(ob->imat, y); + mul_m4_v3(ob->world_to_object, y); } static void calc_brush_local_mat(const Brush *brush, Object *ob, float local_mat[4][4]) @@ -2792,8 +2792,8 @@ static void calc_brush_local_mat(const Brush *brush, Object *ob, float local_mat float angle, v[3]; float up[3]; - /* Ensure `ob->imat` is up to date. */ - invert_m4_m4(ob->imat, ob->object_to_world); + /* Ensure `ob->world_to_object` is up to date. */ + invert_m4_m4(ob->world_to_object, ob->object_to_world); /* Initialize last column of matrix. */ mat[0][3] = 0.0f; @@ -2839,7 +2839,7 @@ void SCULPT_tilt_apply_to_normal(float r_normal[3], StrokeCache *cache, const fl float normal_tilt_xy[3]; rotate_v3_v3v3fl( normal_tilt_xy, normal_tilt_y, cache->vc->rv3d->viewinv[1], cache->x_tilt * rot_max); - mul_v3_mat3_m4v3(r_normal, cache->vc->obact->imat, normal_tilt_xy); + mul_v3_mat3_m4v3(r_normal, cache->vc->obact->world_to_object, normal_tilt_xy); normalize_v3(r_normal); } @@ -4354,10 +4354,10 @@ static void sculpt_update_cache_invariants( /* Cache projection matrix. */ ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat); - invert_m4_m4(ob->imat, ob->object_to_world); + invert_m4_m4(ob->world_to_object, ob->object_to_world); copy_m3_m4(mat, cache->vc->rv3d->viewinv); mul_m3_v3(mat, viewDir); - copy_m3_m4(mat, ob->imat); + copy_m3_m4(mat, ob->world_to_object); mul_m3_v3(mat, viewDir); normalize_v3_v3(cache->true_view_normal, viewDir); @@ -5021,10 +5021,10 @@ bool SCULPT_cursor_geometry_info_update(bContext *C, float radius; /* Update cursor data in SculptSession. */ - invert_m4_m4(ob->imat, ob->object_to_world); + invert_m4_m4(ob->world_to_object, ob->object_to_world); copy_m3_m4(mat, vc.rv3d->viewinv); mul_m3_v3(mat, viewDir); - copy_m3_m4(mat, ob->imat); + copy_m3_m4(mat, ob->world_to_object); mul_m3_v3(mat, viewDir); normalize_v3_v3(ss->cursor_view_normal, viewDir); copy_v3_v3(ss->cursor_normal, srd.face_normal); diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index 078f0217416..c158cf33f6d 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -221,10 +221,10 @@ void SCULPT_filter_cache_init(bContext *C, ED_view3d_ob_project_mat_get(vc.rv3d, ob, projection_mat); - invert_m4_m4(ob->imat, ob->object_to_world); + invert_m4_m4(ob->world_to_object, ob->object_to_world); copy_m3_m4(mat, vc.rv3d->viewinv); mul_m3_v3(mat, viewDir); - copy_m3_m4(mat, ob->imat); + copy_m3_m4(mat, ob->world_to_object); mul_m3_v3(mat, viewDir); normalize_v3_v3(ss->filter_cache->view_normal, viewDir); } diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 83835535d49..f71ce54729c 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -954,9 +954,9 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float memcpy(&ve_median_basis, &tfp->ve_median, sizeof(tfp->ve_median)); if (v3d->flag & V3D_GLOBAL_STATS) { - invert_m4_m4(ob->imat, ob->object_to_world); - mul_m4_v3(ob->imat, median_basis.generic.location); - mul_m4_v3(ob->imat, ve_median_basis.generic.location); + invert_m4_m4(ob->world_to_object, ob->object_to_world); + mul_m4_v3(ob->world_to_object, median_basis.generic.location); + mul_m4_v3(ob->world_to_object, ve_median_basis.generic.location); } sub_vn_vnvn((float *)&median_basis, (float *)&ve_median_basis, diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index f2b952c4f46..8c6f4387851 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -118,7 +118,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) bPoseChannel *pchan_eval; bArmature *arm_eval = ob_eval->data; - invert_m4_m4(ob_eval->imat, ob_eval->object_to_world); + invert_m4_m4(ob_eval->world_to_object, ob_eval->object_to_world); for (pchan_eval = ob_eval->pose->chanbase.first; pchan_eval; pchan_eval = pchan_eval->next) { if (pchan_eval->bone->flag & BONE_SELECTED) { @@ -134,7 +134,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf); vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf); /* Back in object space... */ - mul_m4_v3(ob_eval->imat, vec); + mul_m4_v3(ob_eval->world_to_object, vec); /* Get location of grid point in pose space. */ BKE_armature_loc_pose_to_bone(pchan_eval, vec, vec); @@ -387,8 +387,8 @@ static bool snap_selected_to_location(bContext *C, bArmature *arm = ob->data; float snap_target_local[3]; - invert_m4_m4(ob->imat, ob->object_to_world); - mul_v3_m4v3(snap_target_local, ob->imat, snap_target_global); + invert_m4_m4(ob->world_to_object, ob->object_to_world); + mul_v3_m4v3(snap_target_local, ob->world_to_object, snap_target_global); for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { if ((pchan->bone->flag & BONE_SELECTED) && PBONE_VISIBLE(arm, pchan->bone) && @@ -415,7 +415,7 @@ static bool snap_selected_to_location(bContext *C, mul_v3_m4v3(cursor_pose, ob->object_to_world, pchan->pose_mat[3]); add_v3_v3(cursor_pose, offset_global); - mul_m4_v3(ob->imat, cursor_pose); + mul_m4_v3(ob->world_to_object, cursor_pose); BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose); } else { diff --git a/source/blender/editors/transform/transform_convert_particle.c b/source/blender/editors/transform/transform_convert_particle.c index f212f042773..e6ff730d4d1 100644 --- a/source/blender/editors/transform/transform_convert_particle.c +++ b/source/blender/editors/transform/transform_convert_particle.c @@ -95,7 +95,7 @@ static void createTransParticleVerts(bContext *UNUSED(C), TransInfo *t) unit_m4(mat); - invert_m4_m4(ob->imat, ob->object_to_world); + invert_m4_m4(ob->world_to_object, ob->object_to_world); for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) { TransData *head, *tail; diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index 2be210d24e7..71a449ad10c 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -751,7 +751,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, #define FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) \ { \ - invert_m4_m4(obedit->imat, obedit->object_to_world); \ + invert_m4_m4(obedit->world_to_object, obedit->object_to_world); \ uint objects_len = 0; \ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( \ scene, view_layer, CTX_wm_view3d(C), &objects_len); \ @@ -780,7 +780,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, float mat_local[4][4]; if (use_mat_local) { - mul_m4_m4m4(mat_local, obedit->imat, ob_iter->object_to_world); + mul_m4_m4m4(mat_local, obedit->world_to_object, ob_iter->object_to_world); } BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { @@ -800,7 +800,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, float mat_local[4][4]; if (use_mat_local) { - mul_m4_m4m4(mat_local, obedit->imat, ob_iter->object_to_world); + mul_m4_m4m4(mat_local, obedit->world_to_object, ob_iter->object_to_world); } LISTBASE_FOREACH (EditBone *, ebo, arm->edbo) { if (EBONE_VISIBLE(arm, ebo)) { @@ -833,7 +833,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, float mat_local[4][4]; if (use_mat_local) { - mul_m4_m4m4(mat_local, obedit->imat, ob_iter->object_to_world); + mul_m4_m4m4(mat_local, obedit->world_to_object, ob_iter->object_to_world); } nu = nurbs->first; @@ -893,7 +893,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, float mat_local[4][4]; if (use_mat_local) { - mul_m4_m4m4(mat_local, obedit->imat, ob_iter->object_to_world); + mul_m4_m4m4(mat_local, obedit->world_to_object, ob_iter->object_to_world); } LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) { @@ -913,7 +913,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, float mat_local[4][4]; if (use_mat_local) { - mul_m4_m4m4(mat_local, obedit->imat, ob_iter->object_to_world); + mul_m4_m4m4(mat_local, obedit->world_to_object, ob_iter->object_to_world); } while (a--) { @@ -939,7 +939,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, } } else if (ob && (ob->mode & OB_MODE_POSE)) { - invert_m4_m4(ob->imat, ob->object_to_world); + invert_m4_m4(ob->world_to_object, ob->object_to_world); uint objects_len = 0; Object **objects = BKE_object_pose_array_get(scene, view_layer, v3d, &objects_len); @@ -954,7 +954,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, float mat_local[4][4]; if (use_mat_local) { - mul_m4_m4m4(mat_local, ob->imat, ob_iter->object_to_world); + mul_m4_m4m4(mat_local, ob->world_to_object, ob_iter->object_to_world); } /* Use channels to get stats. */ diff --git a/source/blender/editors/transform/transform_mode_vert_slide.c b/source/blender/editors/transform/transform_mode_vert_slide.c index cc1ea188fbc..a54888fe515 100644 --- a/source/blender/editors/transform/transform_mode_vert_slide.c +++ b/source/blender/editors/transform/transform_mode_vert_slide.c @@ -444,9 +444,9 @@ void drawVertSlide(TransInfo *t) ED_view3d_win_to_delta(t->region, xy_delta, zfac, co_dest_3d); - invert_m4_m4(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat, + invert_m4_m4(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->world_to_object, TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->object_to_world); - mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat, co_dest_3d); + mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->world_to_object, co_dest_3d); add_v3_v3(co_dest_3d, curr_sv->co_orig_3d); diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index de1c88fe896..071f1c44c6b 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -1388,8 +1388,8 @@ static void uv_map_transform_center(const Scene *scene, } case V3D_AROUND_CURSOR: /* cursor center */ { - invert_m4_m4(ob->imat, ob->object_to_world); - mul_v3_m4v3(r_center, ob->imat, scene->cursor.location); + invert_m4_m4(ob->world_to_object, ob->object_to_world); + mul_v3_m4v3(r_center, ob->world_to_object, scene->cursor.location); break; } case V3D_AROUND_ACTIVE: { diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c index 6e31fffd11d..e3b4e1c5e02 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c @@ -240,8 +240,8 @@ static void deformStroke(GpencilModifierData *md, /* just object target */ copy_m4_m4(dmat, mmd->object->object_to_world); } - invert_m4_m4(ob->imat, ob->object_to_world); - mul_m4_series(tData.mat, ob->imat, dmat, mmd->parentinv); + invert_m4_m4(ob->world_to_object, ob->object_to_world); + mul_m4_series(tData.mat, ob->world_to_object, dmat, mmd->parentinv); /* loop points and apply deform */ for (int i = 0; i < gps->totpoints; i++) { diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c index 7add5c7b84e..8331188fbd8 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c @@ -144,7 +144,7 @@ static void deformStroke(GpencilModifierData *md, float coba_res[4]; float matrix[4][4]; if (is_gradient) { - mul_m4_m4m4(matrix, mmd->object->imat, ob->object_to_world); + mul_m4_m4m4(matrix, mmd->object->world_to_object, ob->object_to_world); } /* loop points and apply color. */ diff --git a/source/blender/io/alembic/exporter/abc_writer_points.cc b/source/blender/io/alembic/exporter/abc_writer_points.cc index 29370978b54..6ec6f736818 100644 --- a/source/blender/io/alembic/exporter/abc_writer_points.cc +++ b/source/blender/io/alembic/exporter/abc_writer_points.cc @@ -101,7 +101,7 @@ void ABCPointsWriter::do_write(HierarchyContext &context) } /* location */ - mul_v3_m4v3(pos, context.object->imat, state.co); + mul_v3_m4v3(pos, context.object->world_to_object, state.co); /* velocity */ sub_v3_v3v3(vel, state.co, psys->particles[p].prev_state.co); diff --git a/source/blender/io/alembic/intern/abc_axis_conversion.cc b/source/blender/io/alembic/intern/abc_axis_conversion.cc index 35a19d0fbc0..c7d2a3e1bf4 100644 --- a/source/blender/io/alembic/intern/abc_axis_conversion.cc +++ b/source/blender/io/alembic/intern/abc_axis_conversion.cc @@ -134,8 +134,8 @@ void create_transform_matrix(Object *obj, if (mode == ABC_MATRIX_LOCAL && obj->parent) { /* Note that this produces another matrix than the local matrix, due to * constraints and modifiers as well as the obj->parentinv matrix. */ - invert_m4_m4(obj->parent->imat, obj->parent->object_to_world); - mul_m4_m4m4(zup_mat, obj->parent->imat, obj->object_to_world); + invert_m4_m4(obj->parent->world_to_object, obj->parent->object_to_world); + mul_m4_m4m4(zup_mat, obj->parent->world_to_object, obj->object_to_world); } else { copy_m4_m4(zup_mat, obj->object_to_world); diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 3ef32d28e85..494295f7bb9 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -322,20 +322,14 @@ typedef struct Object { float rotAxis[3], drotAxis[3]; /** Axis angle rotation - angle part. */ float rotAngle, drotAngle; - /** Final world-space matrix with constraints & animsys applied. */ + /** Final transformation matrices with constraints & animsys applied. */ float object_to_world[4][4]; + float world_to_object[4][4]; /** Inverse result of parent, so that object doesn't 'stick' to parent. */ float parentinv[4][4]; /** Inverse result of constraints. * doesn't include effect of parent or object local transform. */ float constinv[4][4]; - /** - * Inverse matrix of 'obmat' for any other use than rendering! - * - * \note this isn't assured to be valid as with 'obmat', - * before using this value you should do: `invert_m4_m4(ob->imat, ob->object_to_world)` - */ - float imat[4][4]; /** Copy of Base's layer in the scene. */ unsigned int lay DNA_DEPRECATED; diff --git a/source/blender/makesdna/intern/dna_rename_defs.h b/source/blender/makesdna/intern/dna_rename_defs.h index 4a009a88f1a..afc907b7780 100644 --- a/source/blender/makesdna/intern/dna_rename_defs.h +++ b/source/blender/makesdna/intern/dna_rename_defs.h @@ -97,6 +97,7 @@ DNA_STRUCT_RENAME_ELEM(Object, dupfacesca, instance_faces_scale) DNA_STRUCT_RENAME_ELEM(Object, restrictflag, visibility_flag) DNA_STRUCT_RENAME_ELEM(Object, size, scale) DNA_STRUCT_RENAME_ELEM(Object, obmat, object_to_world) +DNA_STRUCT_RENAME_ELEM(Object, imat, world_to_object) DNA_STRUCT_RENAME_ELEM(Object_Runtime, crazyspace_num_verts, crazyspace_verts_num) DNA_STRUCT_RENAME_ELEM(MEdge, bweight, bweight_legacy) DNA_STRUCT_RENAME_ELEM(MEdge, crease, crease_legacy) diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c index 7581b2aa8e5..b6e1b5e88c1 100644 --- a/source/blender/modifiers/intern/MOD_cast.c +++ b/source/blender/modifiers/intern/MOD_cast.c @@ -131,8 +131,8 @@ static void sphere_do(CastModifierData *cmd, invert_m4_m4(imat, mat); } - invert_m4_m4(ob->imat, ob->object_to_world); - mul_v3_m4v3(center, ob->imat, ctrl_ob->object_to_world[3]); + invert_m4_m4(ob->world_to_object, ob->object_to_world); + mul_v3_m4v3(center, ob->world_to_object, ctrl_ob->object_to_world[3]); } /* now we check which options the user wants */ @@ -280,8 +280,8 @@ static void cuboid_do(CastModifierData *cmd, invert_m4_m4(imat, mat); } - invert_m4_m4(ob->imat, ob->object_to_world); - mul_v3_m4v3(center, ob->imat, ctrl_ob->object_to_world[3]); + invert_m4_m4(ob->world_to_object, ob->object_to_world); + mul_v3_m4v3(center, ob->world_to_object, ctrl_ob->object_to_world[3]); } if ((flag & MOD_CAST_SIZE_FROM_RADIUS) && has_radius) { diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c index 6cf2e1538e9..231c65998e0 100644 --- a/source/blender/modifiers/intern/MOD_hook.c +++ b/source/blender/modifiers/intern/MOD_hook.c @@ -344,8 +344,8 @@ static void deformVerts_do(HookModifierData *hmd, /* just object target */ copy_m4_m4(dmat, ob_target->object_to_world); } - invert_m4_m4(ob->imat, ob->object_to_world); - mul_m4_series(hd.mat, ob->imat, dmat, hmd->parentinv); + invert_m4_m4(ob->world_to_object, ob->object_to_world); + mul_m4_series(hd.mat, ob->world_to_object, dmat, hmd->parentinv); /* --- done with 'hd' init --- */ /* Regarding index range checking below. diff --git a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc index 778f12d6745..fa7f0690675 100644 --- a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc +++ b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc @@ -134,7 +134,7 @@ static Volume *mesh_to_volume(ModifierData *md, } BKE_mesh_wrapper_ensure_mdata(mesh); - const float4x4 mesh_to_own_object_space_transform = float4x4(ctx->object->imat) * + const float4x4 mesh_to_own_object_space_transform = float4x4(ctx->object->world_to_object) * float4x4(object_to_convert->object_to_world); geometry::MeshToVolumeResolution resolution; resolution.mode = (MeshToVolumeModifierResolutionMode)mvmd->resolution_mode; diff --git a/source/blender/modifiers/intern/MOD_volume_displace.cc b/source/blender/modifiers/intern/MOD_volume_displace.cc index fbd5f27f69a..2d6f8c100e7 100644 --- a/source/blender/modifiers/intern/MOD_volume_displace.cc +++ b/source/blender/modifiers/intern/MOD_volume_displace.cc @@ -262,7 +262,8 @@ struct DisplaceGridOp { return index_to_object; } const openvdb::Mat4s object_to_world = matrix_to_openvdb(ctx.object->object_to_world); - const openvdb::Mat4s world_to_texture = matrix_to_openvdb(vdmd.texture_map_object->imat); + const openvdb::Mat4s world_to_texture = matrix_to_openvdb( + vdmd.texture_map_object->world_to_object); return index_to_object * object_to_world * world_to_texture; } } diff --git a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc index b4ac23b5c61..2a8883dc2eb 100644 --- a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc +++ b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc @@ -158,7 +158,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * openvdb::math::Transform::Ptr transform = local_grid->transform().copy(); transform->postMult(openvdb::Mat4d((float *)vmmd->object->object_to_world)); - openvdb::Mat4d imat = openvdb::Mat4d((float *)ctx->object->imat); + openvdb::Mat4d imat = openvdb::Mat4d((float *)ctx->object->world_to_object); /* `imat` had floating point issues and wasn't affine. */ imat.setCol(3, openvdb::Vec4d(0, 0, 0, 1)); transform->postMult(imat); diff --git a/source/blender/modifiers/intern/MOD_wave.cc b/source/blender/modifiers/intern/MOD_wave.cc index 1489927ba34..dce006bda92 100644 --- a/source/blender/modifiers/intern/MOD_wave.cc +++ b/source/blender/modifiers/intern/MOD_wave.cc @@ -152,8 +152,8 @@ static void waveModifier_do(WaveModifierData *md, if (wmd->objectcenter != nullptr) { float mat[4][4]; /* get the control object's location in local coordinates */ - invert_m4_m4(ob->imat, ob->object_to_world); - mul_m4_m4m4(mat, ob->imat, wmd->objectcenter->object_to_world); + invert_m4_m4(ob->world_to_object, ob->object_to_world); + mul_m4_m4m4(mat, ob->world_to_object, wmd->objectcenter->object_to_world); wmd->startx = mat[3][0]; wmd->starty = mat[3][1]; diff --git a/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc b/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc index 51393ed8709..1129e954360 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc @@ -93,7 +93,7 @@ static void node_geo_exec(GeoNodeExecParams params) if (!reset_children) { add_v3_v3(transform.values[3], child_collection->instance_offset); if (use_relative_transform) { - mul_m4_m4_pre(transform.values, self_object->imat); + mul_m4_m4_pre(transform.values, self_object->world_to_object); } else { sub_v3_v3(transform.values[3], collection->instance_offset); @@ -107,7 +107,7 @@ static void node_geo_exec(GeoNodeExecParams params) float4x4 transform = float4x4::identity(); if (!reset_children) { if (use_relative_transform) { - transform = self_object->imat; + transform = self_object->world_to_object; } else { sub_v3_v3(transform.values[3], collection->instance_offset); @@ -130,7 +130,7 @@ static void node_geo_exec(GeoNodeExecParams params) float4x4 transform = float4x4::identity(); if (use_relative_transform) { copy_v3_v3(transform.values[3], collection->instance_offset); - mul_m4_m4_pre(transform.values, self_object->imat); + mul_m4_m4_pre(transform.values, self_object->world_to_object); } const int handle = instances->add_reference(*collection); diff --git a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc index dc35607fe45..83a2ddb1629 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc @@ -46,7 +46,7 @@ static void node_geo_exec(GeoNodeExecParams params) } const float4x4 &object_matrix = object->object_to_world; - const float4x4 transform = float4x4(self_object->imat) * object_matrix; + const float4x4 transform = float4x4(self_object->world_to_object) * object_matrix; if (transform_space_relative) { params.set_output("Location", transform.translation()); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.cc b/source/blender/nodes/shader/nodes/node_shader_tex_coord.cc index e2a40b79d53..1edf8c2aa55 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.cc @@ -38,7 +38,7 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, /* Use special matrix to let the shader branch to using the render object's matrix. */ float dummy_matrix[4][4]; dummy_matrix[3][3] = 0.0f; - GPUNodeLink *inv_obmat = (ob != nullptr) ? GPU_uniform(&ob->imat[0][0]) : + GPUNodeLink *inv_obmat = (ob != nullptr) ? GPU_uniform(&ob->world_to_object[0][0]) : GPU_uniform(&dummy_matrix[0][0]); /* Optimization: don't request orco if not needed. */ diff --git a/source/blender/render/intern/texture_pointdensity.c b/source/blender/render/intern/texture_pointdensity.c index b285bbd1459..5c31192f62a 100644 --- a/source/blender/render/intern/texture_pointdensity.c +++ b/source/blender/render/intern/texture_pointdensity.c @@ -174,8 +174,8 @@ static void pointdensity_cache_psys( sim.psys = psys; sim.psmd = psys_get_modifier(ob, psys); - /* in case ob->imat isn't up-to-date */ - invert_m4_m4(ob->imat, ob->object_to_world); + /* in case ob->world_to_object isn't up-to-date */ + invert_m4_m4(ob->world_to_object, ob->object_to_world); total_particles = psys->totpart + psys->totchild; psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); @@ -235,7 +235,7 @@ static void pointdensity_cache_psys( copy_v3_v3(partco, state.co); if (pd->psys_cache_space == TEX_PD_OBJECTSPACE) { - mul_m4_v3(ob->imat, partco); + mul_m4_v3(ob->world_to_object, partco); } else if (pd->psys_cache_space == TEX_PD_OBJECTLOC) { sub_v3_v3(partco, ob->loc); -- cgit v1.2.3 From 07ef428c6c41d74d267e2dbd505386e93f26de38 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 2 Nov 2022 16:30:13 +0100 Subject: Cycles: Add regression test for util_md5_string --- intern/cycles/test/CMakeLists.txt | 1 + intern/cycles/test/util_md5_test.cpp | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 intern/cycles/test/util_md5_test.cpp diff --git a/intern/cycles/test/CMakeLists.txt b/intern/cycles/test/CMakeLists.txt index b126247de5f..c3ae81ed1db 100644 --- a/intern/cycles/test/CMakeLists.txt +++ b/intern/cycles/test/CMakeLists.txt @@ -34,6 +34,7 @@ set(SRC render_graph_finalize_test.cpp util_aligned_malloc_test.cpp util_math_test.cpp + util_md5_test.cpp util_path_test.cpp util_string_test.cpp util_task_test.cpp diff --git a/intern/cycles/test/util_md5_test.cpp b/intern/cycles/test/util_md5_test.cpp new file mode 100644 index 00000000000..abc147b70a1 --- /dev/null +++ b/intern/cycles/test/util_md5_test.cpp @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright 2011-2022 Blender Foundation */ + +#include "testing/testing.h" + +#include "util/md5.h" + +CCL_NAMESPACE_BEGIN + +TEST(util, util_md5_string) +{ + /* The hash is calculated using `echo -n "Hello, World\!" | md5 | tr '[:lower:]' '[:upper:]'`. */ + EXPECT_EQ(util_md5_string("Hello, World!"), "65A8E27D8879283831B664BD8B7F0AD4"); +} + +CCL_NAMESPACE_END -- cgit v1.2.3 From 31746e1baa14fd3a64053aec82a40ffc07f95973 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 1 Nov 2022 21:00:56 +0100 Subject: Fix memory leak with Freestyle renders after recent changes Render stored a shallow copy of the scene view layers and views for thread safety, without proper functions to free it. But with the CoW depsgraph this scene is already a copy of the original and an additional copy is not needed. Refactor to use the scene view layers and some other settings directly instead of making a copy. --- .../intern/blender_interface/FRS_freestyle.cpp | 6 +- source/blender/render/intern/engine.cc | 6 -- source/blender/render/intern/pipeline.cc | 77 +++++++--------------- source/blender/render/intern/pipeline.h | 9 +-- source/blender/render/intern/render_result.cc | 6 +- source/blender/render/intern/render_result.h | 5 +- source/blender/render/intern/render_types.h | 3 +- 7 files changed, 33 insertions(+), 79 deletions(-) diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp index 06365c3799f..af9ef7f352e 100644 --- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp +++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp @@ -131,9 +131,9 @@ static void init_view(Render *re) int ymax = re->disprect.ymax; float thickness = 1.0f; - switch (re->r.line_thickness_mode) { + switch (re->scene->r.line_thickness_mode) { case R_LINE_THICKNESS_ABSOLUTE: - thickness = re->r.unit_line_thickness * (re->r.size / 100.0f); + thickness = re->scene->r.unit_line_thickness * (re->r.size / 100.0f); break; case R_LINE_THICKNESS_RELATIVE: thickness = height / 480.0f; @@ -485,7 +485,7 @@ void FRS_composite_result(Render *re, ViewLayer *view_layer, Render *freestyle_r return; } - rl = render_get_active_layer(freestyle_render, freestyle_render->result); + rl = render_get_single_layer(freestyle_render, freestyle_render->result); if (!rl) { if (G.debug & G_DEBUG_FREESTYLE) { cout << "No source render layer to composite" << endl; diff --git a/source/blender/render/intern/engine.cc b/source/blender/render/intern/engine.cc index b8757d33580..acca657f7dc 100644 --- a/source/blender/render/intern/engine.cc +++ b/source/blender/render/intern/engine.cc @@ -1036,12 +1036,6 @@ bool RE_engine_render(Render *re, bool do_all) return true; } - /* update animation here so any render layer animation is applied before - * creating the render result */ - if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) { - render_update_anim_renderdata(re, &re->scene->r, &re->scene->view_layers); - } - /* Create engine. */ RenderEngine *engine = re->engine; diff --git a/source/blender/render/intern/pipeline.cc b/source/blender/render/intern/pipeline.cc index d2929a7f6ea..e71ad1e26c1 100644 --- a/source/blender/render/intern/pipeline.cc +++ b/source/blender/render/intern/pipeline.cc @@ -261,13 +261,10 @@ RenderResult *RE_MultilayerConvert( return render_result_new_from_exr(exrhandle, colorspace, predivide, rectx, recty); } -RenderLayer *render_get_active_layer(Render *re, RenderResult *rr) +RenderLayer *render_get_single_layer(Render *re, RenderResult *rr) { - ViewLayer *view_layer = static_cast( - BLI_findlink(&re->view_layers, re->active_view_layer)); - - if (view_layer) { - RenderLayer *rl = RE_GetRenderLayer(rr, view_layer->name); + if (re->single_view_layer[0]) { + RenderLayer *rl = RE_GetRenderLayer(rr, re->single_view_layer); if (rl) { return rl; @@ -385,8 +382,8 @@ void RE_AcquireResultImageViews(Render *re, RenderResult *rr) RenderView *rv = static_cast(rr->views.first); rr->have_combined = (rv->rectf != nullptr); - /* active layer */ - RenderLayer *rl = render_get_active_layer(re, re->result); + /* single layer */ + RenderLayer *rl = render_get_single_layer(re, re->result); if (rl) { if (rv->rectf == nullptr) { @@ -443,7 +440,7 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id) rr->rect32 = rv->rect32; /* active layer */ - rl = render_get_active_layer(re, re->result); + rl = render_get_single_layer(re, re->result); if (rl) { if (rv->rectf == nullptr) { @@ -583,9 +580,6 @@ void RE_FreeRender(Render *re) BLI_mutex_end(&re->engine_draw_mutex); BLI_mutex_end(&re->highlighted_tiles_mutex); - BLI_freelistN(&re->view_layers); - BLI_freelistN(&re->r.views); - BKE_curvemapping_free_data(&re->r.mblur_shutter_curve); if (re->highlighted_tiles != nullptr) { @@ -705,12 +699,11 @@ static void re_init_resolution(Render *re, Render *source, int winx, int winy, r void render_copy_renderdata(RenderData *to, RenderData *from) { - BLI_freelistN(&to->views); + /* Mostly shallow copy referencing pointers in scene renderdata. */ BKE_curvemapping_free_data(&to->mblur_shutter_curve); memcpy(to, from, sizeof(*to)); - BLI_duplicatelist(&to->views, &from->views); BKE_curvemapping_copy_data(&to->mblur_shutter_curve, &from->mblur_shutter_curve); } @@ -731,9 +724,7 @@ void RE_InitState(Render *re, /* copy render data and render layers for thread safety */ render_copy_renderdata(&re->r, rd); - BLI_freelistN(&re->view_layers); - BLI_duplicatelist(&re->view_layers, render_layers); - re->active_view_layer = 0; + re->single_view_layer[0] = '\0'; if (source) { /* reuse border flags from source renderer */ @@ -762,11 +753,8 @@ void RE_InitState(Render *re, } if (single_layer) { - int index = BLI_findindex(render_layers, single_layer); - if (index != -1) { - re->active_view_layer = index; - re->r.scemode |= R_SINGLE_LAYER; - } + STRNCPY(re->single_view_layer, single_layer->name); + re->r.scemode |= R_SINGLE_LAYER; } /* if preview render, we try to keep old result */ @@ -779,13 +767,16 @@ void RE_InitState(Render *re, re->result = nullptr; } else if (re->result) { - ViewLayer *active_render_layer = static_cast( - BLI_findlink(&re->view_layers, re->active_view_layer)); bool have_layer = false; - LISTBASE_FOREACH (RenderLayer *, rl, &re->result->layers) { - if (STREQ(rl->name, active_render_layer->name)) { - have_layer = true; + if (re->single_view_layer[0] == '\0' && re->result->layers.first) { + have_layer = true; + } + else { + LISTBASE_FOREACH (RenderLayer *, rl, &re->result->layers) { + if (STREQ(rl->name, re->single_view_layer)) { + have_layer = true; + } } } @@ -817,27 +808,6 @@ void RE_InitState(Render *re, RE_point_density_fix_linking(); } -void render_update_anim_renderdata(Render *re, RenderData *rd, ListBase *render_layers) -{ - /* filter */ - re->r.gauss = rd->gauss; - - /* motion blur */ - re->r.blurfac = rd->blurfac; - - /* freestyle */ - re->r.line_thickness_mode = rd->line_thickness_mode; - re->r.unit_line_thickness = rd->unit_line_thickness; - - /* render layers */ - BLI_freelistN(&re->view_layers); - BLI_duplicatelist(&re->view_layers, render_layers); - - /* render views */ - BLI_freelistN(&re->r.views); - BLI_duplicatelist(&re->r.views, &rd->views); -} - void RE_display_init_cb(Render *re, void *handle, void (*f)(void *handle, RenderResult *rr)) { re->display_init = f; @@ -979,7 +949,7 @@ static void render_result_uncrop(Render *re) re->result = rres; /* Weak, the display callback wants an active render-layer pointer. */ - re->result->renlay = render_get_active_layer(re, re->result); + re->result->renlay = render_get_single_layer(re, re->result); BLI_rw_mutex_unlock(&re->resultmutex); @@ -1217,7 +1187,7 @@ static void do_render_compositor(Render *re) /* Weak: the display callback wants an active render-layer pointer. */ if (re->result != nullptr) { - re->result->renlay = render_get_active_layer(re, re->result); + re->result->renlay = render_get_single_layer(re, re->result); re->display_update(re->duh, re->result, nullptr); } } @@ -1676,7 +1646,6 @@ static int render_init_from_main(Render *re, /* not too nice, but it survives anim-border render */ if (anim) { - render_update_anim_renderdata(re, &scene->r, &scene->view_layers); re->disprect = disprect; return 1; } @@ -1890,12 +1859,10 @@ void RE_RenderFreestyleExternal(Render *re) LISTBASE_FOREACH (RenderView *, rv, &re->result->views) { RE_SetActiveRenderView(re, rv->name); - ViewLayer *active_view_layer = static_cast( - BLI_findlink(&re->view_layers, re->active_view_layer)); FRS_begin_stroke_rendering(re); - LISTBASE_FOREACH (ViewLayer *, view_layer, &re->view_layers) { - if ((re->r.scemode & R_SINGLE_LAYER) && view_layer != active_view_layer) { + LISTBASE_FOREACH (ViewLayer *, view_layer, &re->scene->view_layers) { + if ((re->r.scemode & R_SINGLE_LAYER) && !STREQ(view_layer->name, re->single_view_layer)) { continue; } diff --git a/source/blender/render/intern/pipeline.h b/source/blender/render/intern/pipeline.h index 689e4509da3..e5da3cb8830 100644 --- a/source/blender/render/intern/pipeline.h +++ b/source/blender/render/intern/pipeline.h @@ -17,14 +17,7 @@ struct RenderResult; extern "C" { #endif -struct RenderLayer *render_get_active_layer(struct Render *re, struct RenderResult *rr); -/** - * Update some variables that can be animated, and otherwise wouldn't be due to - * #RenderData getting copied once at the start of animation render. - */ -void render_update_anim_renderdata(struct Render *re, - struct RenderData *rd, - struct ListBase *render_layers); +struct RenderLayer *render_get_single_layer(struct Render *re, struct RenderResult *rr); void render_copy_renderdata(struct RenderData *to, struct RenderData *from); #ifdef __cplusplus diff --git a/source/blender/render/intern/render_result.cc b/source/blender/render/intern/render_result.cc index 94f6e2f1509..1cd95831ddf 100644 --- a/source/blender/render/intern/render_result.cc +++ b/source/blender/render/intern/render_result.cc @@ -321,7 +321,7 @@ RenderResult *render_result_new(Render *re, rl->layflag = SCE_LAY_FLAG_DEFAULT; rl->passflag = SCE_PASS_COMBINED; - re->active_view_layer = 0; + re->single_view_layer[0] = '\0'; } /* Border render; calculate offset for use in compositor. compo is centralized coords. */ @@ -768,8 +768,8 @@ void render_result_single_layer_end(Render *re) /* reconstruct render result layers */ int nr = 0; - LISTBASE_FOREACH (ViewLayer *, view_layer, &re->view_layers) { - if (nr == re->active_view_layer) { + LISTBASE_FOREACH (ViewLayer *, view_layer, &re->scene->view_layers) { + if (STREQ(view_layer->name, re->single_view_layer)) { BLI_addtail(&re->result->layers, rl); } else { diff --git a/source/blender/render/intern/render_result.h b/source/blender/render/intern/render_result.h index 2e76efba8a3..6e971d45d31 100644 --- a/source/blender/render/intern/render_result.h +++ b/source/blender/render/intern/render_result.h @@ -136,10 +136,11 @@ void render_result_views_shallowdelete(struct RenderResult *rr); { \ int nr_; \ ViewLayer *iter_; \ - for (nr_ = 0, iter_ = static_cast((re_)->view_layers.first); iter_ != NULL; \ + for (nr_ = 0, iter_ = static_cast((re_)->scene->view_layers.first); \ + iter_ != NULL; \ iter_ = iter_->next, nr_++) { \ if (!G.background && (re_)->r.scemode & R_SINGLE_LAYER) { \ - if (nr_ != re->active_view_layer) { \ + if (!STREQ(iter_->name, re->single_view_layer)) { \ continue; \ } \ } \ diff --git a/source/blender/render/intern/render_types.h b/source/blender/render/intern/render_types.h index 29bac6e2766..ad58f081388 100644 --- a/source/blender/render/intern/render_types.h +++ b/source/blender/render/intern/render_types.h @@ -76,8 +76,7 @@ struct Render { struct Main *main; Scene *scene; RenderData r; - ListBase view_layers; - int active_view_layer; + char single_view_layer[MAX_NAME]; struct Object *camera_override; ThreadMutex highlighted_tiles_mutex; -- cgit v1.2.3 From 15fe7f3d936a8f2a0bb82671cdf0a13f943cfdf7 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 2 Nov 2022 17:57:36 +0100 Subject: Fix arrow key menu navigation using wrong direction Steps to reproduce were: * Right click in 3D View (context menu) press up or down arrow. Or: * Ctrl+Shift+O (Open Recent menu) press up or down arrow. --- source/blender/editors/include/UI_interface.h | 2 ++ source/blender/editors/interface/interface_region_menu_popup.cc | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 1098266331f..66b3d9fba6b 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -133,6 +133,8 @@ enum { /** #uiBlock.flag (controls) */ enum { UI_BLOCK_LOOP = 1 << 0, + /** Indicate that items in a popup are drawn with inverted order. Used for arrow key navigation + * so that it knows to invert the navigation direction to match the drawing order. */ UI_BLOCK_IS_FLIP = 1 << 1, UI_BLOCK_NO_FLIP = 1 << 2, UI_BLOCK_NUMSELECT = 1 << 3, diff --git a/source/blender/editors/interface/interface_region_menu_popup.cc b/source/blender/editors/interface/interface_region_menu_popup.cc index 0d19390d508..b8c8cdf5fa4 100644 --- a/source/blender/editors/interface/interface_region_menu_popup.cc +++ b/source/blender/editors/interface/interface_region_menu_popup.cc @@ -189,7 +189,7 @@ static void ui_popup_menu_create_block(bContext *C, pup->block = UI_block_begin(C, nullptr, block_name, UI_EMBOSS_PULLDOWN); if (!pup->but) { - pup->block->flag |= UI_BLOCK_IS_FLIP | UI_BLOCK_NO_FLIP; + pup->block->flag |= UI_BLOCK_NO_FLIP; } if (title && title[0]) { pup->block->flag |= UI_BLOCK_POPUP_MEMORY; @@ -486,6 +486,8 @@ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C, pup->title = title; ui_popup_menu_create_block(C, pup, title, block_name); + /* Further buttons will be laid out top to bottom by default. */ + pup->block->flag |= UI_BLOCK_IS_FLIP; /* create in advance so we can let buttons point to retval already */ pup->block->handle = MEM_cnew(__func__); -- cgit v1.2.3 From a38b98478a61815f57dee29c226de61d9cd338e1 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 2 Nov 2022 18:01:18 +0100 Subject: Fix empty menu title in some menus (e.g. Text Editor context menu) --- source/blender/editors/interface/interface_region_menu_popup.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/interface/interface_region_menu_popup.cc b/source/blender/editors/interface/interface_region_menu_popup.cc index b8c8cdf5fa4..871fd5c6166 100644 --- a/source/blender/editors/interface/interface_region_menu_popup.cc +++ b/source/blender/editors/interface/interface_region_menu_popup.cc @@ -615,7 +615,9 @@ static void ui_popup_menu_create_from_menutype(bContext *C, { uiPopupBlockHandle *handle = ui_popup_menu_create( C, nullptr, nullptr, title, [mt, title, icon](bContext *C, uiLayout *layout) -> void { - create_title_button(layout, title, icon); + if (title && title[0]) { + create_title_button(layout, title, icon); + } ui_item_menutype_func(C, layout, mt); }); -- cgit v1.2.3 From bad55d56bc71ec9b5f2478de6a1ce350b474de57 Mon Sep 17 00:00:00 2001 From: Erik Abrahamsson Date: Wed, 2 Nov 2022 23:23:20 +0100 Subject: Mesh: Parallelize remesh reprojections In high poly meshes the reprojections after remesh can become slow. This parallelizes reprojection of face sets, paint mask and vertex paint. It also adds flags to disable dependency graph updates on setting remesh options to remove UI lag. Profiling of remeshing a 3.4M poly mesh (in sculpt mode): Before: 19.6s After: 8.7s Differential Revision: https://developer.blender.org/D15638 --- .../blender/blenkernel/intern/mesh_remesh_voxel.cc | 168 +++++++++++---------- source/blender/makesrna/intern/rna_mesh.c | 8 + 2 files changed, 99 insertions(+), 77 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc index 62354c83df1..f38efd2cf65 100644 --- a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc +++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc @@ -19,6 +19,7 @@ #include "BLI_math_vec_types.hh" #include "BLI_math_vector.h" #include "BLI_span.hh" +#include "BLI_task.hh" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -302,17 +303,20 @@ void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, const Mesh *source) &target->vdata, CD_PAINT_MASK, CD_CONSTRUCT, nullptr, target->totvert); } - for (int i = 0; i < target->totvert; i++) { - float from_co[3]; - BVHTreeNearest nearest; - nearest.index = -1; - nearest.dist_sq = FLT_MAX; - copy_v3_v3(from_co, target_verts[i].co); - BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree); - if (nearest.index != -1) { - target_mask[i] = source_mask[nearest.index]; + blender::threading::parallel_for(IndexRange(target->totvert), 4096, [&](const IndexRange range) { + for (const int i : range) { + float from_co[3]; + BVHTreeNearest nearest; + nearest.index = -1; + nearest.dist_sq = FLT_MAX; + copy_v3_v3(from_co, target_verts[i].co); + BLI_bvhtree_find_nearest( + bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree); + if (nearest.index != -1) { + target_mask[i] = source_mask[nearest.index]; + } } - } + }); free_bvhtree_from_mesh(&bvhtree); } @@ -344,21 +348,24 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source) BVHTreeFromMesh bvhtree = {nullptr}; BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_LOOPTRI, 2); - for (int i = 0; i < target->totpoly; i++) { - float from_co[3]; - BVHTreeNearest nearest; - nearest.index = -1; - nearest.dist_sq = FLT_MAX; - const MPoly *mpoly = &target_polys[i]; - BKE_mesh_calc_poly_center(mpoly, &target_loops[mpoly->loopstart], target_verts, from_co); - BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree); - if (nearest.index != -1) { - dst[i] = src[looptri[nearest.index].poly]; - } - else { - dst[i] = 1; + blender::threading::parallel_for(IndexRange(target->totpoly), 2048, [&](const IndexRange range) { + for (const int i : range) { + float from_co[3]; + BVHTreeNearest nearest; + nearest.index = -1; + nearest.dist_sq = FLT_MAX; + const MPoly *mpoly = &target_polys[i]; + BKE_mesh_calc_poly_center(mpoly, &target_loops[mpoly->loopstart], target_verts, from_co); + BLI_bvhtree_find_nearest( + bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree); + if (nearest.index != -1) { + dst[i] = src[looptri[nearest.index].poly]; + } + else { + dst[i] = 1; + } } - } + }); free_bvhtree_from_mesh(&bvhtree); dst_face_sets.finish(); } @@ -399,19 +406,22 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source) MVert *target_verts = (MVert *)CustomData_get_layer(&target->vdata, CD_MVERT); if (domain == ATTR_DOMAIN_POINT) { - for (int i = 0; i < target->totvert; i++) { - BVHTreeNearest nearest; - nearest.index = -1; - nearest.dist_sq = FLT_MAX; - BLI_bvhtree_find_nearest( - bvhtree.tree, target_verts[i].co, &nearest, bvhtree.nearest_callback, &bvhtree); - - if (nearest.index != -1) { - memcpy(POINTER_OFFSET(target_data, size_t(i) * data_size), - POINTER_OFFSET(source_data, size_t(nearest.index) * data_size), - data_size); - } - } + blender::threading::parallel_for( + IndexRange(target->totvert), 4096, [&](const IndexRange range) { + for (const int i : range) { + BVHTreeNearest nearest; + nearest.index = -1; + nearest.dist_sq = FLT_MAX; + BLI_bvhtree_find_nearest( + bvhtree.tree, target_verts[i].co, &nearest, bvhtree.nearest_callback, &bvhtree); + + if (nearest.index != -1) { + memcpy(POINTER_OFFSET(target_data, size_t(i) * data_size), + POINTER_OFFSET(source_data, size_t(nearest.index) * data_size), + data_size); + } + } + }); } else { /* Lazily init vertex -> loop maps. */ @@ -438,46 +448,50 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source) target->totloop); } - for (int i = 0; i < target->totvert; i++) { - BVHTreeNearest nearest; - nearest.index = -1; - nearest.dist_sq = FLT_MAX; - BLI_bvhtree_find_nearest( - bvhtree.tree, target_verts[i].co, &nearest, bvhtree.nearest_callback, &bvhtree); - - if (nearest.index == -1) { - continue; - } - - MeshElemMap *source_loops = source_lmap + nearest.index; - MeshElemMap *target_loops = target_lmap + i; - - if (target_loops->count == 0 || source_loops->count == 0) { - continue; - } - - /* - * Average color data for loops around the source vertex into - * the first target loop around the target vertex - */ - - CustomData_interp(source_cdata, - target_cdata, - source_loops->indices, - nullptr, - nullptr, - source_loops->count, - target_loops->indices[0]); - - void *elem = POINTER_OFFSET(target_data, size_t(target_loops->indices[0]) * data_size); - - /* Copy to rest of target loops. */ - for (int j = 1; j < target_loops->count; j++) { - memcpy(POINTER_OFFSET(target_data, size_t(target_loops->indices[j]) * data_size), - elem, - data_size); - } - } + blender::threading::parallel_for( + IndexRange(target->totvert), 2048, [&](const IndexRange range) { + for (const int i : range) { + BVHTreeNearest nearest; + nearest.index = -1; + nearest.dist_sq = FLT_MAX; + BLI_bvhtree_find_nearest( + bvhtree.tree, target_verts[i].co, &nearest, bvhtree.nearest_callback, &bvhtree); + + if (nearest.index == -1) { + continue; + } + + MeshElemMap *source_loops = source_lmap + nearest.index; + MeshElemMap *target_loops = target_lmap + i; + + if (target_loops->count == 0 || source_loops->count == 0) { + continue; + } + + /* + * Average color data for loops around the source vertex into + * the first target loop around the target vertex + */ + + CustomData_interp(source_cdata, + target_cdata, + source_loops->indices, + nullptr, + nullptr, + source_loops->count, + target_loops->indices[0]); + + void *elem = POINTER_OFFSET(target_data, + size_t(target_loops->indices[0]) * data_size); + + /* Copy to rest of target loops. */ + for (int j = 1; j < target_loops->count; j++) { + memcpy(POINTER_OFFSET(target_data, size_t(target_loops->indices[j]) * data_size), + elem, + data_size); + } + } + }); } } diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index bad099815a4..f13132b5b7c 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -4024,6 +4024,7 @@ static void rna_def_mesh(BlenderRNA *brna) "Size of the voxel in object space used for volume evaluation. Lower " "values preserve finer details"); RNA_def_property_update(prop, 0, "rna_Mesh_update_draw"); + RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE); prop = RNA_def_property(srna, "remesh_voxel_adaptivity", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "remesh_voxel_adaptivity"); @@ -4035,11 +4036,13 @@ static void rna_def_mesh(BlenderRNA *brna) "Reduces the final face count by simplifying geometry where detail is not needed, " "generating triangles. A value greater than 0 disables Fix Poles"); RNA_def_property_update(prop, 0, "rna_Mesh_update_draw"); + RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE); prop = RNA_def_property(srna, "use_remesh_fix_poles", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_REMESH_FIX_POLES); RNA_def_property_ui_text(prop, "Fix Poles", "Produces less poles and a better topology flow"); RNA_def_property_update(prop, 0, "rna_Mesh_update_draw"); + RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE); prop = RNA_def_property(srna, "use_remesh_preserve_volume", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_REMESH_REPROJECT_VOLUME); @@ -4048,29 +4051,34 @@ static void rna_def_mesh(BlenderRNA *brna) "Preserve Volume", "Projects the mesh to preserve the volume and details of the original mesh"); RNA_def_property_update(prop, 0, "rna_Mesh_update_draw"); + RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE); prop = RNA_def_property(srna, "use_remesh_preserve_paint_mask", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_REMESH_REPROJECT_PAINT_MASK); RNA_def_property_ui_text(prop, "Preserve Paint Mask", "Keep the current mask on the new mesh"); RNA_def_property_update(prop, 0, "rna_Mesh_update_draw"); + RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE); prop = RNA_def_property(srna, "use_remesh_preserve_sculpt_face_sets", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_REMESH_REPROJECT_SCULPT_FACE_SETS); RNA_def_property_ui_text( prop, "Preserve Face Sets", "Keep the current Face Sets on the new mesh"); RNA_def_property_update(prop, 0, "rna_Mesh_update_draw"); + RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE); prop = RNA_def_property(srna, "use_remesh_preserve_vertex_colors", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_REMESH_REPROJECT_VERTEX_COLORS); RNA_def_property_ui_text( prop, "Preserve Vertex Colors", "Keep the current vertex colors on the new mesh"); RNA_def_property_update(prop, 0, "rna_Mesh_update_draw"); + RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE); prop = RNA_def_property(srna, "remesh_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "remesh_mode"); RNA_def_property_enum_items(prop, rna_enum_mesh_remesh_mode_items); RNA_def_property_ui_text(prop, "Remesh Mode", ""); RNA_def_property_update(prop, 0, "rna_Mesh_update_draw"); + RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE); /* End remesh */ -- cgit v1.2.3 From b320597697d8c28798342ffc45a330f86ed276ca Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 3 Nov 2022 11:48:47 +1100 Subject: Tests: don't create byte-code cache when calling Python from SVN Creating `__pycache__` directories in SVN's lib/ directory can cause updating SVN to fail. Add the -B flag when TEST_PYTHON_EXE from LIBDIR is used so so Python doesn't generate this cache. --- CMakeLists.txt | 1 + tests/CMakeLists.txt | 13 +++++++++++++ tests/blender_as_python_module/CMakeLists.txt | 2 +- tests/python/CMakeLists.txt | 2 +- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e89943714a..810a6b011fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -550,6 +550,7 @@ endif() option(WITH_GTESTS "Enable GTest unit testing" OFF) option(WITH_OPENGL_RENDER_TESTS "Enable OpenGL render related unit testing (Experimental)" OFF) option(WITH_OPENGL_DRAW_TESTS "Enable OpenGL UI drawing related unit testing (Experimental)" OFF) +# NOTE: All callers of this must add `TEST_PYTHON_EXE_EXTRA_ARGS` before any other arguments. set(TEST_PYTHON_EXE "" CACHE PATH "Python executable to run unit tests") mark_as_advanced(TEST_PYTHON_EXE) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 68fcfc89b96..d2fbec7059f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -31,6 +31,19 @@ elseif(NOT EXISTS ${TEST_PYTHON_EXE}) endif() +# Include these arguments before all others, they must not interfere with Python execution. +set(TEST_PYTHON_EXE_EXTRA_ARGS) + +# Check if this a Blender managed Python installation, if so, don't add `*.pyc` files. +if(LIBDIR) + cmake_path(IS_PREFIX LIBDIR "${TEST_PYTHON_EXE}" NORMALIZE _is_prefix) + if(_is_prefix) + # Keep the Python in Blender's SVN LIBDIR pristine, to avoid conflicts on updating. + set(TEST_PYTHON_EXE_EXTRA_ARGS "-B") + endif() + unset(_is_prefix) +endif() + # For testing with Valgrind # set(TEST_BLENDER_EXE valgrind --track-origins=yes --error-limit=no ${TEST_BLENDER_EXE}) diff --git a/tests/blender_as_python_module/CMakeLists.txt b/tests/blender_as_python_module/CMakeLists.txt index 6e0ce524903..7387d5c41bf 100644 --- a/tests/blender_as_python_module/CMakeLists.txt +++ b/tests/blender_as_python_module/CMakeLists.txt @@ -8,7 +8,7 @@ function(add_blender_as_python_module_test testname testscript) add_test( NAME ${testname} - COMMAND ${TEST_PYTHON_EXE} ${testscript} ${ARGN} + COMMAND ${TEST_PYTHON_EXE} ${TEST_PYTHON_EXE_EXTRA_ARGS} ${testscript} ${ARGN} ) # On macOS, asan library must be loaded early. diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt index b3decc06161..0d74cfafda5 100644 --- a/tests/python/CMakeLists.txt +++ b/tests/python/CMakeLists.txt @@ -41,7 +41,7 @@ function(add_python_test testname testscript) add_test( NAME ${testname} - COMMAND ${TEST_PYTHON_EXE} ${testscript} ${ARGN} + COMMAND ${TEST_PYTHON_EXE} ${TEST_PYTHON_EXE_EXTRA_ARGS} ${testscript} ${ARGN} ) set_tests_properties(${testname} PROPERTIES ENVIRONMENT LSAN_OPTIONS=exitcode=0:$ENV{LSAN_OPTIONS} -- cgit v1.2.3 From 6377d00a61d04e7e5a556e7cb8bbc6e861304b14 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 3 Nov 2022 12:10:16 +1100 Subject: Cleanup: cmake comment line length --- CMakeLists.txt | 7 ++++-- build_files/build_environment/CMakeLists.txt | 9 ++++---- build_files/build_environment/cmake/dpcpp.cmake | 7 ++++-- .../build_environment/cmake/setup_mingw64.cmake | 6 ++--- build_files/build_environment/cmake/usd.cmake | 8 ++++--- build_files/build_environment/cmake/versions.cmake | 5 ++-- .../patches/cmake/modules/FindIlmBase.cmake | 12 +++++++--- .../patches/cmake/modules/FindOpenEXR.cmake | 3 ++- build_files/cmake/Modules/FindOpenEXR.cmake | 3 ++- build_files/cmake/Modules/FindUSD.cmake | 3 ++- build_files/cmake/macros.cmake | 27 +++++++++++++--------- build_files/cmake/platform/platform_win32.cmake | 9 ++++---- extern/mantaflow/CMakeLists.txt | 3 ++- intern/cycles/device/CMakeLists.txt | 3 ++- intern/cycles/kernel/CMakeLists.txt | 7 +++--- source/blender/io/usd/CMakeLists.txt | 7 +++--- source/blender/makesrna/intern/CMakeLists.txt | 5 ++-- tests/CMakeLists.txt | 6 ++--- 18 files changed, 80 insertions(+), 50 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 810a6b011fd..30a186318ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -177,8 +177,11 @@ option(WITH_INTERNATIONAL "Enable I18N (International fonts and text)" ON) option(WITH_PYTHON "Enable Embedded Python API (only disable for development)" ON) option(WITH_PYTHON_SECURITY "Disables execution of scripts within blend files by default" ON) -mark_as_advanced(WITH_PYTHON) # don't want people disabling this unless they really know what they are doing. -mark_as_advanced(WITH_PYTHON_SECURITY) # some distributions see this as a security issue, rather than have them patch it, make a build option. +# Don't want people disabling this unless they really know what they are doing. +mark_as_advanced(WITH_PYTHON) +# Some distributions see this as a security issue, rather than have them patch it, +# make a build option. +mark_as_advanced(WITH_PYTHON_SECURITY) option(WITH_PYTHON_SAFETY "Enable internal API error checking to track invalid data to prevent crash on access (at the expense of some efficiency, only enable for development)." OFF) mark_as_advanced(WITH_PYTHON_SAFETY) diff --git a/build_files/build_environment/CMakeLists.txt b/build_files/build_environment/CMakeLists.txt index 023d113b551..999223603d5 100644 --- a/build_files/build_environment/CMakeLists.txt +++ b/build_files/build_environment/CMakeLists.txt @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-or-later -#################################################################################################### +################################################################################################## # # This is a build system used by platform maintainers to build library dependencies on # Windows, macOS and Linux. @@ -22,7 +22,7 @@ # Install compiler cmake autoconf automake libtool yasm tcl # Run "make deps" from main Blender directory # -#################################################################################################### +################################################################################################## project("BlenderDependencies") cmake_minimum_required(VERSION 3.5) @@ -30,7 +30,8 @@ cmake_minimum_required(VERSION 3.5) include(ExternalProject) include(cmake/check_software.cmake) include(cmake/options.cmake) -# versions.cmake needs to be included after options.cmake due to the BLENDER_PLATFORM_ARM variable being needed. +# `versions.cmake` needs to be included after `options.cmake` +# due to the `BLENDER_PLATFORM_ARM` variable being needed. include(cmake/versions.cmake) include(cmake/boost_build_options.cmake) include(cmake/download.cmake) @@ -88,7 +89,7 @@ include(cmake/package_python.cmake) include(cmake/usd.cmake) include(cmake/potrace.cmake) include(cmake/haru.cmake) -# Boost needs to be included after python.cmake due to the PYTHON_BINARY variable being needed. +# Boost needs to be included after `python.cmake` due to the PYTHON_BINARY variable being needed. include(cmake/boost.cmake) include(cmake/pugixml.cmake) include(cmake/ispc.cmake) diff --git a/build_files/build_environment/cmake/dpcpp.cmake b/build_files/build_environment/cmake/dpcpp.cmake index dbba97b8264..28315d1f703 100644 --- a/build_files/build_environment/cmake/dpcpp.cmake +++ b/build_files/build_environment/cmake/dpcpp.cmake @@ -80,8 +80,11 @@ ExternalProject_Add(external_dpcpp SOURCE_SUBDIR llvm LIST_SEPARATOR ^^ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/dpcpp ${DEFAULT_CMAKE_FLAGS} ${DPCPP_EXTRA_ARGS} - #CONFIGURE_COMMAND ${PYTHON_BINARY} ${BUILD_DIR}/dpcpp/src/external_dpcpp/buildbot/configure.py ${DPCPP_CONFIGURE_ARGS} - #BUILD_COMMAND echo "." #${PYTHON_BINARY} ${BUILD_DIR}/dpcpp/src/external_dpcpp/buildbot/compile.py + # CONFIGURE_COMMAND + # ${PYTHON_BINARY} + # ${BUILD_DIR}/dpcpp/src/external_dpcpp/buildbot/configure.py ${DPCPP_CONFIGURE_ARGS} + # BUILD_COMMAND + # echo "." # ${PYTHON_BINARY} ${BUILD_DIR}/dpcpp/src/external_dpcpp/buildbot/compile.py INSTALL_COMMAND ${CMAKE_COMMAND} --build . -- deploy-sycl-toolchain PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/dpcpp/src/external_dpcpp < ${PATCH_DIR}/dpcpp.diff INSTALL_DIR ${LIBDIR}/dpcpp diff --git a/build_files/build_environment/cmake/setup_mingw64.cmake b/build_files/build_environment/cmake/setup_mingw64.cmake index fa65212e056..6f53edb38ea 100644 --- a/build_files/build_environment/cmake/setup_mingw64.cmake +++ b/build_files/build_environment/cmake/setup_mingw64.cmake @@ -1,10 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-or-later -#################################################################################################################### +################################################################################################## # Mingw64 Builds -#################################################################################################################### +################################################################################################## # This installs mingw64+msys to compile ffmpeg/iconv/libsndfile/fftw3 -#################################################################################################################### +################################################################################################## message("LIBDIR = ${LIBDIR}") macro(cmake_to_msys_path MsysPath ResultingPath) diff --git a/build_files/build_environment/cmake/usd.cmake b/build_files/build_environment/cmake/usd.cmake index 34e43383637..0661be3ba14 100644 --- a/build_files/build_environment/cmake/usd.cmake +++ b/build_files/build_environment/cmake/usd.cmake @@ -58,8 +58,9 @@ set(USD_EXTRA_ARGS -DPXR_BUILD_USD_TOOLS=OFF -DCMAKE_DEBUG_POSTFIX=_d -DBUILD_SHARED_LIBS=Off - # USD is hellbound on making a shared lib, unless you point this variable to a valid cmake file - # doesn't have to make sense, but as long as it points somewhere valid it will skip the shared lib. + # USD is hellbound on making a shared library, + # unless you point this variable to a valid CMAKE file doesn't have to make sense, + # but as long as it points somewhere valid it will skip the shared library. -DPXR_MONOLITHIC_IMPORT=${BUILD_DIR}/usd/src/external_usd/cmake/defaults/Version.cmake -DTBB_INCLUDE_DIRS=${LIBDIR}/tbb/include -DTBB_LIBRARIES=${LIBDIR}/tbb/lib/${LIBPREFIX}${TBB_LIBRARY}${LIBEXT} @@ -86,7 +87,8 @@ add_dependencies( external_opensubdiv ) -# Since USD 21.11 the libraries are prefixed with "usd_", i.e. "libusd_m.a" became "libusd_usd_m.a". +# Since USD 21.11 the libraries are prefixed with "usd_", i.e. +# "libusd_m.a" became "libusd_usd_m.a". # See https://github.com/PixarAnimationStudios/USD/blob/release/CHANGELOG.md#2111---2021-11-01 if(NOT WIN32) if (USD_VERSION VERSION_LESS 21.11) diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake index 328f5b8efc3..4f4330b56f4 100644 --- a/build_files/build_environment/cmake/versions.cmake +++ b/build_files/build_environment/cmake/versions.cmake @@ -225,8 +225,9 @@ set(URLLIB3_CPE "cpe:2.3:a:urllib3:urllib3:${URLLIB3_VERSION}:*:*:*:*:*:*:*") set(CERTIFI_VERSION 2021.10.8) set(REQUESTS_VERSION 2.27.1) set(CYTHON_VERSION 0.29.26) -# The version of the zstd library used to build the Python package should match ZSTD_VERSION defined below. -# At this time of writing, 0.17.0 was already released, but built against zstd 1.5.1, while we use 1.5.0. +# The version of the zstd library used to build the Python package should match ZSTD_VERSION +# defined below. At this time of writing, 0.17.0 was already released, +# but built against zstd 1.5.1, while we use 1.5.0. set(ZSTANDARD_VERSION 0.16.0) set(AUTOPEP8_VERSION 1.6.0) set(PYCODESTYLE_VERSION 2.8.0) diff --git a/build_files/build_environment/patches/cmake/modules/FindIlmBase.cmake b/build_files/build_environment/patches/cmake/modules/FindIlmBase.cmake index 7611ca21708..c74ff788a75 100644 --- a/build_files/build_environment/patches/cmake/modules/FindIlmBase.cmake +++ b/build_files/build_environment/patches/cmake/modules/FindIlmBase.cmake @@ -177,7 +177,8 @@ if(ILMBASE_INCLUDE_DIR) "\\1" XYZ ${ILMBASE_BUILD_SPECIFICATION}) set("ILMBASE_VERSION" ${XYZ} CACHE STRING "Version of ILMBase lib") else() - # Old versions (before 2.0?) do not have any version string, just assuming 2.0 should be fine though. + # Old versions (before 2.0?) do not have any version string, + # just assuming 2.0 should be fine though. message(WARNING "Could not determine ILMBase library version, assuming 2.0.") set("ILMBASE_VERSION" "2.0" CACHE STRING "Version of ILMBase lib") endif() @@ -195,8 +196,13 @@ else() # elseif(${ILMBASE_VERSION} VERSION_LESS "2.1") set(IlmBase_Libraries Half Iex Imath IlmThread) # else() -# string(REGEX REPLACE "([0-9]+)[.]([0-9]+).*" "\\1_\\2" _ilmbase_libs_ver ${ILMBASE_VERSION}) -# set(IlmBase_Libraries Half Iex-${_ilmbase_libs_ver} Imath-${_ilmbase_libs_ver} IlmThread-${_ilmbase_libs_ver}) + # string(REGEX REPLACE "([0-9]+)[.]([0-9]+).*" "\\1_\\2" _ilmbase_libs_ver ${ILMBASE_VERSION}) + # set(IlmBase_Libraries + # Half + # Iex-${_ilmbase_libs_ver} + # Imath-${_ilmbase_libs_ver} + # IlmThread-${_ilmbase_libs_ver} + # ) endif() diff --git a/build_files/build_environment/patches/cmake/modules/FindOpenEXR.cmake b/build_files/build_environment/patches/cmake/modules/FindOpenEXR.cmake index 8b08b047eac..040dfe1c16f 100644 --- a/build_files/build_environment/patches/cmake/modules/FindOpenEXR.cmake +++ b/build_files/build_environment/patches/cmake/modules/FindOpenEXR.cmake @@ -175,7 +175,8 @@ if(OPENEXR_INCLUDE_DIR) "\\1" XYZ ${OPENEXR_BUILD_SPECIFICATION}) set("OPENEXR_VERSION" ${XYZ} CACHE STRING "Version of OpenEXR lib") else() - # Old versions (before 2.0?) do not have any version string, just assuming 2.0 should be fine though. + # Old versions (before 2.0?) do not have any version string, + # just assuming 2.0 should be fine though. message(WARNING "Could not determine ILMBase library version, assuming 2.0.") set("OPENEXR_VERSION" "2.0" CACHE STRING "Version of OpenEXR lib") endif() diff --git a/build_files/cmake/Modules/FindOpenEXR.cmake b/build_files/cmake/Modules/FindOpenEXR.cmake index 9107b562711..1cc3e50ba92 100644 --- a/build_files/cmake/Modules/FindOpenEXR.cmake +++ b/build_files/cmake/Modules/FindOpenEXR.cmake @@ -26,7 +26,8 @@ IF(NOT OPENEXR_ROOT_DIR AND NOT $ENV{OPENEXR_ROOT_DIR} STREQUAL "") SET(OPENEXR_ROOT_DIR $ENV{OPENEXR_ROOT_DIR}) ENDIF() -# Old versions (before 2.0?) do not have any version string, just assuming this should be fine though. +# Old versions (before 2.0?) do not have any version string, +# just assuming this should be fine though. SET(_openexr_libs_ver_init "2.0") SET(_openexr_SEARCH_DIRS diff --git a/build_files/cmake/Modules/FindUSD.cmake b/build_files/cmake/Modules/FindUSD.cmake index 0fd5f06bb35..ba5a3d7c843 100644 --- a/build_files/cmake/Modules/FindUSD.cmake +++ b/build_files/cmake/Modules/FindUSD.cmake @@ -32,7 +32,8 @@ FIND_PATH(USD_INCLUDE_DIR DOC "Universal Scene Description (USD) header files" ) -# Since USD 21.11 the libraries are prefixed with "usd_", i.e. "libusd_m.a" became "libusd_usd_m.a". +# Since USD 21.11 the libraries are prefixed with "usd_", i.e. +# "libusd_m.a" became "libusd_usd_m.a". # See https://github.com/PixarAnimationStudios/USD/blob/release/CHANGELOG.md#2111---2021-11-01 FIND_LIBRARY(USD_LIBRARY NAMES diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 8af45690862..d81767b4009 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -995,7 +995,8 @@ function(data_to_c_simple_icons add_custom_command( OUTPUT ${_file_from} ${_file_to} COMMAND ${CMAKE_COMMAND} -E make_directory ${_file_to_path} - # COMMAND python3 ${CMAKE_SOURCE_DIR}/source/blender/datatoc/datatoc_icon.py ${_path_from_abs} ${_file_from} + # COMMAND python3 ${CMAKE_SOURCE_DIR}/source/blender/datatoc/datatoc_icon.py + # ${_path_from_abs} ${_file_from} COMMAND "$" ${_path_from_abs} ${_file_from} COMMAND "$" ${_file_from} ${_file_to} DEPENDS @@ -1073,23 +1074,27 @@ function(msgfmt_simple endfunction() function(find_python_package - package - relative_include_dir + package + relative_include_dir ) string(TOUPPER ${package} _upper_package) - # set but invalid + # Set but invalid. if((NOT ${PYTHON_${_upper_package}_PATH} STREQUAL "") AND (NOT ${PYTHON_${_upper_package}_PATH} MATCHES NOTFOUND)) -# if(NOT EXISTS "${PYTHON_${_upper_package}_PATH}/${package}") -# message(WARNING "PYTHON_${_upper_package}_PATH is invalid, ${package} not found in '${PYTHON_${_upper_package}_PATH}' " -# "WITH_PYTHON_INSTALL_${_upper_package} option will be ignored when installing python") -# set(WITH_PYTHON_INSTALL${_upper_package} OFF) -# endif() - # not set, so initialize + # if(NOT EXISTS "${PYTHON_${_upper_package}_PATH}/${package}") + # message( + # WARNING + # "PYTHON_${_upper_package}_PATH is invalid, ${package} not found in " + # "'${PYTHON_${_upper_package}_PATH}' " + # "WITH_PYTHON_INSTALL_${_upper_package} option will be ignored when installing Python" + # ) + # set(WITH_PYTHON_INSTALL${_upper_package} OFF) + # endif() + # Not set, so initialize. else() - string(REPLACE "." ";" _PY_VER_SPLIT "${PYTHON_VERSION}") + string(REPLACE "." ";" _PY_VER_SPLIT "${PYTHON_VERSION}") list(GET _PY_VER_SPLIT 0 _PY_VER_MAJOR) # re-cache diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index 3818076634a..7a2d3ad948a 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -150,10 +150,11 @@ endif() # Debug Symbol format # sccache # MSVC_ASAN # format # why -# ON # ON # Z7 # sccache will only play nice with Z7 -# ON # OFF # Z7 # sccache will only play nice with Z7 -# OFF # ON # Zi # Asan will not play nice with Edit and Continue -# OFF # OFF # ZI # Neither asan nor sscache is enabled Edit and Continue is available +# ON # ON # Z7 # sccache will only play nice with Z7. +# ON # OFF # Z7 # sccache will only play nice with Z7. +# OFF # ON # Zi # Asan will not play nice with Edit and Continue. +# OFF # OFF # ZI # Neither ASAN nor sscache is enabled Edit and +# Continue is available. # Release Symbol format # sccache # MSVC_ASAN # format # why diff --git a/extern/mantaflow/CMakeLists.txt b/extern/mantaflow/CMakeLists.txt index 908c5d2ffd9..06767e9af1e 100644 --- a/extern/mantaflow/CMakeLists.txt +++ b/extern/mantaflow/CMakeLists.txt @@ -25,7 +25,8 @@ set(MANTAVERSION "0.13") add_definitions(-DWITH_FLUID=1) # Compile Mantaflow dependencies too (e.g. cnpy for numpy file IO). -# Make sure that dependencies exist before enabling this option by updating the source files in extern/ +# Make sure that dependencies exist before enabling this option +# by updating the source files in `extern/`. set(WITH_MANTA_DEPENDENCIES 0) # Enable Mantaflow numpy support diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt index 5296d819e42..bfca3ab6aea 100644 --- a/intern/cycles/device/CMakeLists.txt +++ b/intern/cycles/device/CMakeLists.txt @@ -224,7 +224,8 @@ include_directories(SYSTEM ${INC_SYS}) cycles_add_library(cycles_device "${LIB}" ${SRC}) if(WITH_CYCLES_DEVICE_ONEAPI) - # Need to have proper rebuilding in case of changes in cycles_kernel_oneapi due external project behaviour + # Need to have proper rebuilding in case of changes + # in cycles_kernel_oneapi due external project behavior. add_dependencies(cycles_device cycles_kernel_oneapi) endif() diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 81c5f593974..3779fdc697a 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -866,8 +866,8 @@ if(WITH_CYCLES_DEVICE_ONEAPI) else() list(APPEND sycl_compiler_flags -fPIC) - # We avoid getting __FAST_MATH__ to be defined when building on CentOS 7 until the compilation crash - # it triggers at either AoT or JIT stages gets fixed. + # We avoid getting __FAST_MATH__ to be defined when building on CentOS 7 until the compilation + # crash it triggers at either AoT or JIT stages gets fixed. list(APPEND sycl_compiler_flags -fhonor-nans) # add $ORIGIN to cycles_kernel_oneapi.so rpath so libsycl.so and @@ -881,7 +881,8 @@ if(WITH_CYCLES_DEVICE_ONEAPI) OUTPUT ${cycles_kernel_oneapi_lib} COMMAND ${CMAKE_COMMAND} -E env "LD_LIBRARY_PATH=${sycl_compiler_root}/../lib:${OCLOC_INSTALL_DIR}/lib:${IGC_INSTALL_DIR}/lib" - "PATH=${OCLOC_INSTALL_DIR}/bin:${sycl_compiler_root}:$ENV{PATH}" # env PATH is for compiler to find ld + # `$ENV{PATH}` is for compiler to find `ld`. + "PATH=${OCLOC_INSTALL_DIR}/bin:${sycl_compiler_root}:$ENV{PATH}" ${SYCL_COMPILER} $<$:-g>$<$:-g> ${sycl_compiler_flags} DEPENDS ${cycles_oneapi_kernel_sources}) endif() diff --git a/source/blender/io/usd/CMakeLists.txt b/source/blender/io/usd/CMakeLists.txt index 4f1bc29cd0d..06a0f12c571 100644 --- a/source/blender/io/usd/CMakeLists.txt +++ b/source/blender/io/usd/CMakeLists.txt @@ -143,7 +143,8 @@ if(WIN32) set_property(TARGET bf_usd APPEND_STRING PROPERTY INTERFACE_LINK_OPTIONS "$<$:/WHOLEARCHIVE:${USD_RELEASE_LIB}>") endif() -# Source: https://github.com/PixarAnimationStudios/USD/blob/master/BUILDING.md#linking-whole-archives +# Source: +# https://github.com/PixarAnimationStudios/USD/blob/master/BUILDING.md#linking-whole-archives if(WIN32) target_link_libraries(bf_usd INTERFACE ${USD_LIBRARIES}) elseif(APPLE) @@ -174,6 +175,6 @@ if(WITH_GTESTS) blender_add_test_lib(bf_io_usd_tests "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${LIB};${TEST_LIB}") endif() -# In cmake version 3.21 and up, we can instead use the NO_CACHE option for -# find_file so we don't need to clear it from the cache here. +# In CMAKE version 3.21 and up, we can instead use the `NO_CACHE` option for +# `find_file` so we don't need to clear it from the cache here. unset(USD_IMAGING_HEADERS CACHE) diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index f028b199098..5c2bdc214d1 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -406,8 +406,9 @@ if(WIN32 AND NOT UNIX) target_link_libraries(makesrna ${PTHREADS_LIBRARIES}) endif() -# Output rna_*_gen.c -# note (linux only): with crashes try add this after COMMAND: valgrind --leak-check=full --track-origins=yes +# Output `rna_*_gen.c`. +# NOTE: (Linux only): with crashes try add this after COMMAND: +# `valgrind --leak-check=full --track-origins=yes` add_custom_command( OUTPUT ${GENSRC} COMMAND "$" ${CMAKE_CURRENT_BINARY_DIR}/ ${CMAKE_CURRENT_BINARY_DIR}/../ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d2fbec7059f..c96c6f2988d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -20,9 +20,9 @@ else() endif() endif() -# The installation directory's Python is the best one to use. However, it can only be there after the install step, -# which means that Python will never be there on a fresh system. To suit different needs, the user can pass -# -DTEST_PYTHON_EXE=/path/to/python to CMake. +# The installation directory's Python is the best one to use. However, it can only be there +# after the install step, # which means that Python will never be there on a fresh system. +# To suit different needs, the user can pass `-DTEST_PYTHON_EXE=/path/to/python` to CMake. if(NOT TEST_PYTHON_EXE) set(TEST_PYTHON_EXE ${PYTHON_EXECUTABLE}) message(STATUS "Tests: Using Python executable: ${TEST_PYTHON_EXE}") -- cgit v1.2.3 From bb0b04f43aa3d4cbc27cadecff6449014934431e Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Wed, 2 Nov 2022 22:14:08 -0400 Subject: UI: Bevel: Specify the width type as "Width Type" in the status bar. Part of T102224 --- source/blender/editors/mesh/editmesh_bevel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 85801668510..92e993f74a2 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -170,7 +170,7 @@ static void edbm_bevel_update_status_text(bContext *C, wmOperator *op) sizeof(status_text), TIP_("%s: Confirm, " "%s: Cancel, " - "%s: Mode (%s), " + "%s: Width Type (%s), " "%s: Width (%s), " "%s: Segments (%d), " "%s: Profile (%.3f), " -- cgit v1.2.3 From ea94d5723f106a1812b474961940f283a9fe6c1f Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Wed, 2 Nov 2022 22:35:42 -0400 Subject: PyDocs: Upgrade Sphinx to 5.3.0 Trivial changes, should not affect us in anyway. --- doc/python_api/requirements.txt | 4 ++-- release/datafiles/locale | 2 +- release/scripts/addons | 2 +- source/tools | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/python_api/requirements.txt b/doc/python_api/requirements.txt index bf120f24995..42acae34789 100644 --- a/doc/python_api/requirements.txt +++ b/doc/python_api/requirements.txt @@ -1,11 +1,11 @@ -sphinx==5.2.3 +sphinx==5.3.0 # Sphinx dependencies that are important Jinja2==3.1.2 Pygments==2.13.0 docutils==0.17.1 snowballstemmer==2.2.0 -babel==2.10.3 +babel==2.11.0 requests==2.28.1 # Only needed to match the theme used for the official documentation. diff --git a/release/datafiles/locale b/release/datafiles/locale index 7be7aff5a18..fe221a8bc93 160000 --- a/release/datafiles/locale +++ b/release/datafiles/locale @@ -1 +1 @@ -Subproject commit 7be7aff5a18c550465b3f7634539ed4168af7c51 +Subproject commit fe221a8bc934385d9f302c46a5c7cbeacddafe3b diff --git a/release/scripts/addons b/release/scripts/addons index eb09be71a96..05f475f231a 160000 --- a/release/scripts/addons +++ b/release/scripts/addons @@ -1 +1 @@ -Subproject commit eb09be71a96c4fe910fdc43373be5ec08b419d2c +Subproject commit 05f475f231abce2701b7424ed6b8231dadc64da8 diff --git a/source/tools b/source/tools index 2a541f164a2..dfa16042bf7 160000 --- a/source/tools +++ b/source/tools @@ -1 +1 @@ -Subproject commit 2a541f164a222ef7bcd036d37687738acee8d946 +Subproject commit dfa16042bf7149475ad318d29a8202d969982abb -- cgit v1.2.3 From 5ba045af7b3bebf2e4a7e1098f35ad134fbd78e8 Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Wed, 2 Nov 2022 22:37:39 -0400 Subject: PyDocs: Upgrade Theme to 1.1.0 Updates to kbd and breadcrumbs along with some fixes to API docs that should'nt affect us. --- doc/python_api/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/python_api/requirements.txt b/doc/python_api/requirements.txt index 42acae34789..4b31c3f1344 100644 --- a/doc/python_api/requirements.txt +++ b/doc/python_api/requirements.txt @@ -10,4 +10,4 @@ requests==2.28.1 # Only needed to match the theme used for the official documentation. # Without this theme, the default theme will be used. -sphinx_rtd_theme==1.0.0 +sphinx_rtd_theme==1.1.0 -- cgit v1.2.3 From 92b2f4d24999d463d20e7a134bff414f0a8a9d77 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 3 Nov 2022 14:17:54 +1100 Subject: BLI_string: C++ support for string joining macros C++ doesn't support taking the temporary address of a temporary array, use inline functions instead. Also change array joining functions to return the length of the string instead of returning the pointer (matching BLI_path_join). --- source/blender/blenlib/BLI_string_utils.h | 393 +++++++++++++++++++-- source/blender/blenlib/intern/string_utils.c | 14 +- .../editors/space_sequencer/sequencer_draw.c | 3 +- 3 files changed, 363 insertions(+), 47 deletions(-) diff --git a/source/blender/blenlib/BLI_string_utils.h b/source/blender/blenlib/BLI_string_utils.h index df82e94ae2e..936e892a9e2 100644 --- a/source/blender/blenlib/BLI_string_utils.h +++ b/source/blender/blenlib/BLI_string_utils.h @@ -47,33 +47,6 @@ void BLI_string_split_suffix(const char *string, char *r_body, char *r_suf, size */ void BLI_string_split_prefix(const char *string, char *r_pre, char *r_body, size_t str_len); -/** - * Join strings, return newly allocated string. - */ -char *BLI_string_join_array(char *result, - size_t result_len, - const char *strings[], - uint strings_len) ATTR_NONNULL(); -/** - * A version of #BLI_string_join that takes a separator which can be any character including '\0'. - */ -char *BLI_string_join_array_by_sep_char(char *result, - size_t result_len, - char sep, - const char *strings[], - uint strings_len) ATTR_NONNULL(); - -/** - * Join an array of strings into a newly allocated, null terminated string. - */ -char *BLI_string_join_arrayN(const char *strings[], uint strings_len) ATTR_WARN_UNUSED_RESULT - ATTR_NONNULL(); -/** - * A version of #BLI_string_joinN that takes a separator which can be any character including '\0'. - */ -char *BLI_string_join_array_by_sep_charN(char sep, - const char *strings[], - uint strings_len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); /** * A version of #BLI_string_join_array_by_sep_charN that takes a table array. * The new location of each string is written into this array. @@ -82,17 +55,7 @@ char *BLI_string_join_array_by_sep_char_with_tableN(char sep, char *table[], const char *strings[], uint strings_len) ATTR_NONNULL(); -/** - * Take multiple arguments, pass as (array, length). - */ -#define BLI_string_join(result, result_len, ...) \ - BLI_string_join_array( \ - result, result_len, ((const char *[]){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__)) -#define BLI_string_joinN(...) \ - BLI_string_join_arrayN(((const char *[]){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__)) -#define BLI_string_join_by_sep_charN(sep, ...) \ - BLI_string_join_array_by_sep_charN( \ - sep, ((const char *[]){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__)) + #define BLI_string_join_by_sep_char_with_tableN(sep, table, ...) \ BLI_string_join_array_by_sep_char_with_tableN( \ sep, table, ((const char *[]){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__)) @@ -149,6 +112,360 @@ bool BLI_uniquename(struct ListBase *list, int name_offset, size_t name_len); +/* Expand array functions. */ + +/* Intentionally no comma after `_BLI_STRING_ARGS_0` to allow it to be empty. */ +#define _BLI_STRING_ARGS_1 _BLI_STRING_ARGS_0 const char *a +#define _BLI_STRING_ARGS_2 _BLI_STRING_ARGS_1, const char *b +#define _BLI_STRING_ARGS_3 _BLI_STRING_ARGS_2, const char *c +#define _BLI_STRING_ARGS_4 _BLI_STRING_ARGS_3, const char *d +#define _BLI_STRING_ARGS_5 _BLI_STRING_ARGS_4, const char *e +#define _BLI_STRING_ARGS_6 _BLI_STRING_ARGS_5, const char *f +#define _BLI_STRING_ARGS_7 _BLI_STRING_ARGS_6, const char *g +#define _BLI_STRING_ARGS_8 _BLI_STRING_ARGS_7, const char *h +#define _BLI_STRING_ARGS_9 _BLI_STRING_ARGS_8, const char *i +#define _BLI_STRING_ARGS_10 _BLI_STRING_ARGS_9, const char *j + +/* ------------------------------------------------------------------------- */ +/** \name Implement: `BLI_string_join(..)` + * \{ */ + +#define _BLI_STRING_ARGS_0 char *__restrict dst, const size_t dst_len, + +/** + * Join strings, return the length of the resulting string. + */ +size_t BLI_string_join_array(char *result, + size_t result_len, + const char *strings[], + uint strings_len) ATTR_NONNULL(); + +#define BLI_string_join(...) VA_NARGS_CALL_OVERLOAD(_BLI_string_join_, __VA_ARGS__) + +BLI_INLINE size_t _BLI_string_join_3(_BLI_STRING_ARGS_1) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_string_join_4(_BLI_STRING_ARGS_2) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_string_join_5(_BLI_STRING_ARGS_3) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_string_join_6(_BLI_STRING_ARGS_4) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_string_join_7(_BLI_STRING_ARGS_5) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_string_join_8(_BLI_STRING_ARGS_6) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_string_join_9(_BLI_STRING_ARGS_7) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_string_join_10(_BLI_STRING_ARGS_8) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_string_join_11(_BLI_STRING_ARGS_9) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_string_join_12(_BLI_STRING_ARGS_10) ATTR_NONNULL(); + +BLI_INLINE size_t _BLI_string_join_3(_BLI_STRING_ARGS_1) +{ + const char *string_array[] = {a}; + return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE size_t _BLI_string_join_4(_BLI_STRING_ARGS_2) +{ + const char *string_array[] = {a, b}; + return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE size_t _BLI_string_join_5(_BLI_STRING_ARGS_3) +{ + const char *string_array[] = {a, b, c}; + return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE size_t _BLI_string_join_6(_BLI_STRING_ARGS_4) +{ + const char *string_array[] = {a, b, c, d}; + return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE size_t _BLI_string_join_7(_BLI_STRING_ARGS_5) +{ + const char *string_array[] = {a, b, c, d, e}; + return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE size_t _BLI_string_join_8(_BLI_STRING_ARGS_6) +{ + const char *string_array[] = {a, b, c, d, e, f}; + return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE size_t _BLI_string_join_9(_BLI_STRING_ARGS_7) +{ + const char *string_array[] = {a, b, c, d, e, f, g}; + return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE size_t _BLI_string_join_10(_BLI_STRING_ARGS_8) +{ + const char *string_array[] = {a, b, c, d, e, f, g, h}; + return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE size_t _BLI_string_join_11(_BLI_STRING_ARGS_9) +{ + const char *string_array[] = {a, b, c, d, e, f, g, h, i}; + return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE size_t _BLI_string_join_12(_BLI_STRING_ARGS_10) +{ + const char *string_array[] = {a, b, c, d, e, f, g, h, i, j}; + return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array)); +} + +#undef _BLI_STRING_ARGS_0 + +/** \} */ + +/* ------------------------------------------------------------------------- */ +/** \name Implement: `BLI_string_joinN(..)` + * \{ */ + +/** + * Join an array of strings into a newly allocated, null terminated string. + */ +char *BLI_string_join_arrayN(const char *strings[], uint strings_len) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); + +#define BLI_string_joinN(...) VA_NARGS_CALL_OVERLOAD(_BLI_string_joinN_, __VA_ARGS__) + +#define _BLI_STRING_ARGS_0 + +BLI_INLINE char *_BLI_string_joinN_1(_BLI_STRING_ARGS_1) ATTR_NONNULL(); +BLI_INLINE char *_BLI_string_joinN_2(_BLI_STRING_ARGS_2) ATTR_NONNULL(); +BLI_INLINE char *_BLI_string_joinN_3(_BLI_STRING_ARGS_3) ATTR_NONNULL(); +BLI_INLINE char *_BLI_string_joinN_4(_BLI_STRING_ARGS_4) ATTR_NONNULL(); +BLI_INLINE char *_BLI_string_joinN_5(_BLI_STRING_ARGS_5) ATTR_NONNULL(); +BLI_INLINE char *_BLI_string_joinN_6(_BLI_STRING_ARGS_6) ATTR_NONNULL(); +BLI_INLINE char *_BLI_string_joinN_7(_BLI_STRING_ARGS_7) ATTR_NONNULL(); +BLI_INLINE char *_BLI_string_joinN_8(_BLI_STRING_ARGS_8) ATTR_NONNULL(); +BLI_INLINE char *_BLI_string_joinN_9(_BLI_STRING_ARGS_9) ATTR_NONNULL(); +BLI_INLINE char *_BLI_string_joinN_10(_BLI_STRING_ARGS_10) ATTR_NONNULL(); + +BLI_INLINE char *_BLI_string_joinN_1(_BLI_STRING_ARGS_1) +{ + const char *string_array[] = {a}; + return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE char *_BLI_string_joinN_2(_BLI_STRING_ARGS_2) +{ + const char *string_array[] = {a, b}; + return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE char *_BLI_string_joinN_3(_BLI_STRING_ARGS_3) +{ + const char *string_array[] = {a, b, c}; + return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE char *_BLI_string_joinN_4(_BLI_STRING_ARGS_4) +{ + const char *string_array[] = {a, b, c, d}; + return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE char *_BLI_string_joinN_5(_BLI_STRING_ARGS_5) +{ + const char *string_array[] = {a, b, c, d, e}; + return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE char *_BLI_string_joinN_6(_BLI_STRING_ARGS_6) +{ + const char *string_array[] = {a, b, c, d, e, f}; + return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE char *_BLI_string_joinN_7(_BLI_STRING_ARGS_7) +{ + const char *string_array[] = {a, b, c, d, e, f, g}; + return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE char *_BLI_string_joinN_8(_BLI_STRING_ARGS_8) +{ + const char *string_array[] = {a, b, c, d, e, f, g, h}; + return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE char *_BLI_string_joinN_9(_BLI_STRING_ARGS_9) +{ + const char *string_array[] = {a, b, c, d, e, f, g, h, i}; + return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE char *_BLI_string_joinN_10(_BLI_STRING_ARGS_10) +{ + const char *string_array[] = {a, b, c, d, e, f, g, h, i, j}; + return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array)); +} + +#undef _BLI_STRING_ARGS_0 + +/** \} */ + +/* ------------------------------------------------------------------------- */ +/** \name Implement: `BLI_string_join_by_sep_char(..)` + * \{ */ + +/** + * A version of #BLI_string_join_array that takes a separator which can be any character + * including '\0'. + */ +size_t BLI_string_join_array_by_sep_char(char *result, + size_t result_len, + char sep, + const char *strings[], + uint strings_len) ATTR_NONNULL(); + +#define BLI_string_join_by_sep_char(...) \ + VA_NARGS_CALL_OVERLOAD(_BLI_string_join_by_sep_char_, __VA_ARGS__) + +#define _BLI_STRING_ARGS_0 char *__restrict dst, const size_t dst_len, const char sep, + +BLI_INLINE size_t _BLI_string_join_by_sep_char_4(_BLI_STRING_ARGS_1) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_string_join_by_sep_char_5(_BLI_STRING_ARGS_2) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_string_join_by_sep_char_6(_BLI_STRING_ARGS_3) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_string_join_by_sep_char_7(_BLI_STRING_ARGS_4) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_string_join_by_sep_char_8(_BLI_STRING_ARGS_5) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_string_join_by_sep_char_9(_BLI_STRING_ARGS_6) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_string_join_by_sep_char_10(_BLI_STRING_ARGS_7) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_string_join_by_sep_char_11(_BLI_STRING_ARGS_8) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_string_join_by_sep_char_12(_BLI_STRING_ARGS_9) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_string_join_by_sep_char_13(_BLI_STRING_ARGS_10) ATTR_NONNULL(); + +BLI_INLINE size_t _BLI_string_join_by_sep_char_4(_BLI_STRING_ARGS_1) +{ + const char *string_array[] = {a}; + return BLI_string_join_array_by_sep_char( + dst, dst_len, sep, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE size_t _BLI_string_join_by_sep_char_5(_BLI_STRING_ARGS_2) +{ + const char *string_array[] = {a, b}; + return BLI_string_join_array_by_sep_char( + dst, dst_len, sep, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE size_t _BLI_string_join_by_sep_char_6(_BLI_STRING_ARGS_3) +{ + const char *string_array[] = {a, b, c}; + return BLI_string_join_array_by_sep_char( + dst, dst_len, sep, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE size_t _BLI_string_join_by_sep_char_7(_BLI_STRING_ARGS_4) +{ + const char *string_array[] = {a, b, c, d}; + return BLI_string_join_array_by_sep_char( + dst, dst_len, sep, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE size_t _BLI_string_join_by_sep_char_8(_BLI_STRING_ARGS_5) +{ + const char *string_array[] = {a, b, c, d, e}; + return BLI_string_join_array_by_sep_char( + dst, dst_len, sep, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE size_t _BLI_string_join_by_sep_char_9(_BLI_STRING_ARGS_6) +{ + const char *string_array[] = {a, b, c, d, e, f}; + return BLI_string_join_array_by_sep_char( + dst, dst_len, sep, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE size_t _BLI_string_join_by_sep_char_10(_BLI_STRING_ARGS_7) +{ + const char *string_array[] = {a, b, c, d, e, f, g}; + return BLI_string_join_array_by_sep_char( + dst, dst_len, sep, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE size_t _BLI_string_join_by_sep_char_11(_BLI_STRING_ARGS_8) +{ + const char *string_array[] = {a, b, c, d, e, f, g, h}; + return BLI_string_join_array_by_sep_char( + dst, dst_len, sep, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE size_t _BLI_string_join_by_sep_char_12(_BLI_STRING_ARGS_9) +{ + const char *string_array[] = {a, b, c, d, e, f, g, h, i}; + return BLI_string_join_array_by_sep_char( + dst, dst_len, sep, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE size_t _BLI_string_join_by_sep_char_13(_BLI_STRING_ARGS_10) +{ + const char *string_array[] = {a, b, c, d, e, f, g, h, i, j}; + return BLI_string_join_array_by_sep_char( + dst, dst_len, sep, string_array, ARRAY_SIZE(string_array)); +} + +#undef _BLI_STRING_ARGS_0 + +/** \} */ + +/* ------------------------------------------------------------------------- */ +/** \name Implement: `BLI_string_join_by_sep_charN(..)` + * \{ */ + +/** + * A version of #BLI_string_join_by_sep_char that takes a separator which can be any character + * including '\0'. + */ +char *BLI_string_join_array_by_sep_charN(char sep, + const char *strings[], + uint strings_len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); + +#define BLI_string_join_by_sep_charN(...) \ + VA_NARGS_CALL_OVERLOAD(_BLI_string_join_by_sep_charN_, __VA_ARGS__) + +#define _BLI_STRING_ARGS_0 const char sep, + +BLI_INLINE char *_BLI_string_join_by_sep_charN_2(_BLI_STRING_ARGS_1) ATTR_NONNULL(); +BLI_INLINE char *_BLI_string_join_by_sep_charN_3(_BLI_STRING_ARGS_2) ATTR_NONNULL(); +BLI_INLINE char *_BLI_string_join_by_sep_charN_4(_BLI_STRING_ARGS_3) ATTR_NONNULL(); +BLI_INLINE char *_BLI_string_join_by_sep_charN_5(_BLI_STRING_ARGS_4) ATTR_NONNULL(); +BLI_INLINE char *_BLI_string_join_by_sep_charN_6(_BLI_STRING_ARGS_5) ATTR_NONNULL(); +BLI_INLINE char *_BLI_string_join_by_sep_charN_7(_BLI_STRING_ARGS_6) ATTR_NONNULL(); +BLI_INLINE char *_BLI_string_join_by_sep_charN_8(_BLI_STRING_ARGS_7) ATTR_NONNULL(); +BLI_INLINE char *_BLI_string_join_by_sep_charN_9(_BLI_STRING_ARGS_8) ATTR_NONNULL(); +BLI_INLINE char *_BLI_string_join_by_sep_charN_10(_BLI_STRING_ARGS_9) ATTR_NONNULL(); +BLI_INLINE char *_BLI_string_join_by_sep_charN_11(_BLI_STRING_ARGS_10) ATTR_NONNULL(); + +BLI_INLINE char *_BLI_string_join_by_sep_charN_2(_BLI_STRING_ARGS_1) +{ + const char *string_array[] = {a}; + return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE char *_BLI_string_join_by_sep_charN_3(_BLI_STRING_ARGS_2) +{ + const char *string_array[] = {a, b}; + return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE char *_BLI_string_join_by_sep_charN_4(_BLI_STRING_ARGS_3) +{ + const char *string_array[] = {a, b, c}; + return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE char *_BLI_string_join_by_sep_charN_5(_BLI_STRING_ARGS_4) +{ + const char *string_array[] = {a, b, c, d}; + return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE char *_BLI_string_join_by_sep_charN_6(_BLI_STRING_ARGS_5) +{ + const char *string_array[] = {a, b, c, d, e}; + return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE char *_BLI_string_join_by_sep_charN_7(_BLI_STRING_ARGS_6) +{ + const char *string_array[] = {a, b, c, d, e, f}; + return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE char *_BLI_string_join_by_sep_charN_8(_BLI_STRING_ARGS_7) +{ + const char *string_array[] = {a, b, c, d, e, f, g}; + return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE char *_BLI_string_join_by_sep_charN_9(_BLI_STRING_ARGS_8) +{ + const char *string_array[] = {a, b, c, d, e, f, g, h}; + return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE char *_BLI_string_join_by_sep_charN_10(_BLI_STRING_ARGS_9) +{ + const char *string_array[] = {a, b, c, d, e, f, g, h, i}; + return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array)); +} +BLI_INLINE char *_BLI_string_join_by_sep_charN_11(_BLI_STRING_ARGS_10) +{ + const char *string_array[] = {a, b, c, d, e, f, g, h, i, j}; + return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array)); +} + +/** \} */ + +#undef _BLI_STRING_ARGS_0 + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/intern/string_utils.c b/source/blender/blenlib/intern/string_utils.c index 0b9baaff3e9..27734d2f429 100644 --- a/source/blender/blenlib/intern/string_utils.c +++ b/source/blender/blenlib/intern/string_utils.c @@ -344,10 +344,10 @@ bool BLI_uniquename( * * \{ */ -char *BLI_string_join_array(char *result, - size_t result_len, - const char *strings[], - uint strings_len) +size_t BLI_string_join_array(char *result, + size_t result_len, + const char *strings[], + uint strings_len) { char *c = result; char *c_end = &result[result_len - 1]; @@ -358,10 +358,10 @@ char *BLI_string_join_array(char *result, } } *c = '\0'; - return c; + return (size_t)(c - result); } -char *BLI_string_join_array_by_sep_char( +size_t BLI_string_join_array_by_sep_char( char *result, size_t result_len, char sep, const char *strings[], uint strings_len) { char *c = result; @@ -378,7 +378,7 @@ char *BLI_string_join_array_by_sep_char( } } *c = '\0'; - return c; + return (size_t)(c - result); } char *BLI_string_join_arrayN(const char *strings[], uint strings_len) diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index a6916f9d031..3a2c62326de 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -890,8 +890,7 @@ static size_t draw_seq_text_get_overlay_string(const Scene *scene, BLI_assert(i <= ARRAY_SIZE(text_array)); - return BLI_string_join_array(r_overlay_string, overlay_string_len, text_array, i) - - r_overlay_string; + return BLI_string_join_array(r_overlay_string, overlay_string_len, text_array, i); } /* Draw info text on a sequence strip. */ -- cgit v1.2.3 From 50c72069b475a917769db077f39355755b4c0774 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 3 Nov 2022 14:35:32 +1100 Subject: Cleanup: replace BLI_join_path with BLI_join_string There is no need to use path joining logic here. --- source/blender/editors/space_file/filelist.cc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/space_file/filelist.cc b/source/blender/editors/space_file/filelist.cc index 3257534f94d..3870178f119 100644 --- a/source/blender/editors/space_file/filelist.cc +++ b/source/blender/editors/space_file/filelist.cc @@ -31,6 +31,7 @@ #include "BLI_linklist.h" #include "BLI_math.h" #include "BLI_stack.h" +#include "BLI_string_utils.h" #include "BLI_task.h" #include "BLI_threads.h" #include "BLI_utildefines.h" @@ -3542,9 +3543,10 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib, LISTBASE_FOREACH (FileListInternEntry *, entry, &entries) { entry->uid = filelist_uid_generate(filelist); - /* When loading entries recursive, the rel_path should be relative from the root dir. - * we combine the relative path to the subdir with the relative path of the entry. */ - BLI_path_join(dir, sizeof(dir), rel_subdir, entry->relpath); + /* When loading entries recursive, the `rel_path` should be relative from the root dir. + * we combine the relative path to the `subdir` with the relative path of the entry. + * Using #BLI_path_join works but isn't needed as `rel_subdir` has a trailing slash. */ + BLI_string_join(dir, sizeof(dir), rel_subdir, entry->relpath); MEM_freeN(entry->relpath); entry->relpath = BLI_strdup(dir + 2); /* + 2 to remove '//' * added by BLI_path_rel to rel_subdir. */ @@ -3553,8 +3555,9 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib, if (filelist_readjob_should_recurse_into_entry( max_recursion, is_lib, recursion_level, entry)) { - /* We have a directory we want to list, add it to todo list! */ - BLI_path_join(dir, sizeof(dir), root, entry->relpath); + /* We have a directory we want to list, add it to todo list! + * Using #BLI_path_join works but isn't needed as `root` has a trailing slash. */ + BLI_string_join(dir, sizeof(dir), root, entry->relpath); BLI_path_normalize_dir(job_params->main_name, dir, sizeof(dir)); td_dir = static_cast(BLI_stack_push_r(todo_dirs)); td_dir->level = recursion_level + 1; -- cgit v1.2.3 From 31d43cb0e7c5a4758e37823029978c43bf138fc1 Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Thu, 3 Nov 2022 00:32:06 -0400 Subject: Update RNA to User manual mappings --- release/scripts/modules/rna_manual_reference.py | 96 +++++++++++++++++++++---- 1 file changed, 81 insertions(+), 15 deletions(-) diff --git a/release/scripts/modules/rna_manual_reference.py b/release/scripts/modules/rna_manual_reference.py index 10925e78ef3..dfebf9132d2 100644 --- a/release/scripts/modules/rna_manual_reference.py +++ b/release/scripts/modules/rna_manual_reference.py @@ -58,6 +58,7 @@ url_manual_mapping = ( ("bpy.types.cyclesrendersettings.preview_denoising_input_passes*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-preview-denoising-input-passes"), ("bpy.types.cyclesrendersettings.preview_denoising_start_sample*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-preview-denoising-start-sample"), ("bpy.types.fluiddomainsettings.sndparticle_sampling_trappedair*", "physics/fluid/type/domain/liquid/particles.html#bpy-types-fluiddomainsettings-sndparticle-sampling-trappedair"), + ("bpy.types.brush.automasking_boundary_edges_propagation_steps*", "sculpt_paint/sculpting/controls.html#bpy-types-brush-automasking-boundary-edges-propagation-steps"), ("bpy.types.fluiddomainsettings.sndparticle_sampling_wavecrest*", "physics/fluid/type/domain/liquid/particles.html#bpy-types-fluiddomainsettings-sndparticle-sampling-wavecrest"), ("bpy.types.lineartgpencilmodifier.use_image_boundary_trimming*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-image-boundary-trimming"), ("bpy.types.materiallineart.use_intersection_priority_override*", "render/materials/line_art.html#bpy-types-materiallineart-use-intersection-priority-override"), @@ -179,6 +180,7 @@ url_manual_mapping = ( ("bpy.types.brushgpencilsettings.use_random_press_hue*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-use-random-press-hue"), ("bpy.types.brushgpencilsettings.use_random_press_sat*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-use-random-press-sat"), ("bpy.types.brushgpencilsettings.use_random_press_val*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-use-random-press-val"), + ("bpy.types.brushgpencilsettings.use_settings_outline*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-use-settings-outline"), ("bpy.types.brushgpencilsettings.use_stroke_random_uv*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-use-stroke-random-uv"), ("bpy.types.cyclesmaterialsettings.homogeneous_volume*", "render/cycles/material_settings.html#bpy-types-cyclesmaterialsettings-homogeneous-volume"), ("bpy.types.cyclesobjectsettings.is_caustics_receiver*", "render/cycles/object_settings/object_data.html#bpy-types-cyclesobjectsettings-is-caustics-receiver"), @@ -203,12 +205,14 @@ url_manual_mapping = ( ("bpy.types.materialgpencilstyle.use_fill_texture_mix*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-use-fill-texture-mix"), ("bpy.types.rendersettings_simplify_gpencil_shader_fx*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil-shader-fx"), ("bpy.types.rendersettings_simplify_gpencil_view_fill*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil-view-fill"), + ("bpy.types.sculpt.use_automasking_boundary_face_sets*", "sculpt_paint/sculpting/controls.html#bpy-types-sculpt-use-automasking-boundary-face-sets"), ("bpy.types.sequencertoolsettings.snap_to_hold_offset*", "video_editing/edit/montage/editing.html#bpy-types-sequencertoolsettings-snap-to-hold-offset"), ("bpy.types.toolsettings.use_mesh_automerge_and_split*", "modeling/meshes/tools/tool_settings.html#bpy-types-toolsettings-use-mesh-automerge-and-split"), ("bpy.ops.scene.view_layer_remove_unused_lightgroups*", "render/layers/passes.html#bpy-ops-scene-view-layer-remove-unused-lightgroups"), ("bpy.types.animvizmotionpaths.show_keyframe_numbers*", "animation/motion_paths.html#bpy-types-animvizmotionpaths-show-keyframe-numbers"), ("bpy.types.brush.cloth_constraint_softbody_strength*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-constraint-softbody-strength"), ("bpy.types.brush.elastic_deform_volume_preservation*", "sculpt_paint/sculpting/tools/elastic_deform.html#bpy-types-brush-elastic-deform-volume-preservation"), + ("bpy.types.brush.use_automasking_boundary_face_sets*", "sculpt_paint/sculpting/tool_settings/brush_settings.html#bpy-types-brush-use-automasking-boundary-face-sets"), ("bpy.types.brushcurvessculptsettings.minimum_length*", "sculpt_paint/curves_sculpting/tools/grow_shrink_curves.html#bpy-types-brushcurvessculptsettings-minimum-length"), ("bpy.types.brushgpencilsettings.fill_simplify_level*", "grease_pencil/modes/draw/tools/fill.html#bpy-types-brushgpencilsettings-fill-simplify-level"), ("bpy.types.brushgpencilsettings.random_value_factor*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-random-value-factor"), @@ -241,6 +245,7 @@ url_manual_mapping = ( ("bpy.types.spacespreadsheet.geometry_component_type*", "editors/spreadsheet.html#bpy-types-spacespreadsheet-geometry-component-type"), ("bpy.types.toolsettings.use_gpencil_weight_data_add*", "grease_pencil/modes/draw/introduction.html#bpy-types-toolsettings-use-gpencil-weight-data-add"), ("bpy.types.view3doverlay.texture_paint_mode_opacity*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-texture-paint-mode-opacity"), + ("bpy.ops.mesh.customdata_bevel_weight_vertex_clear*", "modeling/meshes/properties/custom_data.html#bpy-ops-mesh-customdata-bevel-weight-vertex-clear"), ("bpy.ops.mesh.customdata_custom_splitnormals_clear*", "modeling/meshes/properties/custom_data.html#bpy-ops-mesh-customdata-custom-splitnormals-clear"), ("bpy.types.bakesettings.use_pass_ambient_occlusion*", "render/cycles/baking.html#bpy-types-bakesettings-use-pass-ambient-occlusion"), ("bpy.types.brush.surface_smooth_shape_preservation*", "sculpt_paint/sculpting/tools/smooth.html#bpy-types-brush-surface-smooth-shape-preservation"), @@ -344,9 +349,12 @@ url_manual_mapping = ( ("bpy.types.toolsettings.use_snap_uv_grid_absolute*", "editors/uv/controls/snapping.html#bpy-types-toolsettings-use-snap-uv-grid-absolute"), ("bpy.types.toolsettings.use_transform_data_origin*", "scene_layout/object/tools/tool_settings.html#bpy-types-toolsettings-use-transform-data-origin"), ("bpy.types.view3doverlay.sculpt_mode_mask_opacity*", "sculpt_paint/sculpting/editing/mask.html#bpy-types-view3doverlay-sculpt-mode-mask-opacity"), + ("bpy.ops.mesh.customdata_bevel_weight_edge_clear*", "modeling/meshes/properties/custom_data.html#bpy-ops-mesh-customdata-bevel-weight-edge-clear"), + ("bpy.ops.mesh.customdata_bevel_weight_vertex_add*", "modeling/meshes/properties/custom_data.html#bpy-ops-mesh-customdata-bevel-weight-vertex-add"), ("bpy.ops.mesh.customdata_custom_splitnormals_add*", "modeling/meshes/properties/custom_data.html#bpy-ops-mesh-customdata-custom-splitnormals-add"), ("bpy.ops.outliner.collection_indirect_only_clear*", "render/layers/introduction.html#bpy-ops-outliner-collection-indirect-only-clear"), ("bpy.types.animvizmotionpaths.show_frame_numbers*", "animation/motion_paths.html#bpy-types-animvizmotionpaths-show-frame-numbers"), + ("bpy.types.brushgpencilsettings.fill_extend_mode*", "grease_pencil/modes/draw/tools/fill.html#bpy-types-brushgpencilsettings-fill-extend-mode"), ("bpy.types.brushgpencilsettings.pen_smooth_steps*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-pen-smooth-steps"), ("bpy.types.brushgpencilsettings.show_fill_extend*", "grease_pencil/modes/draw/tools/fill.html#bpy-types-brushgpencilsettings-show-fill-extend"), ("bpy.types.cycleslightsettings.is_caustics_light*", "render/cycles/light_settings.html#bpy-types-cycleslightsettings-is-caustics-light"), @@ -384,6 +392,7 @@ url_manual_mapping = ( ("bpy.types.movietrackingplanetrack.image_opacity*", "movie_clip/tracking/clip/sidebar/track/plane_track.html#bpy-types-movietrackingplanetrack-image-opacity"), ("bpy.types.particlesettings.use_parent_particles*", "physics/particles/emitter/render.html#bpy-types-particlesettings-use-parent-particles"), ("bpy.types.rigidbodyconstraint.solver_iterations*", "physics/rigid_body/constraints/introduction.html#bpy-types-rigidbodyconstraint-solver-iterations"), + ("bpy.types.sculpt.use_automasking_boundary_edges*", "sculpt_paint/sculpting/controls.html#bpy-types-sculpt-use-automasking-boundary-edges"), ("bpy.types.sequenceeditor.use_overlay_frame_lock*", "editors/video_sequencer/preview/sidebar.html#bpy-types-sequenceeditor-use-overlay-frame-lock"), ("bpy.types.sequencerpreviewoverlay.show_metadata*", "editors/video_sequencer/preview/display/overlays.html#bpy-types-sequencerpreviewoverlay-show-metadata"), ("bpy.types.sequencertimelineoverlay.show_fcurves*", "editors/video_sequencer/sequencer/display.html#bpy-types-sequencertimelineoverlay-show-fcurves"), @@ -398,6 +407,7 @@ url_manual_mapping = ( ("bpy.types.viewlayer.use_pass_cryptomatte_object*", "render/layers/passes.html#bpy-types-viewlayer-use-pass-cryptomatte-object"), ("bpy.ops.armature.rigify_apply_selection_colors*", "addons/rigging/rigify/metarigs.html#bpy-ops-armature-rigify-apply-selection-colors"), ("bpy.ops.ed.lib_id_generate_preview_from_object*", "editors/asset_browser.html#bpy-ops-ed-lib-id-generate-preview-from-object"), + ("bpy.types.brush.use_automasking_boundary_edges*", "sculpt_paint/sculpting/tool_settings/brush_settings.html#bpy-types-brush-use-automasking-boundary-edges"), ("bpy.types.brushcurvessculptsettings.add_amount*", "sculpt_paint/curves_sculpting/tools/add_curves.html#bpy-types-brushcurvessculptsettings-add-amount"), ("bpy.types.brushgpencilsettings.fill_layer_mode*", "grease_pencil/modes/draw/tools/fill.html#bpy-types-brushgpencilsettings-fill-layer-mode"), ("bpy.types.brushgpencilsettings.random_strength*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-random-strength"), @@ -444,6 +454,7 @@ url_manual_mapping = ( ("bpy.types.toolsettings.use_snap_align_rotation*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-align-rotation"), ("bpy.types.toolsettings.use_snap_to_same_target*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-to-same-target"), ("bpy.types.viewlayer.use_pass_cryptomatte_asset*", "render/layers/passes.html#bpy-types-viewlayer-use-pass-cryptomatte-asset"), + ("bpy.ops.mesh.customdata_bevel_weight_edge_add*", "modeling/meshes/properties/custom_data.html#bpy-ops-mesh-customdata-bevel-weight-edge-add"), ("bpy.ops.outliner.collection_indirect_only_set*", "render/layers/introduction.html#bpy-ops-outliner-collection-indirect-only-set"), ("bpy.ops.scene.freestyle_geometry_modifier_add*", "render/freestyle/view_layer/line_style/geometry.html#bpy-ops-scene-freestyle-geometry-modifier-add"), ("bpy.ops.scene.view_layer_add_used_lightgroups*", "render/layers/passes.html#bpy-ops-scene-view-layer-add-used-lightgroups"), @@ -574,6 +585,8 @@ url_manual_mapping = ( ("bpy.types.toolsettings.uv_sticky_select_mode*", "editors/uv/selecting.html#bpy-types-toolsettings-uv-sticky-select-mode"), ("bpy.types.volumedisplay.interpolation_method*", "modeling/volumes/properties.html#bpy-types-volumedisplay-interpolation-method"), ("bpy.ops.geometry.color_attribute_render_set*", "modeling/meshes/properties/object_data.html#bpy-ops-geometry-color-attribute-render-set"), + ("bpy.ops.mesh.customdata_crease_vertex_clear*", "modeling/meshes/properties/custom_data.html#bpy-ops-mesh-customdata-crease-vertex-clear"), + ("bpy.types.brush.html#bpy.types.brush.jitter*", "sculpt_paint/brush/stroke.html#bpy-types-brush-html-bpy-types-brush-jitter"), ("bpy.types.brushgpencilsettings.angle_factor*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-angle-factor"), ("bpy.types.brushgpencilsettings.pen_strength*", "grease_pencil/modes/draw/tools/erase.html#bpy-types-brushgpencilsettings-pen-strength"), ("bpy.types.clothsettings.use_pressure_volume*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-use-pressure-volume"), @@ -600,6 +613,7 @@ url_manual_mapping = ( ("bpy.types.geometrynodeinputmeshedgevertices*", "modeling/geometry_nodes/mesh/edge_vertices.html#bpy-types-geometrynodeinputmeshedgevertices"), ("bpy.types.geometrynodeinputmeshfaceisplanar*", "modeling/geometry_nodes/mesh/face_is_planar.html#bpy-types-geometrynodeinputmeshfaceisplanar"), ("bpy.types.geometrynodeinputsplineresolution*", "modeling/geometry_nodes/curve/spline_resolution.html#bpy-types-geometrynodeinputsplineresolution"), + ("bpy.types.geometrynodemeshfacesetboundaries*", "modeling/geometry_nodes/mesh/face_set_boundaries.html#bpy-types-geometrynodemeshfacesetboundaries"), ("bpy.types.greasepencil.curve_edit_threshold*", "grease_pencil/modes/edit/curve_editing.html#bpy-types-greasepencil-curve-edit-threshold"), ("bpy.types.lineartgpencilmodifier.use_crease*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-crease"), ("bpy.types.lineartgpencilmodifier.use_shadow*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-shadow"), @@ -678,13 +692,13 @@ url_manual_mapping = ( ("bpy.types.lineartgpencilmodifier.use_cache*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-cache"), ("bpy.types.lineartgpencilmodifier.use_loose*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-loose"), ("bpy.types.materialgpencilstyle.show_stroke*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-show-stroke"), - ("bpy.types.mesh.use_customdata_vertex_bevel*", "modeling/meshes/properties/custom_data.html#bpy-types-mesh-use-customdata-vertex-bevel"), ("bpy.types.movietrackingcamera.focal_length*", "movie_clip/tracking/clip/sidebar/track/camera.html#bpy-types-movietrackingcamera-focal-length"), ("bpy.types.movietrackingcamera.pixel_aspect*", "movie_clip/tracking/clip/sidebar/track/camera.html#bpy-types-movietrackingcamera-pixel-aspect"), ("bpy.types.movietrackingcamera.sensor_width*", "movie_clip/tracking/clip/sidebar/track/camera.html#bpy-types-movietrackingcamera-sensor-width"), ("bpy.types.posebone.use_ik_rotation_control*", "animation/armatures/posing/bone_constraints/inverse_kinematics/introduction.html#bpy-types-posebone-use-ik-rotation-control"), ("bpy.types.rendersettings.use_bake_multires*", "render/cycles/baking.html#bpy-types-rendersettings-use-bake-multires"), ("bpy.types.scenegpencil.antialias_threshold*", "render/cycles/render_settings/grease_pencil.html#bpy-types-scenegpencil-antialias-threshold"), + ("bpy.types.sculpt.use_automasking_face_sets*", "sculpt_paint/sculpting/controls.html#bpy-types-sculpt-use-automasking-face-sets"), ("bpy.types.spaceclipeditor.show_mask_spline*", "editors/clip/display/mask_display.html#bpy-types-spaceclipeditor-show-mask-spline"), ("bpy.types.spaceclipeditor.show_red_channel*", "editors/clip/display/clip_display.html#bpy-types-spaceclipeditor-show-red-channel"), ("bpy.types.spaceclipeditor.use_mute_footage*", "editors/clip/display/clip_display.html#bpy-types-spaceclipeditor-use-mute-footage"), @@ -698,6 +712,8 @@ url_manual_mapping = ( ("bpy.ops.constraint.disable_keep_transform*", "animation/constraints/interface/common.html#bpy-ops-constraint-disable-keep-transform"), ("bpy.ops.curves.convert_to_particle_system*", "sculpt_paint/curves_sculpting/introduction.html#bpy-ops-curves-convert-to-particle-system"), ("bpy.ops.gpencil.stroke_reset_vertex_color*", "grease_pencil/modes/vertex_paint/editing.html#bpy-ops-gpencil-stroke-reset-vertex-color"), + ("bpy.ops.mesh.customdata_crease_edge_clear*", "modeling/meshes/properties/custom_data.html#bpy-ops-mesh-customdata-crease-edge-clear"), + ("bpy.ops.mesh.customdata_crease_vertex_add*", "modeling/meshes/properties/custom_data.html#bpy-ops-mesh-customdata-crease-vertex-add"), ("bpy.ops.object.modifier_apply_as_shapekey*", "modeling/modifiers/introduction.html#bpy-ops-object-modifier-apply-as-shapekey"), ("bpy.ops.object.vertex_group_normalize_all*", "sculpt_paint/weight_paint/editing.html#bpy-ops-object-vertex-group-normalize-all"), ("bpy.ops.outliner.collection_color_tag_set*", "editors/outliner/editing.html#bpy-ops-outliner-collection-color-tag-set"), @@ -709,6 +725,7 @@ url_manual_mapping = ( ("bpy.types.animvizmotionpaths.frame_before*", "animation/motion_paths.html#bpy-types-animvizmotionpaths-frame-before"), ("bpy.types.brush.disconnected_distance_max*", "sculpt_paint/sculpting/tools/pose.html#bpy-types-brush-disconnected-distance-max"), ("bpy.types.brush.surface_smooth_iterations*", "sculpt_paint/sculpting/tools/smooth.html#bpy-types-brush-surface-smooth-iterations"), + ("bpy.types.brush.use_automasking_face_sets*", "sculpt_paint/sculpting/tool_settings/brush_settings.html#bpy-types-brush-use-automasking-face-sets"), ("bpy.types.brushgpencilsettings.pen_jitter*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-pen-jitter"), ("bpy.types.brushgpencilsettings.show_lasso*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-show-lasso"), ("bpy.types.compositornodeconvertcolorspace*", "compositing/types/converter/color_space.html#bpy-types-compositornodeconvertcolorspace"), @@ -753,7 +770,6 @@ url_manual_mapping = ( ("bpy.types.materialgpencilstyle.fill_style*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-fill-style"), ("bpy.types.materialgpencilstyle.mix_factor*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-mix-factor"), ("bpy.types.materialgpencilstyle.pass_index*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-pass-index"), - ("bpy.types.mesh.use_customdata_edge_crease*", "modeling/meshes/properties/custom_data.html#bpy-types-mesh-use-customdata-edge-crease"), ("bpy.types.nodesocketinterface.description*", "interface/controls/nodes/groups.html#bpy-types-nodesocketinterface-description"), ("bpy.types.rendersettings.dither_intensity*", "render/output/properties/post_processing.html#bpy-types-rendersettings-dither-intensity"), ("bpy.types.rendersettings.film_transparent*", "render/cycles/render_settings/film.html#bpy-types-rendersettings-film-transparent"), @@ -761,6 +777,7 @@ url_manual_mapping = ( ("bpy.types.rendersettings.use_render_cache*", "render/output/properties/output.html#bpy-types-rendersettings-use-render-cache"), ("bpy.types.rendersettings.use_single_layer*", "render/layers/view_layer.html#bpy-types-rendersettings-use-single-layer"), ("bpy.types.sceneeevee.use_taa_reprojection*", "render/eevee/render_settings/sampling.html#bpy-types-sceneeevee-use-taa-reprojection"), + ("bpy.types.sculpt.use_automasking_topology*", "sculpt_paint/sculpting/controls.html#bpy-types-sculpt-use-automasking-topology"), ("bpy.types.spaceclipeditor.cursor_location*", "editors/clip/sidebar.html#bpy-types-spaceclipeditor-cursor-location"), ("bpy.types.spacefilebrowser.recent_folders*", "editors/file_browser.html#bpy-types-spacefilebrowser-recent-folders"), ("bpy.types.spacefilebrowser.system_folders*", "editors/file_browser.html#bpy-types-spacefilebrowser-system-folders"), @@ -789,10 +806,11 @@ url_manual_mapping = ( ("bpy.types.animvizmotionpaths.frame_start*", "animation/motion_paths.html#bpy-types-animvizmotionpaths-frame-start"), ("bpy.types.bakesettings.use_pass_indirect*", "render/cycles/baking.html#bpy-types-bakesettings-use-pass-indirect"), ("bpy.types.brush.cloth_force_falloff_type*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-force-falloff-type"), + ("bpy.types.brush.use_automasking_topology*", "sculpt_paint/sculpting/tool_settings/brush_settings.html#bpy-types-brush-use-automasking-topology"), ("bpy.types.brushgpencilsettings.caps_type*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-caps-type"), - ("bpy.types.brushgpencilsettings.fill_leak*", "grease_pencil/modes/draw/tools/fill.html#bpy-types-brushgpencilsettings-fill-leak"), ("bpy.types.brushgpencilsettings.show_fill*", "grease_pencil/modes/draw/tools/fill.html#bpy-types-brushgpencilsettings-show-fill"), ("bpy.types.brushgpencilsettings.uv_random*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-uv-random"), + ("bpy.types.brushtextureslot.mask_map_mode*", "sculpt_paint/brush/texture_mask.html#bpy-types-brushtextureslot-mask-map-mode"), ("bpy.types.clothsettings.internal_tension*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-internal-tension"), ("bpy.types.colormanagedviewsettings.gamma*", "render/color_management.html#bpy-types-colormanagedviewsettings-gamma"), ("bpy.types.compositornodeplanetrackdeform*", "compositing/types/distort/plane_track_deform.html#bpy-types-compositornodeplanetrackdeform"), @@ -801,7 +819,7 @@ url_manual_mapping = ( ("bpy.types.editbone.bbone_handle_type_end*", "animation/armatures/bones/properties/bendy_bones.html#bpy-types-editbone-bbone-handle-type-end"), ("bpy.types.editbone.use_endroll_as_inroll*", "animation/armatures/bones/properties/bendy_bones.html#bpy-types-editbone-use-endroll-as-inroll"), ("bpy.types.fieldsettings.guide_kink_shape*", "physics/forces/force_fields/types/curve_guide.html#bpy-types-fieldsettings-guide-kink-shape"), - ("bpy.types.fieldsettings.use_max_distance*", "physics/forces/force_fields/types/curve_guide.html#bpy-types-fieldsettings-use-max-distance"), + ("bpy.types.fieldsettings.use_max_distance*", "physics/forces/force_fields/introduction.html#bpy-types-fieldsettings-use-max-distance"), ("bpy.types.fieldsettings.use_min_distance*", "physics/forces/force_fields/introduction.html#bpy-types-fieldsettings-use-min-distance"), ("bpy.types.fileselectparams.filter_search*", "editors/file_browser.html#bpy-types-fileselectparams-filter-search"), ("bpy.types.fluiddomainsettings.cache_type*", "physics/fluid/type/domain/cache.html#bpy-types-fluiddomainsettings-cache-type"), @@ -837,7 +855,6 @@ url_manual_mapping = ( ("bpy.types.material.use_screen_refraction*", "render/eevee/materials/settings.html#bpy-types-material-use-screen-refraction"), ("bpy.types.materialgpencilstyle.mix_color*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-mix-color"), ("bpy.types.materialgpencilstyle.show_fill*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-show-fill"), - ("bpy.types.mesh.use_customdata_edge_bevel*", "modeling/meshes/properties/custom_data.html#bpy-types-mesh-use-customdata-edge-bevel"), ("bpy.types.mesh.use_mirror_vertex_group_x*", "sculpt_paint/weight_paint/tool_settings/symmetry.html#bpy-types-mesh-use-mirror-vertex-group-x"), ("bpy.types.movietrackingcamera.division_k*", "movie_clip/tracking/clip/sidebar/track/camera.html#bpy-types-movietrackingcamera-division-k"), ("bpy.types.movietrackingobject.keyframe_a*", "movie_clip/tracking/clip/toolbar/solve.html#bpy-types-movietrackingobject-keyframe-a"), @@ -858,6 +875,7 @@ url_manual_mapping = ( ("bpy.types.spaceoutliner.show_mode_column*", "editors/outliner/interface.html#bpy-types-spaceoutliner-show-mode-column"), ("bpy.types.spacesequenceeditor.show_gizmo*", "editors/video_sequencer/preview/display/gizmos.html#bpy-types-spacesequenceeditor-show-gizmo"), ("bpy.types.spacetexteditor.use_match_case*", "editors/text_editor.html#bpy-types-spacetexteditor-use-match-case"), + ("bpy.types.spaceuveditor.pixel_round_mode*", "modeling/meshes/uv/editing.html#bpy-types-spaceuveditor-pixel-round-mode"), ("bpy.types.spaceview3d.show_object_select*", "editors/3dview/display/visibility.html#bpy-types-spaceview3d-show-object-select"), ("bpy.types.toolsettings.use_lock_relative*", "sculpt_paint/weight_paint/tool_settings/options.html#bpy-types-toolsettings-use-lock-relative"), ("bpy.types.vertexpaint.use_group_restrict*", "sculpt_paint/weight_paint/tool_settings/options.html#bpy-types-vertexpaint-use-group-restrict"), @@ -865,6 +883,7 @@ url_manual_mapping = ( ("bpy.types.windowmanager.asset_path_dummy*", "editors/asset_browser.html#bpy-types-windowmanager-asset-path-dummy"), ("bpy.ops.armature.rigify_add_bone_groups*", "addons/rigging/rigify/metarigs.html#bpy-ops-armature-rigify-add-bone-groups"), ("bpy.ops.geometry.color_attribute_remove*", "modeling/meshes/properties/object_data.html#bpy-ops-geometry-color-attribute-remove"), + ("bpy.ops.mesh.customdata_crease_edge_add*", "modeling/meshes/properties/custom_data.html#bpy-ops-mesh-customdata-crease-edge-add"), ("bpy.ops.object.assign_property_defaults*", "animation/armatures/posing/editing/apply.html#bpy-ops-object-assign-property-defaults"), ("bpy.ops.object.vertex_group_limit_total*", "sculpt_paint/weight_paint/editing.html#bpy-ops-object-vertex-group-limit-total"), ("bpy.ops.object.vertex_group_remove_from*", "modeling/meshes/properties/vertex_groups/vertex_groups.html#bpy-ops-object-vertex-group-remove-from"), @@ -872,6 +891,7 @@ url_manual_mapping = ( ("bpy.ops.outliner.collection_hide_inside*", "editors/outliner/editing.html#bpy-ops-outliner-collection-hide-inside"), ("bpy.ops.outliner.collection_holdout_set*", "render/layers/introduction.html#bpy-ops-outliner-collection-holdout-set"), ("bpy.ops.outliner.collection_show_inside*", "editors/outliner/editing.html#bpy-ops-outliner-collection-show-inside"), + ("bpy.ops.poselib.pose_asset_select_bones*", "animation/armatures/posing/editing/pose_library.html#bpy-ops-poselib-pose-asset-select-bones"), ("bpy.ops.poselib.restore_previous_action*", "animation/armatures/posing/editing/pose_library.html#bpy-ops-poselib-restore-previous-action"), ("bpy.ops.preferences.reset_default_theme*", "editors/preferences/themes.html#bpy-ops-preferences-reset-default-theme"), ("bpy.ops.scene.view_layer_add_lightgroup*", "render/layers/passes.html#bpy-ops-scene-view-layer-add-lightgroup"), @@ -885,6 +905,7 @@ url_manual_mapping = ( ("bpy.types.brush.multiplane_scrape_angle*", "sculpt_paint/sculpting/tools/multiplane_scrape.html#bpy-types-brush-multiplane-scrape-angle"), ("bpy.types.brushgpencilsettings.hardness*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-hardness"), ("bpy.types.brushgpencilsettings.use_trim*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-use-trim"), + ("bpy.types.brushtextureslot.random_angle*", "sculpt_paint/brush/texture.html#bpy-types-brushtextureslot-random-angle"), ("bpy.types.clothsettings.internal_spring*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-internal-spring"), ("bpy.types.clothsettings.pressure_factor*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-pressure-factor"), ("bpy.types.colormanagedviewsettings.look*", "render/color_management.html#bpy-types-colormanagedviewsettings-look"), @@ -920,6 +941,7 @@ url_manual_mapping = ( ("bpy.types.geometrynodeinputsplinecyclic*", "modeling/geometry_nodes/curve/is_spline_cyclic.html#bpy-types-geometrynodeinputsplinecyclic"), ("bpy.types.geometrynodeinstancestopoints*", "modeling/geometry_nodes/instances/instances_to_points.html#bpy-types-geometrynodeinstancestopoints"), ("bpy.types.gpencillayer.viewlayer_render*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-viewlayer-render"), + ("bpy.types.imagepaint.use_normal_falloff*", "sculpt_paint/brush/falloff.html#bpy-types-imagepaint-use-normal-falloff"), ("bpy.types.layercollection.hide_viewport*", "editors/outliner/interface.html#bpy-types-layercollection-hide-viewport"), ("bpy.types.layercollection.indirect_only*", "editors/outliner/interface.html#bpy-types-layercollection-indirect-only"), ("bpy.types.material.use_backface_culling*", "render/eevee/materials/settings.html#bpy-types-material-use-backface-culling"), @@ -941,7 +963,6 @@ url_manual_mapping = ( ("bpy.types.spacesequenceeditor.view_type*", "editors/video_sequencer/introduction.html#bpy-types-spacesequenceeditor-view-type"), ("bpy.types.spacetexteditor.margin_column*", "editors/text_editor.html#bpy-types-spacetexteditor-margin-column"), ("bpy.types.spacetexteditor.use_find_wrap*", "editors/text_editor.html#bpy-types-spacetexteditor-use-find-wrap"), - ("bpy.types.spaceuveditor.pixel_snap_mode*", "modeling/meshes/uv/editing.html#bpy-types-spaceuveditor-pixel-snap-mode"), ("bpy.types.spaceuveditor.tile_grid_shape*", "editors/uv/overlays.html#bpy-types-spaceuveditor-tile-grid-shape"), ("bpy.types.spaceuveditor.use_custom_grid*", "editors/uv/overlays.html#bpy-types-spaceuveditor-use-custom-grid"), ("bpy.types.spaceuveditor.use_live_unwrap*", "modeling/meshes/uv/editing.html#bpy-types-spaceuveditor-use-live-unwrap"), @@ -955,7 +976,9 @@ url_manual_mapping = ( ("bpy.types.vertexweightproximitymodifier*", "modeling/modifiers/modify/weight_proximity.html#bpy-types-vertexweightproximitymodifier"), ("bpy.types.view3doverlay.show_wireframes*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-show-wireframes"), ("bpy.types.view3dshading.background_type*", "editors/3dview/display/shading.html#bpy-types-view3dshading-background-type"), + ("bpy.types.windowmanager.poselib_flipped*", "animation/armatures/posing/editing/pose_library.html#bpy-types-windowmanager-poselib-flipped"), ("bpy.types.workspace.use_filter_by_owner*", "interface/window_system/workspaces.html#bpy-types-workspace-use-filter-by-owner"), + ("bpy.ops.brush.stencil_fit_image_aspect*", "sculpt_paint/brush/texture.html#bpy-ops-brush-stencil-fit-image-aspect"), ("bpy.ops.gpencil.image_to_grease_pencil*", "editors/image/editing.html#bpy-ops-gpencil-image-to-grease-pencil"), ("bpy.ops.mesh.vertices_smooth_laplacian*", "modeling/meshes/editing/vertex/laplacian_smooth.html#bpy-ops-mesh-vertices-smooth-laplacian"), ("bpy.ops.object.multires_rebuild_subdiv*", "modeling/modifiers/generate/multiresolution.html#bpy-ops-object-multires-rebuild-subdiv"), @@ -1033,6 +1056,7 @@ url_manual_mapping = ( ("bpy.types.volumedisplay.wireframe_type*", "modeling/volumes/properties.html#bpy-types-volumedisplay-wireframe-type"), ("bpy.ops.anim.channels_editable_toggle*", "editors/graph_editor/channels.html#bpy-ops-anim-channels-editable-toggle"), ("bpy.ops.anim.channels_setting_disable*", "editors/graph_editor/channels.html#bpy-ops-anim-channels-setting-disable"), + ("bpy.ops.brush.stencil_reset_transform*", "sculpt_paint/brush/texture.html#bpy-ops-brush-stencil-reset-transform"), ("bpy.ops.curve.normals_make_consistent*", "modeling/curves/editing/control_points.html#bpy-ops-curve-normals-make-consistent"), ("bpy.ops.curves.snap_curves_to_surface*", "sculpt_paint/curves_sculpting/introduction.html#bpy-ops-curves-snap-curves-to-surface"), ("bpy.ops.ed.lib_id_load_custom_preview*", "editors/asset_browser.html#bpy-ops-ed-lib-id-load-custom-preview"), @@ -1061,9 +1085,11 @@ url_manual_mapping = ( ("bpy.types.brush.boundary_falloff_type*", "sculpt_paint/sculpting/tools/boundary.html#bpy-types-brush-boundary-falloff-type"), ("bpy.types.brush.cursor_color_subtract*", "sculpt_paint/brush/cursor.html#bpy-types-brush-cursor-color-subtract"), ("bpy.types.brush.texture_overlay_alpha*", "sculpt_paint/brush/cursor.html#bpy-types-brush-texture-overlay-alpha"), + ("bpy.types.brush.use_space_attenuation*", "sculpt_paint/brush/stroke.html#bpy-types-brush-use-space-attenuation"), ("bpy.types.brushgpencilsettings.aspect*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-aspect"), ("bpy.types.brushgpencilsettings.dilate*", "grease_pencil/modes/draw/tools/fill.html#bpy-types-brushgpencilsettings-dilate"), ("bpy.types.brushgpencilsettings.random*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-random"), + ("bpy.types.brushtextureslot.use_random*", "sculpt_paint/brush/texture.html#bpy-types-brushtextureslot-use-random"), ("bpy.types.clothsettings.target_volume*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-target-volume"), ("bpy.types.colormanageddisplaysettings*", "render/color_management.html#bpy-types-colormanageddisplaysettings"), ("bpy.types.colorramp.hue_interpolation*", "interface/controls/templates/color_ramp.html#bpy-types-colorramp-hue-interpolation"), @@ -1076,7 +1102,7 @@ url_manual_mapping = ( ("bpy.types.editbone.use_local_location*", "animation/armatures/bones/properties/relations.html#bpy-types-editbone-use-local-location"), ("bpy.types.ffmpegsettings.audio_volume*", "render/output/properties/output.html#bpy-types-ffmpegsettings-audio-volume"), ("bpy.types.ffmpegsettings.max_b_frames*", "render/output/properties/output.html#bpy-types-ffmpegsettings-max-b-frames"), - ("bpy.types.fieldsettings.falloff_power*", "physics/forces/force_fields/types/curve_guide.html#bpy-types-fieldsettings-falloff-power"), + ("bpy.types.fieldsettings.falloff_power*", "physics/forces/force_fields/introduction.html#bpy-types-fieldsettings-falloff-power"), ("bpy.types.fieldsettings.guide_minimum*", "physics/forces/force_fields/types/curve_guide.html#bpy-types-fieldsettings-guide-minimum"), ("bpy.types.fileselectparams.use_filter*", "editors/file_browser.html#bpy-types-fileselectparams-use-filter"), ("bpy.types.fluiddomainsettings.gravity*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-gravity"), @@ -1140,6 +1166,7 @@ url_manual_mapping = ( ("bpy.ops.mesh.normals_make_consistent*", "modeling/meshes/editing/mesh/normals.html#bpy-ops-mesh-normals-make-consistent"), ("bpy.ops.mesh.offset_edge_loops_slide*", "modeling/meshes/editing/edge/offset_edge_slide.html#bpy-ops-mesh-offset-edge-loops-slide"), ("bpy.ops.mesh.primitive_uv_sphere_add*", "modeling/meshes/primitives.html#bpy-ops-mesh-primitive-uv-sphere-add"), + ("bpy.ops.object.curves_empty_hair_add*", "modeling/curves/primitives.html#bpy-ops-object-curves-empty-hair-add"), ("bpy.ops.object.duplicate_move_linked*", "scene_layout/object/editing/duplicate_linked.html#bpy-ops-object-duplicate-move-linked"), ("bpy.ops.object.make_override_library*", "files/linked_libraries/library_overrides.html#bpy-ops-object-make-override-library"), ("bpy.ops.object.parent_no_inverse_set*", "scene_layout/object/editing/parent.html#bpy-ops-object-parent-no-inverse-set"), @@ -1157,10 +1184,12 @@ url_manual_mapping = ( ("bpy.types.brush.boundary_deform_type*", "sculpt_paint/sculpting/tools/boundary.html#bpy-types-brush-boundary-deform-type"), ("bpy.types.brush.cursor_overlay_alpha*", "sculpt_paint/brush/cursor.html#bpy-types-brush-cursor-overlay-alpha"), ("bpy.types.brush.normal_radius_factor*", "sculpt_paint/sculpting/tool_settings/brush_settings.html#bpy-types-brush-normal-radius-factor"), - ("bpy.types.brush.smooth_stroke_factor*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brush-smooth-stroke-factor"), - ("bpy.types.brush.smooth_stroke_radius*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brush-smooth-stroke-radius"), + ("bpy.types.brush.smooth_stroke_factor*", "sculpt_paint/brush/stroke.html#bpy-types-brush-smooth-stroke-factor"), + ("bpy.types.brush.smooth_stroke_radius*", "sculpt_paint/brush/stroke.html#bpy-types-brush-smooth-stroke-radius"), ("bpy.types.brush.topology_rake_factor*", "sculpt_paint/sculpting/tool_settings/dyntopo.html#bpy-types-brush-topology-rake-factor"), ("bpy.types.brush.use_pose_ik_anchored*", "sculpt_paint/sculpting/tools/pose.html#bpy-types-brush-use-pose-ik-anchored"), + ("bpy.types.brush.use_pressure_masking*", "sculpt_paint/brush/texture_mask.html#bpy-types-brush-use-pressure-masking"), + ("bpy.types.brush.use_pressure_spacing*", "sculpt_paint/brush/stroke.html#bpy-types-brush-use-pressure-spacing"), ("bpy.types.brushgpencilsettings.angle*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-angle"), ("bpy.types.clothsettings.use_pressure*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-use-pressure"), ("bpy.types.compositornodeantialiasing*", "compositing/types/filter/anti_aliasing.html#bpy-types-compositornodeantialiasing"), @@ -1170,7 +1199,7 @@ url_manual_mapping = ( ("bpy.types.compositornodekeyingscreen*", "compositing/types/matte/keying_screen.html#bpy-types-compositornodekeyingscreen"), ("bpy.types.dynamicpaintcanvassettings*", "physics/dynamic_paint/canvas.html#bpy-types-dynamicpaintcanvassettings"), ("bpy.types.ffmpegsettings.audio_codec*", "render/output/properties/output.html#bpy-types-ffmpegsettings-audio-codec"), - ("bpy.types.fieldsettings.distance_max*", "physics/forces/force_fields/types/curve_guide.html#bpy-types-fieldsettings-distance-max"), + ("bpy.types.fieldsettings.distance_max*", "physics/forces/force_fields/introduction.html#bpy-types-fieldsettings-distance-max"), ("bpy.types.fieldsettings.distance_min*", "physics/forces/force_fields/introduction.html#bpy-types-fieldsettings-distance-min"), ("bpy.types.fieldsettings.falloff_type*", "physics/forces/force_fields/introduction.html#bpy-types-fieldsettings-falloff-type"), ("bpy.types.fileselectparams.directory*", "editors/file_browser.html#bpy-types-fileselectparams-directory"), @@ -1198,7 +1227,7 @@ url_manual_mapping = ( ("bpy.types.object.display_bounds_type*", "scene_layout/object/properties/display.html#bpy-types-object-display-bounds-type"), ("bpy.types.object.show_only_shape_key*", "animation/shape_keys/shape_keys_panel.html#bpy-types-object-show-only-shape-key"), ("bpy.types.regionview3d.lock_rotation*", "editors/3dview/navigate/views.html#bpy-types-regionview3d-lock-rotation"), - ("bpy.types.rendersettings.hair_subdiv*", "render/cycles/render_settings/hair.html#bpy-types-rendersettings-hair-subdiv"), + ("bpy.types.rendersettings.hair_subdiv*", "render/eevee/render_settings/hair.html#bpy-types-rendersettings-hair-subdiv"), ("bpy.types.scene.audio_distance_model*", "scene_layout/scene/properties.html#bpy-types-scene-audio-distance-model"), ("bpy.types.scene.audio_doppler_factor*", "scene_layout/scene/properties.html#bpy-types-scene-audio-doppler-factor"), ("bpy.types.sequencetransform.rotation*", "editors/video_sequencer/sequencer/sidebar/strip.html#bpy-types-sequencetransform-rotation"), @@ -1251,11 +1280,15 @@ url_manual_mapping = ( ("bpy.types.bakesettings.normal_space*", "render/cycles/baking.html#bpy-types-bakesettings-normal-space"), ("bpy.types.brush.crease_pinch_factor*", "sculpt_paint/sculpting/tools/snake_hook.html#bpy-types-brush-crease-pinch-factor"), ("bpy.types.brush.elastic_deform_type*", "sculpt_paint/sculpting/tools/elastic_deform.html#bpy-types-brush-elastic-deform-type"), + ("bpy.types.brush.texture_sample_bias*", "sculpt_paint/brush/texture.html#bpy-types-brush-texture-sample-bias"), ("bpy.types.brush.use_cloth_collision*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-use-cloth-collision"), ("bpy.types.brush.use_grab_silhouette*", "sculpt_paint/sculpting/tools/grab.html#bpy-types-brush-use-grab-silhouette"), + ("bpy.types.brush.use_original_normal*", "sculpt_paint/sculpting/tool_settings/brush_settings.html#bpy-types-brush-use-original-normal"), + ("bpy.types.brush.use_pressure_jitter*", "sculpt_paint/brush/stroke.html#bpy-types-brush-use-pressure-jitter"), ("bpy.types.brush.use_primary_overlay*", "sculpt_paint/brush/cursor.html#bpy-types-brush-use-primary-overlay"), ("bpy.types.brushcurvessculptsettings*", "sculpt_paint/curves_sculpting/index.html#bpy-types-brushcurvessculptsettings"), ("bpy.types.brushtextureslot.map_mode*", "sculpt_paint/brush/texture.html#bpy-types-brushtextureslot-map-mode"), + ("bpy.types.brushtextureslot.use_rake*", "sculpt_paint/brush/texture.html#bpy-types-brushtextureslot-use-rake"), ("bpy.types.camera.passepartout_alpha*", "render/cameras.html#bpy-types-camera-passepartout-alpha"), ("bpy.types.colorrampelement.position*", "interface/controls/templates/color_ramp.html#bpy-types-colorrampelement-position"), ("bpy.types.compositornodechromamatte*", "compositing/types/matte/chroma_key.html#bpy-types-compositornodechromamatte"), @@ -1370,6 +1403,7 @@ url_manual_mapping = ( ("bpy.types.brush.smooth_deform_type*", "sculpt_paint/sculpting/tools/smooth.html#bpy-types-brush-smooth-deform-type"), ("bpy.types.brush.use_connected_only*", "sculpt_paint/sculpting/tools/pose.html#bpy-types-brush-use-connected-only"), ("bpy.types.brush.use_cursor_overlay*", "sculpt_paint/brush/cursor.html#bpy-types-brush-use-cursor-overlay"), + ("bpy.types.brush.use_original_plane*", "sculpt_paint/sculpting/tool_settings/brush_settings.html#bpy-types-brush-use-original-plane"), ("bpy.types.camera.show_passepartout*", "render/cameras.html#bpy-types-camera-show-passepartout"), ("bpy.types.collection.lineart_usage*", "scene_layout/collections/collections.html#bpy-types-collection-lineart-usage"), ("bpy.types.colormanagedviewsettings*", "render/color_management.html#bpy-types-colormanagedviewsettings"), @@ -1440,6 +1474,7 @@ url_manual_mapping = ( ("bpy.types.transformcacheconstraint*", "animation/constraints/transform/transform_cache.html#bpy-types-transformcacheconstraint"), ("bpy.types.unitsettings.length_unit*", "scene_layout/scene/properties.html#bpy-types-unitsettings-length-unit"), ("bpy.types.vertexweighteditmodifier*", "modeling/modifiers/modify/weight_edit.html#bpy-types-vertexweighteditmodifier"), + ("bpy.types.view3dshading.color_type*", "render/workbench/color.html#bpy-types-view3dshading-color-type"), ("bpy.types.volumedisplay.slice_axis*", "modeling/volumes/properties.html#bpy-types-volumedisplay-slice-axis"), ("bpy.ops.action.markers_make_local*", "animation/markers.html#bpy-ops-action-markers-make-local"), ("bpy.ops.anim.channels_clean_empty*", "editors/nla/editing.html#bpy-ops-anim-channels-clean-empty"), @@ -1458,7 +1493,7 @@ url_manual_mapping = ( ("bpy.ops.mask.feather_weight_clear*", "movie_clip/masking/editing.html#bpy-ops-mask-feather-weight-clear"), ("bpy.ops.mask.primitive_circle_add*", "movie_clip/masking/scurve.html#bpy-ops-mask-primitive-circle-add"), ("bpy.ops.mask.primitive_square_add*", "movie_clip/masking/scurve.html#bpy-ops-mask-primitive-square-add"), - ("bpy.ops.mesh.dupli_extrude_cursor*", "modeling/meshes/tools/extrude_cursor.html#bpy-ops-mesh-dupli-extrude-cursor"), + ("bpy.ops.mesh.dupli_extrude_cursor*", "modeling/meshes/editing/vertex/extrude_cursor.html#bpy-ops-mesh-dupli-extrude-cursor"), ("bpy.ops.mesh.primitive_circle_add*", "modeling/meshes/primitives.html#bpy-ops-mesh-primitive-circle-add"), ("bpy.ops.mesh.primitive_monkey_add*", "modeling/meshes/primitives.html#bpy-ops-mesh-primitive-monkey-add"), ("bpy.ops.mesh.select_face_by_sides*", "modeling/meshes/selecting/all_by_trait.html#bpy-ops-mesh-select-face-by-sides"), @@ -1486,6 +1521,8 @@ url_manual_mapping = ( ("bpy.types.brush.cloth_deform_type*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-deform-type"), ("bpy.types.brush.cloth_sim_falloff*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-sim-falloff"), ("bpy.types.brush.slide_deform_type*", "sculpt_paint/sculpting/tools/slide_relax.html#bpy-types-brush-slide-deform-type"), + ("bpy.types.brush.use_scene_spacing*", "sculpt_paint/brush/stroke.html#bpy-types-brush-use-scene-spacing"), + ("bpy.types.brush.use_smooth_stroke*", "sculpt_paint/brush/stroke.html#bpy-types-brush-use-smooth-stroke"), ("bpy.types.camera.show_composition*", "render/cameras.html#bpy-types-camera-show-composition"), ("bpy.types.colorramp.interpolation*", "interface/controls/templates/color_ramp.html#bpy-types-colorramp-interpolation"), ("bpy.types.compositornodealphaover*", "compositing/types/color/alpha_over.html#bpy-types-compositornodealphaover"), @@ -1539,6 +1576,7 @@ url_manual_mapping = ( ("bpy.types.gpencilsculptguide.type*", "grease_pencil/modes/draw/guides.html#bpy-types-gpencilsculptguide-type"), ("bpy.types.greasepencil.onion_mode*", "grease_pencil/properties/onion_skinning.html#bpy-types-greasepencil-onion-mode"), ("bpy.types.greasepencilgrid.offset*", "grease_pencil/properties/display.html#bpy-types-greasepencilgrid-offset"), + ("bpy.types.imagepaint.normal_angle*", "sculpt_paint/brush/falloff.html#bpy-types-imagepaint-normal-angle"), ("bpy.types.laplaciandeformmodifier*", "modeling/modifiers/deform/laplacian_deform.html#bpy-types-laplaciandeformmodifier"), ("bpy.types.laplaciansmoothmodifier*", "modeling/modifiers/deform/laplacian_smooth.html#bpy-types-laplaciansmoothmodifier"), ("bpy.types.layercollection.exclude*", "editors/outliner/interface.html#bpy-types-layercollection-exclude"), @@ -1577,6 +1615,7 @@ url_manual_mapping = ( ("bpy.ops.constraint.move_to_index*", "animation/constraints/interface/header.html#bpy-ops-constraint-move-to-index"), ("bpy.ops.gpencil.frame_clean_fill*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-frame-clean-fill"), ("bpy.ops.gpencil.select_alternate*", "grease_pencil/selecting.html#bpy-ops-gpencil-select-alternate"), + ("bpy.ops.gpencil.stroke_start_set*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-start-set"), ("bpy.ops.gpencil.stroke_subdivide*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-subdivide"), ("bpy.ops.gpencil.vertex_color_hsv*", "grease_pencil/modes/vertex_paint/editing.html#bpy-ops-gpencil-vertex-color-hsv"), ("bpy.ops.gpencil.vertex_color_set*", "grease_pencil/modes/vertex_paint/editing.html#bpy-ops-gpencil-vertex-color-set"), @@ -1600,6 +1639,8 @@ url_manual_mapping = ( ("bpy.ops.outliner.collection_hide*", "editors/outliner/editing.html#bpy-ops-outliner-collection-hide"), ("bpy.ops.outliner.collection_show*", "editors/outliner/editing.html#bpy-ops-outliner-collection-show"), ("bpy.ops.paint.mask_lasso_gesture*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-paint-mask-lasso-gesture"), + ("bpy.ops.poselib.apply_pose_asset*", "animation/armatures/posing/editing/pose_library.html#bpy-ops-poselib-apply-pose-asset"), + ("bpy.ops.poselib.blend_pose_asset*", "animation/armatures/posing/editing/pose_library.html#bpy-ops-poselib-blend-pose-asset"), ("bpy.ops.rigidbody.mass_calculate*", "scene_layout/object/editing/rigid_body.html#bpy-ops-rigidbody-mass-calculate"), ("bpy.ops.screen.spacedata_cleanup*", "advanced/operators.html#bpy-ops-screen-spacedata-cleanup"), ("bpy.ops.sculpt.detail_flood_fill*", "sculpt_paint/sculpting/tool_settings/dyntopo.html#bpy-ops-sculpt-detail-flood-fill"), @@ -1620,6 +1661,8 @@ url_manual_mapping = ( ("bpy.types.brush.pose_deform_type*", "sculpt_paint/sculpting/tools/pose.html#bpy-types-brush-pose-deform-type"), ("bpy.types.brush.pose_ik_segments*", "sculpt_paint/sculpting/tools/pose.html#bpy-types-brush-pose-ik-segments"), ("bpy.types.brush.pose_origin_type*", "sculpt_paint/sculpting/tools/pose.html#bpy-types-brush-pose-origin-type"), + ("bpy.types.brush.use_edge_to_edge*", "sculpt_paint/brush/stroke.html#bpy-types-brush-use-edge-to-edge"), + ("bpy.types.brushtextureslot.angle*", "sculpt_paint/brush/texture.html#bpy-types-brushtextureslot-angle"), ("bpy.types.camerasolverconstraint*", "animation/constraints/motion_tracking/camera_solver.html#bpy-types-camerasolverconstraint"), ("bpy.types.clothcollisionsettings*", "physics/cloth/settings/collisions.html#bpy-types-clothcollisionsettings"), ("bpy.types.collection.hide_select*", "editors/outliner/interface.html#bpy-types-collection-hide-select"), @@ -1681,6 +1724,7 @@ url_manual_mapping = ( ("bpy.types.object.visible_diffuse*", "render/cycles/object_settings/object_data.html#bpy-types-object-visible-diffuse"), ("bpy.types.objectsolverconstraint*", "animation/constraints/motion_tracking/object_solver.html#bpy-types-objectsolverconstraint"), ("bpy.types.opacitygpencilmodifier*", "grease_pencil/modifiers/color/opacity.html#bpy-types-opacitygpencilmodifier"), + ("bpy.types.outlinegpencilmodifier*", "grease_pencil/modifiers/generate/outline.html#bpy-types-outlinegpencilmodifier"), ("bpy.types.particlesystemmodifier*", "physics/particles/index.html#bpy-types-particlesystemmodifier"), ("bpy.types.rendersettings.threads*", "render/cycles/render_settings/performance.html#bpy-types-rendersettings-threads"), ("bpy.types.scenedisplay.render_aa*", "render/workbench/sampling.html#bpy-types-scenedisplay-render-aa"), @@ -1752,6 +1796,7 @@ url_manual_mapping = ( ("bpy.ops.outliner.show_one_level*", "editors/outliner/editing.html#bpy-ops-outliner-show-one-level"), ("bpy.ops.paint.brush_colors_flip*", "sculpt_paint/texture_paint/tool_settings/brush_settings.html#bpy-ops-paint-brush-colors-flip"), ("bpy.ops.paint.weight_from_bones*", "sculpt_paint/weight_paint/editing.html#bpy-ops-paint-weight-from-bones"), + ("bpy.ops.paintcurve.delete_point*", "sculpt_paint/brush/stroke.html#bpy-ops-paintcurve-delete-point"), ("bpy.ops.pose.paths_range_update*", "animation/motion_paths.html#bpy-ops-pose-paths-range-update"), ("bpy.ops.poselib.action_sanitize*", "animation/armatures/properties/pose_library.html#bpy-ops-poselib-action-sanitize"), ("bpy.ops.preferences.studiolight*", "editors/preferences/lights.html#bpy-ops-preferences-studiolight"), @@ -1791,7 +1836,7 @@ url_manual_mapping = ( ("bpy.types.compositornodevecblur*", "compositing/types/filter/vector_blur.html#bpy-types-compositornodevecblur"), ("bpy.types.curve.use_fill_deform*", "modeling/curves/properties/shape.html#bpy-types-curve-use-fill-deform"), ("bpy.types.curve.use_path_follow*", "modeling/curves/properties/path_animation.html#bpy-types-curve-use-path-follow"), - ("bpy.types.curves.surface_uv_map*", "sculpt_paint/curves_sculpting/introduction.html#bpy-types-curves-surface-uv-map"), + ("bpy.types.curves.surface_uv_map*", "modeling/curves/primitives.html#bpy-types-curves-surface-uv-map"), ("bpy.types.dampedtrackconstraint*", "animation/constraints/tracking/damped_track.html#bpy-types-dampedtrackconstraint"), ("bpy.types.distortednoisetexture*", "render/materials/legacy_textures/types/distorted_noise.html#bpy-types-distortednoisetexture"), ("bpy.types.dopesheet.filter_text*", "editors/graph_editor/channels.html#bpy-types-dopesheet-filter-text"), @@ -1862,6 +1907,7 @@ url_manual_mapping = ( ("bpy.ops.gpencil.duplicate_move*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-duplicate-move"), ("bpy.ops.gpencil.select_grouped*", "grease_pencil/selecting.html#bpy-ops-gpencil-select-grouped"), ("bpy.ops.gpencil.stroke_arrange*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-arrange"), + ("bpy.ops.gpencil.stroke_outline*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-outline"), ("bpy.ops.graph.blend_to_default*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-blend-to-default"), ("bpy.ops.graph.equalize_handles*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-equalize-handles"), ("bpy.ops.mball.delete_metaelems*", "modeling/metas/editing.html#bpy-ops-mball-delete-metaelems"), @@ -2041,7 +2087,9 @@ url_manual_mapping = ( ("bpy.types.bakesettings.margin*", "render/cycles/baking.html#bpy-types-bakesettings-margin"), ("bpy.types.bakesettings.target*", "render/cycles/baking.html#bpy-types-bakesettings-target"), ("bpy.types.brush.cloth_damping*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-damping"), + ("bpy.types.brush.falloff_shape*", "sculpt_paint/brush/falloff.html#bpy-types-brush-falloff-shape"), ("bpy.types.brush.icon_filepath*", "sculpt_paint/brush/brush.html#bpy-types-brush-icon-filepath"), + ("bpy.types.brush.stroke_method*", "sculpt_paint/brush/stroke.html#bpy-types-brush-stroke-method"), ("bpy.types.brush.tip_roundness*", "sculpt_paint/sculpting/tools/clay_strips.html#bpy-types-brush-tip-roundness"), ("bpy.types.camera.display_size*", "render/cameras.html#bpy-types-camera-display-size"), ("bpy.types.camera.sensor_width*", "render/cameras.html#bpy-types-camera-sensor-width"), @@ -2074,6 +2122,7 @@ url_manual_mapping = ( ("bpy.types.mesh.use_paint_mask*", "sculpt_paint/brush/introduction.html#bpy-types-mesh-use-paint-mask"), ("bpy.types.object.display_type*", "scene_layout/object/properties/display.html#bpy-types-object-display-type"), ("bpy.types.objectlineart.usage*", "scene_layout/object/properties/line_art.html#bpy-types-objectlineart-usage"), + ("bpy.types.paint.input_samples*", "sculpt_paint/brush/stroke.html#bpy-types-paint-input-samples"), ("bpy.types.particledupliweight*", "physics/particles/emitter/vertex_groups.html#bpy-types-particledupliweight"), ("bpy.types.posebone.bone_group*", "animation/armatures/bones/properties/relations.html#bpy-types-posebone-bone-group"), ("bpy.types.poseboneconstraints*", "animation/armatures/posing/bone_constraints/index.html#bpy-types-poseboneconstraints"), @@ -2109,6 +2158,7 @@ url_manual_mapping = ( ("bpy.types.transformconstraint*", "animation/constraints/transform/transformation.html#bpy-types-transformconstraint"), ("bpy.types.triangulatemodifier*", "modeling/modifiers/generate/triangulate.html#bpy-types-triangulatemodifier"), ("bpy.types.unitsettings.system*", "scene_layout/scene/properties.html#bpy-types-unitsettings-system"), + ("bpy.types.view3dshading.light*", "render/workbench/lighting.html#bpy-types-view3dshading-light"), ("bpy.types.viewlayer.use_solid*", "render/layers/introduction.html#bpy-types-viewlayer-use-solid"), ("bpy.types.volume.frame_offset*", "modeling/volumes/properties.html#bpy-types-volume-frame-offset"), ("bpy.types.windowmanager.addon*", "editors/preferences/addons.html#bpy-types-windowmanager-addon"), @@ -2184,6 +2234,8 @@ url_manual_mapping = ( ("bpy.types.animvizmotionpaths*", "animation/motion_paths.html#bpy-types-animvizmotionpaths"), ("bpy.types.armature.show_axes*", "animation/armatures/properties/display.html#bpy-types-armature-show-axes"), ("bpy.types.armatureconstraint*", "animation/constraints/relationship/armature.html#bpy-types-armatureconstraint"), + ("bpy.types.brush.dash_samples*", "sculpt_paint/brush/stroke.html#bpy-types-brush-dash-samples"), + ("bpy.types.brush.sculpt_plane*", "sculpt_paint/sculpting/tool_settings/brush_settings.html#bpy-types-brush-sculpt-plane"), ("bpy.types.compositornodeblur*", "compositing/types/filter/blur_node.html#bpy-types-compositornodeblur"), ("bpy.types.compositornodecrop*", "compositing/types/distort/crop.html#bpy-types-compositornodecrop"), ("bpy.types.compositornodeflip*", "compositing/types/distort/flip.html#bpy-types-compositornodeflip"), @@ -2242,6 +2294,7 @@ url_manual_mapping = ( ("bpy.types.texturenodechecker*", "editors/texture_node/types/patterns/checker.html#bpy-types-texturenodechecker"), ("bpy.types.texturenodetexture*", "editors/texture_node/types/input/texture.html#bpy-types-texturenodetexture"), ("bpy.types.texturenodetexwood*", "editors/texture_node/types/textures/wood.html#bpy-types-texturenodetexwood"), + ("bpy.types.textureslot.offset*", "sculpt_paint/brush/texture.html#bpy-types-textureslot-offset"), ("bpy.types.view3dshading.type*", "editors/3dview/display/shading.html#bpy-types-view3dshading-type"), ("bpy.types.volume.frame_start*", "modeling/volumes/properties.html#bpy-types-volume-frame-start"), ("bpy.types.volume.is_sequence*", "modeling/volumes/properties.html#bpy-types-volume-is-sequence"), @@ -2320,6 +2373,7 @@ url_manual_mapping = ( ("bpy.types.action.use_cyclic*", "animation/actions.html#bpy-types-action-use-cyclic"), ("bpy.types.alphaoversequence*", "video_editing/edit/montage/strips/effects/alpha_over_under_overdrop.html#bpy-types-alphaoversequence"), ("bpy.types.armatureeditbones*", "animation/armatures/bones/editing/index.html#bpy-types-armatureeditbones"), + ("bpy.types.brush.jitter_unit*", "sculpt_paint/brush/stroke.html#bpy-types-brush-jitter-unit"), ("bpy.types.brush.pose_offset*", "sculpt_paint/sculpting/tools/pose.html#bpy-types-brush-pose-offset"), ("bpy.types.brush.rake_factor*", "sculpt_paint/sculpting/tools/snake_hook.html#bpy-types-brush-rake-factor"), ("bpy.types.camera.sensor_fit*", "render/cameras.html#bpy-types-camera-sensor-fit"), @@ -2374,6 +2428,7 @@ url_manual_mapping = ( ("bpy.types.texturenodeoutput*", "editors/texture_node/types/output/output.html#bpy-types-texturenodeoutput"), ("bpy.types.texturenoderotate*", "editors/texture_node/types/distort/rotate.html#bpy-types-texturenoderotate"), ("bpy.types.texturenodeviewer*", "editors/texture_node/types/output/viewer.html#bpy-types-texturenodeviewer"), + ("bpy.types.textureslot.scale*", "sculpt_paint/brush/texture.html#bpy-types-textureslot-scale"), ("bpy.types.tracktoconstraint*", "animation/constraints/tracking/track_to.html#bpy-types-tracktoconstraint"), ("bpy.types.transformsequence*", "video_editing/edit/montage/strips/effects/transform.html#bpy-types-transformsequence"), ("bpy.types.uvprojectmodifier*", "modeling/modifiers/modify/uv_project.html#bpy-types-uvprojectmodifier"), @@ -2383,6 +2438,7 @@ url_manual_mapping = ( ("bpy.types.worldmistsettings*", "render/cycles/world_settings.html#bpy-types-worldmistsettings"), ("bpy.ops.anim.channels_move*", "editors/graph_editor/channels.html#bpy-ops-anim-channels-move"), ("bpy.ops.armature.subdivide*", "animation/armatures/bones/editing/subdivide.html#bpy-ops-armature-subdivide"), + ("bpy.ops.brush.curve_preset*", "sculpt_paint/brush/falloff.html#bpy-ops-brush-curve-preset"), ("bpy.ops.buttons.toggle_pin*", "editors/properties_editor.html#bpy-ops-buttons-toggle-pin"), ("bpy.ops.clip.delete_marker*", "movie_clip/tracking/clip/editing/track.html#bpy-ops-clip-delete-marker"), ("bpy.ops.clip.filter_tracks*", "movie_clip/tracking/clip/editing/track.html#bpy-ops-clip-filter-tracks"), @@ -2444,6 +2500,7 @@ url_manual_mapping = ( ("bpy.types.bone.head_radius*", "animation/armatures/bones/properties/deform.html#bpy-types-bone-head-radius"), ("bpy.types.bone.tail_radius*", "animation/armatures/bones/properties/deform.html#bpy-types-bone-tail-radius"), ("bpy.types.brush.cloth_mass*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-mass"), + ("bpy.types.brush.dash_ratio*", "sculpt_paint/brush/stroke.html#bpy-types-brush-dash-ratio"), ("bpy.types.brushtextureslot*", "sculpt_paint/brush/texture.html#bpy-types-brushtextureslot"), ("bpy.types.colormixsequence*", "video_editing/edit/montage/strips/effects/color_mix.html#bpy-types-colormixsequence"), ("bpy.types.curve.dimensions*", "modeling/curves/properties/shape.html#bpy-types-curve-dimensions"), @@ -2541,6 +2598,7 @@ url_manual_mapping = ( ("bpy.ops.object.pointcloud*", "modeling/point_cloud.html#bpy-ops-object-pointcloud"), ("bpy.ops.object.select_all*", "scene_layout/object/selecting.html#bpy-ops-object-select-all"), ("bpy.ops.object.shade_flat*", "scene_layout/object/editing/shading.html#bpy-ops-object-shade-flat"), + ("bpy.ops.paintcurve.select*", "sculpt_paint/brush/stroke.html#bpy-ops-paintcurve-select"), ("bpy.ops.pose.group_assign*", "animation/armatures/properties/bone_groups.html#bpy-ops-pose-group-assign"), ("bpy.ops.pose.group_select*", "animation/armatures/properties/bone_groups.html#bpy-ops-pose-group-select"), ("bpy.ops.pose.paths_update*", "animation/motion_paths.html#bpy-ops-pose-paths-update"), @@ -2552,6 +2610,7 @@ url_manual_mapping = ( ("bpy.ops.screen.area_split*", "interface/window_system/areas.html#bpy-ops-screen-area-split"), ("bpy.ops.screen.screenshot*", "interface/window_system/topbar.html#bpy-ops-screen-screenshot"), ("bpy.ops.sculpt.dirty_mask*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-sculpt-dirty-mask"), + ("bpy.ops.sculpt.reveal_all*", "sculpt_paint/sculpting/editing/face_sets.html#bpy-ops-sculpt-reveal-all"), ("bpy.ops.sculpt.symmetrize*", "sculpt_paint/sculpting/tool_settings/symmetry.html#bpy-ops-sculpt-symmetrize"), ("bpy.ops.uv.remove_doubles*", "modeling/meshes/uv/editing.html#bpy-ops-uv-remove-doubles"), ("bpy.ops.uv.select_similar*", "editors/uv/selecting.html#bpy-ops-uv-select-similar"), @@ -2655,7 +2714,7 @@ url_manual_mapping = ( ("bpy.ops.wm.save_mainfile*", "files/blend/open_save.html#bpy-ops-wm-save-mainfile"), ("bpy.types.bone.show_wire*", "animation/armatures/bones/properties/display.html#bpy-types-bone-show-wire"), ("bpy.types.brush.hardness*", "sculpt_paint/sculpting/tool_settings/brush_settings.html#bpy-types-brush-hardness"), - ("bpy.types.curves.surface*", "sculpt_paint/curves_sculpting/introduction.html#bpy-types-curves-surface"), + ("bpy.types.curves.surface*", "modeling/curves/primitives.html#bpy-types-curves-surface"), ("bpy.types.curvesmodifier*", "editors/video_sequencer/sequencer/sidebar/modifiers.html#bpy-types-curvesmodifier"), ("bpy.types.ffmpegsettings*", "render/output/properties/output.html#bpy-types-ffmpegsettings"), ("bpy.types.fmodifiernoise*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifiernoise"), @@ -2725,13 +2784,13 @@ url_manual_mapping = ( ("bpy.ops.object.face_map*", "modeling/meshes/properties/object_data.html#bpy-ops-object-face-map"), ("bpy.ops.object.join_uvs*", "scene_layout/object/editing/link_transfer/copy_uvmaps.html#bpy-ops-object-join-uvs"), ("bpy.ops.outliner.delete*", "editors/outliner/editing.html#bpy-ops-outliner-delete"), + ("bpy.ops.paintcurve.draw*", "sculpt_paint/brush/stroke.html#bpy-ops-paintcurve-draw"), ("bpy.ops.pose.relax_rest*", "animation/armatures/posing/editing/in_betweens.html#bpy-ops-pose-relax-rest"), ("bpy.ops.pose.select_all*", "animation/armatures/posing/selecting.html#bpy-ops-pose-select-all"), ("bpy.ops.rigidbody.world*", "physics/rigid_body/world.html#bpy-ops-rigidbody-world"), ("bpy.ops.sculpt.optimize*", "sculpt_paint/sculpting/editing/sculpt.html#bpy-ops-sculpt-optimize"), ("bpy.ops.sequencer.split*", "video_editing/edit/montage/editing.html#bpy-ops-sequencer-split"), ("bpy.ops.transform.shear*", "modeling/meshes/editing/mesh/transform/shear.html#bpy-ops-transform-shear"), - ("bpy.ops.ui.eyedropper_**", "interface/controls/buttons/eyedropper.html#bpy-ops-ui-eyedropper"), ("bpy.ops.uv.cube_project*", "modeling/meshes/editing/uv.html#bpy-ops-uv-cube-project"), ("bpy.ops.uv.pack_islands*", "modeling/meshes/uv/editing.html#bpy-ops-uv-pack-islands"), ("bpy.ops.uv.select_split*", "modeling/meshes/uv/editing.html#bpy-ops-uv-select-split"), @@ -2743,12 +2802,14 @@ url_manual_mapping = ( ("bpy.ops.wm.batch_rename*", "files/blend/rename.html#bpy-ops-wm-batch-rename"), ("bpy.ops.wm.owner_enable*", "interface/window_system/workspaces.html#bpy-ops-wm-owner-enable"), ("bpy.ops.wm.redraw_timer*", "advanced/operators.html#bpy-ops-wm-redraw-timer"), + ("bpy.ops.wm.splash_about*", "interface/window_system/topbar.html#bpy-ops-wm-splash-about"), ("bpy.types.*light.shadow*", "render/eevee/lighting.html#bpy-types-light-shadow"), ("bpy.types.armature.show*", "animation/armatures/properties/display.html#bpy-types-armature-show"), ("bpy.types.armaturebones*", "animation/armatures/bones/index.html#bpy-types-armaturebones"), ("bpy.types.arraymodifier*", "modeling/modifiers/generate/array.html#bpy-types-arraymodifier"), ("bpy.types.assetmetadata*", "editors/asset_browser.html#bpy-types-assetmetadata"), ("bpy.types.bevelmodifier*", "modeling/modifiers/generate/bevel.html#bpy-types-bevelmodifier"), + ("bpy.types.brush.spacing*", "sculpt_paint/brush/stroke.html#bpy-types-brush-spacing"), ("bpy.types.buildmodifier*", "modeling/modifiers/generate/build.html#bpy-types-buildmodifier"), ("bpy.types.clothmodifier*", "physics/cloth/index.html#bpy-types-clothmodifier"), ("bpy.types.clothsettings*", "physics/cloth/settings/index.html#bpy-types-clothsettings"), @@ -2783,6 +2844,7 @@ url_manual_mapping = ( ("bpy.types.sequence.name*", "editors/video_sequencer/sequencer/sidebar/strip.html#bpy-types-sequence-name"), ("bpy.types.sequenceproxy*", "editors/video_sequencer/sequencer/sidebar/proxy.html#bpy-types-sequenceproxy"), ("bpy.types.shaderfxswirl*", "grease_pencil/visual_effects/swirl.html#bpy-types-shaderfxswirl"), + ("bpy.types.shadernodemix*", "render/shader_nodes/converter/mix.html#bpy-types-shadernodemix"), ("bpy.types.shadernodergb*", "render/shader_nodes/input/rgb.html#bpy-types-shadernodergb"), ("bpy.types.shapekey.mute*", "animation/shape_keys/shape_keys_panel.html#bpy-types-shapekey-mute"), ("bpy.types.soundsequence*", "video_editing/edit/montage/strips/sound.html#bpy-types-soundsequence"), @@ -2821,6 +2883,7 @@ url_manual_mapping = ( ("bpy.ops.object.convert*", "scene_layout/object/editing/convert.html#bpy-ops-object-convert"), ("bpy.ops.object.gpencil*", "grease_pencil/index.html#bpy-ops-object-gpencil"), ("bpy.ops.object.speaker*", "render/output/audio/speaker.html#bpy-ops-object-speaker"), + ("bpy.ops.paintcurve.new*", "sculpt_paint/brush/stroke.html#bpy-ops-paintcurve-new"), ("bpy.ops.pose.breakdown*", "animation/armatures/posing/editing/in_betweens.html#bpy-ops-pose-breakdown"), ("bpy.ops.pose.loc_clear*", "animation/armatures/posing/editing/clear.html#bpy-ops-pose-loc-clear"), ("bpy.ops.pose.propagate*", "animation/armatures/posing/editing/propagate.html#bpy-ops-pose-propagate"), @@ -2902,6 +2965,7 @@ url_manual_mapping = ( ("bpy.ops.script.reload*", "advanced/operators.html#bpy-ops-script-reload"), ("bpy.ops.sculpt.expand*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-sculpt-expand"), ("bpy.ops.sculpt_curves*", "sculpt_paint/curves_sculpting/index.html#bpy-ops-sculpt-curves"), + ("bpy.ops.ui.eyedropper*", "interface/controls/buttons/eyedropper.html#bpy-ops-ui-eyedropper"), ("bpy.ops.view3d.select*", "editors/3dview/selecting.html#bpy-ops-view3d-select"), ("bpy.ops.wm.debug_menu*", "advanced/operators.html#bpy-ops-wm-debug-menu"), ("bpy.ops.wm.obj_export*", "files/import_export/obj.html#bpy-ops-wm-obj-export"), @@ -2911,6 +2975,7 @@ url_manual_mapping = ( ("bpy.ops.wm.usd_export*", "files/import_export/usd.html#bpy-ops-wm-usd-export"), ("bpy.types.addsequence*", "video_editing/edit/montage/strips/effects/add.html#bpy-types-addsequence"), ("bpy.types.brush.cloth*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth"), + ("bpy.types.brush.curve*", "sculpt_paint/brush/falloff.html#bpy-types-brush-curve"), ("bpy.types.camera.show*", "render/cameras.html#bpy-types-camera-show"), ("bpy.types.consoleline*", "editors/python_console.html#bpy-types-consoleline"), ("bpy.types.curve.bevel*", "modeling/curves/properties/geometry.html#bpy-types-curve-bevel"), @@ -2960,6 +3025,7 @@ url_manual_mapping = ( ("bpy.types.areaspaces*", "interface/window_system/areas.html#bpy-types-areaspaces"), ("bpy.types.bonegroups*", "animation/armatures/properties/bone_groups.html#bpy-types-bonegroups"), ("bpy.types.bpy_struct*", "files/data_blocks.html#bpy-types-bpy-struct"), + ("bpy.types.brush.rate*", "sculpt_paint/brush/stroke.html#bpy-types-brush-rate"), ("bpy.types.collection*", "scene_layout/collections/collections.html#bpy-types-collection"), ("bpy.types.compositor*", "compositing/index.html#bpy-types-compositor"), ("bpy.types.constraint*", "animation/constraints/index.html#bpy-types-constraint"), -- cgit v1.2.3 From 65e4d169baa95e5f2dfbd65e5b4e995851a857df Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 3 Nov 2022 15:28:01 +1100 Subject: BLI_path: skip "/./" and "/." in BLI_path_name_at_index This avoids having to run BLI_path_normalize before calling BLI_path_name_at_index. --- source/blender/blenlib/BLI_path_util.h | 5 +- source/blender/blenlib/intern/path_util.c | 72 ++++++++++++++-------- source/blender/blenlib/tests/BLI_path_util_test.cc | 58 +++++++++++++++++ 3 files changed, 108 insertions(+), 27 deletions(-) diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 1b723ab038d..4ea059391b6 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -202,7 +202,10 @@ const char *BLI_path_basename(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_ * - 1 or -2: `path` * - 2 or -1: `file.txt` * - * Ignores multiple slashes at any point in the path (including start/end). + * Ignored elements in the path: + * - Multiple slashes at any point in the path (including start/end). + * - Single '.' in the path: `/./` except for the beginning of the path + * where it's used to signify a $PWD relative path. */ bool BLI_path_name_at_index(const char *__restrict path, int index, diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 3a87b39a446..179a1a305d1 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1597,39 +1597,47 @@ const char *BLI_path_basename(const char *path) return filename ? filename + 1 : path; } -bool BLI_path_name_at_index(const char *__restrict path, - const int index, - int *__restrict r_offset, - int *__restrict r_len) +static bool path_name_at_index_forward(const char *__restrict path, + const int index, + int *__restrict r_offset, + int *__restrict r_len) { - if (index >= 0) { - int index_step = 0; - int prev = -1; - int i = 0; - while (true) { - const char c = path[i]; - if (ELEM(c, SEP, '\0')) { - if (prev + 1 != i) { - prev += 1; + BLI_assert(index >= 0); + int index_step = 0; + int prev = -1; + int i = 0; + while (true) { + const char c = path[i]; + if (ELEM(c, SEP, '\0')) { + if (prev + 1 != i) { + prev += 1; + /* Skip '/./' (behave as if they don't exist). */ + if (!((i - prev == 1) && (prev != 0) && (path[prev] == '.'))) { if (index_step == index) { *r_offset = prev; *r_len = i - prev; - // printf("!!! %d %d\n", start, end); return true; } index_step += 1; } - if (c == '\0') { - break; - } - prev = i; } - i += 1; + if (c == '\0') { + break; + } + prev = i; } - return false; + i += 1; } + return false; +} - /* negative number, reverse where -1 is the last element */ +static bool path_name_at_index_backward(const char *__restrict path, + const int index, + int *__restrict r_offset, + int *__restrict r_len) +{ + /* Negative number, reverse where -1 is the last element. */ + BLI_assert(index < 0); int index_step = -1; int prev = strlen(path); int i = prev - 1; @@ -1638,12 +1646,15 @@ bool BLI_path_name_at_index(const char *__restrict path, if (ELEM(c, SEP, '\0')) { if (prev - 1 != i) { i += 1; - if (index_step == index) { - *r_offset = i; - *r_len = prev - i; - return true; + /* Skip '/./' (behave as if they don't exist). */ + if (!((prev - i == 1) && (i != 0) && (path[i] == '.'))) { + if (index_step == index) { + *r_offset = i; + *r_len = prev - i; + return true; + } + index_step -= 1; } - index_step -= 1; } if (c == '\0') { break; @@ -1655,6 +1666,15 @@ bool BLI_path_name_at_index(const char *__restrict path, return false; } +bool BLI_path_name_at_index(const char *__restrict path, + const int index, + int *__restrict r_offset, + int *__restrict r_len) +{ + return (index >= 0) ? path_name_at_index_forward(path, index, r_offset, r_len) : + path_name_at_index_backward(path, index, r_offset, r_len); +} + bool BLI_path_contains(const char *container_path, const char *containee_path) { char container_native[PATH_MAX]; diff --git a/source/blender/blenlib/tests/BLI_path_util_test.cc b/source/blender/blenlib/tests/BLI_path_util_test.cc index 293d353efcc..9d5422d62ff 100644 --- a/source/blender/blenlib/tests/BLI_path_util_test.cc +++ b/source/blender/blenlib/tests/BLI_path_util_test.cc @@ -259,6 +259,64 @@ TEST(path_util, NameAtIndex_MiscNeg) AT_INDEX("/how/now/brown/cow/", 4, nullptr); } +#define TEST_STR "./a/./b/./c/." + +TEST(path_util, NameAtIndex_SingleDot) +{ + AT_INDEX(TEST_STR, 0, "."); + AT_INDEX(TEST_STR, 1, "a"); + AT_INDEX(TEST_STR, 2, "b"); + AT_INDEX(TEST_STR, 3, "c"); + AT_INDEX(TEST_STR, 4, nullptr); +} + +TEST(path_util, NameAtIndex_SingleDotNeg) +{ + AT_INDEX(TEST_STR, -5, nullptr); + AT_INDEX(TEST_STR, -4, "."); + AT_INDEX(TEST_STR, -3, "a"); + AT_INDEX(TEST_STR, -2, "b"); + AT_INDEX(TEST_STR, -1, "c"); +} + +#undef TEST_STR + +#define TEST_STR ".//a//.//b//.//c//.//" + +TEST(path_util, NameAtIndex_SingleDotDoubleSlash) +{ + AT_INDEX(TEST_STR, 0, "."); + AT_INDEX(TEST_STR, 1, "a"); + AT_INDEX(TEST_STR, 2, "b"); + AT_INDEX(TEST_STR, 3, "c"); + AT_INDEX(TEST_STR, 4, nullptr); +} + +TEST(path_util, NameAtIndex_SingleDotDoubleSlashNeg) +{ + AT_INDEX(TEST_STR, -5, nullptr); + AT_INDEX(TEST_STR, -4, "."); + AT_INDEX(TEST_STR, -3, "a"); + AT_INDEX(TEST_STR, -2, "b"); + AT_INDEX(TEST_STR, -1, "c"); +} + +#undef TEST_STR + +TEST(path_util, NameAtIndex_SingleDotSeries) +{ + AT_INDEX("abc/././/././xyz", 0, "abc"); + AT_INDEX("abc/././/././xyz", 1, "xyz"); + AT_INDEX("abc/././/././xyz", 2, nullptr); +} + +TEST(path_util, NameAtIndex_SingleDotSeriesNeg) +{ + AT_INDEX("abc/././/././xyz", -3, nullptr); + AT_INDEX("abc/././/././xyz", -2, "abc"); + AT_INDEX("abc/././/././xyz", -1, "xyz"); +} + TEST(path_util, NameAtIndex_MiscComplex) { AT_INDEX("how//now/brown/cow", 0, "how"); -- cgit v1.2.3 From d5ce854fb1c70febf49ebc1242c48dd1ffa3a4aa Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 3 Nov 2022 16:39:58 +1100 Subject: CMake: workaround unsupported cmake_path(IS_PREFIX ..) in v3.20 Add a macro that implements something similar to cmake_path's IS_PREFIX which isn't supported in older versions of CMake. This caused the build-bot to fail. --- build_files/cmake/macros.cmake | 19 +++++++++++++++++++ build_files/cmake/platform/platform_unix.cmake | 2 +- tests/CMakeLists.txt | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index d81767b4009..73883376060 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -57,6 +57,25 @@ macro(path_ensure_trailing_slash unset(_path_sep) endmacro() +# Our own version of `cmake_path(IS_PREFIX ..)`. +# This can be removed when 3.20 or greater is the minimum supported version. +macro(path_is_prefix + path_prefix path result_var + ) + # Remove when CMAKE version is bumped to "3.20" or greater. + # `cmake_path(IS_PREFIX ${path_prefix} ${path} NORMALIZE result_var)` + # Get the normalized paths (needed to remove `..`). + get_filename_component(_abs_prefix "${${path_prefix}}" ABSOLUTE) + get_filename_component(_abs_suffix "${${path}}" ABSOLUTE) + string(LENGTH "${_abs_prefix}" _len) + string(SUBSTRING "${_abs_suffix}" 0 "${_len}" _substr) + string(COMPARE EQUAL "${_abs_prefix}" "${_substr}" "${result_var}") + unset(_abs_prefix) + unset(_abs_suffix) + unset(_len) + unset(_substr) +endmacro() + # foo_bar.spam --> foo_barMySuffix.spam macro(file_suffix file_name_new file_name file_suffix diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake index 343ed6d8ef4..f1ce3221440 100644 --- a/build_files/cmake/platform/platform_unix.cmake +++ b/build_files/cmake/platform/platform_unix.cmake @@ -151,7 +151,7 @@ if(WITH_PYTHON) # Installing into `site-packages`, warn when installing into `./../lib/` # which script authors almost certainly don't want. if(EXISTS ${LIBDIR}) - cmake_path(IS_PREFIX LIBDIR "${PYTHON_SITE_PACKAGES}" NORMALIZE _is_prefix) + path_is_prefix(LIBDIR PYTHON_SITE_PACKAGES _is_prefix) if(_is_prefix) message(WARNING " Building Blender with the following configuration: diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c96c6f2988d..9f634af7143 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -36,7 +36,7 @@ set(TEST_PYTHON_EXE_EXTRA_ARGS) # Check if this a Blender managed Python installation, if so, don't add `*.pyc` files. if(LIBDIR) - cmake_path(IS_PREFIX LIBDIR "${TEST_PYTHON_EXE}" NORMALIZE _is_prefix) + path_is_prefix(LIBDIR TEST_PYTHON_EXE _is_prefix) if(_is_prefix) # Keep the Python in Blender's SVN LIBDIR pristine, to avoid conflicts on updating. set(TEST_PYTHON_EXE_EXTRA_ARGS "-B") -- cgit v1.2.3 From 666135c32af3032d1e6c62ee953d65f399da7d0f Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Thu, 3 Nov 2022 10:08:10 +0100 Subject: Blender 3.4 - Beta * BLENDER_VERSION_CYCLE set to beta * Update pipeline_config.yaml to point to 3.2 branches and svn tags * Update and uncomment BLENDER_VERSION in download.cmake --- build_files/build_environment/cmake/download.cmake | 2 +- build_files/config/pipeline_config.yaml | 18 +++++++++--------- source/blender/blenkernel/BKE_blender_version.h | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build_files/build_environment/cmake/download.cmake b/build_files/build_environment/cmake/download.cmake index 8d75f0ff0ed..5db1a4e56fa 100644 --- a/build_files/build_environment/cmake/download.cmake +++ b/build_files/build_environment/cmake/download.cmake @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-or-later ## Update and uncomment this in the release branch -# set(BLENDER_VERSION 3.1) +set(BLENDER_VERSION 3.4) function(download_source dep) set(TARGET_FILE ${${dep}_FILE}) diff --git a/build_files/config/pipeline_config.yaml b/build_files/config/pipeline_config.yaml index 3359f89c41e..7c8f15de777 100644 --- a/build_files/config/pipeline_config.yaml +++ b/build_files/config/pipeline_config.yaml @@ -5,38 +5,38 @@ update-code: git: submodules: - - branch: master + - branch: blender-v3.4-release commit_id: HEAD path: release/scripts/addons - - branch: master + - branch: blender-v3.4-release commit_id: HEAD path: release/scripts/addons_contrib - - branch: master + - branch: blender-v3.4-release commit_id: HEAD path: release/datafiles/locale - - branch: master + - branch: blender-v3.4-release commit_id: HEAD path: source/tools svn: libraries: darwin-arm64: - branch: trunk + branch: tags/blender-3.4-release commit_id: HEAD path: lib/darwin_arm64 darwin-x86_64: - branch: trunk + branch: tags/blender-3.4-release commit_id: HEAD path: lib/darwin linux-x86_64: - branch: trunk + branch: tags/blender-3.4-release commit_id: HEAD path: lib/linux_centos7_x86_64 windows-amd64: - branch: trunk + branch: tags/blender-3.4-release commit_id: HEAD path: lib/win64_vc15 tests: - branch: trunk + branch: tags/blender-3.4-release commit_id: HEAD path: lib/tests benchmarks: diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 1a642cf4eb3..a7150913290 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -21,7 +21,7 @@ extern "C" { /* Blender patch version for bugfix releases. */ #define BLENDER_VERSION_PATCH 0 /** Blender release cycle stage: alpha/beta/rc/release. */ -#define BLENDER_VERSION_CYCLE alpha +#define BLENDER_VERSION_CYCLE beta /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -- cgit v1.2.3 From ba8754cf1122d911dd804c330e1a9c423ba2c918 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Thu, 3 Nov 2022 10:11:13 +0100 Subject: Blender 3.5 Alpha: Start of new release cycle. --- doc/doxygen/Doxyfile | 2 +- source/blender/blenkernel/BKE_blender_version.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index 18c16a60993..e1d8ac39bcf 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = Blender # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = V3.4 +PROJECT_NUMBER = V3.5 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 1a642cf4eb3..4bffa5492b5 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -17,7 +17,7 @@ extern "C" { */ /* Blender major and minor version. */ -#define BLENDER_VERSION 304 +#define BLENDER_VERSION 305 /* Blender patch version for bugfix releases. */ #define BLENDER_VERSION_PATCH 0 /** Blender release cycle stage: alpha/beta/rc/release. */ @@ -25,7 +25,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 6 +#define BLENDER_FILE_SUBVERSION 0 /* 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 -- cgit v1.2.3 From a16dd407b3d3f830c40646fcda5ea5b89b3ad4ee Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Thu, 3 Nov 2022 10:12:46 +0100 Subject: Revert "Blender 3.4 - Beta" This reverts commit 666135c32af3032d1e6c62ee953d65f399da7d0f. --- build_files/build_environment/cmake/download.cmake | 2 +- build_files/config/pipeline_config.yaml | 18 +++++++++--------- source/blender/blenkernel/BKE_blender_version.h | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build_files/build_environment/cmake/download.cmake b/build_files/build_environment/cmake/download.cmake index 5db1a4e56fa..8d75f0ff0ed 100644 --- a/build_files/build_environment/cmake/download.cmake +++ b/build_files/build_environment/cmake/download.cmake @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-or-later ## Update and uncomment this in the release branch -set(BLENDER_VERSION 3.4) +# set(BLENDER_VERSION 3.1) function(download_source dep) set(TARGET_FILE ${${dep}_FILE}) diff --git a/build_files/config/pipeline_config.yaml b/build_files/config/pipeline_config.yaml index 7c8f15de777..3359f89c41e 100644 --- a/build_files/config/pipeline_config.yaml +++ b/build_files/config/pipeline_config.yaml @@ -5,38 +5,38 @@ update-code: git: submodules: - - branch: blender-v3.4-release + - branch: master commit_id: HEAD path: release/scripts/addons - - branch: blender-v3.4-release + - branch: master commit_id: HEAD path: release/scripts/addons_contrib - - branch: blender-v3.4-release + - branch: master commit_id: HEAD path: release/datafiles/locale - - branch: blender-v3.4-release + - branch: master commit_id: HEAD path: source/tools svn: libraries: darwin-arm64: - branch: tags/blender-3.4-release + branch: trunk commit_id: HEAD path: lib/darwin_arm64 darwin-x86_64: - branch: tags/blender-3.4-release + branch: trunk commit_id: HEAD path: lib/darwin linux-x86_64: - branch: tags/blender-3.4-release + branch: trunk commit_id: HEAD path: lib/linux_centos7_x86_64 windows-amd64: - branch: tags/blender-3.4-release + branch: trunk commit_id: HEAD path: lib/win64_vc15 tests: - branch: tags/blender-3.4-release + branch: trunk commit_id: HEAD path: lib/tests benchmarks: diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 82b75d5b598..4bffa5492b5 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -21,7 +21,7 @@ extern "C" { /* Blender patch version for bugfix releases. */ #define BLENDER_VERSION_PATCH 0 /** Blender release cycle stage: alpha/beta/rc/release. */ -#define BLENDER_VERSION_CYCLE beta +#define BLENDER_VERSION_CYCLE alpha /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -- cgit v1.2.3 From 09b9e1e95ee4a5cea5297d06af26385b73856aeb Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 3 Nov 2022 10:42:48 +0100 Subject: Fix T102225: Crash opening menus Seems to be introduced by 99e5024e97f. The crash is caused by the difference in the expected alignment of the `uiPopupMenu` which is 16 bytes and the actual alignment returned by the `MEM_mallocN()` which is 8 bytes due to the memory head. Now made it so that `MEM_new()` can be used for types with any alignment. Differential Revision: https://developer.blender.org/D16375 --- intern/guardedalloc/MEM_guardedalloc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h index fdd77fb9eef..5ae33343949 100644 --- a/intern/guardedalloc/MEM_guardedalloc.h +++ b/intern/guardedalloc/MEM_guardedalloc.h @@ -271,7 +271,7 @@ void MEM_use_guarded_allocator(void); template inline T *MEM_new(const char *allocation_name, Args &&...args) { - void *buffer = MEM_mallocN(sizeof(T), allocation_name); + void *buffer = MEM_mallocN_aligned(sizeof(T), alignof(T), allocation_name); return new (buffer) T(std::forward(args)...); } -- cgit v1.2.3 From 74c293863ded1c052601b4caed07efe3453d697d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 3 Nov 2022 15:08:46 +0100 Subject: Cycles: Remove use of sprintf() in MD5 code The new Xcode declares the `sprintf()` function deprecated and suggests to sue `snprintf()` as a safer alternative. This change actually moves away from any formatted printing and uses inlined byte-to-hex-string conversion which is also safe and is (unmesurably) faster. Differential Revision: https://developer.blender.org/D16378 --- intern/cycles/util/md5.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/intern/cycles/util/md5.cpp b/intern/cycles/util/md5.cpp index 1c7e6b9bf3e..3342d7a509a 100644 --- a/intern/cycles/util/md5.cpp +++ b/intern/cycles/util/md5.cpp @@ -347,13 +347,18 @@ void MD5Hash::finish(uint8_t digest[16]) string MD5Hash::get_hex() { + constexpr char kHexDigits[] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + uint8_t digest[16]; char buf[16 * 2 + 1]; finish(digest); - for (int i = 0; i < 16; i++) - sprintf(buf + i * 2, "%02X", (unsigned int)digest[i]); + for (int i = 0; i < 16; i++) { + buf[i * 2 + 0] = kHexDigits[digest[i] / 0x10]; + buf[i * 2 + 1] = kHexDigits[digest[i] % 0x10]; + } buf[sizeof(buf) - 1] = '\0'; return string(buf); -- cgit v1.2.3 From 41c692ee2f0f5a92d6162e65652e6f8d399df1a9 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 2 Nov 2022 16:12:48 +0100 Subject: Fix deprecation warnings in FFmpeg related code The non-deprecated API dates back to 2017, so it should be safe to simply migrate to it. Fixes verbose error prints, making it easier to see actual issues. Differential Revision: https://developer.blender.org/D16370 --- intern/ffmpeg/tests/ffmpeg_codecs.cc | 2 +- source/blender/blenkernel/intern/writeffmpeg.c | 34 +++++++++++++------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/intern/ffmpeg/tests/ffmpeg_codecs.cc b/intern/ffmpeg/tests/ffmpeg_codecs.cc index e5c33202417..10cbe4b938b 100644 --- a/intern/ffmpeg/tests/ffmpeg_codecs.cc +++ b/intern/ffmpeg/tests/ffmpeg_codecs.cc @@ -40,7 +40,7 @@ bool test_acodec(const AVCodec *codec, AVSampleFormat fmt) if (ctx) { ctx->sample_fmt = fmt; ctx->sample_rate = 48000; - ctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_from_mask(&ctx->ch_layout, AV_CH_LAYOUT_MONO); ctx->bit_rate = 128000; int open = avcodec_open2(ctx, codec, NULL); if (open >= 0) { diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index ee827cd8cd4..d71db8f71a5 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -141,19 +141,18 @@ static int write_audio_frame(FFMpegContext *context) frame->pts = context->audio_time / av_q2d(c->time_base); frame->nb_samples = context->audio_input_samples; frame->format = c->sample_fmt; - frame->channels = c->channels; - frame->channel_layout = c->channel_layout; + av_channel_layout_copy(&frame->ch_layout, &c->ch_layout); if (context->audio_deinterleave) { int channel, i; uint8_t *temp; - for (channel = 0; channel < c->channels; channel++) { + for (channel = 0; channel < c->ch_layout.nb_channels; channel++) { for (i = 0; i < frame->nb_samples; i++) { memcpy(context->audio_deinterleave_buffer + (i + channel * frame->nb_samples) * context->audio_sample_size, context->audio_input_buffer + - (c->channels * i + channel) * context->audio_sample_size, + (c->ch_layout.nb_channels * i + channel) * context->audio_sample_size, context->audio_sample_size); } } @@ -164,10 +163,11 @@ static int write_audio_frame(FFMpegContext *context) } avcodec_fill_audio_frame(frame, - c->channels, + c->ch_layout.nb_channels, c->sample_fmt, context->audio_input_buffer, - context->audio_input_samples * c->channels * context->audio_sample_size, + context->audio_input_samples * c->ch_layout.nb_channels * + context->audio_sample_size, 1); int success = 1; @@ -944,23 +944,23 @@ static AVStream *alloc_audio_stream(FFMpegContext *context, c->sample_rate = rd->ffcodecdata.audio_mixrate; c->bit_rate = context->ffmpeg_audio_bitrate * 1000; c->sample_fmt = AV_SAMPLE_FMT_S16; - c->channels = rd->ffcodecdata.audio_channels; + c->ch_layout.nb_channels = rd->ffcodecdata.audio_channels; switch (rd->ffcodecdata.audio_channels) { case FFM_CHANNELS_MONO: - c->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_from_mask(&c->ch_layout, AV_CH_LAYOUT_MONO); break; case FFM_CHANNELS_STEREO: - c->channel_layout = AV_CH_LAYOUT_STEREO; + av_channel_layout_from_mask(&c->ch_layout, AV_CH_LAYOUT_STEREO); break; case FFM_CHANNELS_SURROUND4: - c->channel_layout = AV_CH_LAYOUT_QUAD; + av_channel_layout_from_mask(&c->ch_layout, AV_CH_LAYOUT_QUAD); break; case FFM_CHANNELS_SURROUND51: - c->channel_layout = AV_CH_LAYOUT_5POINT1_BACK; + av_channel_layout_from_mask(&c->ch_layout, AV_CH_LAYOUT_5POINT1_BACK); break; case FFM_CHANNELS_SURROUND71: - c->channel_layout = AV_CH_LAYOUT_7POINT1; + av_channel_layout_from_mask(&c->ch_layout, AV_CH_LAYOUT_7POINT1); break; } @@ -1027,7 +1027,7 @@ static AVStream *alloc_audio_stream(FFMpegContext *context, * not sure if that is needed anymore, so let's try out if there are any * complaints regarding some FFmpeg versions users might have. */ context->audio_input_samples = AV_INPUT_BUFFER_MIN_SIZE * 8 / c->bits_per_coded_sample / - c->channels; + c->ch_layout.nb_channels; } else { context->audio_input_samples = c->frame_size; @@ -1037,11 +1037,11 @@ static AVStream *alloc_audio_stream(FFMpegContext *context, context->audio_sample_size = av_get_bytes_per_sample(c->sample_fmt); - context->audio_input_buffer = (uint8_t *)av_malloc(context->audio_input_samples * c->channels * - context->audio_sample_size); + context->audio_input_buffer = (uint8_t *)av_malloc( + context->audio_input_samples * c->ch_layout.nb_channels * context->audio_sample_size); if (context->audio_deinterleave) { context->audio_deinterleave_buffer = (uint8_t *)av_malloc( - context->audio_input_samples * c->channels * context->audio_sample_size); + context->audio_input_samples * c->ch_layout.nb_channels * context->audio_sample_size); } context->audio_time = 0.0f; @@ -1432,7 +1432,7 @@ int BKE_ffmpeg_start(void *context_v, AVCodecContext *c = context->audio_codec; AUD_DeviceSpecs specs; - specs.channels = c->channels; + specs.channels = c->ch_layout.nb_channels; switch (av_get_packed_sample_fmt(c->sample_fmt)) { case AV_SAMPLE_FMT_U8: -- cgit v1.2.3