Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Tönne <lukas.toenne@gmail.com>2021-08-25 09:55:50 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2021-08-25 09:55:50 +0300
commitdf05fae12695d00a092bdb694786310bface6cbe (patch)
treefa7ee49ca3413064f053efc6a80b501b6ff4ad36
parent4793154d0d8f881134a0f662921646d4f04e546c (diff)
parent820d50d3cbf3a3995ca5a4051c82e8ee24805796 (diff)
Merge branch 'master' into temp-runtime-node-def
-rw-r--r--CMakeLists.txt3
-rw-r--r--build_files/config/pipeline_config.yaml4
-rw-r--r--intern/cycles/blender/blender_util.h2
-rw-r--r--intern/cycles/kernel/closure/bsdf_principled_diffuse.h6
-rw-r--r--intern/cycles/kernel/geom/geom_triangle.h11
-rw-r--r--intern/cycles/kernel/svm/svm_tex_coord.h2
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/blender_default.py18
-rw-r--r--release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py19
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py1
-rw-r--r--source/blender/blenfont/BLF_api.h49
-rw-r--r--source/blender/blenfont/intern/blf.c92
-rw-r--r--source/blender/blenfont/intern/blf_default.c8
-rw-r--r--source/blender/blenfont/intern/blf_font.c164
-rw-r--r--source/blender/blenfont/intern/blf_internal.h39
-rw-r--r--source/blender/blenkernel/BKE_lib_id.h8
-rw-r--r--source/blender/blenkernel/BKE_mesh.h5
-rw-r--r--source/blender/blenkernel/BKE_node.h2
-rw-r--r--source/blender/blenkernel/BKE_particle.h5
-rw-r--r--source/blender/blenkernel/intern/bvhutils.cc3
-rw-r--r--source/blender/blenkernel/intern/camera.c7
-rw-r--r--source/blender/blenkernel/intern/collection.c4
-rw-r--r--source/blender/blenkernel/intern/gpencil_geom.cc28
-rw-r--r--source/blender/blenkernel/intern/lib_id.c19
-rw-r--r--source/blender/blenkernel/intern/mesh.c26
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c63
-rw-r--r--source/blender/blenkernel/intern/object.c6
-rw-r--r--source/blender/blenkernel/intern/particle.c14
-rw-r--r--source/blender/blenkernel/intern/scene.c8
-rw-r--r--source/blender/blenkernel/intern/spline_base.cc2
-rw-r--r--source/blender/blenkernel/intern/text.c23
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c2
-rw-r--r--source/blender/blenlib/BLI_math_base.h5
-rw-r--r--source/blender/blenlib/BLI_string_utf8.h17
-rw-r--r--source/blender/blenlib/intern/filereader_zstd.c6
-rw-r--r--source/blender/blenlib/intern/freetypefont.c2
-rw-r--r--source/blender/blenlib/intern/math_base_inline.c20
-rw-r--r--source/blender/blenlib/intern/string_cursor_utf8.c20
-rw-r--r--source/blender/blenlib/intern/string_search.cc17
-rw-r--r--source/blender/blenlib/intern/string_utf8.c129
-rw-r--r--source/blender/blenlib/tests/BLI_string_utf8_test.cc115
-rw-r--r--source/blender/blenloader/intern/versioning_300.c13
-rw-r--r--source/blender/compositor/CMakeLists.txt6
-rw-r--r--source/blender/compositor/COM_defines.h4
-rw-r--r--source/blender/compositor/intern/COM_CompositorContext.h6
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.cc69
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.h99
-rw-r--r--source/blender/compositor/intern/COM_NodeGraph.cc9
-rw-r--r--source/blender/compositor/intern/COM_NodeGraph.h4
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.cc6
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.h11
-rw-r--r--source/blender/compositor/nodes/COM_CryptomatteNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_RotateNode.cc25
-rw-r--r--source/blender/compositor/nodes/COM_Stabilize2dNode.cc100
-rw-r--r--source/blender/compositor/nodes/COM_TransformNode.cc61
-rw-r--r--source/blender/compositor/operations/COM_BlurBaseOperation.cc95
-rw-r--r--source/blender/compositor/operations/COM_BlurBaseOperation.h22
-rw-r--r--source/blender/compositor/operations/COM_BokehBlurOperation.cc178
-rw-r--r--source/blender/compositor/operations/COM_BokehBlurOperation.h12
-rw-r--r--source/blender/compositor/operations/COM_ChannelMatteOperation.cc34
-rw-r--r--source/blender/compositor/operations/COM_ChannelMatteOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_ChromaMatteOperation.cc55
-rw-r--r--source/blender/compositor/operations/COM_ChromaMatteOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_ColorMatteOperation.cc37
-rw-r--r--source/blender/compositor/operations/COM_ColorMatteOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_ColorRampOperation.cc10
-rw-r--r--source/blender/compositor/operations/COM_ColorRampOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_ColorSpillOperation.cc33
-rw-r--r--source/blender/compositor/operations/COM_ColorSpillOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_ConvertOperation.cc164
-rw-r--r--source/blender/compositor/operations/COM_ConvertOperation.h68
-rw-r--r--source/blender/compositor/operations/COM_CropOperation.cc45
-rw-r--r--source/blender/compositor/operations/COM_CropOperation.h13
-rw-r--r--source/blender/compositor/operations/COM_CryptomatteOperation.cc30
-rw-r--r--source/blender/compositor/operations/COM_CryptomatteOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_DifferenceMatteOperation.cc41
-rw-r--r--source/blender/compositor/operations/COM_DifferenceMatteOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_DisplaceOperation.cc95
-rw-r--r--source/blender/compositor/operations/COM_DisplaceOperation.h22
-rw-r--r--source/blender/compositor/operations/COM_DisplaceSimpleOperation.cc52
-rw-r--r--source/blender/compositor/operations/COM_DisplaceSimpleOperation.h9
-rw-r--r--source/blender/compositor/operations/COM_DistanceRGBMatteOperation.cc42
-rw-r--r--source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_DistanceYCCMatteOperation.cc2
-rw-r--r--source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_FastGaussianBlurOperation.cc106
-rw-r--r--source/blender/compositor/operations/COM_FastGaussianBlurOperation.h21
-rw-r--r--source/blender/compositor/operations/COM_FlipOperation.cc38
-rw-r--r--source/blender/compositor/operations/COM_FlipOperation.h9
-rw-r--r--source/blender/compositor/operations/COM_GammaCorrectOperation.cc57
-rw-r--r--source/blender/compositor/operations/COM_GammaCorrectOperation.h14
-rw-r--r--source/blender/compositor/operations/COM_GaussianAlphaBlurBaseOperation.cc168
-rw-r--r--source/blender/compositor/operations/COM_GaussianAlphaBlurBaseOperation.h62
-rw-r--r--source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cc13
-rw-r--r--source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h23
-rw-r--r--source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cc15
-rw-r--r--source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h23
-rw-r--r--source/blender/compositor/operations/COM_GaussianBlurBaseOperation.cc154
-rw-r--r--source/blender/compositor/operations/COM_GaussianBlurBaseOperation.h50
-rw-r--r--source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cc213
-rw-r--r--source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h18
-rw-r--r--source/blender/compositor/operations/COM_GaussianXBlurOperation.cc15
-rw-r--r--source/blender/compositor/operations/COM_GaussianXBlurOperation.h11
-rw-r--r--source/blender/compositor/operations/COM_GaussianYBlurOperation.cc13
-rw-r--r--source/blender/compositor/operations/COM_GaussianYBlurOperation.h11
-rw-r--r--source/blender/compositor/operations/COM_KeyingBlurOperation.cc63
-rw-r--r--source/blender/compositor/operations/COM_KeyingBlurOperation.h11
-rw-r--r--source/blender/compositor/operations/COM_KeyingClipOperation.cc85
-rw-r--r--source/blender/compositor/operations/COM_KeyingClipOperation.h11
-rw-r--r--source/blender/compositor/operations/COM_KeyingDespillOperation.cc29
-rw-r--r--source/blender/compositor/operations/COM_KeyingDespillOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_KeyingOperation.cc45
-rw-r--r--source/blender/compositor/operations/COM_KeyingOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_KeyingScreenOperation.cc95
-rw-r--r--source/blender/compositor/operations/COM_KeyingScreenOperation.h12
-rw-r--r--source/blender/compositor/operations/COM_LuminanceMatteOperation.cc36
-rw-r--r--source/blender/compositor/operations/COM_LuminanceMatteOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_MapUVOperation.cc97
-rw-r--r--source/blender/compositor/operations/COM_MapUVOperation.h21
-rw-r--r--source/blender/compositor/operations/COM_MathBaseOperation.cc322
-rw-r--r--source/blender/compositor/operations/COM_MathBaseOperation.h154
-rw-r--r--source/blender/compositor/operations/COM_MovieDistortionOperation.cc47
-rw-r--r--source/blender/compositor/operations/COM_MovieDistortionOperation.h9
-rw-r--r--source/blender/compositor/operations/COM_PlaneCornerPinOperation.cc99
-rw-r--r--source/blender/compositor/operations/COM_PlaneCornerPinOperation.h7
-rw-r--r--source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cc115
-rw-r--r--source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h16
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackOperation.cc26
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cc54
-rw-r--r--source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h11
-rw-r--r--source/blender/compositor/operations/COM_RotateOperation.cc86
-rw-r--r--source/blender/compositor/operations/COM_RotateOperation.h37
-rw-r--r--source/blender/compositor/operations/COM_ScaleOperation.cc13
-rw-r--r--source/blender/compositor/operations/COM_ScaleOperation.h9
-rw-r--r--source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cc189
-rw-r--r--source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h13
-rw-r--r--source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.cc12
-rw-r--r--source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_SetAlphaReplaceOperation.cc13
-rw-r--r--source/blender/compositor/operations/COM_SetAlphaReplaceOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_TransformOperation.cc156
-rw-r--r--source/blender/compositor/operations/COM_TransformOperation.h87
-rw-r--r--source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cc161
-rw-r--r--source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h17
-rw-r--r--source/blender/draw/engines/image/image_engine.c65
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c5
-rw-r--r--source/blender/draw/intern/draw_cache_extract.h178
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh.cc53
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh_render_data.c53
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c689
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh.c6
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh.h8
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc8
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc12
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc22
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc4
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc4
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc4
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc8
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc4
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc2
-rw-r--r--source/blender/editors/curve/editfont.c4
-rw-r--r--source/blender/editors/include/ED_node.h5
-rw-r--r--source/blender/editors/include/ED_transform.h1
-rw-r--r--source/blender/editors/include/UI_resources.h2
-rw-r--r--source/blender/editors/include/UI_view2d.h17
-rw-r--r--source/blender/editors/interface/interface_handlers.c4
-rw-r--r--source/blender/editors/interface/resources.c2
-rw-r--r--source/blender/editors/interface/view2d_edge_pan.c54
-rw-r--r--source/blender/editors/object/object_add.c20
-rw-r--r--source/blender/editors/object/object_modifier.c2
-rw-r--r--source/blender/editors/physics/particle_object.c3
-rw-r--r--source/blender/editors/space_buttons/buttons_ops.c12
-rw-r--r--source/blender/editors/space_console/console_ops.c6
-rw-r--r--source/blender/editors/space_image/image_edit.c10
-rw-r--r--source/blender/editors/space_image/image_ops.c2
-rw-r--r--source/blender/editors/space_image/image_sequence.c2
-rw-r--r--source/blender/editors/space_info/info_ops.c2
-rw-r--r--source/blender/editors/space_node/node_draw.cc4
-rw-r--r--source/blender/editors/space_node/node_geometry_attribute_search.cc1
-rw-r--r--source/blender/editors/space_node/node_relationships.cc13
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c2
-rw-r--r--source/blender/editors/space_script/script_edit.c7
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c10
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c9
-rw-r--r--source/blender/editors/space_text/text_autocomplete.c7
-rw-r--r--source/blender/editors/space_text/text_ops.c7
-rw-r--r--source/blender/editors/transform/transform.c7
-rw-r--r--source/blender/editors/transform/transform.h2
-rw-r--r--source/blender/editors/transform/transform_convert.c13
-rw-r--r--source/blender/editors/transform/transform_convert.h4
-rw-r--r--source/blender/editors/transform/transform_convert_action.c9
-rw-r--r--source/blender/editors/transform/transform_convert_node.c38
-rw-r--r--source/blender/editors/transform/transform_convert_sequencer.c15
-rw-r--r--source/blender/editors/transform/transform_generics.c5
-rw-r--r--source/blender/editors/transform/transform_ops.c8
-rw-r--r--source/blender/editors/util/numinput.c2
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c2
-rw-r--r--source/blender/makesdna/DNA_node_types.h6
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h3
-rw-r--r--source/blender/makesrna/RNA_access.h9
-rw-r--r--source/blender/makesrna/intern/rna_access.c25
-rw-r--r--source/blender/makesrna/intern/rna_color.c6
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c8
-rw-r--r--source/blender/makesrna/intern/rna_sequencer_api.c26
-rw-r--r--source/blender/makesrna/intern/rna_wm.c5
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c2
-rw-r--r--source/blender/nodes/composite/node_composite_tree.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_idMask.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_math.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_premulkey.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_setalpha.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_switchview.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_valToRgb.c4
-rw-r--r--source/blender/nodes/function/nodes/node_fn_boolean_math.cc2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_float_compare.cc2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_float_to_int.cc2
-rw-r--r--source/blender/nodes/geometry/node_geometry_tree.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc67
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_switch.cc2
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_blackbody.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_clamp.cc2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_map_range.cc2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.cc2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_shaderToRgb.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_squeeze.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_valToRgb.cc4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_wavelength.c2
-rw-r--r--source/blender/nodes/texture/node_texture_tree.c2
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_distance.c2
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_math.c2
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_valToNor.c2
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_valToRgb.c4
-rw-r--r--source/blender/python/intern/bpy_rna.c2
-rw-r--r--source/blender/render/RE_pipeline.h2
-rw-r--r--source/blender/render/intern/engine.c11
-rw-r--r--source/blender/render/intern/pipeline.c1
-rw-r--r--source/blender/render/intern/render_result.c65
-rw-r--r--source/blender/render/intern/render_result.h2
-rw-r--r--source/blender/sequencer/CMakeLists.txt1
-rw-r--r--source/blender/sequencer/SEQ_edit.h3
-rw-r--r--source/blender/sequencer/SEQ_iterator.h1
-rw-r--r--source/blender/sequencer/SEQ_relations.h3
-rw-r--r--source/blender/sequencer/intern/effects.c212
-rw-r--r--source/blender/sequencer/intern/effects.h4
-rw-r--r--source/blender/sequencer/intern/iterator.c8
-rw-r--r--source/blender/sequencer/intern/prefetch.c122
-rw-r--r--source/blender/sequencer/intern/render.c2
-rw-r--r--source/blender/sequencer/intern/strip_edit.c126
-rw-r--r--source/blender/sequencer/intern/strip_relations.c26
-rw-r--r--source/blender/sequencer/intern/strip_transform.c10
-rw-r--r--source/blender/sequencer/intern/utils.c21
-rw-r--r--source/blender/sequencer/intern/utils.h4
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c2
-rw-r--r--tests/python/CMakeLists.txt7
282 files changed, 6265 insertions, 1843 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5a555876d21..47712f0ac1e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1598,8 +1598,7 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNUSED_PARAMETER -Wunused-parameter)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ALL -Wall)
- # Designated initializer is a C++20 feature & breaks MSVC build. Dropping MSVC 2019 or
- # updating to C++20 allows removing this.
+ # Using C++20 features while having C++17 as the project language isn't allowed by MSVC.
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_CXX20_DESIGNATOR -Wc++20-designator)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_AUTOLOGICAL_COMPARE -Wno-tautological-compare)
diff --git a/build_files/config/pipeline_config.yaml b/build_files/config/pipeline_config.yaml
index 611df59caec..5d1a24a30f1 100644
--- a/build_files/config/pipeline_config.yaml
+++ b/build_files/config/pipeline_config.yaml
@@ -51,9 +51,9 @@ buildbot:
gcc:
version: '9.0.0'
cuda10:
- version: '10.1.0'
+ version: '10.1.243'
cuda11:
- version: '11.4.0'
+ version: '11.4.1'
optix:
version: '7.1.0'
cmake:
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index 3cf75b338dc..f6824f31b7b 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -424,7 +424,7 @@ static inline void set_enum(PointerRNA &ptr, const char *name, const string &ide
static inline string get_string(PointerRNA &ptr, const char *name)
{
char cstrbuf[1024];
- char *cstr = RNA_string_get_alloc(&ptr, name, cstrbuf, sizeof(cstrbuf));
+ char *cstr = RNA_string_get_alloc(&ptr, name, cstrbuf, sizeof(cstrbuf), NULL);
string str(cstr);
if (cstr != cstrbuf)
MEM_freeN(cstr);
diff --git a/intern/cycles/kernel/closure/bsdf_principled_diffuse.h b/intern/cycles/kernel/closure/bsdf_principled_diffuse.h
index 43646aaeb5b..d5d012068ff 100644
--- a/intern/cycles/kernel/closure/bsdf_principled_diffuse.h
+++ b/intern/cycles/kernel/closure/bsdf_principled_diffuse.h
@@ -36,10 +36,10 @@ static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledDiffuseBsdf),
ccl_device float3 calculate_principled_diffuse_brdf(
const PrincipledDiffuseBsdf *bsdf, float3 N, float3 V, float3 L, float3 H, float *pdf)
{
- float NdotL = max(dot(N, L), 0.0f);
- float NdotV = max(dot(N, V), 0.0f);
+ float NdotL = dot(N, L);
+ float NdotV = dot(N, V);
- if (NdotL < 0 || NdotV < 0) {
+ if (NdotL <= 0 || NdotV <= 0) {
*pdf = 0.0f;
return make_float3(0.0f, 0.0f, 0.0f);
}
diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h
index 1e7fbd9c7fb..ff7909ca425 100644
--- a/intern/cycles/kernel/geom/geom_triangle.h
+++ b/intern/cycles/kernel/geom/geom_triangle.h
@@ -107,8 +107,8 @@ triangle_smooth_normal(KernelGlobals *kg, float3 Ng, int prim, float u, float v)
return is_zero(N) ? Ng : N;
}
-ccl_device_inline float3
-triangle_smooth_normal_unnormalized(KernelGlobals *kg, float3 Ng, int prim, float u, float v)
+ccl_device_inline float3 triangle_smooth_normal_unnormalized(
+ KernelGlobals *kg, ShaderData *sd, float3 Ng, int prim, float u, float v)
{
/* load triangle vertices */
const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
@@ -116,6 +116,13 @@ triangle_smooth_normal_unnormalized(KernelGlobals *kg, float3 Ng, int prim, floa
float3 n1 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.y));
float3 n2 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.z));
+ /* ensure that the normals are in object space */
+ if (sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED) {
+ object_inverse_normal_transform(kg, sd, &n0);
+ object_inverse_normal_transform(kg, sd, &n1);
+ object_inverse_normal_transform(kg, sd, &n2);
+ }
+
float3 N = (1.0f - u - v) * n2 + u * n0 + v * n1;
return is_zero(N) ? Ng : N;
diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h
index fec6a2cc27f..46600551cc4 100644
--- a/intern/cycles/kernel/svm/svm_tex_coord.h
+++ b/intern/cycles/kernel/svm/svm_tex_coord.h
@@ -289,7 +289,7 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st
float3 normal;
if (sd->shader & SHADER_SMOOTH_NORMAL) {
- normal = triangle_smooth_normal_unnormalized(kg, sd->Ng, sd->prim, sd->u, sd->v);
+ normal = triangle_smooth_normal_unnormalized(kg, sd, sd->Ng, sd->prim, sd->u, sd->v);
}
else {
normal = sd->Ng;
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index d9538930f33..55f60329a97 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -1909,19 +1909,19 @@ def km_node_editor(params):
("node.clipboard_paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
("node.viewer_border", {"type": 'B', "value": 'PRESS', "ctrl": True}, None),
("node.clear_viewer_border", {"type": 'B', "value": 'PRESS', "ctrl": True, "alt": True}, None),
- ("node.translate_attach", {"type": 'G', "value": 'PRESS'}, None),
- ("node.translate_attach", {"type": 'EVT_TWEAK_L', "value": 'ANY'}, None),
- ("node.translate_attach", {"type": params.select_tweak, "value": 'ANY'}, None),
- ("transform.translate", {"type": 'G', "value": 'PRESS'}, None),
+ ("node.translate_attach", {"type": 'G', "value": 'PRESS'}, {"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}),
+ ("node.translate_attach", {"type": 'EVT_TWEAK_L', "value": 'ANY'}, {"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}),
+ ("node.translate_attach", {"type": params.select_tweak, "value": 'ANY'}, {"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}),
+ ("transform.translate", {"type": 'G', "value": 'PRESS'}, {"properties": [("view2d_edge_pan", True)]}),
("transform.translate", {"type": 'EVT_TWEAK_L', "value": 'ANY'},
- {"properties": [("release_confirm", True)]}),
+ {"properties": [("release_confirm", True), ("view2d_edge_pan", True)]}),
("transform.translate", {"type": params.select_tweak, "value": 'ANY'},
- {"properties": [("release_confirm", True)]}),
+ {"properties": [("release_confirm", True), ("view2d_edge_pan", True)]}),
("transform.rotate", {"type": 'R', "value": 'PRESS'}, None),
("transform.resize", {"type": 'S', "value": 'PRESS'}, None),
- ("node.move_detach_links", {"type": 'D', "value": 'PRESS', "alt": True}, None),
- ("node.move_detach_links_release", {"type": params.action_tweak, "value": 'ANY', "alt": True}, None),
- ("node.move_detach_links", {"type": params.select_tweak, "value": 'ANY', "alt": True}, None),
+ ("node.move_detach_links", {"type": 'D', "value": 'PRESS', "alt": True}, {"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}),
+ ("node.move_detach_links_release", {"type": params.action_tweak, "value": 'ANY', "alt": True}, {"properties": [("NODE_OT_translate_attach", [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])])]}),
+ ("node.move_detach_links", {"type": params.select_tweak, "value": 'ANY', "alt": True}, {"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}),
("wm.context_toggle", {"type": 'TAB', "value": 'PRESS', "shift": True},
{"properties": [("data_path", 'tool_settings.use_snap')]}),
("wm.context_menu_enum", {"type": 'TAB', "value": 'PRESS', "shift": True, "ctrl": True},
diff --git a/release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py b/release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py
index 247a1ec342e..05ecac4d70c 100644
--- a/release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py
+++ b/release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py
@@ -29,9 +29,28 @@ def update_factory_startup_screens():
params.use_filter_folder = True
+def update_factory_startup_ffmpeg_preset():
+ preset = "H264_in_MP4"
+ preset_filepath = bpy.utils.preset_find(preset, preset_path="ffmpeg")
+ if not preset_filepath:
+ print("Preset %r not found" % preset)
+
+ for scene in bpy.data.scenes:
+ render = scene.render
+ render.image_settings.file_format = 'FFMPEG'
+
+ if preset_filepath:
+ bpy.ops.script.python_file_run({"scene": scene}, filepath=preset_filepath)
+
+ render.ffmpeg.audio_codec = 'AAC'
+ render.ffmpeg.audio_bitrate = 256
+
+
@persistent
def load_handler(_):
update_factory_startup_screens()
+ if bpy.app.build_options.codec_ffmpeg:
+ update_factory_startup_ffmpeg_preset()
def register():
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 003f2f223ea..708701c4804 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -997,7 +997,6 @@ class USERPREF_PT_theme_text_style(ThemePanel, CenterAlignMixIn, Panel):
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
col = flow.column()
- col.row().prop(font_style, "font_kerning_style", expand=True)
col.prop(font_style, "points")
col = flow.column(align=True)
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index eb3f9805240..4de7e704a7e 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -98,13 +98,13 @@ void BLF_batch_draw_flush(void);
void BLF_batch_draw_end(void);
/* Draw the string using the current font. */
-void BLF_draw_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
+void BLF_draw_ex(int fontid, const char *str, size_t str_len, struct ResultBLF *r_info)
ATTR_NONNULL(2);
-void BLF_draw(int fontid, const char *str, size_t len) ATTR_NONNULL(2);
-void BLF_draw_ascii_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
+void BLF_draw(int fontid, const char *str, size_t str_len) ATTR_NONNULL(2);
+void BLF_draw_ascii_ex(int fontid, const char *str, size_t str_len, struct ResultBLF *r_info)
ATTR_NONNULL(2);
-void BLF_draw_ascii(int fontid, const char *str, size_t len) ATTR_NONNULL(2);
-int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth) ATTR_NONNULL(2);
+void BLF_draw_ascii(int fontid, const char *str, size_t str_len) ATTR_NONNULL(2);
+int BLF_draw_mono(int fontid, const char *str, size_t str_len, int cwidth) ATTR_NONNULL(2);
typedef bool (*BLF_GlyphBoundsFn)(const char *str,
const size_t str_step_ofs,
@@ -116,43 +116,45 @@ typedef bool (*BLF_GlyphBoundsFn)(const char *str,
void BLF_boundbox_foreach_glyph_ex(int fontid,
const char *str,
- size_t len,
+ size_t str_len,
BLF_GlyphBoundsFn user_fn,
void *user_data,
struct ResultBLF *r_info) ATTR_NONNULL(2);
void BLF_boundbox_foreach_glyph(int fontid,
const char *str,
- size_t len,
+ size_t str_len,
BLF_GlyphBoundsFn user_fn,
void *user_data) ATTR_NONNULL(2);
/* Get the string byte offset that fits within a given width */
-size_t BLF_width_to_strlen(int fontid, const char *str, size_t len, float width, float *r_width)
- ATTR_NONNULL(2);
+size_t BLF_width_to_strlen(
+ int fontid, const char *str, size_t str_len, float width, float *r_width) ATTR_NONNULL(2);
/* Same as BLF_width_to_strlen but search from the string end */
-size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width, float *r_width)
- ATTR_NONNULL(2);
+size_t BLF_width_to_rstrlen(
+ int fontid, const char *str, size_t str_len, float width, float *r_width) ATTR_NONNULL(2);
/* This function return the bounding box of the string
* and are not multiplied by the aspect.
*/
void BLF_boundbox_ex(int fontid,
const char *str,
- size_t len,
+ size_t str_len,
struct rctf *box,
struct ResultBLF *r_info) ATTR_NONNULL(2);
-void BLF_boundbox(int fontid, const char *str, size_t len, struct rctf *box) ATTR_NONNULL();
+void BLF_boundbox(int fontid, const char *str, size_t str_len, struct rctf *box) ATTR_NONNULL();
/* The next both function return the width and height
* of the string, using the current font and both value
* are multiplied by the aspect of the font.
*/
-float BLF_width_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
+float BLF_width_ex(int fontid, const char *str, size_t str_len, struct ResultBLF *r_info)
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2);
-float BLF_width(int fontid, const char *str, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BLF_height_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
+float BLF_width(int fontid, const char *str, size_t str_len) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+float BLF_height_ex(int fontid, const char *str, size_t str_len, struct ResultBLF *r_info)
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2);
-float BLF_height(int fontid, const char *str, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BLF_height(int fontid, const char *str, size_t str_len) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
/* Return dimensions of the font without any sample text. */
int BLF_height_max(int fontid) ATTR_WARN_UNUSED_RESULT;
@@ -163,8 +165,8 @@ float BLF_ascender(int fontid) ATTR_WARN_UNUSED_RESULT;
/* The following function return the width and height of the string, but
* just in one call, so avoid extra freetype2 stuff.
*/
-void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_width, float *r_height)
- ATTR_NONNULL();
+void BLF_width_and_height(
+ int fontid, const char *str, size_t str_len, float *r_width, float *r_height) ATTR_NONNULL();
/* For fixed width fonts only, returns the width of a
* character.
@@ -221,9 +223,9 @@ void BLF_buffer_col(int fontid, const float rgba[4]) ATTR_NONNULL(2);
/* Draw the string into the buffer, this function draw in both buffer,
* float and unsigned char _BUT_ it's not necessary set both buffer, NULL is valid here.
*/
-void BLF_draw_buffer_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
+void BLF_draw_buffer_ex(int fontid, const char *str, size_t str_len, struct ResultBLF *r_info)
ATTR_NONNULL(2);
-void BLF_draw_buffer(int fontid, const char *str, size_t len) ATTR_NONNULL(2);
+void BLF_draw_buffer(int fontid, const char *str, size_t str_len) ATTR_NONNULL(2);
/* Add a path to the font dir paths. */
void BLF_dir_add(const char *path) ATTR_NONNULL();
@@ -254,8 +256,9 @@ void BLF_default_dpi(int dpi);
void BLF_default_set(int fontid);
int BLF_default(void); /* get default font ID so we can pass it to other functions */
/* Draw the string using the default font, size and dpi. */
-void BLF_draw_default(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL();
-void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL();
+void BLF_draw_default(float x, float y, float z, const char *str, size_t str_len) ATTR_NONNULL();
+void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t str_len)
+ ATTR_NONNULL();
/* Set size and DPI, and return default font ID. */
int BLF_set_default(void);
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index 2f9eb0753ac..86d67c80fd4 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -521,7 +521,7 @@ static void blf_draw_gl__end(FontBLF *font)
}
}
-void BLF_draw_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
+void BLF_draw_ex(int fontid, const char *str, const size_t str_len, struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
@@ -530,27 +530,27 @@ void BLF_draw_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_in
if (font) {
blf_draw_gl__start(font);
if (font->flags & BLF_WORD_WRAP) {
- blf_font_draw__wrap(font, str, len, r_info);
+ blf_font_draw__wrap(font, str, str_len, r_info);
}
else {
- blf_font_draw(font, str, len, r_info);
+ blf_font_draw(font, str, str_len, r_info);
}
blf_draw_gl__end(font);
}
}
-void BLF_draw(int fontid, const char *str, size_t len)
+void BLF_draw(int fontid, const char *str, const size_t str_len)
{
- if (len == 0 || str[0] == '\0') {
+ if (str_len == 0 || str[0] == '\0') {
return;
}
/* Avoid bgl usage to corrupt BLF drawing. */
GPU_bgl_end();
- BLF_draw_ex(fontid, str, len, NULL);
+ BLF_draw_ex(fontid, str, str_len, NULL);
}
-void BLF_draw_ascii_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
+void BLF_draw_ascii_ex(int fontid, const char *str, const size_t str_len, struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
@@ -560,27 +560,27 @@ void BLF_draw_ascii_ex(int fontid, const char *str, size_t len, struct ResultBLF
blf_draw_gl__start(font);
if (font->flags & BLF_WORD_WRAP) {
/* Use non-ASCII draw function for word-wrap. */
- blf_font_draw__wrap(font, str, len, r_info);
+ blf_font_draw__wrap(font, str, str_len, r_info);
}
else {
- blf_font_draw_ascii(font, str, len, r_info);
+ blf_font_draw_ascii(font, str, str_len, r_info);
}
blf_draw_gl__end(font);
}
}
-void BLF_draw_ascii(int fontid, const char *str, size_t len)
+void BLF_draw_ascii(int fontid, const char *str, const size_t str_len)
{
- if (len == 0 || str[0] == '\0') {
+ if (str_len == 0 || str[0] == '\0') {
return;
}
- BLF_draw_ascii_ex(fontid, str, len, NULL);
+ BLF_draw_ascii_ex(fontid, str, str_len, NULL);
}
-int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
+int BLF_draw_mono(int fontid, const char *str, const size_t str_len, int cwidth)
{
- if (len == 0 || str[0] == '\0') {
+ if (str_len == 0 || str[0] == '\0') {
return 0;
}
@@ -589,7 +589,7 @@ int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
if (font) {
blf_draw_gl__start(font);
- columns = blf_font_draw_mono(font, str, len, cwidth);
+ columns = blf_font_draw_mono(font, str, str_len, cwidth);
blf_draw_gl__end(font);
}
@@ -606,7 +606,7 @@ int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
*/
void BLF_boundbox_foreach_glyph_ex(int fontid,
const char *str,
- size_t len,
+ size_t str_len,
BLF_GlyphBoundsFn user_fn,
void *user_data,
struct ResultBLF *r_info)
@@ -621,25 +621,26 @@ void BLF_boundbox_foreach_glyph_ex(int fontid,
BLI_assert(0);
}
else {
- blf_font_boundbox_foreach_glyph(font, str, len, user_fn, user_data, r_info);
+ blf_font_boundbox_foreach_glyph(font, str, str_len, user_fn, user_data, r_info);
}
}
}
void BLF_boundbox_foreach_glyph(
- int fontid, const char *str, size_t len, BLF_GlyphBoundsFn user_fn, void *user_data)
+ int fontid, const char *str, const size_t str_len, BLF_GlyphBoundsFn user_fn, void *user_data)
{
- BLF_boundbox_foreach_glyph_ex(fontid, str, len, user_fn, user_data, NULL);
+ BLF_boundbox_foreach_glyph_ex(fontid, str, str_len, user_fn, user_data, NULL);
}
-size_t BLF_width_to_strlen(int fontid, const char *str, size_t len, float width, float *r_width)
+size_t BLF_width_to_strlen(
+ int fontid, const char *str, const size_t str_len, float width, float *r_width)
{
FontBLF *font = blf_get(fontid);
if (font) {
const float xa = (font->flags & BLF_ASPECT) ? font->aspect[0] : 1.0f;
size_t ret;
- ret = blf_font_width_to_strlen(font, str, len, width / xa, r_width);
+ ret = blf_font_width_to_strlen(font, str, str_len, width / xa, r_width);
if (r_width) {
*r_width *= xa;
}
@@ -652,14 +653,15 @@ size_t BLF_width_to_strlen(int fontid, const char *str, size_t len, float width,
return 0;
}
-size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width, float *r_width)
+size_t BLF_width_to_rstrlen(
+ int fontid, const char *str, const size_t str_len, float width, float *r_width)
{
FontBLF *font = blf_get(fontid);
if (font) {
const float xa = (font->flags & BLF_ASPECT) ? font->aspect[0] : 1.0f;
size_t ret;
- ret = blf_font_width_to_rstrlen(font, str, len, width / xa, r_width);
+ ret = blf_font_width_to_rstrlen(font, str, str_len, width / xa, r_width);
if (r_width) {
*r_width *= xa;
}
@@ -673,7 +675,7 @@ size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width
}
void BLF_boundbox_ex(
- int fontid, const char *str, size_t len, rctf *r_box, struct ResultBLF *r_info)
+ int fontid, const char *str, const size_t str_len, rctf *r_box, struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
@@ -681,47 +683,48 @@ void BLF_boundbox_ex(
if (font) {
if (font->flags & BLF_WORD_WRAP) {
- blf_font_boundbox__wrap(font, str, len, r_box, r_info);
+ blf_font_boundbox__wrap(font, str, str_len, r_box, r_info);
}
else {
- blf_font_boundbox(font, str, len, r_box, r_info);
+ blf_font_boundbox(font, str, str_len, r_box, r_info);
}
}
}
-void BLF_boundbox(int fontid, const char *str, size_t len, rctf *r_box)
+void BLF_boundbox(int fontid, const char *str, const size_t str_len, rctf *r_box)
{
- BLF_boundbox_ex(fontid, str, len, r_box, NULL);
+ BLF_boundbox_ex(fontid, str, str_len, r_box, NULL);
}
-void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_width, float *r_height)
+void BLF_width_and_height(
+ int fontid, const char *str, const size_t str_len, float *r_width, float *r_height)
{
FontBLF *font = blf_get(fontid);
if (font) {
- blf_font_width_and_height(font, str, len, r_width, r_height, NULL);
+ blf_font_width_and_height(font, str, str_len, r_width, r_height, NULL);
}
else {
*r_width = *r_height = 0.0f;
}
}
-float BLF_width_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
+float BLF_width_ex(int fontid, const char *str, const size_t str_len, struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
BLF_RESULT_CHECK_INIT(r_info);
if (font) {
- return blf_font_width(font, str, len, r_info);
+ return blf_font_width(font, str, str_len, r_info);
}
return 0.0f;
}
-float BLF_width(int fontid, const char *str, size_t len)
+float BLF_width(int fontid, const char *str, const size_t str_len)
{
- return BLF_width_ex(fontid, str, len, NULL);
+ return BLF_width_ex(fontid, str, str_len, NULL);
}
float BLF_fixed_width(int fontid)
@@ -735,22 +738,22 @@ float BLF_fixed_width(int fontid)
return 0.0f;
}
-float BLF_height_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
+float BLF_height_ex(int fontid, const char *str, const size_t str_len, struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
BLF_RESULT_CHECK_INIT(r_info);
if (font) {
- return blf_font_height(font, str, len, r_info);
+ return blf_font_height(font, str, str_len, r_info);
}
return 0.0f;
}
-float BLF_height(int fontid, const char *str, size_t len)
+float BLF_height(int fontid, const char *str, const size_t str_len)
{
- return BLF_height_ex(fontid, str, len, NULL);
+ return BLF_height_ex(fontid, str, str_len, NULL);
}
int BLF_height_max(int fontid)
@@ -894,24 +897,27 @@ void blf_draw_buffer__end(void)
{
}
-void BLF_draw_buffer_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
+void BLF_draw_buffer_ex(int fontid,
+ const char *str,
+ const size_t str_len,
+ struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
if (font && (font->buf_info.fbuf || font->buf_info.cbuf)) {
blf_draw_buffer__start(font);
if (font->flags & BLF_WORD_WRAP) {
- blf_font_draw_buffer__wrap(font, str, len, r_info);
+ blf_font_draw_buffer__wrap(font, str, str_len, r_info);
}
else {
- blf_font_draw_buffer(font, str, len, r_info);
+ blf_font_draw_buffer(font, str, str_len, r_info);
}
blf_draw_buffer__end();
}
}
-void BLF_draw_buffer(int fontid, const char *str, size_t len)
+void BLF_draw_buffer(int fontid, const char *str, const size_t str_len)
{
- BLF_draw_buffer_ex(fontid, str, len, NULL);
+ BLF_draw_buffer_ex(fontid, str, str_len, NULL);
}
char *BLF_display_name_from_file(const char *filename)
diff --git a/source/blender/blenfont/intern/blf_default.c b/source/blender/blenfont/intern/blf_default.c
index 7bbc865128d..1b458e8aaef 100644
--- a/source/blender/blenfont/intern/blf_default.c
+++ b/source/blender/blenfont/intern/blf_default.c
@@ -68,23 +68,23 @@ int BLF_set_default(void)
return global_font_default;
}
-void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
+void BLF_draw_default(float x, float y, float z, const char *str, const size_t str_len)
{
ASSERT_DEFAULT_SET;
const uiStyle *style = UI_style_get();
BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi);
BLF_position(global_font_default, x, y, z);
- BLF_draw(global_font_default, str, len);
+ BLF_draw(global_font_default, str, str_len);
}
/* same as above but call 'BLF_draw_ascii' */
-void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len)
+void BLF_draw_default_ascii(float x, float y, float z, const char *str, const size_t str_len)
{
ASSERT_DEFAULT_SET;
const uiStyle *style = UI_style_get();
BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi);
BLF_position(global_font_default, x, y, z);
- BLF_draw_ascii(global_font_default, str, len); /* XXX, use real length */
+ BLF_draw_ascii(global_font_default, str, str_len); /* XXX, use real length */
}
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 75a2e893119..426008c9395 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -298,7 +298,7 @@ static void blf_batch_draw_end(void)
*/
BLI_INLINE GlyphBLF *blf_utf8_next_fast(
- FontBLF *font, GlyphCacheBLF *gc, const char *str, size_t *i_p, uint *r_c)
+ FontBLF *font, GlyphCacheBLF *gc, const char *str, size_t str_len, size_t *i_p, uint *r_c)
{
GlyphBLF *g;
if ((*r_c = str[*i_p]) < GLYPH_ASCII_TABLE_SIZE) {
@@ -309,15 +309,13 @@ BLI_INLINE GlyphBLF *blf_utf8_next_fast(
}
(*i_p)++;
}
- else if ((*r_c = BLI_str_utf8_as_unicode_step(str, i_p)) != BLI_UTF8_ERR) {
+ else {
+ *r_c = BLI_str_utf8_as_unicode_step(str, str_len, i_p);
g = blf_glyph_search(gc, *r_c);
if (UNLIKELY(g == NULL)) {
g = blf_glyph_add(font, gc, FT_Get_Char_Index(font->face, *r_c), *r_c);
}
}
- else {
- g = NULL;
- }
return g;
}
@@ -365,7 +363,7 @@ BLI_INLINE void blf_kerning_step_fast(FontBLF *font,
static void blf_font_draw_ex(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
- size_t len,
+ const size_t str_len,
struct ResultBLF *r_info,
int pen_y)
{
@@ -374,15 +372,15 @@ static void blf_font_draw_ex(FontBLF *font,
int pen_x = 0;
size_t i = 0;
- if (len == 0) {
+ if (str_len == 0) {
/* early output, don't do any IMM OpenGL. */
return;
}
blf_batch_draw_begin(font);
- while ((i < len) && str[i]) {
- g = blf_utf8_next_fast(font, gc, str, &i, &c);
+ while ((i < str_len) && str[i]) {
+ g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
break;
@@ -407,16 +405,16 @@ static void blf_font_draw_ex(FontBLF *font,
r_info->width = pen_x;
}
}
-void blf_font_draw(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+void blf_font_draw(FontBLF *font, const char *str, const size_t str_len, struct ResultBLF *r_info)
{
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- blf_font_draw_ex(font, gc, str, len, r_info, 0);
+ blf_font_draw_ex(font, gc, str, str_len, r_info, 0);
blf_glyph_cache_release(font);
}
/* faster version of blf_font_draw, ascii only for view dimensions */
static void blf_font_draw_ascii_ex(
- FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info, int pen_y)
+ FontBLF *font, const char *str, size_t str_len, struct ResultBLF *r_info, int pen_y)
{
unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev = NULL;
@@ -426,7 +424,7 @@ static void blf_font_draw_ascii_ex(
blf_batch_draw_begin(font);
- while ((c = *(str++)) && len--) {
+ while ((c = *(str++)) && str_len--) {
BLI_assert(c < GLYPH_ASCII_TABLE_SIZE);
g = gc->glyph_ascii_table[c];
if (UNLIKELY(g == NULL)) {
@@ -456,13 +454,16 @@ static void blf_font_draw_ascii_ex(
blf_glyph_cache_release(font);
}
-void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+void blf_font_draw_ascii(FontBLF *font,
+ const char *str,
+ const size_t str_len,
+ struct ResultBLF *r_info)
{
- blf_font_draw_ascii_ex(font, str, len, r_info, 0);
+ blf_font_draw_ascii_ex(font, str, str_len, r_info, 0);
}
/* use fixed column width, but an utf8 character may occupy multiple columns */
-int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
+int blf_font_draw_mono(FontBLF *font, const char *str, const size_t str_len, int cwidth)
{
unsigned int c;
GlyphBLF *g;
@@ -474,8 +475,8 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
blf_batch_draw_begin(font);
- while ((i < len) && str[i]) {
- g = blf_utf8_next_fast(font, gc, str, &i, &c);
+ while ((i < str_len) && str[i]) {
+ g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
break;
@@ -505,14 +506,14 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Text Drawgin: Buffer
+/** \name Text Drawing: Buffer
* \{ */
/* Sanity checks are done by BLF_draw_buffer() */
static void blf_font_draw_buffer_ex(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
- size_t len,
+ const size_t str_len,
struct ResultBLF *r_info,
int pen_y)
{
@@ -531,8 +532,8 @@ static void blf_font_draw_buffer_ex(FontBLF *font,
/* another buffer specific call for color conversion */
- while ((i < len) && str[i]) {
- g = blf_utf8_next_fast(font, gc, str, &i, &c);
+ while ((i < str_len) && str[i]) {
+ g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
break;
@@ -646,10 +647,13 @@ static void blf_font_draw_buffer_ex(FontBLF *font,
}
}
-void blf_font_draw_buffer(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+void blf_font_draw_buffer(FontBLF *font,
+ const char *str,
+ const size_t str_len,
+ struct ResultBLF *r_info)
{
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- blf_font_draw_buffer_ex(font, gc, str, len, r_info, 0);
+ blf_font_draw_buffer_ex(font, gc, str, str_len, r_info, 0);
blf_glyph_cache_release(font);
}
@@ -685,7 +689,7 @@ static bool blf_font_width_to_strlen_glyph_process(FontBLF *font,
}
size_t blf_font_width_to_strlen(
- FontBLF *font, const char *str, size_t len, float width, float *r_width)
+ FontBLF *font, const char *str, const size_t str_len, float width, float *r_width)
{
unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev;
@@ -695,9 +699,9 @@ size_t blf_font_width_to_strlen(
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
const int width_i = (int)width;
- for (i_prev = i = 0, width_new = pen_x = 0, g_prev = NULL, c_prev = 0; (i < len) && str[i];
+ for (i_prev = i = 0, width_new = pen_x = 0, g_prev = NULL, c_prev = 0; (i < str_len) && str[i];
i_prev = i, width_new = pen_x, c_prev = c, g_prev = g) {
- g = blf_utf8_next_fast(font, gc, str, &i, &c);
+ g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
if (blf_font_width_to_strlen_glyph_process(font, c_prev, c, g_prev, g, &pen_x, width_i)) {
break;
@@ -713,7 +717,7 @@ size_t blf_font_width_to_strlen(
}
size_t blf_font_width_to_rstrlen(
- FontBLF *font, const char *str, size_t len, float width, float *r_width)
+ FontBLF *font, const char *str, const size_t str_len, float width, float *r_width)
{
unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev;
@@ -724,14 +728,14 @@ size_t blf_font_width_to_rstrlen(
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
const int width_i = (int)width;
- i = BLI_strnlen(str, len);
+ i = BLI_strnlen(str, str_len);
s = BLI_str_find_prev_char_utf8(str, &str[i]);
i = (size_t)((s != NULL) ? s - str : 0);
s_prev = BLI_str_find_prev_char_utf8(str, s);
i_prev = (size_t)((s_prev != NULL) ? s_prev - str : 0);
i_tmp = i;
- g = blf_utf8_next_fast(font, gc, str, &i_tmp, &c);
+ g = blf_utf8_next_fast(font, gc, str, str_len, &i_tmp, &c);
for (width_new = pen_x = 0; (s != NULL);
i = i_prev, s = s_prev, c = c_prev, g = g_prev, g_prev = NULL, width_new = pen_x) {
s_prev = BLI_str_find_prev_char_utf8(str, s);
@@ -739,7 +743,7 @@ size_t blf_font_width_to_rstrlen(
if (s_prev != NULL) {
i_tmp = i_prev;
- g_prev = blf_utf8_next_fast(font, gc, str, &i_tmp, &c_prev);
+ g_prev = blf_utf8_next_fast(font, gc, str, str_len, &i_tmp, &c_prev);
BLI_assert(i_tmp == i);
}
@@ -765,7 +769,7 @@ size_t blf_font_width_to_rstrlen(
static void blf_font_boundbox_ex(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
- size_t len,
+ const size_t str_len,
rctf *box,
struct ResultBLF *r_info,
int pen_y)
@@ -781,8 +785,8 @@ static void blf_font_boundbox_ex(FontBLF *font,
box->ymin = 32000.0f;
box->ymax = -32000.0f;
- while ((i < len) && str[i]) {
- g = blf_utf8_next_fast(font, gc, str, &i, &c);
+ while ((i < str_len) && str[i]) {
+ g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
break;
@@ -829,16 +833,16 @@ static void blf_font_boundbox_ex(FontBLF *font,
}
}
void blf_font_boundbox(
- FontBLF *font, const char *str, size_t len, rctf *r_box, struct ResultBLF *r_info)
+ FontBLF *font, const char *str, const size_t str_len, rctf *r_box, struct ResultBLF *r_info)
{
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- blf_font_boundbox_ex(font, gc, str, len, r_box, r_info, 0);
+ blf_font_boundbox_ex(font, gc, str, str_len, r_box, r_info, 0);
blf_glyph_cache_release(font);
}
void blf_font_width_and_height(FontBLF *font,
const char *str,
- size_t len,
+ const size_t str_len,
float *r_width,
float *r_height,
struct ResultBLF *r_info)
@@ -856,16 +860,19 @@ void blf_font_width_and_height(FontBLF *font,
}
if (font->flags & BLF_WORD_WRAP) {
- blf_font_boundbox__wrap(font, str, len, &box, r_info);
+ blf_font_boundbox__wrap(font, str, str_len, &box, r_info);
}
else {
- blf_font_boundbox(font, str, len, &box, r_info);
+ blf_font_boundbox(font, str, str_len, &box, r_info);
}
*r_width = (BLI_rctf_size_x(&box) * xa);
*r_height = (BLI_rctf_size_y(&box) * ya);
}
-float blf_font_width(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+float blf_font_width(FontBLF *font,
+ const char *str,
+ const size_t str_len,
+ struct ResultBLF *r_info)
{
float xa;
rctf box;
@@ -878,15 +885,18 @@ float blf_font_width(FontBLF *font, const char *str, size_t len, struct ResultBL
}
if (font->flags & BLF_WORD_WRAP) {
- blf_font_boundbox__wrap(font, str, len, &box, r_info);
+ blf_font_boundbox__wrap(font, str, str_len, &box, r_info);
}
else {
- blf_font_boundbox(font, str, len, &box, r_info);
+ blf_font_boundbox(font, str, str_len, &box, r_info);
}
return BLI_rctf_size_x(&box) * xa;
}
-float blf_font_height(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+float blf_font_height(FontBLF *font,
+ const char *str,
+ const size_t str_len,
+ struct ResultBLF *r_info)
{
float ya;
rctf box;
@@ -899,10 +909,10 @@ float blf_font_height(FontBLF *font, const char *str, size_t len, struct ResultB
}
if (font->flags & BLF_WORD_WRAP) {
- blf_font_boundbox__wrap(font, str, len, &box, r_info);
+ blf_font_boundbox__wrap(font, str, str_len, &box, r_info);
}
else {
- blf_font_boundbox(font, str, len, &box, r_info);
+ blf_font_boundbox(font, str, str_len, &box, r_info);
}
return BLI_rctf_size_y(&box) * ya;
}
@@ -930,7 +940,7 @@ float blf_font_fixed_width(FontBLF *font)
static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
- size_t len,
+ const size_t str_len,
BLF_GlyphBoundsFn user_fn,
void *user_data,
struct ResultBLF *r_info,
@@ -942,14 +952,14 @@ static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
size_t i = 0, i_curr;
rcti gbox;
- if (len == 0) {
+ if (str_len == 0) {
/* early output. */
return;
}
- while ((i < len) && str[i]) {
+ while ((i < str_len) && str[i]) {
i_curr = i;
- g = blf_utf8_next_fast(font, gc, str, &i, &c);
+ g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
break;
@@ -981,13 +991,13 @@ static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
}
void blf_font_boundbox_foreach_glyph(FontBLF *font,
const char *str,
- size_t len,
+ const size_t str_len,
BLF_GlyphBoundsFn user_fn,
void *user_data,
struct ResultBLF *r_info)
{
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- blf_font_boundbox_foreach_glyph_ex(font, gc, str, len, user_fn, user_data, r_info, 0);
+ blf_font_boundbox_foreach_glyph_ex(font, gc, str, str_len, user_fn, user_data, r_info, 0);
blf_glyph_cache_release(font);
}
@@ -1008,12 +1018,12 @@ void blf_font_boundbox_foreach_glyph(FontBLF *font,
*/
static void blf_font_wrap_apply(FontBLF *font,
const char *str,
- size_t len,
+ const size_t str_len,
struct ResultBLF *r_info,
void (*callback)(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
- size_t len,
+ const size_t str_len,
int pen_y,
void *userdata),
void *userdata)
@@ -1032,14 +1042,14 @@ static void blf_font_wrap_apply(FontBLF *font,
size_t start, last[2];
} wrap = {font->wrap_width != -1 ? font->wrap_width : INT_MAX, 0, {0, 0}};
- // printf("%s wrapping (%d, %d) `%s`:\n", __func__, len, strlen(str), str);
- while ((i < len) && str[i]) {
+ // printf("%s wrapping (%d, %d) `%s`:\n", __func__, str_len, strlen(str), str);
+ while ((i < str_len) && str[i]) {
/* wrap vars */
size_t i_curr = i;
bool do_draw = false;
- g = blf_utf8_next_fast(font, gc, str, &i, &c);
+ g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
break;
@@ -1061,7 +1071,7 @@ static void blf_font_wrap_apply(FontBLF *font,
if (UNLIKELY((pen_x_next >= wrap.wrap_width) && (wrap.start != wrap.last[0]))) {
do_draw = true;
}
- else if (UNLIKELY(((i < len) && str[i]) == 0)) {
+ else if (UNLIKELY(((i < str_len) && str[i]) == 0)) {
/* need check here for trailing newline, else we draw it */
wrap.last[0] = i + ((g->c != '\n') ? 1 : 0);
wrap.last[1] = i;
@@ -1112,54 +1122,61 @@ static void blf_font_wrap_apply(FontBLF *font,
static void blf_font_draw__wrap_cb(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
- size_t len,
+ const size_t str_len,
int pen_y,
void *UNUSED(userdata))
{
- blf_font_draw_ex(font, gc, str, len, NULL, pen_y);
+ blf_font_draw_ex(font, gc, str, str_len, NULL, pen_y);
}
-void blf_font_draw__wrap(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+void blf_font_draw__wrap(FontBLF *font,
+ const char *str,
+ const size_t str_len,
+ struct ResultBLF *r_info)
{
- blf_font_wrap_apply(font, str, len, r_info, blf_font_draw__wrap_cb, NULL);
+ blf_font_wrap_apply(font, str, str_len, r_info, blf_font_draw__wrap_cb, NULL);
}
/* blf_font_boundbox__wrap */
-static void blf_font_boundbox_wrap_cb(
- FontBLF *font, GlyphCacheBLF *gc, const char *str, size_t len, int pen_y, void *userdata)
+static void blf_font_boundbox_wrap_cb(FontBLF *font,
+ GlyphCacheBLF *gc,
+ const char *str,
+ const size_t str_len,
+ int pen_y,
+ void *userdata)
{
rctf *box = userdata;
rctf box_single;
- blf_font_boundbox_ex(font, gc, str, len, &box_single, NULL, pen_y);
+ blf_font_boundbox_ex(font, gc, str, str_len, &box_single, NULL, pen_y);
BLI_rctf_union(box, &box_single);
}
void blf_font_boundbox__wrap(
- FontBLF *font, const char *str, size_t len, rctf *box, struct ResultBLF *r_info)
+ FontBLF *font, const char *str, const size_t str_len, rctf *box, struct ResultBLF *r_info)
{
box->xmin = 32000.0f;
box->xmax = -32000.0f;
box->ymin = 32000.0f;
box->ymax = -32000.0f;
- blf_font_wrap_apply(font, str, len, r_info, blf_font_boundbox_wrap_cb, box);
+ blf_font_wrap_apply(font, str, str_len, r_info, blf_font_boundbox_wrap_cb, box);
}
/* blf_font_draw_buffer__wrap */
static void blf_font_draw_buffer__wrap_cb(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
- size_t len,
+ const size_t str_len,
int pen_y,
void *UNUSED(userdata))
{
- blf_font_draw_buffer_ex(font, gc, str, len, NULL, pen_y);
+ blf_font_draw_buffer_ex(font, gc, str, str_len, NULL, pen_y);
}
void blf_font_draw_buffer__wrap(FontBLF *font,
const char *str,
- size_t len,
+ const size_t str_len,
struct ResultBLF *r_info)
{
- blf_font_wrap_apply(font, str, len, r_info, blf_font_draw_buffer__wrap_cb, NULL);
+ blf_font_wrap_apply(font, str, str_len, r_info, blf_font_draw_buffer__wrap_cb, NULL);
}
/** \} */
@@ -1170,20 +1187,21 @@ void blf_font_draw_buffer__wrap(FontBLF *font,
int blf_font_count_missing_chars(FontBLF *font,
const char *str,
- const size_t len,
+ const size_t str_len,
int *r_tot_chars)
{
int missing = 0;
size_t i = 0;
*r_tot_chars = 0;
- while (i < len) {
+ while (i < str_len) {
unsigned int c;
if ((c = str[i]) < GLYPH_ASCII_TABLE_SIZE) {
i++;
}
- else if ((c = BLI_str_utf8_as_unicode_step(str, &i)) != BLI_UTF8_ERR) {
+ else {
+ c = BLI_str_utf8_as_unicode_step(str, str_len, &i);
if (FT_Get_Char_Index((font)->face, c) == 0) {
missing++;
}
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index ab2a26b1e06..6fd5e8b7503 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -53,46 +53,55 @@ struct FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem
void blf_font_attach_from_mem(struct FontBLF *font, const unsigned char *mem, int mem_size);
void blf_font_size(struct FontBLF *font, unsigned int size, unsigned int dpi);
-void blf_font_draw(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
+void blf_font_draw(struct FontBLF *font,
+ const char *str,
+ size_t str_len,
+ struct ResultBLF *r_info);
void blf_font_draw__wrap(struct FontBLF *font,
const char *str,
- size_t len,
+ size_t str_len,
struct ResultBLF *r_info);
void blf_font_draw_ascii(struct FontBLF *font,
const char *str,
- size_t len,
+ size_t str_len,
struct ResultBLF *r_info);
-int blf_font_draw_mono(struct FontBLF *font, const char *str, size_t len, int cwidth);
+int blf_font_draw_mono(struct FontBLF *font, const char *str, size_t str_len, int cwidth);
void blf_font_draw_buffer(struct FontBLF *font,
const char *str,
- size_t len,
+ size_t str_len,
struct ResultBLF *r_info);
void blf_font_draw_buffer__wrap(struct FontBLF *font,
const char *str,
- size_t len,
+ size_t str_len,
struct ResultBLF *r_info);
size_t blf_font_width_to_strlen(
- struct FontBLF *font, const char *str, size_t len, float width, float *r_width);
+ struct FontBLF *font, const char *str, size_t str_len, float width, float *r_width);
size_t blf_font_width_to_rstrlen(
- struct FontBLF *font, const char *str, size_t len, float width, float *r_width);
+ struct FontBLF *font, const char *str, size_t str_len, float width, float *r_width);
void blf_font_boundbox(struct FontBLF *font,
const char *str,
- size_t len,
+ size_t str_len,
struct rctf *r_box,
struct ResultBLF *r_info);
void blf_font_boundbox__wrap(struct FontBLF *font,
const char *str,
- size_t len,
+ size_t str_len,
struct rctf *r_box,
struct ResultBLF *r_info);
void blf_font_width_and_height(struct FontBLF *font,
const char *str,
- size_t len,
+ size_t str_len,
float *r_width,
float *r_height,
struct ResultBLF *r_info);
-float blf_font_width(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
-float blf_font_height(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
+float blf_font_width(struct FontBLF *font,
+ const char *str,
+ size_t str_len,
+ struct ResultBLF *r_info);
+float blf_font_height(struct FontBLF *font,
+ const char *str,
+ size_t str_len,
+ struct ResultBLF *r_info);
float blf_font_fixed_width(struct FontBLF *font);
int blf_font_height_max(struct FontBLF *font);
int blf_font_width_max(struct FontBLF *font);
@@ -103,7 +112,7 @@ char *blf_display_name(struct FontBLF *font);
void blf_font_boundbox_foreach_glyph(struct FontBLF *font,
const char *str,
- size_t len,
+ size_t str_len,
bool (*user_fn)(const char *str,
const size_t str_step_ofs,
const struct rcti *glyph_step_bounds,
@@ -116,7 +125,7 @@ void blf_font_boundbox_foreach_glyph(struct FontBLF *font,
int blf_font_count_missing_chars(struct FontBLF *font,
const char *str,
- const size_t len,
+ const size_t str_len,
int *r_tot_chars);
void blf_font_free(struct FontBLF *font);
diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h
index bb875f8d1c9..a50faedcc3c 100644
--- a/source/blender/blenkernel/BKE_lib_id.h
+++ b/source/blender/blenkernel/BKE_lib_id.h
@@ -166,8 +166,14 @@ struct ID *BKE_libblock_find_name(struct Main *bmain,
*/
typedef enum eLibIDDuplicateFlags {
/** This call to a duplicate function is part of another call for some parent ID.
- * Therefore, this sub-process should not clear `newid` pointers, nor handle remapping itself. */
+ * Therefore, this sub-process should not clear `newid` pointers, nor handle remapping itself.
+ * NOTE: In some cases (like Object one), the duplicate function may be called on the root ID
+ * with this flag set, as remapping and/or other similar tasks need to be handled by the caller.
+ */
LIB_ID_DUPLICATE_IS_SUBPROCESS = 1 << 0,
+ /** This call is performed on a 'root' ID, and should therefore perform some decisions regarding
+ * sub-IDs (dependencies), check for linked vs. locale data, etc. */
+ LIB_ID_DUPLICATE_IS_ROOT_ID = 1 << 1,
} eLibIDDuplicateFlags;
/* lib_remap.c (keep here since they're general functions) */
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index ae464a48e9e..dbcefb8b6d5 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -143,11 +143,6 @@ int BKE_mesh_mface_index_validate(struct MFace *mface,
struct Mesh *BKE_mesh_from_object(struct Object *ob);
void BKE_mesh_assign_object(struct Main *bmain, struct Object *ob, struct Mesh *me);
void BKE_mesh_from_metaball(struct ListBase *lb, struct Mesh *me);
-void BKE_mesh_from_nurbs_displist(struct Main *bmain,
- struct Object *ob,
- struct ListBase *dispbase,
- const char *obdata_name,
- bool temporary);
void BKE_mesh_to_curve_nurblist(const struct Mesh *me,
struct ListBase *nurblist,
const int edge_users_test);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index c4393246926..06528cd213c 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -346,7 +346,7 @@ typedef struct bNodeType {
#define NODE_CLASS_OP_FILTER 5
#define NODE_CLASS_GROUP 6
// #define NODE_CLASS_FILE 7
-#define NODE_CLASS_CONVERTOR 8
+#define NODE_CLASS_CONVERTER 8
#define NODE_CLASS_MATTE 9
#define NODE_CLASS_DISTORT 10
// #define NODE_CLASS_OP_DYNAMIC 11 /* deprecated */
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index e5b547d2557..78a6e47ec48 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -368,7 +368,10 @@ struct ModifierData *object_copy_particle_system(struct Main *bmain,
struct Scene *scene,
struct Object *ob,
const struct ParticleSystem *psys_orig);
-void object_remove_particle_system(struct Main *bmain, struct Scene *scene, struct Object *ob);
+void object_remove_particle_system(struct Main *bmain,
+ struct Scene *scene,
+ struct Object *ob,
+ struct ParticleSystem *psys);
struct ParticleSettings *BKE_particlesettings_add(struct Main *bmain, const char *name);
void psys_reset(struct ParticleSystem *psys, int mode);
diff --git a/source/blender/blenkernel/intern/bvhutils.cc b/source/blender/blenkernel/intern/bvhutils.cc
index 164f921c7ac..707201207d9 100644
--- a/source/blender/blenkernel/intern/bvhutils.cc
+++ b/source/blender/blenkernel/intern/bvhutils.cc
@@ -1254,11 +1254,10 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
bool in_cache = bvhcache_find(
bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
BVHCache *bvh_cache = *bvh_cache_p;
- bvhtree_balance(tree, true);
-
if (in_cache == false) {
tree = bvhtree_from_editmesh_looptri_create_tree(
epsilon, tree_type, axis, em, looptri_mask, looptri_num_active);
+ bvhtree_balance(tree, true);
/* Save on cache for later use */
// printf("BVHTree built and saved on cache\n");
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 46b079fb42e..b77855f8f95 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -92,11 +92,6 @@ static void camera_copy_data(Main *UNUSED(bmain),
BLI_duplicatelist(&cam_dst->bg_images, &cam_src->bg_images);
}
-static void camera_make_local(Main *bmain, ID *id, const int flags)
-{
- BKE_lib_id_make_local_generic(bmain, id, flags);
-}
-
/** Free (or release) any data used by this camera (does not free the camera itself). */
static void camera_free_data(ID *id)
{
@@ -192,7 +187,7 @@ IDTypeInfo IDType_ID_CA = {
.init_data = camera_init_data,
.copy_data = camera_copy_data,
.free_data = camera_free_data,
- .make_local = camera_make_local,
+ .make_local = NULL,
.foreach_id = camera_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index d36e9b67d00..2d172f23428 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -692,14 +692,18 @@ Collection *BKE_collection_duplicate(Main *bmain,
eLibIDDuplicateFlags duplicate_options)
{
const bool is_subprocess = (duplicate_options & LIB_ID_DUPLICATE_IS_SUBPROCESS) != 0;
+ const bool is_root_id = (duplicate_options & LIB_ID_DUPLICATE_IS_ROOT_ID) != 0;
if (!is_subprocess) {
BKE_main_id_newptr_and_tag_clear(bmain);
+ }
+ if (is_root_id) {
/* In case root duplicated ID is linked, assume we want to get a local copy of it and duplicate
* all expected linked data. */
if (ID_IS_LINKED(collection)) {
duplicate_flags |= USER_DUP_LINKED_ID;
}
+ duplicate_options &= ~LIB_ID_DUPLICATE_IS_ROOT_ID;
}
Collection *collection_new = collection_duplicate_recursive(
diff --git a/source/blender/blenkernel/intern/gpencil_geom.cc b/source/blender/blenkernel/intern/gpencil_geom.cc
index 0f218d6166c..5bca20ecd44 100644
--- a/source/blender/blenkernel/intern/gpencil_geom.cc
+++ b/source/blender/blenkernel/intern/gpencil_geom.cc
@@ -620,7 +620,10 @@ bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const
}
if (new_count == 1) {
- BKE_gpencil_free_stroke_weights(gps);
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
MEM_freeN(gps->points);
gps->points = nullptr;
gps->dvert = nullptr;
@@ -628,27 +631,24 @@ bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const
return false;
}
- new_pt = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * new_count, "gp_stroke_points_trimmed");
-
- for (int i = 0; i < new_count; i++) {
- memcpy(&new_pt[i], &pt[i + index_from], sizeof(bGPDspoint));
- }
+ new_pt = (bGPDspoint *)MEM_mallocN(sizeof(bGPDspoint) * new_count, "gp_stroke_points_trimmed");
+ memcpy(new_pt, &pt[index_from], sizeof(bGPDspoint) * new_count);
if (gps->dvert) {
- new_dv = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * new_count,
+ new_dv = (MDeformVert *)MEM_mallocN(sizeof(MDeformVert) * new_count,
"gp_stroke_dverts_trimmed");
for (int i = 0; i < new_count; i++) {
dv = &gps->dvert[i + index_from];
new_dv[i].flag = dv->flag;
new_dv[i].totweight = dv->totweight;
- new_dv[i].dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight,
+ new_dv[i].dw = (MDeformWeight *)MEM_mallocN(sizeof(MDeformWeight) * dv->totweight,
"gp_stroke_dverts_dw_trimmed");
for (int j = 0; j < dv->totweight; j++) {
new_dv[i].dw[j].weight = dv->dw[j].weight;
new_dv[i].dw[j].def_nr = dv->dw[j].def_nr;
}
- BKE_defvert_clear(dv);
}
+ BKE_gpencil_free_stroke_weights(gps);
MEM_freeN(gps->dvert);
gps->dvert = new_dv;
}
@@ -692,25 +692,21 @@ bool BKE_gpencil_stroke_split(bGPdata *gpd,
gpf, gps, gps->mat_nr, new_count, gps->thickness);
new_pt = new_gps->points; /* Allocated from above. */
-
- for (int i = 0; i < new_count; i++) {
- memcpy(&new_pt[i], &pt[i + before_index], sizeof(bGPDspoint));
- }
+ memcpy(new_pt, &pt[before_index], sizeof(bGPDspoint) * new_count);
if (gps->dvert) {
- new_dv = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * new_count,
+ new_dv = (MDeformVert *)MEM_mallocN(sizeof(MDeformVert) * new_count,
"gp_stroke_dverts_remaining(MDeformVert)");
for (int i = 0; i < new_count; i++) {
dv = &gps->dvert[i + before_index];
new_dv[i].flag = dv->flag;
new_dv[i].totweight = dv->totweight;
- new_dv[i].dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight,
+ new_dv[i].dw = (MDeformWeight *)MEM_mallocN(sizeof(MDeformWeight) * dv->totweight,
"gp_stroke_dverts_dw_remaining(MDeformWeight)");
for (int j = 0; j < dv->totweight; j++) {
new_dv[i].dw[j].weight = dv->dw[j].weight;
new_dv[i].dw[j].def_nr = dv->dw[j].def_nr;
}
- BKE_defvert_clear(dv);
}
new_gps->dvert = new_dv;
}
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 0f880d16358..aa458bc1b27 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -153,7 +153,7 @@ static int lib_id_clear_library_data_users_update_cb(LibraryIDLinkCallbackData *
* Pull an ID out of a library (make it local). Only call this for IDs that
* don't have other library users.
*/
-static void lib_id_clear_library_data_ex(Main *bmain, ID *id)
+void BKE_lib_id_clear_library_data(Main *bmain, ID *id)
{
const bool id_in_mainlist = (id->tag & LIB_TAG_NO_MAIN) == 0 &&
(id->flag & LIB_EMBEDDED_DATA) == 0;
@@ -193,17 +193,12 @@ static void lib_id_clear_library_data_ex(Main *bmain, ID *id)
* IDs here, this is down automatically in `lib_id_expand_local_cb()`. */
Key *key = BKE_key_from_id(id);
if (key != NULL) {
- lib_id_clear_library_data_ex(bmain, &key->id);
+ BKE_lib_id_clear_library_data(bmain, &key->id);
}
DEG_relations_tag_update(bmain);
}
-void BKE_lib_id_clear_library_data(Main *bmain, ID *id)
-{
- lib_id_clear_library_data_ex(bmain, id);
-}
-
void id_lib_extern(ID *id)
{
if (id && ID_IS_LINKED(id)) {
@@ -369,7 +364,7 @@ static int lib_id_expand_local_cb(LibraryIDLinkCallbackData *cb_data)
if (*id_pointer != NULL && ID_IS_LINKED(*id_pointer)) {
BLI_assert(*id_pointer != id_self);
- lib_id_clear_library_data_ex(bmain, *id_pointer);
+ BKE_lib_id_clear_library_data(bmain, *id_pointer);
}
return IDWALK_RET_NOP;
}
@@ -429,7 +424,7 @@ void BKE_lib_id_make_local_generic(Main *bmain, ID *id, const int flags)
if (lib_local || is_local) {
if (!is_lib) {
- lib_id_clear_library_data_ex(bmain, id);
+ BKE_lib_id_clear_library_data(bmain, id);
BKE_lib_id_expand_local(bmain, id);
}
else {
@@ -1481,7 +1476,7 @@ static bool id_name_final_build(char *name, char *base_name, size_t base_name_le
/* Code above may have generated invalid utf-8 string, due to raw truncation.
* Ensure we get a valid one now. */
- base_name_len -= (size_t)BLI_utf8_invalid_strip(base_name, base_name_len);
+ base_name_len -= (size_t)BLI_str_utf8_invalid_strip(base_name, base_name_len);
/* Also truncate orig name, and start the whole check again. */
name[base_name_len] = '\0';
@@ -1731,7 +1726,7 @@ bool BKE_id_new_name_validate(ListBase *lb, ID *id, const char *tname, const boo
else {
/* disallow non utf8 chars,
* the interface checks for this but new ID's based on file names don't */
- BLI_utf8_invalid_strip(name, strlen(name));
+ BLI_str_utf8_invalid_strip(name, strlen(name));
}
ID *id_sorting_hint = NULL;
@@ -2014,7 +2009,7 @@ void BKE_library_make_local(Main *bmain,
* currently there are some indirect usages. So instead of making a copy that we'll likely
* get rid of later, directly make that data block local.
* Saves a tremendous amount of time with complex scenes... */
- lib_id_clear_library_data_ex(bmain, id);
+ BKE_lib_id_clear_library_data(bmain, id);
BKE_lib_id_expand_local(bmain, id);
id->tag &= ~LIB_TAG_DOIT;
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index eb8e6aad736..e3650e03c8a 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -466,8 +466,10 @@ static int customdata_compare(
int vtot = m1->totvert;
for (j = 0; j < vtot; j++, v1++, v2++) {
- if (len_squared_v3v3(v1->co, v2->co) > thresh_sq) {
- return MESHCMP_VERTCOMISMATCH;
+ for (int k = 0; k < 3; k++) {
+ if (compare_threshold_relative(v1->co[k], v2->co[k], thresh)) {
+ return MESHCMP_VERTCOMISMATCH;
+ }
}
/* I don't care about normals, let's just do coordinates. */
}
@@ -547,8 +549,7 @@ static int customdata_compare(
int ltot = m1->totloop;
for (j = 0; j < ltot; j++, lp1++, lp2++) {
- if (abs(lp1->r - lp2->r) > thresh || abs(lp1->g - lp2->g) > thresh ||
- abs(lp1->b - lp2->b) > thresh || abs(lp1->a - lp2->a) > thresh) {
+ if (lp1->r != lp2->r || lp1->g != lp2->g || lp1->b != lp2->b || lp1->a != lp2->a) {
return MESHCMP_LOOPCOLMISMATCH;
}
}
@@ -583,7 +584,7 @@ static int customdata_compare(
const float *l2_data = l2->data;
for (int i = 0; i < total_length; i++) {
- if (fabsf(l1_data[i] - l2_data[i]) > thresh) {
+ if (compare_threshold_relative(l1_data[i], l2_data[i], thresh)) {
return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
}
}
@@ -594,7 +595,10 @@ static int customdata_compare(
const float(*l2_data)[2] = l2->data;
for (int i = 0; i < total_length; i++) {
- if (len_squared_v2v2(l1_data[i], l2_data[i]) > thresh_sq) {
+ if (compare_threshold_relative(l1_data[i][0], l2_data[i][0], thresh)) {
+ return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
+ }
+ if (compare_threshold_relative(l1_data[i][1], l2_data[i][1], thresh)) {
return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
}
}
@@ -605,7 +609,13 @@ static int customdata_compare(
const float(*l2_data)[3] = l2->data;
for (int i = 0; i < total_length; i++) {
- if (len_squared_v3v3(l1_data[i], l2_data[i]) > thresh_sq) {
+ if (compare_threshold_relative(l1_data[i][0], l2_data[i][0], thresh)) {
+ return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
+ }
+ if (compare_threshold_relative(l1_data[i][1], l2_data[i][1], thresh)) {
+ return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
+ }
+ if (compare_threshold_relative(l1_data[i][2], l2_data[i][2], thresh)) {
return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
}
}
@@ -639,7 +649,7 @@ static int customdata_compare(
for (int i = 0; i < total_length; i++) {
for (j = 0; j < 4; j++) {
- if (fabsf(l1_data[i].color[j] - l2_data[i].color[j]) > thresh) {
+ if (compare_threshold_relative(l1_data[i].color[j], l2_data[i].color[j], thresh)) {
return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
}
}
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index 4b1eb5b39ce..d5524312612 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -548,11 +548,12 @@ Mesh *BKE_mesh_new_nomain_from_curve(const Object *ob)
return BKE_mesh_new_nomain_from_curve_displist(ob, &disp);
}
-/* this may fail replacing ob->data, be sure to check ob->type */
-void BKE_mesh_from_nurbs_displist(
- Main *bmain, Object *ob, ListBase *dispbase, const char *obdata_name, bool temporary)
+static void mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const char *obdata_name)
{
- Object *ob1;
+ if (ob->runtime.data_eval && GS(((ID *)ob->runtime.data_eval)->name) != ID_ME) {
+ return;
+ }
+
Mesh *me_eval = (Mesh *)ob->runtime.data_eval;
Mesh *me;
MVert *allvert = NULL;
@@ -581,12 +582,7 @@ void BKE_mesh_from_nurbs_displist(
}
/* make mesh */
- if (bmain != NULL) {
- me = BKE_mesh_add(bmain, obdata_name);
- }
- else {
- me = BKE_id_new_nomain(ID_ME, obdata_name);
- }
+ me = BKE_id_new_nomain(ID_ME, obdata_name);
me->totvert = totvert;
me->totedge = totedge;
@@ -607,12 +603,7 @@ void BKE_mesh_from_nurbs_displist(
BKE_mesh_calc_normals(me);
}
else {
- if (bmain != NULL) {
- me = BKE_mesh_add(bmain, obdata_name);
- }
- else {
- me = BKE_id_new_nomain(ID_ME, obdata_name);
- }
+ me = BKE_id_new_nomain(ID_ME, obdata_name);
ob->runtime.data_eval = NULL;
BKE_mesh_nomain_to_mesh(me_eval, me, ob, &CD_MASK_MESH, true);
@@ -641,30 +632,10 @@ void BKE_mesh_from_nurbs_displist(
ob->data = me;
ob->type = OB_MESH;
- /* other users */
- if (bmain != NULL) {
- ob1 = bmain->objects.first;
- while (ob1) {
- if (ob1->data == cu) {
- ob1->type = OB_MESH;
-
- id_us_min((ID *)ob1->data);
- ob1->data = ob->data;
- id_us_plus((ID *)ob1->data);
- }
- ob1 = ob1->id.next;
- }
- }
-
- if (temporary) {
- /* For temporary objects in BKE_mesh_new_from_object don't remap
- * the entire scene with associated depsgraph updates, which are
- * problematic for renderers exporting data. */
- BKE_id_free(NULL, cu);
- }
- else {
- BKE_id_free_us(bmain, cu);
- }
+ /* For temporary objects in BKE_mesh_new_from_object don't remap
+ * the entire scene with associated depsgraph updates, which are
+ * problematic for renderers exporting data. */
+ BKE_id_free(NULL, cu);
}
typedef struct EdgeLink {
@@ -965,7 +936,7 @@ void BKE_pointcloud_to_mesh(Main *bmain, Depsgraph *depsgraph, Scene *UNUSED(sce
/* Create a temporary object to be used for nurbs-to-mesh conversion.
*
- * This is more complex that it should be because BKE_mesh_from_nurbs_displist() will do more than
+ * This is more complex that it should be because #mesh_from_nurbs_displist will do more than
* simply conversion and will attempt to take over ownership of evaluated result and will also
* modify the input object. */
static Object *object_for_curve_to_mesh_create(Object *object)
@@ -1063,7 +1034,7 @@ static void curve_to_mesh_eval_ensure(Object *object)
* they are only used for modifier stack, which we have explicitly disabled for all objects.
*
* TODO(sergey): This is a very fragile logic, but proper solution requires re-writing quite a
- * bit of internal functions (BKE_mesh_from_nurbs_displist, BKE_mesh_nomain_to_mesh) and also
+ * bit of internal functions (#mesh_from_nurbs_displist, BKE_mesh_nomain_to_mesh) and also
* Mesh From Curve operator.
* Brecht says hold off with that. */
Mesh *mesh_eval = NULL;
@@ -1102,10 +1073,10 @@ static Mesh *mesh_new_from_curve_type_object(Object *object)
temp_curve->editnurb = NULL;
/* Convert to mesh. */
- BKE_mesh_from_nurbs_displist(
- NULL, temp_object, &temp_object->runtime.curve_cache->disp, curve->id.name + 2, true);
+ mesh_from_nurbs_displist(
+ temp_object, &temp_object->runtime.curve_cache->disp, curve->id.name + 2);
- /* BKE_mesh_from_nurbs_displist changes the type to a mesh, check it worked. If it didn't
+ /* #mesh_from_nurbs_displist changes the type to a mesh, check it worked. If it didn't
* the curve did not have any segments or otherwise would have generated an empty mesh. */
if (temp_object->type != OB_MESH) {
BKE_id_free(NULL, temp_object->data);
@@ -1117,7 +1088,7 @@ static Mesh *mesh_new_from_curve_type_object(Object *object)
BKE_id_free(NULL, temp_object);
- /* NOTE: Materials are copied in BKE_mesh_from_nurbs_displist(). */
+ /* NOTE: Materials are copied in #mesh_from_nurbs_displist(). */
return mesh_result;
}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 1c08a46adc3..6e26ed4925d 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -2614,17 +2614,21 @@ void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
Object *BKE_object_duplicate(Main *bmain,
Object *ob,
eDupli_ID_Flags dupflag,
- const eLibIDDuplicateFlags duplicate_options)
+ eLibIDDuplicateFlags duplicate_options)
{
const bool is_subprocess = (duplicate_options & LIB_ID_DUPLICATE_IS_SUBPROCESS) != 0;
+ const bool is_root_id = (duplicate_options & LIB_ID_DUPLICATE_IS_ROOT_ID) != 0;
if (!is_subprocess) {
BKE_main_id_newptr_and_tag_clear(bmain);
+ }
+ if (is_root_id) {
/* In case root duplicated ID is linked, assume we want to get a local copy of it and duplicate
* all expected linked data. */
if (ID_IS_LINKED(ob)) {
dupflag |= USER_DUP_LINKED_ID;
}
+ duplicate_options &= ~LIB_ID_DUPLICATE_IS_ROOT_ID;
}
Material ***matarar;
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 29849c69b6f..50b0fb1c9f5 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -3967,16 +3967,18 @@ ModifierData *object_copy_particle_system(Main *bmain,
return object_add_or_copy_particle_system(bmain, scene, ob, NULL, psys_orig);
}
-void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob)
+void object_remove_particle_system(Main *bmain,
+ Scene *UNUSED(scene),
+ Object *ob,
+ ParticleSystem *psys)
{
- ParticleSystem *psys = psys_get_current(ob);
- ParticleSystemModifierData *psmd;
- ModifierData *md;
-
- if (!psys) {
+ if (!ob || !psys) {
return;
}
+ ParticleSystemModifierData *psmd;
+ ModifierData *md;
+
/* Clear particle system in fluid modifier. */
if ((md = BKE_modifiers_findby_type(ob, eModifierType_Fluid))) {
FluidModifierData *fmd = (FluidModifierData *)md;
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 3fe00adc4d5..5a668746956 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -1176,11 +1176,6 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
seq->flag |= SEQ_EFFECT_NOT_LOADED;
}
- if (seq->type == SEQ_TYPE_SPEED) {
- SpeedControlVars *s = seq->effectdata;
- s->frameMap = NULL;
- }
-
if (seq->type == SEQ_TYPE_TEXT) {
TextVars *t = seq->effectdata;
t->text_blf_id = SEQ_FONT_NOT_LOADED;
@@ -1989,9 +1984,12 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
if (type == SCE_COPY_FULL) {
/* Scene duplication is always root of duplication currently. */
const bool is_subprocess = false;
+ const bool is_root_id = true;
if (!is_subprocess) {
BKE_main_id_newptr_and_tag_clear(bmain);
+ }
+ if (is_root_id) {
/* In case root duplicated ID is linked, assume we want to get a local copy of it and
* duplicate all expected linked data. */
if (ID_IS_LINKED(sce)) {
diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc
index dda7abea0fc..732fabc6582 100644
--- a/source/blender/blenkernel/intern/spline_base.cc
+++ b/source/blender/blenkernel/intern/spline_base.cc
@@ -123,7 +123,7 @@ int Spline::evaluated_edges_size() const
float Spline::length() const
{
Span<float> lengths = this->evaluated_lengths();
- return (lengths.size() == 0) ? 0 : this->evaluated_lengths().last();
+ return lengths.is_empty() ? 0.0f : this->evaluated_lengths().last();
}
int Spline::segments_size() const
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 275cf0d4c38..7f1f6590e48 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -308,7 +308,7 @@ int txt_extended_ascii_as_utf8(char **str)
int added = 0;
while ((*str)[i]) {
- if ((bad_char = BLI_utf8_invalid_byte(*str + i, length - i)) == -1) {
+ if ((bad_char = BLI_str_utf8_invalid_byte(*str + i, length - i)) == -1) {
break;
}
@@ -322,7 +322,7 @@ int txt_extended_ascii_as_utf8(char **str)
i = 0;
while ((*str)[i]) {
- if ((bad_char = BLI_utf8_invalid_byte((*str) + i, length - i)) == -1) {
+ if ((bad_char = BLI_str_utf8_invalid_byte((*str) + i, length - i)) == -1) {
memcpy(newstr + mi, (*str) + i, length - i + 1);
break;
}
@@ -1660,7 +1660,7 @@ void txt_insert_buf(Text *text, const char *in_buffer)
/* Read the first line (or as close as possible */
while (buffer[i] && buffer[i] != '\n') {
- txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &i));
+ txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, len, &i));
}
if (buffer[i] == '\n') {
@@ -1682,7 +1682,7 @@ void txt_insert_buf(Text *text, const char *in_buffer)
}
else {
for (j = i - l; j < i && j < len;) {
- txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &j));
+ txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, len, &j));
}
break;
}
@@ -1888,8 +1888,9 @@ void txt_delete_char(Text *text)
}
}
else { /* Just deleting a char */
- size_t c_len = 0;
- c = BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &c_len);
+ size_t c_len = text->curc;
+ c = BLI_str_utf8_as_unicode_step(text->curl->line, text->curl->len, &c_len);
+ c_len -= text->curc;
UNUSED_VARS(c);
memmove(text->curl->line + text->curc,
@@ -1937,9 +1938,11 @@ void txt_backspace_char(Text *text)
txt_pop_sel(text);
}
else { /* Just backspacing a char */
- size_t c_len = 0;
const char *prev = BLI_str_prev_char_utf8(text->curl->line + text->curc);
- c = BLI_str_utf8_as_unicode_and_size(prev, &c_len);
+ size_t c_len = prev - text->curl->line;
+ c = BLI_str_utf8_as_unicode_step(text->curl->line, text->curl->len, &c_len);
+ c_len -= prev - text->curl->line;
+
UNUSED_VARS(c);
/* source and destination overlap, don't use memcpy() */
@@ -2053,7 +2056,9 @@ bool txt_replace_char(Text *text, unsigned int add)
return txt_add_char(text, add);
}
- del = BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &del_size);
+ del_size = text->curc;
+ del = BLI_str_utf8_as_unicode_step(text->curl->line, text->curl->len, &del_size);
+ del_size -= text->curc;
UNUSED_VARS(del);
add_size = BLI_str_utf8_from_unicode(add, ch);
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 323da7473b5..a20c918c517 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -1248,7 +1248,7 @@ static void flush_ffmpeg(AVCodecContext *c, AVStream *stream, AVFormatContext *o
packet->stream_index = stream->index;
av_packet_rescale_ts(packet, c->time_base, stream->time_base);
# ifdef FFMPEG_USE_DURATION_WORKAROUND
- my_guess_pkt_duration(context->outfile, stream, packet);
+ my_guess_pkt_duration(outfile, stream, packet);
# endif
int write_ret = av_interleaved_write_frame(outfile, packet);
diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h
index e877503e835..9b54f780296 100644
--- a/source/blender/blenlib/BLI_math_base.h
+++ b/source/blender/blenlib/BLI_math_base.h
@@ -172,6 +172,9 @@ MINLINE size_t clamp_z(size_t value, size_t min, size_t max);
MINLINE int compare_ff(float a, float b, const float max_diff);
MINLINE int compare_ff_relative(float a, float b, const float max_diff, const int max_ulps);
+MINLINE bool compare_threshold_relative(const float value1,
+ const float value2,
+ const float thresh);
MINLINE float signf(float f);
MINLINE int signum_i_ex(float a, float eps);
@@ -196,6 +199,8 @@ MINLINE unsigned int log2_ceil_u(unsigned int x);
MINLINE int divide_round_i(int a, int b);
MINLINE int mod_i(int i, int n);
+MINLINE float round_to_even(float f);
+
MINLINE signed char round_fl_to_char(float a);
MINLINE unsigned char round_fl_to_uchar(float a);
MINLINE short round_fl_to_short(float a);
diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h
index 65d9d7863c3..b97c8748ca4 100644
--- a/source/blender/blenlib/BLI_string_utf8.h
+++ b/source/blender/blenlib/BLI_string_utf8.h
@@ -31,20 +31,21 @@ char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t
ATTR_NONNULL();
size_t BLI_strncpy_utf8_rlen(char *__restrict dst, const char *__restrict src, size_t maxncpy)
ATTR_NONNULL();
-ptrdiff_t BLI_utf8_invalid_byte(const char *str, size_t length) ATTR_NONNULL();
-int BLI_utf8_invalid_strip(char *str, size_t length) ATTR_NONNULL();
+ptrdiff_t BLI_str_utf8_invalid_byte(const char *str, size_t length) ATTR_NONNULL();
+int BLI_str_utf8_invalid_strip(char *str, size_t length) ATTR_NONNULL();
/* warning, can return -1 on bad chars */
int BLI_str_utf8_size(const char *p) ATTR_NONNULL();
int BLI_str_utf8_size_safe(const char *p) ATTR_NONNULL();
/* copied from glib */
unsigned int BLI_str_utf8_as_unicode(const char *p) ATTR_NONNULL();
-unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index)
- ATTR_NONNULL();
-unsigned int BLI_str_utf8_as_unicode_and_size_safe(const char *__restrict p,
- size_t *__restrict index) ATTR_NONNULL();
-unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index)
- ATTR_NONNULL();
+unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p,
+ size_t p_len,
+ size_t *__restrict index) ATTR_NONNULL(1, 3);
+unsigned int BLI_str_utf8_as_unicode_step_or_error(const char *__restrict p,
+ size_t p_len,
+ size_t *__restrict index) ATTR_NONNULL(1, 3);
+
size_t BLI_str_utf8_from_unicode(unsigned int c, char *outbuf);
size_t BLI_str_utf8_as_utf32(char32_t *__restrict dst_w,
const char *__restrict src_c,
diff --git a/source/blender/blenlib/intern/filereader_zstd.c b/source/blender/blenlib/intern/filereader_zstd.c
index 785a40cd1a1..55ce32713d9 100644
--- a/source/blender/blenlib/intern/filereader_zstd.c
+++ b/source/blender/blenlib/intern/filereader_zstd.c
@@ -79,7 +79,7 @@ static bool zstd_read_seek_table(ZstdReader *zstd)
if (base->seek(base, -5, SEEK_END) < 0 || base->read(base, &flags, 1) != 1) {
return false;
}
- /* Bit 7 indicates checksums. Bits 5 and 6 must be zero. */
+ /* Bit 7 indicates check-sums. Bits 5 and 6 must be zero. */
bool has_checksums = (flags & 0x80);
if (flags & 0x60) {
return false;
@@ -134,7 +134,7 @@ static bool zstd_read_seek_table(ZstdReader *zstd)
zstd->seek.compressed_ofs[num_frames] = compressed_ofs;
zstd->seek.uncompressed_ofs[num_frames] = uncompressed_ofs;
- /* Seek to the end of the previous frame for the following BHead frame detection. */
+ /* Seek to the end of the previous frame for the following #BHead frame detection. */
if (seek_frame_start != compressed_ofs || base->seek(base, seek_frame_start, SEEK_SET) < 0) {
MEM_freeN(zstd->seek.compressed_ofs);
MEM_freeN(zstd->seek.uncompressed_ofs);
@@ -178,7 +178,7 @@ static const char *zstd_ensure_cache(ZstdReader *zstd, int frame)
return zstd->seek.cached_content;
}
- /* Cached frame doesn't match, so discard it and cache the wanted one onstead. */
+ /* Cached frame doesn't match, so discard it and cache the wanted one instead. */
MEM_SAFE_FREE(zstd->seek.cached_content);
size_t compressed_size = zstd->seek.compressed_ofs[frame + 1] - zstd->seek.compressed_ofs[frame];
diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c
index a8b50b66f5f..e1e3aa273b5 100644
--- a/source/blender/blenlib/intern/freetypefont.c
+++ b/source/blender/blenlib/intern/freetypefont.c
@@ -302,7 +302,7 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile *pf)
/* Get the name. */
if (face->family_name) {
BLI_snprintf(vfd->name, sizeof(vfd->name), "%s %s", face->family_name, face->style_name);
- BLI_utf8_invalid_strip(vfd->name, strlen(vfd->name));
+ BLI_str_utf8_invalid_strip(vfd->name, strlen(vfd->name));
}
/* Select a character map. */
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index a80c495ecf3..49f9faf1704 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -363,6 +363,14 @@ MINLINE signed char round_db_to_char_clamp(double a){
#undef _round_clamp_fl_impl
#undef _round_clamp_db_impl
+/**
+ * Round to closest even number, halfway cases are rounded away from zero.
+ */
+MINLINE float round_to_even(float f)
+{
+ return roundf(f * 0.5f) * 2.0f;
+}
+
/* integer division that rounds 0.5 up, particularly useful for color blending
* with integers, to avoid gradual darkening when rounding down */
MINLINE int divide_round_i(int a, int b)
@@ -648,6 +656,18 @@ MINLINE int compare_ff_relative(float a, float b, const float max_diff, const in
return ((ua.i < 0) != (ub.i < 0)) ? 0 : (abs(ua.i - ub.i) <= max_ulps) ? 1 : 0;
}
+MINLINE bool compare_threshold_relative(const float value1, const float value2, const float thresh)
+{
+ const float abs_diff = fabsf(value1 - value2);
+ /* Avoid letting the threshold get too small just because the values happen to be close to zero.
+ */
+ if (fabsf(value2) < 1) {
+ return abs_diff > thresh;
+ }
+ /* Using relative threshold in general. */
+ return abs_diff > thresh * fabsf(value2);
+}
+
MINLINE float signf(float f)
{
return (f < 0.0f) ? -1.0f : 1.0f;
diff --git a/source/blender/blenlib/intern/string_cursor_utf8.c b/source/blender/blenlib/intern/string_cursor_utf8.c
index 90fde02b11f..59b9f4eeca0 100644
--- a/source/blender/blenlib/intern/string_cursor_utf8.c
+++ b/source/blender/blenlib/intern/string_cursor_utf8.c
@@ -101,11 +101,14 @@ static eStrCursorDelimType cursor_delim_type_unicode(const uint uch)
return STRCUR_DELIM_ALPHANUMERIC; /* Not quite true, but ok for now */
}
-static eStrCursorDelimType cursor_delim_type_utf8(const char *ch_utf8)
+static eStrCursorDelimType cursor_delim_type_utf8(const char *ch_utf8,
+ const size_t ch_utf8_len,
+ const int pos)
{
/* for full unicode support we really need to have large lookup tables to figure
* out what's what in every possible char set - and python, glib both have these. */
- uint uch = BLI_str_utf8_as_unicode(ch_utf8);
+ size_t index = (size_t)pos;
+ uint uch = BLI_str_utf8_as_unicode_step_or_error(ch_utf8, ch_utf8_len, &index);
return cursor_delim_type_unicode(uch);
}
@@ -157,14 +160,16 @@ void BLI_str_cursor_step_utf8(const char *str,
}
if (jump != STRCUR_JUMP_NONE) {
- const eStrCursorDelimType delim_type = (*pos) < maxlen ? cursor_delim_type_utf8(&str[*pos]) :
- STRCUR_DELIM_NONE;
+ const eStrCursorDelimType delim_type = (*pos) < maxlen ?
+ cursor_delim_type_utf8(str, maxlen, *pos) :
+ STRCUR_DELIM_NONE;
/* jump between special characters (/,\,_,-, etc.),
* look at function cursor_delim_type() for complete
* list of special character, ctr -> */
while ((*pos) < maxlen) {
if (BLI_str_cursor_step_next_utf8(str, maxlen, pos)) {
- if ((jump != STRCUR_JUMP_ALL) && (delim_type != cursor_delim_type_utf8(&str[*pos]))) {
+ if ((jump != STRCUR_JUMP_ALL) &&
+ (delim_type != cursor_delim_type_utf8(str, maxlen, *pos))) {
break;
}
}
@@ -184,7 +189,7 @@ void BLI_str_cursor_step_utf8(const char *str,
if (jump != STRCUR_JUMP_NONE) {
const eStrCursorDelimType delim_type = (*pos) > 0 ?
- cursor_delim_type_utf8(&str[(*pos) - 1]) :
+ cursor_delim_type_utf8(str, maxlen, *pos - 1) :
STRCUR_DELIM_NONE;
/* jump between special characters (/,\,_,-, etc.),
* look at function cursor_delim_type() for complete
@@ -192,7 +197,8 @@ void BLI_str_cursor_step_utf8(const char *str,
while ((*pos) > 0) {
const int pos_prev = *pos;
if (BLI_str_cursor_step_prev_utf8(str, maxlen, pos)) {
- if ((jump != STRCUR_JUMP_ALL) && (delim_type != cursor_delim_type_utf8(&str[*pos]))) {
+ if ((jump != STRCUR_JUMP_ALL) &&
+ (delim_type != cursor_delim_type_utf8(str, maxlen, (size_t)*pos))) {
/* left only: compensate for index/change in direction */
if ((pos_orig - (*pos)) >= 1) {
*pos = pos_prev;
diff --git a/source/blender/blenlib/intern/string_search.cc b/source/blender/blenlib/intern/string_search.cc
index 25a13674932..a466c124073 100644
--- a/source/blender/blenlib/intern/string_search.cc
+++ b/source/blender/blenlib/intern/string_search.cc
@@ -71,12 +71,12 @@ int damerau_levenshtein_distance(StringRef a, StringRef b)
for (const int i : IndexRange(size_a)) {
v2[0] = (i + 1) * deletion_cost;
- const uint32_t unicode_a = BLI_str_utf8_as_unicode_and_size(a.data() + offset_a, &offset_a);
+ const uint32_t unicode_a = BLI_str_utf8_as_unicode_step(a.data(), a.size(), &offset_a);
uint32_t prev_unicode_b;
size_t offset_b = 0;
for (const int j : IndexRange(size_b)) {
- const uint32_t unicode_b = BLI_str_utf8_as_unicode_and_size(b.data() + offset_b, &offset_b);
+ const uint32_t unicode_b = BLI_str_utf8_as_unicode_step(b.data(), b.size(), &offset_b);
/* Check how costly the different operations would be and pick the cheapest - the one with
* minimal cost. */
@@ -202,8 +202,8 @@ static bool match_word_initials(StringRef query,
int first_found_word_index = -1;
while (query_index < query.size()) {
- const uint query_unicode = BLI_str_utf8_as_unicode_and_size(query.data() + query_index,
- &query_index);
+ const uint query_unicode = BLI_str_utf8_as_unicode_step(
+ query.data(), query.size(), &query_index);
while (true) {
/* We are at the end of words, no complete match has been found yet. */
if (word_index >= words.size()) {
@@ -226,8 +226,8 @@ static bool match_word_initials(StringRef query,
StringRef word = words[word_index];
/* Try to match the current character with the current word. */
if (static_cast<int>(char_index) < word.size()) {
- const uint32_t char_unicode = BLI_str_utf8_as_unicode_and_size(word.data() + char_index,
- &char_index);
+ const uint32_t char_unicode = BLI_str_utf8_as_unicode_step(
+ word.data(), word.size(), &char_index);
if (query_unicode == char_unicode) {
r_word_is_matched[word_index] = true;
if (first_found_word_index == -1) {
@@ -368,8 +368,9 @@ void extract_normalized_words(StringRef str,
size_t word_start = 0;
size_t offset = 0;
while (offset < str_size_in_bytes) {
- size_t size = 0;
- uint32_t unicode = BLI_str_utf8_as_unicode_and_size(str.data() + offset, &size);
+ size_t size = offset;
+ uint32_t unicode = BLI_str_utf8_as_unicode_step(str.data(), str.size(), &size);
+ size -= offset;
if (is_separator(unicode)) {
if (is_in_word) {
r_words.append(
diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c
index 19ff8764259..cc6a192f6ba 100644
--- a/source/blender/blenlib/intern/string_utf8.c
+++ b/source/blender/blenlib/intern/string_utf8.c
@@ -70,7 +70,7 @@ static const size_t utf8_skip_data[256] = {
*
* \return the offset of the first invalid byte.
*/
-ptrdiff_t BLI_utf8_invalid_byte(const char *str, size_t length)
+ptrdiff_t BLI_str_utf8_invalid_byte(const char *str, size_t length)
{
const unsigned char *p, *perr, *pend = (const unsigned char *)str + length;
unsigned char c;
@@ -200,14 +200,14 @@ utf8_error:
*
* \return number of stripped bytes.
*/
-int BLI_utf8_invalid_strip(char *str, size_t length)
+int BLI_str_utf8_invalid_strip(char *str, size_t length)
{
ptrdiff_t bad_char;
int tot = 0;
BLI_assert(str[length] == '\0');
- while ((bad_char = BLI_utf8_invalid_byte(str, length)) != -1) {
+ while ((bad_char = BLI_str_utf8_invalid_byte(str, length)) != -1) {
str += bad_char;
length -= (size_t)(bad_char + 1);
@@ -546,85 +546,64 @@ uint BLI_str_utf8_as_unicode(const char *p)
return result;
}
-/* variant that increments the length */
-uint BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index)
+/**
+ * UTF8 decoding that steps over the index (unless an error is encountered).
+ *
+ * \param p: The text to step over.
+ * \param p_len: The length of `p`.
+ * \param index: Index of `p` to step over.
+ * \return the code-point or #BLI_UTF8_ERR if there is a decoding error.
+ *
+ * \note The behavior for clipped text (where `p_len` limits decoding trailing bytes)
+ * must have the same behavior is encountering a nil byte,
+ * so functions that only use the first part of a string has matching behavior to functions
+ * that null terminate the text.
+ */
+uint BLI_str_utf8_as_unicode_step_or_error(const char *__restrict p,
+ const size_t p_len,
+ size_t *__restrict index)
{
int i, len;
uint mask = 0;
uint result;
- const unsigned char c = (unsigned char)*p;
+ const unsigned char c = (unsigned char)*(p += *index);
+
+ BLI_assert(*index < p_len);
+ BLI_assert(c != '\0');
UTF8_COMPUTE(c, mask, len, -1);
- if (UNLIKELY(len == -1)) {
+ if (UNLIKELY(len == -1) || (*index + (size_t)len > p_len)) {
return BLI_UTF8_ERR;
}
UTF8_GET(result, p, i, mask, len, BLI_UTF8_ERR);
- *index += (size_t)len;
- return result;
-}
-
-uint BLI_str_utf8_as_unicode_and_size_safe(const char *__restrict p, size_t *__restrict index)
-{
- int i, len;
- uint mask = 0;
- uint result;
- const unsigned char c = (unsigned char)*p;
-
- UTF8_COMPUTE(c, mask, len, -1);
- if (UNLIKELY(len == -1)) {
- *index += 1;
- return c;
+ if (UNLIKELY(result == BLI_UTF8_ERR)) {
+ return BLI_UTF8_ERR;
}
- UTF8_GET(result, p, i, mask, len, BLI_UTF8_ERR);
*index += (size_t)len;
+ BLI_assert(*index <= p_len);
return result;
}
/**
- * Another variant that steps over the index.
- * \note currently this also falls back to latin1 for text drawing.
+ * UTF8 decoding that steps over the index (unless an error is encountered).
+ *
+ * \param p: The text to step over.
+ * \param p_len: The length of `p`.
+ * \param index: Index of `p` to step over.
+ * \return the code-point `(p + *index)` if there is a decoding error.
+ *
+ * \note Falls back to `LATIN1` for text drawing.
*/
-uint BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index)
+uint BLI_str_utf8_as_unicode_step(const char *__restrict p,
+ const size_t p_len,
+ size_t *__restrict index)
{
- int i, len;
- uint mask = 0;
- uint result;
- unsigned char c;
-
- p += *index;
- c = (unsigned char)*p;
-
- UTF8_COMPUTE(c, mask, len, -1);
- if (UNLIKELY(len == -1)) {
- /* when called with NULL end, result will never be NULL,
- * checks for a NULL character */
- const char *p_next = BLI_str_find_next_char_utf8(p, NULL);
- /* will never return the same pointer unless '\0',
- * eternal loop is prevented */
- *index += (size_t)(p_next - p);
- return BLI_UTF8_ERR;
- }
-
- /* this is tricky since there are a few ways we can bail out of bad unicode
- * values, 3 possible solutions. */
-#if 0
- UTF8_GET(result, p, i, mask, len, BLI_UTF8_ERR);
-#elif 1
- /* WARNING: this is NOT part of glib, or supported by similar functions.
- * this is added for text drawing because some filepaths can have latin1
- * characters */
- UTF8_GET(result, p, i, mask, len, BLI_UTF8_ERR);
- if (result == BLI_UTF8_ERR) {
- len = 1;
- result = *p;
+ uint result = BLI_str_utf8_as_unicode_step_or_error(p, p_len, index);
+ if (UNLIKELY(result == BLI_UTF8_ERR)) {
+ result = (uint)p[*index];
+ *index += 1;
}
- /* end warning! */
-#else
- /* without a fallback like '?', text drawing will stop on this value */
- UTF8_GET(result, p, i, mask, len, '?');
-#endif
-
- *index += (size_t)len;
+ BLI_assert(*index <= p_len);
return result;
}
@@ -696,16 +675,23 @@ size_t BLI_str_utf8_as_utf32(char32_t *__restrict dst_w,
memset(dst_w, 0xff, sizeof(*dst_w) * maxncpy);
#endif
- while (*src_c && len != maxlen) {
- size_t step = 0;
- uint unicode = BLI_str_utf8_as_unicode_and_size(src_c, &step);
+ const size_t src_c_len = strlen(src_c);
+ const char *src_c_end = src_c + src_c_len;
+ size_t index = 0;
+ while ((index < src_c_len) && (len != maxlen)) {
+ const uint unicode = BLI_str_utf8_as_unicode_step_or_error(src_c, src_c_len, &index);
if (unicode != BLI_UTF8_ERR) {
*dst_w = unicode;
- src_c += step;
}
else {
*dst_w = '?';
- src_c = BLI_str_find_next_char_utf8(src_c, NULL);
+ const char *src_c_next = BLI_str_find_next_char_utf8(src_c + index, src_c_end);
+ if (src_c_next != NULL) {
+ index = (size_t)(src_c_next - src_c);
+ }
+ else {
+ index += 1;
+ }
}
dst_w++;
len++;
@@ -810,6 +796,7 @@ char *BLI_str_find_next_char_utf8(const char *p, const char *end)
{
if (*p) {
if (end) {
+ BLI_assert(end >= p);
for (++p; p < end && (*p & 0xc0) == 0x80; p++) {
/* do nothing */
}
@@ -884,7 +871,9 @@ size_t BLI_str_partition_ex_utf8(const char *str,
index = 0;
*sep >= str && (!end || *sep < end) && **sep != '\0';
*sep = (char *)(from_right ? BLI_str_find_prev_char_utf8(str, *sep) : str + index)) {
- const uint c = BLI_str_utf8_as_unicode_and_size(*sep, &index);
+ size_t index_ofs = 0;
+ const uint c = BLI_str_utf8_as_unicode_step_or_error(*sep, (size_t)(end - *sep), &index_ofs);
+ index += index_ofs;
if (c == BLI_UTF8_ERR) {
*suf = *sep = NULL;
diff --git a/source/blender/blenlib/tests/BLI_string_utf8_test.cc b/source/blender/blenlib/tests/BLI_string_utf8_test.cc
index 9ddc372e6d1..b25f2310e1e 100644
--- a/source/blender/blenlib/tests/BLI_string_utf8_test.cc
+++ b/source/blender/blenlib/tests/BLI_string_utf8_test.cc
@@ -2,6 +2,7 @@
#include "testing/testing.h"
+#include "BLI_rand.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_utildefines.h"
@@ -11,7 +12,8 @@
* quite their share of lines, they deserved their own file. */
/* -------------------------------------------------------------------- */
-/* tests */
+/** \name Test #BLI_str_utf8_invalid_strip
+ * \{ */
/* Breaking strings is confusing here, prefer over-long lines. */
/* clang-format off */
@@ -266,7 +268,7 @@ static const char *utf8_invalid_tests[][3] = {
};
/* clang-format on */
-/* BLI_utf8_invalid_strip (and indirectly, BLI_utf8_invalid_byte). */
+/* BLI_str_utf8_invalid_strip (and indirectly, BLI_str_utf8_invalid_byte). */
TEST(string, Utf8InvalidBytes)
{
for (int i = 0; utf8_invalid_tests[i][0] != nullptr; i++) {
@@ -277,10 +279,117 @@ TEST(string, Utf8InvalidBytes)
char buff[80];
memcpy(buff, tst, sizeof(buff));
- const int num_errors_found = BLI_utf8_invalid_strip(buff, sizeof(buff) - 1);
+ const int num_errors_found = BLI_str_utf8_invalid_strip(buff, sizeof(buff) - 1);
printf("[%02d] -> [%02d] \"%s\" -> \"%s\"\n", num_errors, num_errors_found, tst, buff);
EXPECT_EQ(num_errors_found, num_errors);
EXPECT_STREQ(buff, tst_stripped);
}
}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Test #BLI_str_utf8_as_unicode_step
+ * \{ */
+
+static size_t utf8_as_char32(const char *str, const char str_len, char32_t *r_result)
+{
+ size_t i = 0, result_len = 0;
+ while ((i < str_len) && (str[i] != '\0')) {
+ char32_t c = BLI_str_utf8_as_unicode_step(str, str_len, &i);
+ if (c != BLI_UTF8_ERR) {
+ r_result[result_len++] = c;
+ }
+ }
+ return i;
+}
+
+template<size_t Size, size_t SizeWithPadding>
+void utf8_as_char32_test_compare_with_pad_bytes(const char utf8_src[Size])
+{
+ char utf8_src_with_pad[SizeWithPadding] = {0};
+
+ memcpy(utf8_src_with_pad, utf8_src, Size);
+
+ char32_t unicode_dst_a[Size], unicode_dst_b[Size];
+
+ memset(unicode_dst_a, 0xff, sizeof(unicode_dst_a));
+ const size_t index_a = utf8_as_char32(utf8_src, Size, unicode_dst_a);
+
+ /* Test with padded and un-padded size,
+ * to ensure that extra available space doesn't yield a different result. */
+ for (int pass = 0; pass < 2; pass++) {
+ memset(unicode_dst_b, 0xff, sizeof(unicode_dst_b));
+ const size_t index_b = utf8_as_char32(
+ utf8_src_with_pad, pass ? Size : SizeWithPadding, unicode_dst_b);
+
+ /* Check the resulting content matches. */
+ EXPECT_EQ_ARRAY(unicode_dst_a, unicode_dst_b, Size);
+ /* Check the index of the source strings match. */
+ EXPECT_EQ(index_a, index_b);
+ }
+}
+
+template<size_t Size> void utf8_as_char32_test_compare(const char utf8_src[Size])
+{
+ /* Note that 7 is a little arbitrary,
+ * chosen since it's the maximum length of multi-byte character + 1
+ * to account for any errors that read past null bytes. */
+ utf8_as_char32_test_compare_with_pad_bytes<Size, Size + 1>(utf8_src);
+ utf8_as_char32_test_compare_with_pad_bytes<Size, Size + 7>(utf8_src);
+}
+
+template<size_t Size> void utf8_as_char32_test_at_buffer_size()
+{
+ char utf8_src[Size];
+
+ /* Test uniform bytes, also with offsets ascending & descending. */
+ for (int i = 0; i <= 0xff; i++) {
+ memset(utf8_src, i, sizeof(utf8_src));
+ utf8_as_char32_test_compare<Size>(utf8_src);
+
+ /* Offset trailing bytes up and down in steps of 1, 2, 4 .. etc. */
+ if (Size > 1) {
+ for (int mul = 1; mul < 256; mul *= 2) {
+ for (int ofs = 1; ofs < (int)Size; ofs++) {
+ utf8_src[ofs] = (char)(i + (ofs * mul));
+ }
+ utf8_as_char32_test_compare<Size>(utf8_src);
+
+ for (int ofs = 1; ofs < (int)Size; ofs++) {
+ utf8_src[ofs] = (char)(i - (ofs * mul));
+ }
+ utf8_as_char32_test_compare<Size>(utf8_src);
+ }
+ }
+ }
+
+ /* Random bytes. */
+ RNG *rng = BLI_rng_new(1);
+ for (int i = 0; i < 256; i++) {
+ BLI_rng_get_char_n(rng, utf8_src, sizeof(utf8_src));
+ utf8_as_char32_test_compare<Size>(utf8_src);
+ }
+ BLI_rng_free(rng);
+}
+
+TEST(string, Utf8AsUnicodeStep)
+{
+
+ /* Run tests at different buffer sizes. */
+ utf8_as_char32_test_at_buffer_size<1>();
+ utf8_as_char32_test_at_buffer_size<2>();
+ utf8_as_char32_test_at_buffer_size<3>();
+ utf8_as_char32_test_at_buffer_size<4>();
+ utf8_as_char32_test_at_buffer_size<5>();
+ utf8_as_char32_test_at_buffer_size<6>();
+ utf8_as_char32_test_at_buffer_size<7>();
+ utf8_as_char32_test_at_buffer_size<8>();
+ utf8_as_char32_test_at_buffer_size<9>();
+ utf8_as_char32_test_at_buffer_size<10>();
+ utf8_as_char32_test_at_buffer_size<11>();
+ utf8_as_char32_test_at_buffer_size<12>();
+}
+
+/** \} */
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index eb01bfbfb9c..72572b05ef6 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -805,5 +805,18 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
FOREACH_NODETREE_END;
+
+ /* Disable Fade Inactive Overlay by default as it is redundant after introducing flash on mode
+ * transfer. */
+ for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ v3d->overlay.flag &= ~V3D_OVERLAY_FADE_INACTIVE;
+ }
+ }
+ }
+ }
}
}
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index ee287c65fe9..8ddcf11602a 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -328,10 +328,14 @@ set(SRC
operations/COM_FastGaussianBlurOperation.h
operations/COM_GammaCorrectOperation.cc
operations/COM_GammaCorrectOperation.h
+ operations/COM_GaussianAlphaBlurBaseOperation.cc
+ operations/COM_GaussianAlphaBlurBaseOperation.h
operations/COM_GaussianAlphaXBlurOperation.cc
operations/COM_GaussianAlphaXBlurOperation.h
operations/COM_GaussianAlphaYBlurOperation.cc
operations/COM_GaussianAlphaYBlurOperation.h
+ operations/COM_GaussianBlurBaseOperation.cc
+ operations/COM_GaussianBlurBaseOperation.h
operations/COM_GaussianBokehBlurOperation.cc
operations/COM_GaussianBokehBlurOperation.h
operations/COM_GaussianXBlurOperation.cc
@@ -515,6 +519,8 @@ set(SRC
operations/COM_ScaleOperation.h
operations/COM_ScreenLensDistortionOperation.cc
operations/COM_ScreenLensDistortionOperation.h
+ operations/COM_TransformOperation.cc
+ operations/COM_TransformOperation.h
operations/COM_TranslateOperation.cc
operations/COM_TranslateOperation.h
operations/COM_WrapOperation.cc
diff --git a/source/blender/compositor/COM_defines.h b/source/blender/compositor/COM_defines.h
index 40a1e0da2a8..e270eeb3386 100644
--- a/source/blender/compositor/COM_defines.h
+++ b/source/blender/compositor/COM_defines.h
@@ -33,6 +33,8 @@ enum class eExecutionModel {
FullFrame
};
+enum class eDimension { X, Y };
+
/**
* \brief possible data types for sockets
* \ingroup Model
@@ -119,6 +121,8 @@ constexpr float COM_PREVIEW_SIZE = 140.f;
constexpr float COM_RULE_OF_THIRDS_DIVIDER = 100.0f;
constexpr float COM_BLUR_BOKEH_PIXELS = 512;
+constexpr rcti COM_SINGLE_ELEM_AREA = {0, 1, 0, 1};
+
constexpr IndexRange XRange(const rcti &area)
{
return IndexRange(area.xmin, area.xmax - area.xmin);
diff --git a/source/blender/compositor/intern/COM_CompositorContext.h b/source/blender/compositor/intern/COM_CompositorContext.h
index 403ec62e359..c6e83f93777 100644
--- a/source/blender/compositor/intern/COM_CompositorContext.h
+++ b/source/blender/compositor/intern/COM_CompositorContext.h
@@ -239,6 +239,12 @@ class CompositorContext {
this->m_hasActiveOpenCLDevices = hasAvtiveOpenCLDevices;
}
+ /** Whether it has a view with a specific name and not the default one. */
+ bool has_explicit_view() const
+ {
+ return m_viewName && m_viewName[0] != '\0';
+ }
+
/**
* \brief get the active rendering view
*/
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cc b/source/blender/compositor/intern/COM_MemoryBuffer.cc
index 6b954072a9a..1fbf502fea6 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.cc
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.cc
@@ -245,7 +245,9 @@ void MemoryBuffer::copy_from(const MemoryBuffer *src,
void MemoryBuffer::copy_from(const uchar *src, const rcti &area)
{
- copy_from(src, area, 0, this->get_num_channels(), this->get_num_channels(), 0);
+ const int elem_stride = this->get_num_channels();
+ const int row_stride = elem_stride * getWidth();
+ copy_from(src, area, 0, this->get_num_channels(), elem_stride, row_stride, 0);
}
void MemoryBuffer::copy_from(const uchar *src,
@@ -253,10 +255,18 @@ void MemoryBuffer::copy_from(const uchar *src,
const int channel_offset,
const int elem_size,
const int elem_stride,
+ const int row_stride,
const int to_channel_offset)
{
- copy_from(
- src, area, channel_offset, elem_size, elem_stride, area.xmin, area.ymin, to_channel_offset);
+ copy_from(src,
+ area,
+ channel_offset,
+ elem_size,
+ elem_stride,
+ row_stride,
+ area.xmin,
+ area.ymin,
+ to_channel_offset);
}
void MemoryBuffer::copy_from(const uchar *src,
@@ -264,6 +274,7 @@ void MemoryBuffer::copy_from(const uchar *src,
const int channel_offset,
const int elem_size,
const int elem_stride,
+ const int row_stride,
const int to_x,
const int to_y,
const int to_channel_offset)
@@ -273,10 +284,9 @@ void MemoryBuffer::copy_from(const uchar *src,
const int width = BLI_rcti_size_x(&area);
const int height = BLI_rcti_size_y(&area);
- const int src_row_stride = width * elem_stride;
- const uchar *const src_start = src + area.ymin * src_row_stride + channel_offset;
+ const uchar *const src_start = src + area.ymin * row_stride + channel_offset;
for (int y = 0; y < height; y++) {
- const uchar *from_elem = src_start + y * src_row_stride;
+ const uchar *from_elem = src_start + y * row_stride + area.xmin * elem_stride;
float *to_elem = &this->get_value(to_x, to_y + y, to_channel_offset);
const float *row_end = to_elem + width * this->elem_stride;
while (to_elem < row_end) {
@@ -346,7 +356,16 @@ void MemoryBuffer::copy_from(const ImBuf *src,
else if (src->rect) {
const uchar *uc_buf = (uchar *)src->rect;
const int elem_stride = src->channels;
- copy_from(uc_buf, area, channel_offset, elem_size, elem_stride, to_x, to_y, to_channel_offset);
+ const int row_stride = elem_stride * src->x;
+ copy_from(uc_buf,
+ area,
+ channel_offset,
+ elem_size,
+ elem_stride,
+ row_stride,
+ to_x,
+ to_y,
+ to_channel_offset);
if (ensure_linear_space) {
colorspace_to_scene_linear(this, area, src->rect_colorspace);
}
@@ -405,12 +424,48 @@ void MemoryBuffer::addPixel(int x, int y, const float color[4])
}
}
+static void read_ewa_elem(void *userdata, int x, int y, float result[4])
+{
+ const MemoryBuffer *buffer = static_cast<const MemoryBuffer *>(userdata);
+ buffer->read_elem_checked(x, y, result);
+}
+
+void MemoryBuffer::read_elem_filtered(
+ const float x, const float y, float dx[2], float dy[2], float *out) const
+{
+ BLI_assert(this->m_datatype == DataType::Color);
+
+ const float deriv[2][2] = {{dx[0], dx[1]}, {dy[0], dy[1]}};
+
+ float inv_width = 1.0f / (float)this->getWidth(), inv_height = 1.0f / (float)this->getHeight();
+ /* TODO(sergey): Render pipeline uses normalized coordinates and derivatives,
+ * but compositor uses pixel space. For now let's just divide the values and
+ * switch compositor to normalized space for EWA later.
+ */
+ float uv_normal[2] = {get_relative_x(x) * inv_width, get_relative_y(y) * inv_height};
+ float du_normal[2] = {deriv[0][0] * inv_width, deriv[0][1] * inv_height};
+ float dv_normal[2] = {deriv[1][0] * inv_width, deriv[1][1] * inv_height};
+
+ BLI_ewa_filter(this->getWidth(),
+ this->getHeight(),
+ false,
+ true,
+ uv_normal,
+ du_normal,
+ dv_normal,
+ read_ewa_elem,
+ const_cast<MemoryBuffer *>(this),
+ out);
+}
+
+/* TODO(manzanilla): to be removed with tiled implementation. */
static void read_ewa_pixel_sampled(void *userdata, int x, int y, float result[4])
{
MemoryBuffer *buffer = (MemoryBuffer *)userdata;
buffer->read(result, x, y);
}
+/* TODO(manzanilla): to be removed with tiled implementation. */
void MemoryBuffer::readEWA(float *result, const float uv[2], const float derivatives[2][2])
{
if (m_is_a_single_elem) {
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h
index 310e87b6a4b..f3e15c2a495 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.h
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.h
@@ -191,23 +191,96 @@ class MemoryBuffer {
void read_elem(int x, int y, float *out) const
{
- memcpy(out, get_elem(x, y), m_num_channels * sizeof(float));
+ memcpy(out, get_elem(x, y), get_elem_bytes_len());
+ }
+
+ void read_elem_checked(int x, int y, float *out) const
+ {
+ if (x < m_rect.xmin || x >= m_rect.xmax || y < m_rect.ymin || y >= m_rect.ymax) {
+ clear_elem(out);
+ }
+ else {
+ read_elem(x, y, out);
+ }
+ }
+
+ void read_elem_checked(float x, float y, float *out) const
+ {
+ if (x < m_rect.xmin || x >= m_rect.xmax || y < m_rect.ymin || y >= m_rect.ymax) {
+ clear_elem(out);
+ }
+ else {
+ read_elem(x, y, out);
+ }
+ }
+
+ void read_elem_bilinear(float x, float y, float *out) const
+ {
+ /* Only clear past +/-1 borders to be able to smooth edges. */
+ if (x <= m_rect.xmin - 1.0f || x >= m_rect.xmax || y <= m_rect.ymin - 1.0f ||
+ y >= m_rect.ymax) {
+ clear_elem(out);
+ return;
+ }
+
+ if (m_is_a_single_elem) {
+ if (x >= m_rect.xmin && x < m_rect.xmax - 1.0f && y >= m_rect.ymin &&
+ y < m_rect.ymax - 1.0f) {
+ memcpy(out, m_buffer, get_elem_bytes_len());
+ return;
+ }
+
+ /* Do sampling at borders to smooth edges. */
+ const float last_x = getWidth() - 1.0f;
+ const float rel_x = get_relative_x(x);
+ float single_x = 0.0f;
+ if (rel_x < 0.0f) {
+ single_x = rel_x;
+ }
+ else if (rel_x > last_x) {
+ single_x = rel_x - last_x;
+ }
+
+ const float last_y = getHeight() - 1.0f;
+ const float rel_y = get_relative_y(y);
+ float single_y = 0.0f;
+ if (rel_y < 0.0f) {
+ single_y = rel_y;
+ }
+ else if (rel_y > last_y) {
+ single_y = rel_y - last_y;
+ }
+
+ BLI_bilinear_interpolation_fl(m_buffer, out, 1, 1, m_num_channels, single_x, single_y);
+ return;
+ }
+
+ BLI_bilinear_interpolation_fl(m_buffer,
+ out,
+ getWidth(),
+ getHeight(),
+ m_num_channels,
+ get_relative_x(x),
+ get_relative_y(y));
}
void read_elem_sampled(float x, float y, PixelSampler sampler, float *out) const
{
switch (sampler) {
case PixelSampler::Nearest:
- this->read_elem(x, y, out);
+ read_elem_checked(x, y, out);
break;
case PixelSampler::Bilinear:
case PixelSampler::Bicubic:
/* No bicubic. Current implementation produces fuzzy results. */
- this->readBilinear(out, x, y);
+ read_elem_bilinear(x, y, out);
break;
}
}
+ void read_elem_filtered(
+ const float x, const float y, float dx[2], float dy[2], float *out) const;
+
/**
* Get channel value at given coordinates.
*/
@@ -403,6 +476,8 @@ class MemoryBuffer {
y = y + m_rect.ymin;
}
+ /* TODO(manzanilla): to be removed with tiled implementation. For applying #MemoryBufferExtend
+ * use #wrap_pixel. */
inline void read(float *result,
int x,
int y,
@@ -425,6 +500,7 @@ class MemoryBuffer {
}
}
+ /* TODO(manzanilla): to be removed with tiled implementation. */
inline void readNoCheck(float *result,
int x,
int y,
@@ -507,12 +583,14 @@ class MemoryBuffer {
int channel_offset,
int elem_size,
int elem_stride,
+ int row_stride,
int to_channel_offset);
void copy_from(const uchar *src,
const rcti &area,
int channel_offset,
int elem_size,
int elem_stride,
+ int row_stride,
int to_x,
int to_y,
int to_channel_offset);
@@ -582,6 +660,21 @@ class MemoryBuffer {
return get_memory_width() * get_memory_height();
}
+ void clear_elem(float *out) const
+ {
+ memset(out, 0, this->m_num_channels * sizeof(float));
+ }
+
+ template<typename T> T get_relative_x(T x) const
+ {
+ return x - m_rect.xmin;
+ }
+
+ template<typename T> T get_relative_y(T y) const
+ {
+ return y - m_rect.ymin;
+ }
+
void copy_single_elem_from(const MemoryBuffer *src,
int channel_offset,
int elem_size,
diff --git a/source/blender/compositor/intern/COM_NodeGraph.cc b/source/blender/compositor/intern/COM_NodeGraph.cc
index 205fbcc0440..1872fbcf656 100644
--- a/source/blender/compositor/intern/COM_NodeGraph.cc
+++ b/source/blender/compositor/intern/COM_NodeGraph.cc
@@ -248,7 +248,9 @@ void NodeGraph::add_proxies_group_inputs(bNode *b_node, bNode *b_node_io)
}
}
-void NodeGraph::add_proxies_group_outputs(bNode *b_node, bNode *b_node_io, bool use_buffer)
+void NodeGraph::add_proxies_group_outputs(const CompositorContext &context,
+ bNode *b_node,
+ bNode *b_node_io)
{
bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
BLI_assert(b_group_tree); /* should have been checked in advance */
@@ -261,7 +263,8 @@ void NodeGraph::add_proxies_group_outputs(bNode *b_node, bNode *b_node_io, bool
b_sock_io = b_sock_io->next) {
bNodeSocket *b_sock_group = find_b_node_output(b_node, b_sock_io->identifier);
if (b_sock_group) {
- if (use_buffer) {
+ if (context.isGroupnodeBufferEnabled() &&
+ context.get_execution_model() == eExecutionModel::Tiled) {
SocketBufferNode *buffer = new SocketBufferNode(b_node_io, b_sock_io, b_sock_group);
add_node(buffer, b_group_tree, key, is_active_group);
}
@@ -297,7 +300,7 @@ void NodeGraph::add_proxies_group(const CompositorContext &context,
}
if (b_node_io->type == NODE_GROUP_OUTPUT && (b_node_io->flag & NODE_DO_OUTPUT)) {
- add_proxies_group_outputs(b_node, b_node_io, context.isGroupnodeBufferEnabled());
+ add_proxies_group_outputs(context, b_node, b_node_io);
}
}
diff --git a/source/blender/compositor/intern/COM_NodeGraph.h b/source/blender/compositor/intern/COM_NodeGraph.h
index 7fa01593e1e..dfcc6c2fcf9 100644
--- a/source/blender/compositor/intern/COM_NodeGraph.h
+++ b/source/blender/compositor/intern/COM_NodeGraph.h
@@ -107,7 +107,9 @@ class NodeGraph {
bool is_active_group);
void add_proxies_group_inputs(bNode *b_node, bNode *b_node_io);
- void add_proxies_group_outputs(bNode *b_node, bNode *b_node_io, bool use_buffer);
+ void add_proxies_group_outputs(const CompositorContext &context,
+ bNode *b_node,
+ bNode *b_node_io);
void add_proxies_group(const CompositorContext &context, bNode *b_node, bNodeInstanceKey key);
void add_proxies_reroute(bNodeTree *b_ntree,
diff --git a/source/blender/compositor/intern/COM_NodeOperation.cc b/source/blender/compositor/intern/COM_NodeOperation.cc
index 575e8446abe..1b87cdf72fb 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.cc
+++ b/source/blender/compositor/intern/COM_NodeOperation.cc
@@ -82,8 +82,12 @@ void NodeOperation::determineResolution(unsigned int resolution[2],
input.determineResolution(resolution, preferredResolution);
used_resolution_index = m_resolutionInputSocketIndex;
}
- unsigned int temp2[2] = {resolution[0], resolution[1]};
+ if (modify_determined_resolution_fn_) {
+ modify_determined_resolution_fn_(resolution);
+ }
+
+ unsigned int temp2[2] = {resolution[0], resolution[1]};
unsigned int temp[2];
for (unsigned int index = 0; index < m_inputs.size(); index++) {
if (index == used_resolution_index) {
diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h
index 934007d25ce..b402dc7f174 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.h
+++ b/source/blender/compositor/intern/COM_NodeOperation.h
@@ -287,6 +287,8 @@ class NodeOperation {
*/
unsigned int m_resolutionInputSocketIndex;
+ std::function<void(unsigned int resolution[2])> modify_determined_resolution_fn_;
+
/**
* \brief mutex reference for very special node initializations
* \note only use when you really know what you are doing.
@@ -518,6 +520,15 @@ class NodeOperation {
void setResolutionInputSocketIndex(unsigned int index);
/**
+ * Set a custom function to modify determined resolution from main input just before setting it
+ * as preferred resolution for the other inputs.
+ */
+ void set_determined_resolution_modifier(std::function<void(unsigned int resolution[2])> fn)
+ {
+ modify_determined_resolution_fn_ = fn;
+ }
+
+ /**
* \brief get the render priority of this node.
* \note only applicable for output operations like ViewerOperation
* \return eCompositorPriority
diff --git a/source/blender/compositor/nodes/COM_CryptomatteNode.cc b/source/blender/compositor/nodes/COM_CryptomatteNode.cc
index 4032a655633..5835f051ce3 100644
--- a/source/blender/compositor/nodes/COM_CryptomatteNode.cc
+++ b/source/blender/compositor/nodes/COM_CryptomatteNode.cc
@@ -124,6 +124,10 @@ void CryptomatteNode::input_operations_from_render_source(
RenderLayer *render_layer = RE_GetRenderLayer(render_result, view_layer->name);
if (render_layer) {
LISTBASE_FOREACH (RenderPass *, render_pass, &render_layer->passes) {
+ if (context.has_explicit_view() && !STREQ(render_pass->view, context.getViewName())) {
+ continue;
+ }
+
const std::string combined_name = combined_layer_pass_name(render_layer, render_pass);
if (blender::StringRef(combined_name).startswith(prefix)) {
RenderLayersProg *op = new RenderLayersProg(
diff --git a/source/blender/compositor/nodes/COM_RotateNode.cc b/source/blender/compositor/nodes/COM_RotateNode.cc
index af5baa733dc..c2fd8ed5594 100644
--- a/source/blender/compositor/nodes/COM_RotateNode.cc
+++ b/source/blender/compositor/nodes/COM_RotateNode.cc
@@ -30,20 +30,31 @@ RotateNode::RotateNode(bNode *editorNode) : Node(editorNode)
}
void RotateNode::convertToOperations(NodeConverter &converter,
- const CompositorContext & /*context*/) const
+ const CompositorContext &context) const
{
NodeInput *inputSocket = this->getInputSocket(0);
NodeInput *inputDegreeSocket = this->getInputSocket(1);
NodeOutput *outputSocket = this->getOutputSocket(0);
RotateOperation *operation = new RotateOperation();
- SetSamplerOperation *sampler = new SetSamplerOperation();
- sampler->setSampler((PixelSampler)this->getbNode()->custom1);
-
- converter.addOperation(sampler);
converter.addOperation(operation);
- converter.addLink(sampler->getOutputSocket(), operation->getInputSocket(0));
- converter.mapInputSocket(inputSocket, sampler->getInputSocket(0));
+ PixelSampler sampler = (PixelSampler)this->getbNode()->custom1;
+ switch (context.get_execution_model()) {
+ case eExecutionModel::Tiled: {
+ SetSamplerOperation *sampler_op = new SetSamplerOperation();
+ sampler_op->setSampler(sampler);
+ converter.addOperation(sampler_op);
+ converter.addLink(sampler_op->getOutputSocket(), operation->getInputSocket(0));
+ converter.mapInputSocket(inputSocket, sampler_op->getInputSocket(0));
+ break;
+ }
+ case eExecutionModel::FullFrame: {
+ operation->set_sampler(sampler);
+ converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
+ break;
+ }
+ }
+
converter.mapInputSocket(inputDegreeSocket, operation->getInputSocket(1));
converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
}
diff --git a/source/blender/compositor/nodes/COM_Stabilize2dNode.cc b/source/blender/compositor/nodes/COM_Stabilize2dNode.cc
index 0262f653d1a..7b2388bebca 100644
--- a/source/blender/compositor/nodes/COM_Stabilize2dNode.cc
+++ b/source/blender/compositor/nodes/COM_Stabilize2dNode.cc
@@ -22,6 +22,7 @@
#include "COM_RotateOperation.h"
#include "COM_ScaleOperation.h"
#include "COM_SetSamplerOperation.h"
+#include "COM_TransformOperation.h"
#include "COM_TranslateOperation.h"
#include "BKE_tracking.h"
@@ -42,18 +43,12 @@ void Stabilize2dNode::convertToOperations(NodeConverter &converter,
NodeInput *imageInput = this->getInputSocket(0);
MovieClip *clip = (MovieClip *)editorNode->id;
bool invert = (editorNode->custom2 & CMP_NODEFLAG_STABILIZE_INVERSE) != 0;
+ const PixelSampler sampler = (PixelSampler)editorNode->custom1;
- ScaleRelativeOperation *scaleOperation = new ScaleRelativeOperation();
- scaleOperation->setSampler((PixelSampler)editorNode->custom1);
- RotateOperation *rotateOperation = new RotateOperation();
- rotateOperation->setDoDegree2RadConversion(false);
- TranslateOperation *translateOperation = new TranslateOperation();
MovieClipAttributeOperation *scaleAttribute = new MovieClipAttributeOperation();
MovieClipAttributeOperation *angleAttribute = new MovieClipAttributeOperation();
MovieClipAttributeOperation *xAttribute = new MovieClipAttributeOperation();
MovieClipAttributeOperation *yAttribute = new MovieClipAttributeOperation();
- SetSamplerOperation *psoperation = new SetSamplerOperation();
- psoperation->setSampler((PixelSampler)editorNode->custom1);
scaleAttribute->setAttribute(MCA_SCALE);
scaleAttribute->setFramenumber(context.getFramenumber());
@@ -79,38 +74,67 @@ void Stabilize2dNode::convertToOperations(NodeConverter &converter,
converter.addOperation(angleAttribute);
converter.addOperation(xAttribute);
converter.addOperation(yAttribute);
- converter.addOperation(scaleOperation);
- converter.addOperation(translateOperation);
- converter.addOperation(rotateOperation);
- converter.addOperation(psoperation);
- converter.addLink(scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(1));
- converter.addLink(scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(2));
-
- converter.addLink(angleAttribute->getOutputSocket(), rotateOperation->getInputSocket(1));
-
- converter.addLink(xAttribute->getOutputSocket(), translateOperation->getInputSocket(1));
- converter.addLink(yAttribute->getOutputSocket(), translateOperation->getInputSocket(2));
-
- converter.mapOutputSocket(getOutputSocket(), psoperation->getOutputSocket());
-
- if (invert) {
- // Translate -> Rotate -> Scale.
- converter.mapInputSocket(imageInput, translateOperation->getInputSocket(0));
-
- converter.addLink(translateOperation->getOutputSocket(), rotateOperation->getInputSocket(0));
- converter.addLink(rotateOperation->getOutputSocket(), scaleOperation->getInputSocket(0));
-
- converter.addLink(scaleOperation->getOutputSocket(), psoperation->getInputSocket(0));
- }
- else {
- // Scale -> Rotate -> Translate.
- converter.mapInputSocket(imageInput, scaleOperation->getInputSocket(0));
-
- converter.addLink(scaleOperation->getOutputSocket(), rotateOperation->getInputSocket(0));
- converter.addLink(rotateOperation->getOutputSocket(), translateOperation->getInputSocket(0));
-
- converter.addLink(translateOperation->getOutputSocket(), psoperation->getInputSocket(0));
+ switch (context.get_execution_model()) {
+ case eExecutionModel::Tiled: {
+ ScaleRelativeOperation *scaleOperation = new ScaleRelativeOperation();
+ scaleOperation->setSampler(sampler);
+ RotateOperation *rotateOperation = new RotateOperation();
+ rotateOperation->setDoDegree2RadConversion(false);
+ TranslateOperation *translateOperation = new TranslateOperation();
+ SetSamplerOperation *psoperation = new SetSamplerOperation();
+ psoperation->setSampler(sampler);
+
+ converter.addOperation(scaleOperation);
+ converter.addOperation(translateOperation);
+ converter.addOperation(rotateOperation);
+ converter.addOperation(psoperation);
+
+ converter.addLink(scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(1));
+ converter.addLink(scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(2));
+
+ converter.addLink(angleAttribute->getOutputSocket(), rotateOperation->getInputSocket(1));
+
+ converter.addLink(xAttribute->getOutputSocket(), translateOperation->getInputSocket(1));
+ converter.addLink(yAttribute->getOutputSocket(), translateOperation->getInputSocket(2));
+
+ converter.mapOutputSocket(getOutputSocket(), psoperation->getOutputSocket());
+
+ if (invert) {
+ // Translate -> Rotate -> Scale.
+ converter.mapInputSocket(imageInput, translateOperation->getInputSocket(0));
+
+ converter.addLink(translateOperation->getOutputSocket(),
+ rotateOperation->getInputSocket(0));
+ converter.addLink(rotateOperation->getOutputSocket(), scaleOperation->getInputSocket(0));
+
+ converter.addLink(scaleOperation->getOutputSocket(), psoperation->getInputSocket(0));
+ }
+ else {
+ // Scale -> Rotate -> Translate.
+ converter.mapInputSocket(imageInput, scaleOperation->getInputSocket(0));
+
+ converter.addLink(scaleOperation->getOutputSocket(), rotateOperation->getInputSocket(0));
+ converter.addLink(rotateOperation->getOutputSocket(),
+ translateOperation->getInputSocket(0));
+
+ converter.addLink(translateOperation->getOutputSocket(), psoperation->getInputSocket(0));
+ }
+ break;
+ }
+ case eExecutionModel::FullFrame: {
+ TransformOperation *transform_op = new TransformOperation();
+ transform_op->set_sampler(sampler);
+ transform_op->set_convert_rotate_degree_to_rad(false);
+ transform_op->set_invert(invert);
+ converter.addOperation(transform_op);
+ converter.mapInputSocket(imageInput, transform_op->getInputSocket(0));
+ converter.addLink(xAttribute->getOutputSocket(), transform_op->getInputSocket(1));
+ converter.addLink(yAttribute->getOutputSocket(), transform_op->getInputSocket(2));
+ converter.addLink(angleAttribute->getOutputSocket(), transform_op->getInputSocket(3));
+ converter.addLink(scaleAttribute->getOutputSocket(), transform_op->getInputSocket(4));
+ converter.mapOutputSocket(getOutputSocket(), transform_op->getOutputSocket());
+ }
}
}
diff --git a/source/blender/compositor/nodes/COM_TransformNode.cc b/source/blender/compositor/nodes/COM_TransformNode.cc
index e1deaf616a4..d2fb7b54633 100644
--- a/source/blender/compositor/nodes/COM_TransformNode.cc
+++ b/source/blender/compositor/nodes/COM_TransformNode.cc
@@ -22,6 +22,7 @@
#include "COM_ScaleOperation.h"
#include "COM_SetSamplerOperation.h"
#include "COM_SetValueOperation.h"
+#include "COM_TransformOperation.h"
#include "COM_TranslateOperation.h"
namespace blender::compositor {
@@ -32,7 +33,7 @@ TransformNode::TransformNode(bNode *editorNode) : Node(editorNode)
}
void TransformNode::convertToOperations(NodeConverter &converter,
- const CompositorContext & /*context*/) const
+ const CompositorContext &context) const
{
NodeInput *imageInput = this->getInputSocket(0);
NodeInput *xInput = this->getInputSocket(1);
@@ -40,33 +41,51 @@ void TransformNode::convertToOperations(NodeConverter &converter,
NodeInput *angleInput = this->getInputSocket(3);
NodeInput *scaleInput = this->getInputSocket(4);
- ScaleRelativeOperation *scaleOperation = new ScaleRelativeOperation();
- converter.addOperation(scaleOperation);
+ switch (context.get_execution_model()) {
+ case eExecutionModel::Tiled: {
+ ScaleRelativeOperation *scaleOperation = new ScaleRelativeOperation();
+ converter.addOperation(scaleOperation);
- RotateOperation *rotateOperation = new RotateOperation();
- rotateOperation->setDoDegree2RadConversion(false);
- converter.addOperation(rotateOperation);
+ RotateOperation *rotateOperation = new RotateOperation();
+ rotateOperation->setDoDegree2RadConversion(false);
+ converter.addOperation(rotateOperation);
- TranslateOperation *translateOperation = new TranslateOperation();
- converter.addOperation(translateOperation);
+ TranslateOperation *translateOperation = new TranslateOperation();
+ converter.addOperation(translateOperation);
- SetSamplerOperation *sampler = new SetSamplerOperation();
- sampler->setSampler((PixelSampler)this->getbNode()->custom1);
- converter.addOperation(sampler);
+ SetSamplerOperation *sampler = new SetSamplerOperation();
+ sampler->setSampler((PixelSampler)this->getbNode()->custom1);
+ converter.addOperation(sampler);
- converter.mapInputSocket(imageInput, sampler->getInputSocket(0));
- converter.addLink(sampler->getOutputSocket(), scaleOperation->getInputSocket(0));
- converter.mapInputSocket(scaleInput, scaleOperation->getInputSocket(1));
- converter.mapInputSocket(scaleInput, scaleOperation->getInputSocket(2)); // xscale = yscale
+ converter.mapInputSocket(imageInput, sampler->getInputSocket(0));
+ converter.addLink(sampler->getOutputSocket(), scaleOperation->getInputSocket(0));
+ converter.mapInputSocket(scaleInput, scaleOperation->getInputSocket(1));
+ converter.mapInputSocket(scaleInput, scaleOperation->getInputSocket(2)); // xscale = yscale
- converter.addLink(scaleOperation->getOutputSocket(), rotateOperation->getInputSocket(0));
- converter.mapInputSocket(angleInput, rotateOperation->getInputSocket(1));
+ converter.addLink(scaleOperation->getOutputSocket(), rotateOperation->getInputSocket(0));
+ converter.mapInputSocket(angleInput, rotateOperation->getInputSocket(1));
- converter.addLink(rotateOperation->getOutputSocket(), translateOperation->getInputSocket(0));
- converter.mapInputSocket(xInput, translateOperation->getInputSocket(1));
- converter.mapInputSocket(yInput, translateOperation->getInputSocket(2));
+ converter.addLink(rotateOperation->getOutputSocket(), translateOperation->getInputSocket(0));
+ converter.mapInputSocket(xInput, translateOperation->getInputSocket(1));
+ converter.mapInputSocket(yInput, translateOperation->getInputSocket(2));
- converter.mapOutputSocket(getOutputSocket(), translateOperation->getOutputSocket());
+ converter.mapOutputSocket(getOutputSocket(), translateOperation->getOutputSocket());
+ break;
+ }
+ case eExecutionModel::FullFrame: {
+ TransformOperation *op = new TransformOperation();
+ op->set_sampler((PixelSampler)this->getbNode()->custom1);
+ converter.addOperation(op);
+
+ converter.mapInputSocket(imageInput, op->getInputSocket(0));
+ converter.mapInputSocket(xInput, op->getInputSocket(1));
+ converter.mapInputSocket(yInput, op->getInputSocket(2));
+ converter.mapInputSocket(angleInput, op->getInputSocket(3));
+ converter.mapInputSocket(scaleInput, op->getInputSocket(4));
+ converter.mapOutputSocket(getOutputSocket(), op->getOutputSocket());
+ break;
+ }
+ }
}
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.cc b/source/blender/compositor/operations/COM_BlurBaseOperation.cc
index 8b73624ca79..058b422c4a5 100644
--- a/source/blender/compositor/operations/COM_BlurBaseOperation.cc
+++ b/source/blender/compositor/operations/COM_BlurBaseOperation.cc
@@ -17,6 +17,8 @@
*/
#include "COM_BlurBaseOperation.h"
+#include "COM_ConstantOperation.h"
+
#include "BLI_math.h"
#include "MEM_guardedalloc.h"
@@ -36,11 +38,15 @@ BlurBaseOperation::BlurBaseOperation(DataType data_type)
this->m_size = 1.0f;
this->m_sizeavailable = false;
this->m_extend_bounds = false;
+ use_variable_size_ = false;
}
-void BlurBaseOperation::initExecution()
+
+void BlurBaseOperation::init_data()
{
- this->m_inputProgram = this->getInputSocketReader(0);
- this->m_inputSize = this->getInputSocketReader(1);
+ if (execution_model_ == eExecutionModel::FullFrame) {
+ updateSize();
+ }
+
this->m_data.image_in_width = this->getWidth();
this->m_data.image_in_height = this->getHeight();
if (this->m_data.relative) {
@@ -61,6 +67,12 @@ void BlurBaseOperation::initExecution()
this->m_data.sizex = round_fl_to_int(this->m_data.percentx * 0.01f * sizex);
this->m_data.sizey = round_fl_to_int(this->m_data.percenty * 0.01f * sizey);
}
+}
+
+void BlurBaseOperation::initExecution()
+{
+ this->m_inputProgram = this->getInputSocketReader(0);
+ this->m_inputSize = this->getInputSocketReader(1);
QualityStepHelper::initExecution(COM_QH_MULTIPLY);
}
@@ -165,23 +177,82 @@ void BlurBaseOperation::setData(const NodeBlurData *data)
memcpy(&m_data, data, sizeof(NodeBlurData));
}
+int BlurBaseOperation::get_blur_size(eDimension dim) const
+{
+ switch (dim) {
+ case eDimension::X:
+ return m_data.sizex;
+ case eDimension::Y:
+ return m_data.sizey;
+ }
+ return -1;
+}
+
void BlurBaseOperation::updateSize()
{
- if (!this->m_sizeavailable) {
- float result[4];
- this->getInputSocketReader(1)->readSampled(result, 0, 0, PixelSampler::Nearest);
- this->m_size = result[0];
- this->m_sizeavailable = true;
+ if (this->m_sizeavailable || use_variable_size_) {
+ return;
}
+
+ switch (execution_model_) {
+ case eExecutionModel::Tiled: {
+ float result[4];
+ this->getInputSocketReader(1)->readSampled(result, 0, 0, PixelSampler::Nearest);
+ this->m_size = result[0];
+ break;
+ }
+ case eExecutionModel::FullFrame: {
+ NodeOperation *size_input = get_input_operation(SIZE_INPUT_INDEX);
+ if (size_input->get_flags().is_constant_operation) {
+ m_size = *static_cast<ConstantOperation *>(size_input)->get_constant_elem();
+ } /* Else use default. */
+ break;
+ }
+ }
+ this->m_sizeavailable = true;
}
void BlurBaseOperation::determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2])
{
- NodeOperation::determineResolution(resolution, preferredResolution);
- if (this->m_extend_bounds) {
- resolution[0] += 2 * this->m_size * m_data.sizex;
- resolution[1] += 2 * this->m_size * m_data.sizey;
+ if (!m_extend_bounds) {
+ NodeOperation::determineResolution(resolution, preferredResolution);
+ return;
+ }
+
+ switch (execution_model_) {
+ case eExecutionModel::Tiled: {
+ NodeOperation::determineResolution(resolution, preferredResolution);
+ resolution[0] += 2 * m_size * m_data.sizex;
+ resolution[1] += 2 * m_size * m_data.sizey;
+ break;
+ }
+ case eExecutionModel::FullFrame: {
+ /* Setting a modifier ensures all non main inputs have extended bounds as preferred
+ * resolution, avoiding unnecessary resolution conversions that would hide constant
+ * operations. */
+ set_determined_resolution_modifier([=](unsigned int res[2]) {
+ /* Rounding to even prevents jiggling in backdrop while switching size values. */
+ res[0] += round_to_even(2 * m_size * m_data.sizex);
+ res[1] += round_to_even(2 * m_size * m_data.sizey);
+ });
+ NodeOperation::determineResolution(resolution, preferredResolution);
+ break;
+ }
+ }
+}
+
+void BlurBaseOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ switch (input_idx) {
+ case 0:
+ r_input_area = output_area;
+ break;
+ case 1:
+ r_input_area = use_variable_size_ ? output_area : COM_SINGLE_ELEM_AREA;
+ break;
}
}
diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.h b/source/blender/compositor/operations/COM_BlurBaseOperation.h
index 7937ebd69dc..78b1e919aa6 100644
--- a/source/blender/compositor/operations/COM_BlurBaseOperation.h
+++ b/source/blender/compositor/operations/COM_BlurBaseOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
#include "COM_QualityStepHelper.h"
#define MAX_GAUSSTAB_RADIUS 30000
@@ -27,10 +27,16 @@
namespace blender::compositor {
-class BlurBaseOperation : public NodeOperation, public QualityStepHelper {
+class BlurBaseOperation : public MultiThreadedOperation, public QualityStepHelper {
private:
+ bool m_extend_bounds;
+
+ protected:
+ static constexpr int IMAGE_INPUT_INDEX = 0;
+ static constexpr int SIZE_INPUT_INDEX = 1;
+
protected:
- BlurBaseOperation(DataType data_type);
+ BlurBaseOperation(DataType data_type8);
float *make_gausstab(float rad, int size);
#ifdef BLI_HAVE_SSE2
__m128 *convert_gausstab_sse(const float *gausstab, int size);
@@ -49,9 +55,11 @@ class BlurBaseOperation : public NodeOperation, public QualityStepHelper {
float m_size;
bool m_sizeavailable;
- bool m_extend_bounds;
+ /* Flags for inheriting classes. */
+ bool use_variable_size_;
public:
+ virtual void init_data() override;
/**
* Initialize the execution
*/
@@ -75,8 +83,14 @@ class BlurBaseOperation : public NodeOperation, public QualityStepHelper {
this->m_extend_bounds = extend_bounds;
}
+ int get_blur_size(eDimension dim) const;
+
void determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2]) override;
+
+ virtual void get_area_of_interest(int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.cc b/source/blender/compositor/operations/COM_BokehBlurOperation.cc
index 3f98732b403..f2a43b7dbca 100644
--- a/source/blender/compositor/operations/COM_BokehBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_BokehBlurOperation.cc
@@ -17,6 +17,8 @@
*/
#include "COM_BokehBlurOperation.h"
+#include "COM_ConstantOperation.h"
+
#include "BLI_math.h"
#include "COM_OpenCLDevice.h"
@@ -24,6 +26,11 @@
namespace blender::compositor {
+constexpr int IMAGE_INPUT_INDEX = 0;
+constexpr int BOKEH_INPUT_INDEX = 1;
+constexpr int BOUNDING_BOX_INPUT_INDEX = 2;
+constexpr int SIZE_INPUT_INDEX = 3;
+
BokehBlurOperation::BokehBlurOperation()
{
this->addInputSocket(DataType::Color);
@@ -44,6 +51,23 @@ BokehBlurOperation::BokehBlurOperation()
this->m_extend_bounds = false;
}
+void BokehBlurOperation::init_data()
+{
+ if (execution_model_ == eExecutionModel::FullFrame) {
+ updateSize();
+ }
+
+ NodeOperation *bokeh = get_input_operation(BOKEH_INPUT_INDEX);
+ const int width = bokeh->getWidth();
+ const int height = bokeh->getHeight();
+
+ const float dimension = MIN2(width, height);
+
+ m_bokehMidX = width / 2.0f;
+ m_bokehMidY = height / 2.0f;
+ m_bokehDimension = dimension / 2.0f;
+}
+
void *BokehBlurOperation::initializeTileData(rcti * /*rect*/)
{
lockMutex();
@@ -58,18 +82,11 @@ void *BokehBlurOperation::initializeTileData(rcti * /*rect*/)
void BokehBlurOperation::initExecution()
{
initMutex();
+
this->m_inputProgram = getInputSocketReader(0);
this->m_inputBokehProgram = getInputSocketReader(1);
this->m_inputBoundingBoxReader = getInputSocketReader(2);
- int width = this->m_inputBokehProgram->getWidth();
- int height = this->m_inputBokehProgram->getHeight();
-
- float dimension = MIN2(width, height);
-
- this->m_bokehMidX = width / 2.0f;
- this->m_bokehMidY = height / 2.0f;
- this->m_bokehDimension = dimension / 2.0f;
QualityStepHelper::initExecution(COM_QH_INCREASE);
}
@@ -225,23 +242,146 @@ void BokehBlurOperation::executeOpenCL(OpenCLDevice *device,
void BokehBlurOperation::updateSize()
{
- if (!this->m_sizeavailable) {
- float result[4];
- this->getInputSocketReader(3)->readSampled(result, 0, 0, PixelSampler::Nearest);
- this->m_size = result[0];
- CLAMP(this->m_size, 0.0f, 10.0f);
- this->m_sizeavailable = true;
+ if (this->m_sizeavailable) {
+ return;
}
+
+ switch (execution_model_) {
+ case eExecutionModel::Tiled: {
+ float result[4];
+ this->getInputSocketReader(3)->readSampled(result, 0, 0, PixelSampler::Nearest);
+ this->m_size = result[0];
+ CLAMP(this->m_size, 0.0f, 10.0f);
+ break;
+ }
+ case eExecutionModel::FullFrame: {
+ NodeOperation *size_input = get_input_operation(SIZE_INPUT_INDEX);
+ if (size_input->get_flags().is_constant_operation) {
+ m_size = *static_cast<ConstantOperation *>(size_input)->get_constant_elem();
+ CLAMP(m_size, 0.0f, 10.0f);
+ } /* Else use default. */
+ break;
+ }
+ }
+ this->m_sizeavailable = true;
}
void BokehBlurOperation::determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2])
{
- NodeOperation::determineResolution(resolution, preferredResolution);
- if (this->m_extend_bounds) {
- const float max_dim = MAX2(resolution[0], resolution[1]);
- resolution[0] += 2 * this->m_size * max_dim / 100.0f;
- resolution[1] += 2 * this->m_size * max_dim / 100.0f;
+ if (!m_extend_bounds) {
+ NodeOperation::determineResolution(resolution, preferredResolution);
+ return;
+ }
+
+ switch (execution_model_) {
+ case eExecutionModel::Tiled: {
+ NodeOperation::determineResolution(resolution, preferredResolution);
+ const float max_dim = MAX2(resolution[0], resolution[1]);
+ resolution[0] += 2 * this->m_size * max_dim / 100.0f;
+ resolution[1] += 2 * this->m_size * max_dim / 100.0f;
+ break;
+ }
+ case eExecutionModel::FullFrame: {
+ set_determined_resolution_modifier([=](unsigned int res[2]) {
+ const float max_dim = MAX2(res[0], res[1]);
+ /* Rounding to even prevents image jiggling in backdrop while switching size values. */
+ float add_size = round_to_even(2 * this->m_size * max_dim / 100.0f);
+ res[0] += add_size;
+ res[1] += add_size;
+ });
+ NodeOperation::determineResolution(resolution, preferredResolution);
+ break;
+ }
+ }
+}
+
+void BokehBlurOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ switch (input_idx) {
+ case IMAGE_INPUT_INDEX: {
+ const float max_dim = MAX2(this->getWidth(), this->getHeight());
+ const float add_size = m_size * max_dim / 100.0f;
+ r_input_area.xmin = output_area.xmin - add_size;
+ r_input_area.xmax = output_area.xmax + add_size;
+ r_input_area.ymin = output_area.ymin - add_size;
+ r_input_area.ymax = output_area.ymax + add_size;
+ break;
+ }
+ case BOKEH_INPUT_INDEX: {
+ NodeOperation *bokeh_input = getInputOperation(BOKEH_INPUT_INDEX);
+ r_input_area.xmin = 0;
+ r_input_area.xmax = bokeh_input->getWidth();
+ r_input_area.ymin = 0;
+ r_input_area.ymax = bokeh_input->getHeight();
+ break;
+ }
+ case BOUNDING_BOX_INPUT_INDEX:
+ r_input_area = output_area;
+ break;
+ case SIZE_INPUT_INDEX: {
+ r_input_area = COM_SINGLE_ELEM_AREA;
+ break;
+ }
+ }
+}
+
+void BokehBlurOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const float max_dim = MAX2(this->getWidth(), this->getHeight());
+ const int pixel_size = m_size * max_dim / 100.0f;
+ const float m = m_bokehDimension / pixel_size;
+
+ const MemoryBuffer *image_input = inputs[IMAGE_INPUT_INDEX];
+ const MemoryBuffer *bokeh_input = inputs[BOKEH_INPUT_INDEX];
+ MemoryBuffer *bounding_input = inputs[BOUNDING_BOX_INPUT_INDEX];
+ BuffersIterator<float> it = output->iterate_with({bounding_input}, area);
+ const rcti &image_rect = image_input->get_rect();
+ for (; !it.is_end(); ++it) {
+ const int x = it.x;
+ const int y = it.y;
+ const float bounding_box = *it.in(0);
+ if (bounding_box <= 0.0f) {
+ image_input->read_elem(x, y, it.out);
+ continue;
+ }
+
+ float color_accum[4] = {0};
+ float multiplier_accum[4] = {0};
+ if (pixel_size < 2) {
+ image_input->read_elem(x, y, color_accum);
+ multiplier_accum[0] = 1.0f;
+ multiplier_accum[1] = 1.0f;
+ multiplier_accum[2] = 1.0f;
+ multiplier_accum[3] = 1.0f;
+ }
+ const int miny = MAX2(y - pixel_size, image_rect.ymin);
+ const int maxy = MIN2(y + pixel_size, image_rect.ymax);
+ const int minx = MAX2(x - pixel_size, image_rect.xmin);
+ const int maxx = MIN2(x + pixel_size, image_rect.xmax);
+ const int step = getStep();
+ const int elem_stride = image_input->elem_stride * step;
+ const int row_stride = image_input->row_stride * step;
+ const float *row_color = image_input->get_elem(minx, miny);
+ for (int ny = miny; ny < maxy; ny += step, row_color += row_stride) {
+ const float *color = row_color;
+ const float v = m_bokehMidY - (ny - y) * m;
+ for (int nx = minx; nx < maxx; nx += step, color += elem_stride) {
+ const float u = m_bokehMidX - (nx - x) * m;
+ float bokeh[4];
+ bokeh_input->read_elem_checked(u, v, bokeh);
+ madd_v4_v4v4(color_accum, bokeh, color);
+ add_v4_v4(multiplier_accum, bokeh);
+ }
+ }
+ it.out[0] = color_accum[0] * (1.0f / multiplier_accum[0]);
+ it.out[1] = color_accum[1] * (1.0f / multiplier_accum[1]);
+ it.out[2] = color_accum[2] * (1.0f / multiplier_accum[2]);
+ it.out[3] = color_accum[3] * (1.0f / multiplier_accum[3]);
}
}
diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.h b/source/blender/compositor/operations/COM_BokehBlurOperation.h
index 3ce06adb5d6..59c14305393 100644
--- a/source/blender/compositor/operations/COM_BokehBlurOperation.h
+++ b/source/blender/compositor/operations/COM_BokehBlurOperation.h
@@ -18,12 +18,12 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
#include "COM_QualityStepHelper.h"
namespace blender::compositor {
-class BokehBlurOperation : public NodeOperation, public QualityStepHelper {
+class BokehBlurOperation : public MultiThreadedOperation, public QualityStepHelper {
private:
SocketReader *m_inputProgram;
SocketReader *m_inputBokehProgram;
@@ -31,6 +31,7 @@ class BokehBlurOperation : public NodeOperation, public QualityStepHelper {
void updateSize();
float m_size;
bool m_sizeavailable;
+
float m_bokehMidX;
float m_bokehMidY;
float m_bokehDimension;
@@ -39,6 +40,8 @@ class BokehBlurOperation : public NodeOperation, public QualityStepHelper {
public:
BokehBlurOperation();
+ void init_data() override;
+
void *initializeTileData(rcti *rect) override;
/**
* The inner loop of this operation.
@@ -79,6 +82,11 @@ class BokehBlurOperation : public NodeOperation, public QualityStepHelper {
void determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2]) override;
+
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ChannelMatteOperation.cc b/source/blender/compositor/operations/COM_ChannelMatteOperation.cc
index ec4331dc231..65742d0cfcc 100644
--- a/source/blender/compositor/operations/COM_ChannelMatteOperation.cc
+++ b/source/blender/compositor/operations/COM_ChannelMatteOperation.cc
@@ -27,6 +27,7 @@ ChannelMatteOperation::ChannelMatteOperation()
addOutputSocket(DataType::Value);
this->m_inputImageProgram = nullptr;
+ flags.can_be_constant = true;
}
void ChannelMatteOperation::initExecution()
@@ -121,4 +122,37 @@ void ChannelMatteOperation::executePixelSampled(float output[4],
output[0] = MIN2(alpha, inColor[3]);
}
+void ChannelMatteOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const float *color = it.in(0);
+
+ /* Matte operation. */
+ float alpha = color[this->m_ids[0]] - MAX2(color[this->m_ids[1]], color[this->m_ids[2]]);
+
+ /* Flip because 0.0 is transparent, not 1.0. */
+ alpha = 1.0f - alpha;
+
+ /* Test range. */
+ if (alpha > m_limit_max) {
+ alpha = color[3]; /* Whatever it was prior. */
+ }
+ else if (alpha < m_limit_min) {
+ alpha = 0.0f;
+ }
+ else { /* Blend. */
+ alpha = (alpha - m_limit_min) / m_limit_range;
+ }
+
+ /* Store matte(alpha) value in [0] to go with
+ * COM_SetAlphaMultiplyOperation and the Value output.
+ */
+
+ /* Don't make something that was more transparent less transparent. */
+ *it.out = MIN2(alpha, color[3]);
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ChannelMatteOperation.h b/source/blender/compositor/operations/COM_ChannelMatteOperation.h
index 6e9dcccd36e..ba50105dd3b 100644
--- a/source/blender/compositor/operations/COM_ChannelMatteOperation.h
+++ b/source/blender/compositor/operations/COM_ChannelMatteOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_MixOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
@@ -26,7 +26,7 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
-class ChannelMatteOperation : public NodeOperation {
+class ChannelMatteOperation : public MultiThreadedOperation {
private:
SocketReader *m_inputImageProgram;
@@ -71,6 +71,10 @@ class ChannelMatteOperation : public NodeOperation {
this->m_limit_channel = nodeChroma->channel;
this->m_matte_channel = custom2;
}
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ChromaMatteOperation.cc b/source/blender/compositor/operations/COM_ChromaMatteOperation.cc
index b7fec5f07e5..0784f266b19 100644
--- a/source/blender/compositor/operations/COM_ChromaMatteOperation.cc
+++ b/source/blender/compositor/operations/COM_ChromaMatteOperation.cc
@@ -29,6 +29,7 @@ ChromaMatteOperation::ChromaMatteOperation()
this->m_inputImageProgram = nullptr;
this->m_inputKeyProgram = nullptr;
+ flags.can_be_constant = true;
}
void ChromaMatteOperation::initExecution()
@@ -110,4 +111,58 @@ void ChromaMatteOperation::executePixelSampled(float output[4],
}
}
+void ChromaMatteOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const float acceptance = this->m_settings->t1; /* In radians. */
+ const float cutoff = this->m_settings->t2; /* In radians. */
+ const float gain = this->m_settings->fstrength;
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const float *in_image = it.in(0);
+ const float *in_key = it.in(1);
+
+ /* Store matte(alpha) value in [0] to go with
+ * #COM_SetAlphaMultiplyOperation and the Value output. */
+
+ /* Algorithm from book "Video Demystified", does not include the spill reduction part. */
+ /* Find theta, the angle that the color space should be rotated based on key. */
+
+ /* Rescale to `-1.0..1.0`. */
+ // const float image_Y = (in_image[0] * 2.0f) - 1.0f; // UNUSED
+ const float image_cb = (in_image[1] * 2.0f) - 1.0f;
+ const float image_cr = (in_image[2] * 2.0f) - 1.0f;
+
+ // const float key_Y = (in_key[0] * 2.0f) - 1.0f; // UNUSED
+ const float key_cb = (in_key[1] * 2.0f) - 1.0f;
+ const float key_cr = (in_key[2] * 2.0f) - 1.0f;
+
+ const float theta = atan2(key_cr, key_cb);
+
+ /* Rotate the cb and cr into x/z space. */
+ const float x_angle = image_cb * cosf(theta) + image_cr * sinf(theta);
+ const float z_angle = image_cr * cosf(theta) - image_cb * sinf(theta);
+
+ /* If within the acceptance angle. */
+ /* If kfg is <0 then the pixel is outside of the key color. */
+ const float kfg = x_angle - (fabsf(z_angle) / tanf(acceptance / 2.0f));
+
+ if (kfg > 0.0f) { /* Found a pixel that is within key color. */
+ const float beta = atan2(z_angle, x_angle);
+ float alpha = 1.0f - (kfg / gain);
+
+ /* Ff beta is within the cutoff angle. */
+ if (fabsf(beta) < (cutoff / 2.0f)) {
+ alpha = 0.0f;
+ }
+
+ /* Don't make something that was more transparent less transparent. */
+ it.out[0] = alpha < in_image[3] ? alpha : in_image[3];
+ }
+ else { /* Pixel is outside key color. */
+ it.out[0] = in_image[3]; /* Make pixel just as transparent as it was before. */
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ChromaMatteOperation.h b/source/blender/compositor/operations/COM_ChromaMatteOperation.h
index 48c3a785011..065349910a7 100644
--- a/source/blender/compositor/operations/COM_ChromaMatteOperation.h
+++ b/source/blender/compositor/operations/COM_ChromaMatteOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_MixOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
@@ -26,7 +26,7 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
-class ChromaMatteOperation : public NodeOperation {
+class ChromaMatteOperation : public MultiThreadedOperation {
private:
NodeChroma *m_settings;
SocketReader *m_inputImageProgram;
@@ -50,6 +50,10 @@ class ChromaMatteOperation : public NodeOperation {
{
this->m_settings = nodeChroma;
}
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorMatteOperation.cc b/source/blender/compositor/operations/COM_ColorMatteOperation.cc
index ddfbf415d9c..dec6571f217 100644
--- a/source/blender/compositor/operations/COM_ColorMatteOperation.cc
+++ b/source/blender/compositor/operations/COM_ColorMatteOperation.cc
@@ -29,6 +29,7 @@ ColorMatteOperation::ColorMatteOperation()
this->m_inputImageProgram = nullptr;
this->m_inputKeyProgram = nullptr;
+ flags.can_be_constant = true;
}
void ColorMatteOperation::initExecution()
@@ -82,4 +83,40 @@ void ColorMatteOperation::executePixelSampled(float output[4],
}
}
+void ColorMatteOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const float hue = m_settings->t1;
+ const float sat = m_settings->t2;
+ const float val = m_settings->t3;
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const float *in_color = it.in(0);
+ const float *in_key = it.in(1);
+
+ /* Store matte(alpha) value in [0] to go with
+ * COM_SetAlphaMultiplyOperation and the Value output.
+ */
+
+ float h_wrap;
+ if (
+ /* Do hue last because it needs to wrap, and does some more checks. */
+
+ /* #sat */ (fabsf(in_color[1] - in_key[1]) < sat) &&
+ /* #val */ (fabsf(in_color[2] - in_key[2]) < val) &&
+
+ /* Multiply by 2 because it wraps on both sides of the hue,
+ * otherwise 0.5 would key all hue's. */
+
+ /* #hue */
+ ((h_wrap = 2.0f * fabsf(in_color[0] - in_key[0])) < hue || (2.0f - h_wrap) < hue)) {
+ it.out[0] = 0.0f; /* Make transparent. */
+ }
+
+ else { /* Pixel is outside key color. */
+ it.out[0] = in_color[3]; /* Make pixel just as transparent as it was before. */
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorMatteOperation.h b/source/blender/compositor/operations/COM_ColorMatteOperation.h
index 439a3b0741d..49d06e62e65 100644
--- a/source/blender/compositor/operations/COM_ColorMatteOperation.h
+++ b/source/blender/compositor/operations/COM_ColorMatteOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_MixOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
@@ -26,7 +26,7 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
-class ColorMatteOperation : public NodeOperation {
+class ColorMatteOperation : public MultiThreadedOperation {
private:
NodeChroma *m_settings;
SocketReader *m_inputImageProgram;
@@ -50,6 +50,10 @@ class ColorMatteOperation : public NodeOperation {
{
this->m_settings = nodeChroma;
}
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorRampOperation.cc b/source/blender/compositor/operations/COM_ColorRampOperation.cc
index 0ee65a6529e..6c1b23ea731 100644
--- a/source/blender/compositor/operations/COM_ColorRampOperation.cc
+++ b/source/blender/compositor/operations/COM_ColorRampOperation.cc
@@ -29,6 +29,7 @@ ColorRampOperation::ColorRampOperation()
this->m_inputProgram = nullptr;
this->m_colorBand = nullptr;
+ this->flags.can_be_constant = true;
}
void ColorRampOperation::initExecution()
{
@@ -51,4 +52,13 @@ void ColorRampOperation::deinitExecution()
this->m_inputProgram = nullptr;
}
+void ColorRampOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ BKE_colorband_evaluate(m_colorBand, *it.in(0), it.out);
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorRampOperation.h b/source/blender/compositor/operations/COM_ColorRampOperation.h
index d32af9bea24..ab64b9928fd 100644
--- a/source/blender/compositor/operations/COM_ColorRampOperation.h
+++ b/source/blender/compositor/operations/COM_ColorRampOperation.h
@@ -18,12 +18,12 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
#include "DNA_texture_types.h"
namespace blender::compositor {
-class ColorRampOperation : public NodeOperation {
+class ColorRampOperation : public MultiThreadedOperation {
private:
/**
* Cached reference to the inputProgram
@@ -53,6 +53,10 @@ class ColorRampOperation : public NodeOperation {
{
this->m_colorBand = colorBand;
}
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorSpillOperation.cc b/source/blender/compositor/operations/COM_ColorSpillOperation.cc
index 7dc7e2775fc..4b0e0520b75 100644
--- a/source/blender/compositor/operations/COM_ColorSpillOperation.cc
+++ b/source/blender/compositor/operations/COM_ColorSpillOperation.cc
@@ -32,6 +32,7 @@ ColorSpillOperation::ColorSpillOperation()
this->m_inputFacReader = nullptr;
this->m_spillChannel = 1; // GREEN
this->m_spillMethod = 0;
+ flags.can_be_constant = true;
}
void ColorSpillOperation::initExecution()
@@ -118,4 +119,36 @@ void ColorSpillOperation::executePixelSampled(float output[4],
}
}
+void ColorSpillOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const float *color = it.in(0);
+ const float factor = MIN2(1.0f, *it.in(1));
+
+ float map;
+ switch (m_spillMethod) {
+ case 0: /* simple */
+ map = factor *
+ (color[m_spillChannel] - (m_settings->limscale * color[m_settings->limchan]));
+ break;
+ default: /* average */
+ map = factor * (color[m_spillChannel] -
+ (m_settings->limscale * AVG(color[m_channel2], color[m_channel3])));
+ break;
+ }
+
+ if (map > 0.0f) {
+ it.out[0] = color[0] + m_rmut * (m_settings->uspillr * map);
+ it.out[1] = color[1] + m_gmut * (m_settings->uspillg * map);
+ it.out[2] = color[2] + m_bmut * (m_settings->uspillb * map);
+ it.out[3] = color[3];
+ }
+ else {
+ copy_v4_v4(it.out, color);
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorSpillOperation.h b/source/blender/compositor/operations/COM_ColorSpillOperation.h
index 9b82e720527..6a5e688c160 100644
--- a/source/blender/compositor/operations/COM_ColorSpillOperation.h
+++ b/source/blender/compositor/operations/COM_ColorSpillOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
@@ -26,7 +26,7 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
-class ColorSpillOperation : public NodeOperation {
+class ColorSpillOperation : public MultiThreadedOperation {
protected:
NodeColorspill *m_settings;
SocketReader *m_inputImageReader;
@@ -65,6 +65,10 @@ class ColorSpillOperation : public NodeOperation {
}
float calculateMapValue(float fac, float *input);
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ConvertOperation.cc b/source/blender/compositor/operations/COM_ConvertOperation.cc
index 384936533c7..d377903efea 100644
--- a/source/blender/compositor/operations/COM_ConvertOperation.cc
+++ b/source/blender/compositor/operations/COM_ConvertOperation.cc
@@ -27,6 +27,7 @@ namespace blender::compositor {
ConvertBaseOperation::ConvertBaseOperation()
{
this->m_inputOperation = nullptr;
+ this->flags.can_be_constant = true;
}
void ConvertBaseOperation::initExecution()
@@ -39,6 +40,14 @@ void ConvertBaseOperation::deinitExecution()
this->m_inputOperation = nullptr;
}
+void ConvertBaseOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ BuffersIterator<float> it = output->iterate_with(inputs, area);
+ update_memory_buffer_partial(it);
+}
+
/* ******** Value to Color ******** */
ConvertValueToColorOperation::ConvertValueToColorOperation() : ConvertBaseOperation()
@@ -58,6 +67,14 @@ void ConvertValueToColorOperation::executePixelSampled(float output[4],
output[3] = 1.0f;
}
+void ConvertValueToColorOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ it.out[0] = it.out[1] = it.out[2] = *it.in(0);
+ it.out[3] = 1.0f;
+ }
+}
+
/* ******** Color to Value ******** */
ConvertColorToValueOperation::ConvertColorToValueOperation() : ConvertBaseOperation()
@@ -76,6 +93,14 @@ void ConvertColorToValueOperation::executePixelSampled(float output[4],
output[0] = (inputColor[0] + inputColor[1] + inputColor[2]) / 3.0f;
}
+void ConvertColorToValueOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float *in = it.in(0);
+ it.out[0] = (in[0] + in[1] + in[2]) / 3.0f;
+ }
+}
+
/* ******** Color to BW ******** */
ConvertColorToBWOperation::ConvertColorToBWOperation() : ConvertBaseOperation()
@@ -94,6 +119,13 @@ void ConvertColorToBWOperation::executePixelSampled(float output[4],
output[0] = IMB_colormanagement_get_luminance(inputColor);
}
+void ConvertColorToBWOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ it.out[0] = IMB_colormanagement_get_luminance(it.in(0));
+ }
+}
+
/* ******** Color to Vector ******** */
ConvertColorToVectorOperation::ConvertColorToVectorOperation() : ConvertBaseOperation()
@@ -112,6 +144,13 @@ void ConvertColorToVectorOperation::executePixelSampled(float output[4],
copy_v3_v3(output, color);
}
+void ConvertColorToVectorOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ copy_v3_v3(it.out, it.in(0));
+ }
+}
+
/* ******** Value to Vector ******** */
ConvertValueToVectorOperation::ConvertValueToVectorOperation() : ConvertBaseOperation()
@@ -130,6 +169,13 @@ void ConvertValueToVectorOperation::executePixelSampled(float output[4],
output[0] = output[1] = output[2] = value;
}
+void ConvertValueToVectorOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ it.out[0] = it.out[1] = it.out[2] = *it.in(0);
+ }
+}
+
/* ******** Vector to Color ******** */
ConvertVectorToColorOperation::ConvertVectorToColorOperation() : ConvertBaseOperation()
@@ -147,6 +193,14 @@ void ConvertVectorToColorOperation::executePixelSampled(float output[4],
output[3] = 1.0f;
}
+void ConvertVectorToColorOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ copy_v3_v3(it.out, it.in(0));
+ it.out[3] = 1.0f;
+ }
+}
+
/* ******** Vector to Value ******** */
ConvertVectorToValueOperation::ConvertVectorToValueOperation() : ConvertBaseOperation()
@@ -165,6 +219,14 @@ void ConvertVectorToValueOperation::executePixelSampled(float output[4],
output[0] = (input[0] + input[1] + input[2]) / 3.0f;
}
+void ConvertVectorToValueOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float *in = it.in(0);
+ it.out[0] = (in[0] + in[1] + in[2]) / 3.0f;
+ }
+}
+
/* ******** RGB to YCC ******** */
ConvertRGBToYCCOperation::ConvertRGBToYCCOperation() : ConvertBaseOperation()
@@ -207,6 +269,18 @@ void ConvertRGBToYCCOperation::executePixelSampled(float output[4],
output[3] = inputColor[3];
}
+void ConvertRGBToYCCOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float *in = it.in(0);
+ rgb_to_ycc(in[0], in[1], in[2], &it.out[0], &it.out[1], &it.out[2], this->m_mode);
+
+ /* Normalize for viewing (#rgb_to_ycc returns 0-255 values). */
+ mul_v3_fl(it.out, 1.0f / 255.0f);
+ it.out[3] = in[3];
+ }
+}
+
/* ******** YCC to RGB ******** */
ConvertYCCToRGBOperation::ConvertYCCToRGBOperation() : ConvertBaseOperation()
@@ -253,6 +327,22 @@ void ConvertYCCToRGBOperation::executePixelSampled(float output[4],
output[3] = inputColor[3];
}
+void ConvertYCCToRGBOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float *in = it.in(0);
+ /* Multiply by 255 to un-normalize (#ycc_to_rgb needs input values in 0-255 range). */
+ ycc_to_rgb(in[0] * 255.0f,
+ in[1] * 255.0f,
+ in[2] * 255.0f,
+ &it.out[0],
+ &it.out[1],
+ &it.out[2],
+ this->m_mode);
+ it.out[3] = in[3];
+ }
+}
+
/* ******** RGB to YUV ******** */
ConvertRGBToYUVOperation::ConvertRGBToYUVOperation() : ConvertBaseOperation()
@@ -278,6 +368,15 @@ void ConvertRGBToYUVOperation::executePixelSampled(float output[4],
output[3] = inputColor[3];
}
+void ConvertRGBToYUVOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float *in = it.in(0);
+ rgb_to_yuv(in[0], in[1], in[2], &it.out[0], &it.out[1], &it.out[2], BLI_YUV_ITU_BT709);
+ it.out[3] = in[3];
+ }
+}
+
/* ******** YUV to RGB ******** */
ConvertYUVToRGBOperation::ConvertYUVToRGBOperation() : ConvertBaseOperation()
@@ -303,6 +402,15 @@ void ConvertYUVToRGBOperation::executePixelSampled(float output[4],
output[3] = inputColor[3];
}
+void ConvertYUVToRGBOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float *in = it.in(0);
+ yuv_to_rgb(in[0], in[1], in[2], &it.out[0], &it.out[1], &it.out[2], BLI_YUV_ITU_BT709);
+ it.out[3] = in[3];
+ }
+}
+
/* ******** RGB to HSV ******** */
ConvertRGBToHSVOperation::ConvertRGBToHSVOperation() : ConvertBaseOperation()
@@ -322,6 +430,15 @@ void ConvertRGBToHSVOperation::executePixelSampled(float output[4],
output[3] = inputColor[3];
}
+void ConvertRGBToHSVOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float *in = it.in(0);
+ rgb_to_hsv_v(in, it.out);
+ it.out[3] = in[3];
+ }
+}
+
/* ******** HSV to RGB ******** */
ConvertHSVToRGBOperation::ConvertHSVToRGBOperation() : ConvertBaseOperation()
@@ -344,6 +461,18 @@ void ConvertHSVToRGBOperation::executePixelSampled(float output[4],
output[3] = inputColor[3];
}
+void ConvertHSVToRGBOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float *in = it.in(0);
+ hsv_to_rgb_v(in, it.out);
+ it.out[0] = max_ff(it.out[0], 0.0f);
+ it.out[1] = max_ff(it.out[1], 0.0f);
+ it.out[2] = max_ff(it.out[2], 0.0f);
+ it.out[3] = in[3];
+ }
+}
+
/* ******** Premul to Straight ******** */
ConvertPremulToStraightOperation::ConvertPremulToStraightOperation() : ConvertBaseOperation()
@@ -363,6 +492,13 @@ void ConvertPremulToStraightOperation::executePixelSampled(float output[4],
copy_v4_v4(output, converted);
}
+void ConvertPremulToStraightOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ copy_v4_v4(it.out, ColorSceneLinear4f<eAlpha::Premultiplied>(it.in(0)).unpremultiply_alpha());
+ }
+}
+
/* ******** Straight to Premul ******** */
ConvertStraightToPremulOperation::ConvertStraightToPremulOperation() : ConvertBaseOperation()
@@ -382,6 +518,13 @@ void ConvertStraightToPremulOperation::executePixelSampled(float output[4],
copy_v4_v4(output, converted);
}
+void ConvertStraightToPremulOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ copy_v4_v4(it.out, ColorSceneLinear4f<eAlpha::Straight>(it.in(0)).premultiply_alpha());
+ }
+}
+
/* ******** Separate Channels ******** */
SeparateChannelOperation::SeparateChannelOperation()
@@ -410,6 +553,15 @@ void SeparateChannelOperation::executePixelSampled(float output[4],
output[0] = input[this->m_channel];
}
+void SeparateChannelOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ it.out[0] = it.in(0)[this->m_channel];
+ }
+}
+
/* ******** Combine Channels ******** */
CombineChannelsOperation::CombineChannelsOperation()
@@ -466,4 +618,16 @@ void CombineChannelsOperation::executePixelSampled(float output[4],
}
}
+void CombineChannelsOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ it.out[0] = *it.in(0);
+ it.out[1] = *it.in(1);
+ it.out[2] = *it.in(2);
+ it.out[3] = *it.in(3);
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ConvertOperation.h b/source/blender/compositor/operations/COM_ConvertOperation.h
index 7a726e35c7c..0334959ae7e 100644
--- a/source/blender/compositor/operations/COM_ConvertOperation.h
+++ b/source/blender/compositor/operations/COM_ConvertOperation.h
@@ -18,11 +18,11 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
-class ConvertBaseOperation : public NodeOperation {
+class ConvertBaseOperation : public MultiThreadedOperation {
protected:
SocketReader *m_inputOperation;
@@ -31,6 +31,13 @@ class ConvertBaseOperation : public NodeOperation {
void initExecution() override;
void deinitExecution() override;
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) final;
+
+ protected:
+ virtual void update_memory_buffer_partial(BuffersIterator<float> &it) = 0;
};
class ConvertValueToColorOperation : public ConvertBaseOperation {
@@ -38,6 +45,9 @@ class ConvertValueToColorOperation : public ConvertBaseOperation {
ConvertValueToColorOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertColorToValueOperation : public ConvertBaseOperation {
@@ -45,6 +55,9 @@ class ConvertColorToValueOperation : public ConvertBaseOperation {
ConvertColorToValueOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertColorToBWOperation : public ConvertBaseOperation {
@@ -52,6 +65,9 @@ class ConvertColorToBWOperation : public ConvertBaseOperation {
ConvertColorToBWOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertColorToVectorOperation : public ConvertBaseOperation {
@@ -59,6 +75,9 @@ class ConvertColorToVectorOperation : public ConvertBaseOperation {
ConvertColorToVectorOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertValueToVectorOperation : public ConvertBaseOperation {
@@ -66,6 +85,9 @@ class ConvertValueToVectorOperation : public ConvertBaseOperation {
ConvertValueToVectorOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertVectorToColorOperation : public ConvertBaseOperation {
@@ -73,6 +95,9 @@ class ConvertVectorToColorOperation : public ConvertBaseOperation {
ConvertVectorToColorOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertVectorToValueOperation : public ConvertBaseOperation {
@@ -80,6 +105,9 @@ class ConvertVectorToValueOperation : public ConvertBaseOperation {
ConvertVectorToValueOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertRGBToYCCOperation : public ConvertBaseOperation {
@@ -94,6 +122,9 @@ class ConvertRGBToYCCOperation : public ConvertBaseOperation {
/** Set the YCC mode */
void setMode(int mode);
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertYCCToRGBOperation : public ConvertBaseOperation {
@@ -108,6 +139,9 @@ class ConvertYCCToRGBOperation : public ConvertBaseOperation {
/** Set the YCC mode */
void setMode(int mode);
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertRGBToYUVOperation : public ConvertBaseOperation {
@@ -115,6 +149,9 @@ class ConvertRGBToYUVOperation : public ConvertBaseOperation {
ConvertRGBToYUVOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertYUVToRGBOperation : public ConvertBaseOperation {
@@ -122,6 +159,9 @@ class ConvertYUVToRGBOperation : public ConvertBaseOperation {
ConvertYUVToRGBOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertRGBToHSVOperation : public ConvertBaseOperation {
@@ -129,6 +169,9 @@ class ConvertRGBToHSVOperation : public ConvertBaseOperation {
ConvertRGBToHSVOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertHSVToRGBOperation : public ConvertBaseOperation {
@@ -136,6 +179,9 @@ class ConvertHSVToRGBOperation : public ConvertBaseOperation {
ConvertHSVToRGBOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertPremulToStraightOperation : public ConvertBaseOperation {
@@ -143,6 +189,9 @@ class ConvertPremulToStraightOperation : public ConvertBaseOperation {
ConvertPremulToStraightOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertStraightToPremulOperation : public ConvertBaseOperation {
@@ -150,9 +199,12 @@ class ConvertStraightToPremulOperation : public ConvertBaseOperation {
ConvertStraightToPremulOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
-class SeparateChannelOperation : public NodeOperation {
+class SeparateChannelOperation : public MultiThreadedOperation {
private:
SocketReader *m_inputOperation;
int m_channel;
@@ -168,9 +220,13 @@ class SeparateChannelOperation : public NodeOperation {
{
this->m_channel = channel;
}
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
-class CombineChannelsOperation : public NodeOperation {
+class CombineChannelsOperation : public MultiThreadedOperation {
private:
SocketReader *m_inputChannel1Operation;
SocketReader *m_inputChannel2Operation;
@@ -183,6 +239,10 @@ class CombineChannelsOperation : public NodeOperation {
void initExecution() override;
void deinitExecution() override;
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_CropOperation.cc b/source/blender/compositor/operations/COM_CropOperation.cc
index f12d93bc8d3..12833660fcb 100644
--- a/source/blender/compositor/operations/COM_CropOperation.cc
+++ b/source/blender/compositor/operations/COM_CropOperation.cc
@@ -95,6 +95,22 @@ void CropOperation::executePixelSampled(float output[4], float x, float y, Pixel
}
}
+void CropOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ rcti crop_area;
+ BLI_rcti_init(&crop_area, m_xmin, m_xmax, m_ymin, m_ymax);
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ if (BLI_rcti_isect_pt(&crop_area, it.x, it.y)) {
+ copy_v4_v4(it.out, it.in(0));
+ }
+ else {
+ zero_v4(it.out);
+ }
+ }
+}
+
CropImageOperation::CropImageOperation() : CropBaseOperation()
{
/* pass */
@@ -114,6 +130,18 @@ bool CropImageOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+void CropImageOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ BLI_assert(input_idx == 0);
+ UNUSED_VARS_NDEBUG(input_idx);
+ r_input_area.xmax = output_area.xmax + this->m_xmin;
+ r_input_area.xmin = output_area.xmin + this->m_xmin;
+ r_input_area.ymax = output_area.ymax + this->m_ymin;
+ r_input_area.ymin = output_area.ymin + this->m_ymin;
+}
+
void CropImageOperation::determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2])
{
@@ -136,4 +164,21 @@ void CropImageOperation::executePixelSampled(float output[4],
}
}
+void CropImageOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ rcti op_area;
+ BLI_rcti_init(&op_area, 0, getWidth(), 0, getHeight());
+ const MemoryBuffer *input = inputs[0];
+ for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
+ if (BLI_rcti_isect_pt(&op_area, it.x, it.y)) {
+ input->read_elem_checked(it.x + this->m_xmin, it.y + this->m_ymin, it.out);
+ }
+ else {
+ zero_v4(it.out);
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_CropOperation.h b/source/blender/compositor/operations/COM_CropOperation.h
index acdff79a77c..57caa4e5834 100644
--- a/source/blender/compositor/operations/COM_CropOperation.h
+++ b/source/blender/compositor/operations/COM_CropOperation.h
@@ -18,11 +18,11 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
-class CropBaseOperation : public NodeOperation {
+class CropBaseOperation : public MultiThreadedOperation {
protected:
SocketReader *m_inputOperation;
NodeTwoXYs *m_settings;
@@ -53,6 +53,10 @@ class CropOperation : public CropBaseOperation {
public:
CropOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
class CropImageOperation : public CropBaseOperation {
@@ -65,6 +69,11 @@ class CropImageOperation : public CropBaseOperation {
void determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2]) override;
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_CryptomatteOperation.cc b/source/blender/compositor/operations/COM_CryptomatteOperation.cc
index 1a86fadad76..02e7c5607d8 100644
--- a/source/blender/compositor/operations/COM_CryptomatteOperation.cc
+++ b/source/blender/compositor/operations/COM_CryptomatteOperation.cc
@@ -71,4 +71,34 @@ void CryptomatteOperation::executePixel(float output[4], int x, int y, void *dat
}
}
+void CryptomatteOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ zero_v4(it.out);
+ for (int i = 0; i < it.get_num_inputs(); i++) {
+ const float *input = it.in(i);
+ if (i == 0) {
+ /* Write the front-most object as false color for picking. */
+ it.out[0] = input[0];
+ uint32_t m3hash;
+ ::memcpy(&m3hash, &input[0], sizeof(uint32_t));
+ /* Since the red channel is likely to be out of display range,
+ * setting green and blue gives more meaningful images. */
+ it.out[1] = ((float)(m3hash << 8) / (float)UINT32_MAX);
+ it.out[2] = ((float)(m3hash << 16) / (float)UINT32_MAX);
+ }
+ for (const float hash : m_objectIndex) {
+ if (input[0] == hash) {
+ it.out[3] += input[1];
+ }
+ if (input[2] == hash) {
+ it.out[3] += input[3];
+ }
+ }
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_CryptomatteOperation.h b/source/blender/compositor/operations/COM_CryptomatteOperation.h
index 1b91358d228..f1bf4cdf624 100644
--- a/source/blender/compositor/operations/COM_CryptomatteOperation.h
+++ b/source/blender/compositor/operations/COM_CryptomatteOperation.h
@@ -18,11 +18,11 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
-class CryptomatteOperation : public NodeOperation {
+class CryptomatteOperation : public MultiThreadedOperation {
private:
Vector<float> m_objectIndex;
@@ -35,6 +35,10 @@ class CryptomatteOperation : public NodeOperation {
void executePixel(float output[4], int x, int y, void *data) override;
void addObjectIndex(float objectIndex);
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DifferenceMatteOperation.cc b/source/blender/compositor/operations/COM_DifferenceMatteOperation.cc
index 0acdfc1651f..31714b03b06 100644
--- a/source/blender/compositor/operations/COM_DifferenceMatteOperation.cc
+++ b/source/blender/compositor/operations/COM_DifferenceMatteOperation.cc
@@ -29,6 +29,7 @@ DifferenceMatteOperation::DifferenceMatteOperation()
this->m_inputImage1Program = nullptr;
this->m_inputImage2Program = nullptr;
+ flags.can_be_constant = true;
}
void DifferenceMatteOperation::initExecution()
@@ -86,4 +87,44 @@ void DifferenceMatteOperation::executePixelSampled(float output[4],
}
}
+void DifferenceMatteOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const float *color1 = it.in(0);
+ const float *color2 = it.in(1);
+
+ float difference = (fabsf(color2[0] - color1[0]) + fabsf(color2[1] - color1[1]) +
+ fabsf(color2[2] - color1[2]));
+
+ /* Average together the distances. */
+ difference = difference / 3.0f;
+
+ const float tolerance = m_settings->t1;
+ const float falloff = m_settings->t2;
+
+ /* Make 100% transparent. */
+ if (difference <= tolerance) {
+ it.out[0] = 0.0f;
+ }
+ /* In the falloff region, make partially transparent. */
+ else if (difference <= falloff + tolerance) {
+ difference = difference - tolerance;
+ const float alpha = difference / falloff;
+ /* Only change if more transparent than before. */
+ if (alpha < color1[3]) {
+ it.out[0] = alpha;
+ }
+ else { /* Leave as before. */
+ it.out[0] = color1[3];
+ }
+ }
+ else {
+ /* Foreground object. */
+ it.out[0] = color1[3];
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DifferenceMatteOperation.h b/source/blender/compositor/operations/COM_DifferenceMatteOperation.h
index d3963fee1c1..0a86535d946 100644
--- a/source/blender/compositor/operations/COM_DifferenceMatteOperation.h
+++ b/source/blender/compositor/operations/COM_DifferenceMatteOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_MixOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
@@ -26,7 +26,7 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
-class DifferenceMatteOperation : public NodeOperation {
+class DifferenceMatteOperation : public MultiThreadedOperation {
private:
NodeChroma *m_settings;
SocketReader *m_inputImage1Program;
@@ -50,6 +50,10 @@ class DifferenceMatteOperation : public NodeOperation {
{
this->m_settings = nodeChroma;
}
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DisplaceOperation.cc b/source/blender/compositor/operations/COM_DisplaceOperation.cc
index 9f3f5cfe489..a4c01fda7ca 100644
--- a/source/blender/compositor/operations/COM_DisplaceOperation.cc
+++ b/source/blender/compositor/operations/COM_DisplaceOperation.cc
@@ -32,20 +32,30 @@ DisplaceOperation::DisplaceOperation()
this->flags.complex = true;
this->m_inputColorProgram = nullptr;
- this->m_inputVectorProgram = nullptr;
- this->m_inputScaleXProgram = nullptr;
- this->m_inputScaleYProgram = nullptr;
}
void DisplaceOperation::initExecution()
{
this->m_inputColorProgram = this->getInputSocketReader(0);
- this->m_inputVectorProgram = this->getInputSocketReader(1);
- this->m_inputScaleXProgram = this->getInputSocketReader(2);
- this->m_inputScaleYProgram = this->getInputSocketReader(3);
+ NodeOperation *vector = this->getInputSocketReader(1);
+ NodeOperation *scale_x = this->getInputSocketReader(2);
+ NodeOperation *scale_y = this->getInputSocketReader(3);
+ if (execution_model_ == eExecutionModel::Tiled) {
+ vector_read_fn_ = [=](float x, float y, float *out) {
+ vector->readSampled(out, x, y, PixelSampler::Bilinear);
+ };
+ scale_x_read_fn_ = [=](float x, float y, float *out) {
+ scale_x->readSampled(out, x, y, PixelSampler::Nearest);
+ };
+ scale_y_read_fn_ = [=](float x, float y, float *out) {
+ scale_y->readSampled(out, x, y, PixelSampler::Nearest);
+ };
+ }
this->m_width_x4 = this->getWidth() * 4;
this->m_height_x4 = this->getHeight() * 4;
+ input_vector_width_ = vector->getWidth();
+ input_vector_height_ = vector->getHeight();
}
void DisplaceOperation::executePixelSampled(float output[4],
@@ -69,8 +79,8 @@ void DisplaceOperation::executePixelSampled(float output[4],
bool DisplaceOperation::read_displacement(
float x, float y, float xscale, float yscale, const float origin[2], float &r_u, float &r_v)
{
- float width = m_inputVectorProgram->getWidth();
- float height = m_inputVectorProgram->getHeight();
+ float width = input_vector_width_;
+ float height = input_vector_height_;
if (x < 0.0f || x >= width || y < 0.0f || y >= height) {
r_u = 0.0f;
r_v = 0.0f;
@@ -78,7 +88,7 @@ bool DisplaceOperation::read_displacement(
}
float col[4];
- m_inputVectorProgram->readSampled(col, x, y, PixelSampler::Bilinear);
+ vector_read_fn_(x, y, col);
r_u = origin[0] - col[0] * xscale;
r_v = origin[1] - col[1] * yscale;
return true;
@@ -90,9 +100,9 @@ void DisplaceOperation::pixelTransform(const float xy[2], float r_uv[2], float r
float uv[2]; /* temporary variables for derivative estimation */
int num;
- m_inputScaleXProgram->readSampled(col, xy[0], xy[1], PixelSampler::Nearest);
+ scale_x_read_fn_(xy[0], xy[1], col);
float xs = col[0];
- m_inputScaleYProgram->readSampled(col, xy[0], xy[1], PixelSampler::Nearest);
+ scale_y_read_fn_(xy[0], xy[1], col);
float ys = col[0];
/* clamp x and y displacement to triple image resolution -
* to prevent hangs from huge values mistakenly plugged in eg. z buffers */
@@ -146,9 +156,9 @@ void DisplaceOperation::pixelTransform(const float xy[2], float r_uv[2], float r
void DisplaceOperation::deinitExecution()
{
this->m_inputColorProgram = nullptr;
- this->m_inputVectorProgram = nullptr;
- this->m_inputScaleXProgram = nullptr;
- this->m_inputScaleYProgram = nullptr;
+ vector_read_fn_ = nullptr;
+ scale_x_read_fn_ = nullptr;
+ scale_y_read_fn_ = nullptr;
}
bool DisplaceOperation::determineDependingAreaOfInterest(rcti *input,
@@ -195,4 +205,61 @@ bool DisplaceOperation::determineDependingAreaOfInterest(rcti *input,
return false;
}
+void DisplaceOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ switch (input_idx) {
+ case 0: {
+ r_input_area.xmin = 0;
+ r_input_area.ymin = 0;
+ r_input_area.xmax = getInputOperation(input_idx)->getWidth();
+ r_input_area.ymax = getInputOperation(input_idx)->getHeight();
+ break;
+ }
+ case 1: {
+ r_input_area = output_area;
+ expand_area_for_sampler(r_input_area, PixelSampler::Bilinear);
+ break;
+ }
+ default: {
+ r_input_area = output_area;
+ break;
+ }
+ }
+}
+
+void DisplaceOperation::update_memory_buffer_started(MemoryBuffer *UNUSED(output),
+ const rcti &UNUSED(area),
+ Span<MemoryBuffer *> inputs)
+{
+ MemoryBuffer *vector = inputs[1];
+ MemoryBuffer *scale_x = inputs[2];
+ MemoryBuffer *scale_y = inputs[3];
+ vector_read_fn_ = [=](float x, float y, float *out) { vector->read_elem_bilinear(x, y, out); };
+ scale_x_read_fn_ = [=](float x, float y, float *out) { scale_x->read_elem_checked(x, y, out); };
+ scale_y_read_fn_ = [=](float x, float y, float *out) { scale_y->read_elem_checked(x, y, out); };
+}
+
+void DisplaceOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const MemoryBuffer *input_color = inputs[0];
+ for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
+ const float xy[2] = {(float)it.x, (float)it.y};
+ float uv[2];
+ float deriv[2][2];
+
+ pixelTransform(xy, uv, deriv);
+ if (is_zero_v2(deriv[0]) && is_zero_v2(deriv[1])) {
+ input_color->read_elem_bilinear(uv[0], uv[1], it.out);
+ }
+ else {
+ /* EWA filtering (without nearest it gets blurry with NO distortion). */
+ input_color->read_elem_filtered(uv[0], uv[1], deriv[0], deriv[1], it.out);
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DisplaceOperation.h b/source/blender/compositor/operations/COM_DisplaceOperation.h
index fd82692f687..5be914ab672 100644
--- a/source/blender/compositor/operations/COM_DisplaceOperation.h
+++ b/source/blender/compositor/operations/COM_DisplaceOperation.h
@@ -18,23 +18,27 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
-class DisplaceOperation : public NodeOperation {
+class DisplaceOperation : public MultiThreadedOperation {
private:
/**
* Cached reference to the inputProgram
*/
SocketReader *m_inputColorProgram;
- SocketReader *m_inputVectorProgram;
- SocketReader *m_inputScaleXProgram;
- SocketReader *m_inputScaleYProgram;
float m_width_x4;
float m_height_x4;
+ int input_vector_width_;
+ int input_vector_height_;
+
+ std::function<void(float x, float y, float *out)> vector_read_fn_;
+ std::function<void(float x, float y, float *out)> scale_x_read_fn_;
+ std::function<void(float x, float y, float *out)> scale_y_read_fn_;
+
public:
DisplaceOperation();
@@ -62,6 +66,14 @@ class DisplaceOperation : public NodeOperation {
*/
void deinitExecution() override;
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+ void update_memory_buffer_started(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
+
private:
bool read_displacement(
float x, float y, float xscale, float yscale, const float origin[2], float &r_u, float &r_v);
diff --git a/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cc b/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cc
index f4b77f5d32c..e1c531bd49e 100644
--- a/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cc
+++ b/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cc
@@ -132,4 +132,56 @@ bool DisplaceSimpleOperation::determineDependingAreaOfInterest(rcti *input,
return false;
}
+void DisplaceSimpleOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ switch (input_idx) {
+ case 0: {
+ r_input_area.xmin = 0;
+ r_input_area.ymin = 0;
+ r_input_area.xmax = getInputOperation(input_idx)->getWidth();
+ r_input_area.ymax = getInputOperation(input_idx)->getHeight();
+ break;
+ }
+ default: {
+ r_input_area = output_area;
+ break;
+ }
+ }
+}
+
+void DisplaceSimpleOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const float width = this->getWidth();
+ const float height = this->getHeight();
+ const MemoryBuffer *input_color = inputs[0];
+ for (BuffersIterator<float> it = output->iterate_with(inputs.drop_front(1), area); !it.is_end();
+ ++it) {
+ float scale_x = *it.in(1);
+ float scale_y = *it.in(2);
+
+ /* Clamp x and y displacement to triple image resolution -
+ * to prevent hangs from huge values mistakenly plugged in eg. z buffers. */
+ CLAMP(scale_x, -m_width_x4, m_width_x4);
+ CLAMP(scale_y, -m_height_x4, m_height_x4);
+
+ /* Main displacement in pixel space. */
+ const float *vector = it.in(0);
+ const float p_dx = vector[0] * scale_x;
+ const float p_dy = vector[1] * scale_y;
+
+ /* Displaced pixel in uv coords, for image sampling. */
+ /* Clamp nodes to avoid glitches. */
+ float u = it.x - p_dx + 0.5f;
+ float v = it.y - p_dy + 0.5f;
+ CLAMP(u, 0.0f, width - 1.0f);
+ CLAMP(v, 0.0f, height - 1.0f);
+
+ input_color->read_elem_checked(u, v, it.out);
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DisplaceSimpleOperation.h b/source/blender/compositor/operations/COM_DisplaceSimpleOperation.h
index 15e6fcd0523..99f52155466 100644
--- a/source/blender/compositor/operations/COM_DisplaceSimpleOperation.h
+++ b/source/blender/compositor/operations/COM_DisplaceSimpleOperation.h
@@ -18,11 +18,11 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
-class DisplaceSimpleOperation : public NodeOperation {
+class DisplaceSimpleOperation : public MultiThreadedOperation {
private:
/**
* Cached reference to the inputProgram
@@ -59,6 +59,11 @@ class DisplaceSimpleOperation : public NodeOperation {
* Deinitialize the execution
*/
void deinitExecution() override;
+
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.cc b/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.cc
index 1b3403cbb29..8155ff769a0 100644
--- a/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.cc
+++ b/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.cc
@@ -29,6 +29,7 @@ DistanceRGBMatteOperation::DistanceRGBMatteOperation()
this->m_inputImageProgram = nullptr;
this->m_inputKeyProgram = nullptr;
+ flags.can_be_constant = true;
}
void DistanceRGBMatteOperation::initExecution()
@@ -43,7 +44,7 @@ void DistanceRGBMatteOperation::deinitExecution()
this->m_inputKeyProgram = nullptr;
}
-float DistanceRGBMatteOperation::calculateDistance(float key[4], float image[4])
+float DistanceRGBMatteOperation::calculateDistance(const float key[4], const float image[4])
{
return len_v3v3(key, image);
}
@@ -93,4 +94,43 @@ void DistanceRGBMatteOperation::executePixelSampled(float output[4],
}
}
+void DistanceRGBMatteOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const float *in_image = it.in(0);
+ const float *in_key = it.in(1);
+
+ float distance = this->calculateDistance(in_key, in_image);
+ const float tolerance = this->m_settings->t1;
+ const float falloff = this->m_settings->t2;
+
+ /* Store matte(alpha) value in [0] to go with
+ * COM_SetAlphaMultiplyOperation and the Value output.
+ */
+
+ /* Make 100% transparent. */
+ if (distance < tolerance) {
+ it.out[0] = 0.0f;
+ }
+ /* In the falloff region, make partially transparent. */
+ else if (distance < falloff + tolerance) {
+ distance = distance - tolerance;
+ const float alpha = distance / falloff;
+ /* Only change if more transparent than before. */
+ if (alpha < in_image[3]) {
+ it.out[0] = alpha;
+ }
+ else { /* Leave as before. */
+ it.out[0] = in_image[3];
+ }
+ }
+ else {
+ /* Leave as before. */
+ it.out[0] = in_image[3];
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h b/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h
index 6fe603233b7..ba6682214ae 100644
--- a/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h
+++ b/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_MixOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
@@ -26,13 +26,13 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
-class DistanceRGBMatteOperation : public NodeOperation {
+class DistanceRGBMatteOperation : public MultiThreadedOperation {
protected:
NodeChroma *m_settings;
SocketReader *m_inputImageProgram;
SocketReader *m_inputKeyProgram;
- virtual float calculateDistance(float key[4], float image[4]);
+ virtual float calculateDistance(const float key[4], const float image[4]);
public:
/**
@@ -52,6 +52,10 @@ class DistanceRGBMatteOperation : public NodeOperation {
{
this->m_settings = nodeChroma;
}
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.cc b/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.cc
index 597545dd706..50e473ea5b3 100644
--- a/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.cc
+++ b/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.cc
@@ -21,7 +21,7 @@
namespace blender::compositor {
-float DistanceYCCMatteOperation::calculateDistance(float key[4], float image[4])
+float DistanceYCCMatteOperation::calculateDistance(const float key[4], const float image[4])
{
/* only measure the second 2 values */
return len_v2v2(key + 1, image + 1);
diff --git a/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h b/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h
index a87e885e5d8..0e178fddc39 100644
--- a/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h
+++ b/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h
@@ -29,7 +29,7 @@ namespace blender::compositor {
*/
class DistanceYCCMatteOperation : public DistanceRGBMatteOperation {
protected:
- float calculateDistance(float key[4], float image[4]) override;
+ float calculateDistance(const float key[4], const float image[4]) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cc b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cc
index 3804e6ec646..e0fc45811cb 100644
--- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cc
@@ -62,6 +62,13 @@ bool FastGaussianBlurOperation::determineDependingAreaOfInterest(
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+void FastGaussianBlurOperation::init_data()
+{
+ BlurBaseOperation::init_data();
+ this->m_sx = this->m_data.sizex * this->m_size / 2.0f;
+ this->m_sy = this->m_data.sizey * this->m_size / 2.0f;
+}
+
void FastGaussianBlurOperation::initExecution()
{
BlurBaseOperation::initExecution();
@@ -117,6 +124,7 @@ void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src,
unsigned int chan,
unsigned int xy)
{
+ BLI_assert(!src->is_a_single_elem());
double q, q2, sc, cf[4], tsM[9], tsu[3], tsv[3];
double *X, *Y, *W;
const unsigned int src_width = src->getWidth();
@@ -257,6 +265,64 @@ void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src,
#undef YVV
}
+void FastGaussianBlurOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ switch (input_idx) {
+ case IMAGE_INPUT_INDEX:
+ r_input_area.xmin = 0;
+ r_input_area.xmax = getWidth();
+ r_input_area.ymin = 0;
+ r_input_area.ymax = getHeight();
+ break;
+ default:
+ BlurBaseOperation::get_area_of_interest(input_idx, output_area, r_input_area);
+ return;
+ }
+}
+
+void FastGaussianBlurOperation::update_memory_buffer_started(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ /* TODO(manzanilla): Add a render test and make #IIR_gauss multi-threaded with support for
+ * an output buffer. */
+ const MemoryBuffer *input = inputs[IMAGE_INPUT_INDEX];
+ MemoryBuffer *image = nullptr;
+ const bool is_full_output = BLI_rcti_compare(&output->get_rect(), &area);
+ if (is_full_output) {
+ image = output;
+ }
+ else {
+ image = new MemoryBuffer(getOutputSocket()->getDataType(), area);
+ }
+ image->copy_from(input, area);
+
+ if ((this->m_sx == this->m_sy) && (this->m_sx > 0.0f)) {
+ for (const int c : IndexRange(COM_DATA_TYPE_COLOR_CHANNELS)) {
+ IIR_gauss(image, this->m_sx, c, 3);
+ }
+ }
+ else {
+ if (this->m_sx > 0.0f) {
+ for (const int c : IndexRange(COM_DATA_TYPE_COLOR_CHANNELS)) {
+ IIR_gauss(image, this->m_sx, c, 1);
+ }
+ }
+ if (this->m_sy > 0.0f) {
+ for (const int c : IndexRange(COM_DATA_TYPE_COLOR_CHANNELS)) {
+ IIR_gauss(image, this->m_sy, c, 2);
+ }
+ }
+ }
+
+ if (!is_full_output) {
+ output->copy_from(image, area);
+ delete image;
+ }
+}
+
FastGaussianBlurValueOperation::FastGaussianBlurValueOperation()
{
this->addInputSocket(DataType::Value);
@@ -341,4 +407,44 @@ void *FastGaussianBlurValueOperation::initializeTileData(rcti *rect)
return this->m_iirgaus;
}
+void FastGaussianBlurValueOperation::get_area_of_interest(const int UNUSED(input_idx),
+ const rcti &UNUSED(output_area),
+ rcti &r_input_area)
+{
+ r_input_area.xmin = 0;
+ r_input_area.xmax = getWidth();
+ r_input_area.ymin = 0;
+ r_input_area.ymax = getHeight();
+}
+
+void FastGaussianBlurValueOperation::update_memory_buffer_started(MemoryBuffer *UNUSED(output),
+ const rcti &UNUSED(area),
+ Span<MemoryBuffer *> inputs)
+{
+ if (m_iirgaus == nullptr) {
+ const MemoryBuffer *image = inputs[0];
+ MemoryBuffer *gauss = new MemoryBuffer(*image);
+ FastGaussianBlurOperation::IIR_gauss(gauss, m_sigma, 0, 3);
+ m_iirgaus = gauss;
+ }
+}
+
+void FastGaussianBlurValueOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ MemoryBuffer *image = inputs[0];
+ BuffersIterator<float> it = output->iterate_with({image, m_iirgaus}, area);
+ if (this->m_overlay == FAST_GAUSS_OVERLAY_MIN) {
+ for (; !it.is_end(); ++it) {
+ *it.out = MIN2(*it.in(0), *it.in(1));
+ }
+ }
+ else if (this->m_overlay == FAST_GAUSS_OVERLAY_MAX) {
+ for (; !it.is_end(); ++it) {
+ *it.out = MAX2(*it.in(0), *it.in(1));
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h
index c25afe6c4a4..f42fc76a119 100644
--- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h
+++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h
@@ -38,8 +38,19 @@ class FastGaussianBlurOperation : public BlurBaseOperation {
static void IIR_gauss(MemoryBuffer *src, float sigma, unsigned int channel, unsigned int xy);
void *initializeTileData(rcti *rect) override;
+ void init_data() override;
void deinitExecution() override;
void initExecution() override;
+
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+ void update_memory_buffer_started(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
+ void update_memory_buffer_partial(MemoryBuffer *UNUSED(output),
+ const rcti &UNUSED(area),
+ Span<MemoryBuffer *> UNUSED(inputs)) override
+ {
+ }
};
enum {
@@ -48,7 +59,7 @@ enum {
FAST_GAUSS_OVERLAY_MAX = 1,
};
-class FastGaussianBlurValueOperation : public NodeOperation {
+class FastGaussianBlurValueOperation : public MultiThreadedOperation {
private:
float m_sigma;
MemoryBuffer *m_iirgaus;
@@ -80,6 +91,14 @@ class FastGaussianBlurValueOperation : public NodeOperation {
{
this->m_overlay = overlay;
}
+
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+ void update_memory_buffer_started(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_FlipOperation.cc b/source/blender/compositor/operations/COM_FlipOperation.cc
index 8afbec4ddbe..d0dc6c0b570 100644
--- a/source/blender/compositor/operations/COM_FlipOperation.cc
+++ b/source/blender/compositor/operations/COM_FlipOperation.cc
@@ -75,4 +75,42 @@ bool FlipOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+void FlipOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ BLI_assert(input_idx == 0);
+ UNUSED_VARS_NDEBUG(input_idx);
+ if (this->m_flipX) {
+ const int w = (int)this->getWidth() - 1;
+ r_input_area.xmax = (w - output_area.xmin) + 1;
+ r_input_area.xmin = (w - output_area.xmax) - 1;
+ }
+ else {
+ r_input_area.xmin = output_area.xmin;
+ r_input_area.xmax = output_area.xmax;
+ }
+ if (this->m_flipY) {
+ const int h = (int)this->getHeight() - 1;
+ r_input_area.ymax = (h - output_area.ymin) + 1;
+ r_input_area.ymin = (h - output_area.ymax) - 1;
+ }
+ else {
+ r_input_area.ymin = output_area.ymin;
+ r_input_area.ymax = output_area.ymax;
+ }
+}
+
+void FlipOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const MemoryBuffer *input_img = inputs[0];
+ for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
+ const int nx = this->m_flipX ? ((int)this->getWidth() - 1) - it.x : it.x;
+ const int ny = this->m_flipY ? ((int)this->getHeight() - 1) - it.y : it.y;
+ input_img->read_elem(nx, ny, it.out);
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_FlipOperation.h b/source/blender/compositor/operations/COM_FlipOperation.h
index f26d587fde6..dba7f82c341 100644
--- a/source/blender/compositor/operations/COM_FlipOperation.h
+++ b/source/blender/compositor/operations/COM_FlipOperation.h
@@ -18,11 +18,11 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
-class FlipOperation : public NodeOperation {
+class FlipOperation : public MultiThreadedOperation {
private:
SocketReader *m_inputOperation;
bool m_flipX;
@@ -45,6 +45,11 @@ class FlipOperation : public NodeOperation {
{
this->m_flipY = flipY;
}
+
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GammaCorrectOperation.cc b/source/blender/compositor/operations/COM_GammaCorrectOperation.cc
index 16b79fddd06..1bff3b965c6 100644
--- a/source/blender/compositor/operations/COM_GammaCorrectOperation.cc
+++ b/source/blender/compositor/operations/COM_GammaCorrectOperation.cc
@@ -26,6 +26,7 @@ GammaCorrectOperation::GammaCorrectOperation()
this->addInputSocket(DataType::Color);
this->addOutputSocket(DataType::Color);
this->m_inputProgram = nullptr;
+ flags.can_be_constant = true;
}
void GammaCorrectOperation::initExecution()
{
@@ -58,6 +59,34 @@ void GammaCorrectOperation::executePixelSampled(float output[4],
}
}
+void GammaCorrectOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const MemoryBuffer *input = inputs[0];
+ for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
+ float color[4];
+ input->read_elem(it.x, it.y, color);
+ if (color[3] > 0.0f) {
+ color[0] /= color[3];
+ color[1] /= color[3];
+ color[2] /= color[3];
+ }
+
+ /* Check for negative to avoid nan's. */
+ it.out[0] = color[0] > 0.0f ? color[0] * color[0] : 0.0f;
+ it.out[1] = color[1] > 0.0f ? color[1] * color[1] : 0.0f;
+ it.out[2] = color[2] > 0.0f ? color[2] * color[2] : 0.0f;
+ it.out[3] = color[3];
+
+ if (color[3] > 0.0f) {
+ it.out[0] *= color[3];
+ it.out[1] *= color[3];
+ it.out[2] *= color[3];
+ }
+ }
+}
+
void GammaCorrectOperation::deinitExecution()
{
this->m_inputProgram = nullptr;
@@ -68,6 +97,7 @@ GammaUncorrectOperation::GammaUncorrectOperation()
this->addInputSocket(DataType::Color);
this->addOutputSocket(DataType::Color);
this->m_inputProgram = nullptr;
+ flags.can_be_constant = true;
}
void GammaUncorrectOperation::initExecution()
{
@@ -100,6 +130,33 @@ void GammaUncorrectOperation::executePixelSampled(float output[4],
}
}
+void GammaUncorrectOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const MemoryBuffer *input = inputs[0];
+ for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
+ float color[4];
+ input->read_elem(it.x, it.y, color);
+ if (color[3] > 0.0f) {
+ color[0] /= color[3];
+ color[1] /= color[3];
+ color[2] /= color[3];
+ }
+
+ it.out[0] = color[0] > 0.0f ? sqrtf(color[0]) : 0.0f;
+ it.out[1] = color[1] > 0.0f ? sqrtf(color[1]) : 0.0f;
+ it.out[2] = color[2] > 0.0f ? sqrtf(color[2]) : 0.0f;
+ it.out[3] = color[3];
+
+ if (color[3] > 0.0f) {
+ it.out[0] *= color[3];
+ it.out[1] *= color[3];
+ it.out[2] *= color[3];
+ }
+ }
+}
+
void GammaUncorrectOperation::deinitExecution()
{
this->m_inputProgram = nullptr;
diff --git a/source/blender/compositor/operations/COM_GammaCorrectOperation.h b/source/blender/compositor/operations/COM_GammaCorrectOperation.h
index ac3d45b94b1..2a9fde70e87 100644
--- a/source/blender/compositor/operations/COM_GammaCorrectOperation.h
+++ b/source/blender/compositor/operations/COM_GammaCorrectOperation.h
@@ -18,11 +18,11 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
-class GammaCorrectOperation : public NodeOperation {
+class GammaCorrectOperation : public MultiThreadedOperation {
private:
/**
* Cached reference to the inputProgram
@@ -46,9 +46,13 @@ class GammaCorrectOperation : public NodeOperation {
* Deinitialize the execution
*/
void deinitExecution() override;
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
-class GammaUncorrectOperation : public NodeOperation {
+class GammaUncorrectOperation : public MultiThreadedOperation {
private:
/**
* Cached reference to the inputProgram
@@ -72,6 +76,10 @@ class GammaUncorrectOperation : public NodeOperation {
* Deinitialize the execution
*/
void deinitExecution() override;
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianAlphaBlurBaseOperation.cc b/source/blender/compositor/operations/COM_GaussianAlphaBlurBaseOperation.cc
new file mode 100644
index 00000000000..9bdc652b466
--- /dev/null
+++ b/source/blender/compositor/operations/COM_GaussianAlphaBlurBaseOperation.cc
@@ -0,0 +1,168 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#include "COM_GaussianAlphaBlurBaseOperation.h"
+
+namespace blender::compositor {
+
+GaussianAlphaBlurBaseOperation::GaussianAlphaBlurBaseOperation(eDimension dim)
+ : BlurBaseOperation(DataType::Value)
+{
+ this->m_gausstab = nullptr;
+ this->m_filtersize = 0;
+ this->m_falloff = -1; /* Intentionally invalid, so we can detect uninitialized values. */
+ dimension_ = dim;
+}
+
+void GaussianAlphaBlurBaseOperation::init_data()
+{
+ BlurBaseOperation::init_data();
+ if (execution_model_ == eExecutionModel::FullFrame) {
+ rad_ = max_ff(m_size * this->get_blur_size(dimension_), 0.0f);
+ rad_ = min_ff(rad_, MAX_GAUSSTAB_RADIUS);
+ m_filtersize = min_ii(ceil(rad_), MAX_GAUSSTAB_RADIUS);
+ }
+}
+
+void GaussianAlphaBlurBaseOperation::initExecution()
+{
+ BlurBaseOperation::initExecution();
+ if (execution_model_ == eExecutionModel::FullFrame) {
+ m_gausstab = BlurBaseOperation::make_gausstab(rad_, m_filtersize);
+ m_distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad_, m_filtersize, m_falloff);
+ }
+}
+
+void GaussianAlphaBlurBaseOperation::deinitExecution()
+{
+ BlurBaseOperation::deinitExecution();
+
+ if (this->m_gausstab) {
+ MEM_freeN(this->m_gausstab);
+ this->m_gausstab = nullptr;
+ }
+
+ if (this->m_distbuf_inv) {
+ MEM_freeN(this->m_distbuf_inv);
+ this->m_distbuf_inv = nullptr;
+ }
+}
+
+void GaussianAlphaBlurBaseOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ if (input_idx != IMAGE_INPUT_INDEX) {
+ BlurBaseOperation::get_area_of_interest(input_idx, output_area, r_input_area);
+ return;
+ }
+
+ r_input_area = output_area;
+ switch (dimension_) {
+ case eDimension::X:
+ r_input_area.xmin = output_area.xmin - m_filtersize - 1;
+ r_input_area.xmax = output_area.xmax + m_filtersize + 1;
+ break;
+ case eDimension::Y:
+ r_input_area.ymin = output_area.ymin - m_filtersize - 1;
+ r_input_area.ymax = output_area.ymax + m_filtersize + 1;
+ break;
+ }
+}
+
+BLI_INLINE float finv_test(const float f, const bool test)
+{
+ return (LIKELY(test == false)) ? f : 1.0f - f;
+}
+
+void GaussianAlphaBlurBaseOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ MemoryBuffer *input = inputs[IMAGE_INPUT_INDEX];
+ const rcti &input_rect = input->get_rect();
+ BuffersIterator<float> it = output->iterate_with({input}, area);
+
+ int min_input_coord = -1;
+ int max_input_coord = -1;
+ int elem_stride = -1;
+ std::function<int()> get_current_coord;
+ switch (dimension_) {
+ case eDimension::X:
+ min_input_coord = input_rect.xmin;
+ max_input_coord = input_rect.xmax;
+ get_current_coord = [&] { return it.x; };
+ elem_stride = input->elem_stride;
+ break;
+ case eDimension::Y:
+ min_input_coord = input_rect.ymin;
+ max_input_coord = input_rect.ymax;
+ get_current_coord = [&] { return it.y; };
+ elem_stride = input->row_stride;
+ break;
+ }
+
+ for (; !it.is_end(); ++it) {
+ const int coord = get_current_coord();
+ const int coord_min = max_ii(coord - m_filtersize, min_input_coord);
+ const int coord_max = min_ii(coord + m_filtersize + 1, max_input_coord);
+
+ /* *** This is the main part which is different to #GaussianBlurBaseOperation. *** */
+ /* Gauss. */
+ float alpha_accum = 0.0f;
+ float multiplier_accum = 0.0f;
+
+ /* Dilate. */
+ const bool do_invert = m_do_subtract;
+ /* Init with the current color to avoid unneeded lookups. */
+ float value_max = finv_test(*it.in(0), do_invert);
+ float distfacinv_max = 1.0f; /* 0 to 1 */
+
+ const int step = QualityStepHelper::getStep();
+ const float *in = it.in(0) + ((intptr_t)coord_min - coord) * elem_stride;
+ const int in_stride = elem_stride * step;
+ int index = (coord_min - coord) + m_filtersize;
+ const int index_end = index + (coord_max - coord_min);
+ for (; index < index_end; in += in_stride, index += step) {
+ float value = finv_test(*in, do_invert);
+
+ /* Gauss. */
+ float multiplier = m_gausstab[index];
+ alpha_accum += value * multiplier;
+ multiplier_accum += multiplier;
+
+ /* Dilate - find most extreme color. */
+ if (value > value_max) {
+ multiplier = m_distbuf_inv[index];
+ value *= multiplier;
+ if (value > value_max) {
+ value_max = value;
+ distfacinv_max = multiplier;
+ }
+ }
+ }
+
+ /* Blend between the max value and gauss blue - gives nice feather. */
+ const float value_blur = alpha_accum / multiplier_accum;
+ const float value_final = (value_max * distfacinv_max) +
+ (value_blur * (1.0f - distfacinv_max));
+ *it.out = finv_test(value_final, do_invert);
+ }
+}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianAlphaBlurBaseOperation.h b/source/blender/compositor/operations/COM_GaussianAlphaBlurBaseOperation.h
new file mode 100644
index 00000000000..d7ca975ca0a
--- /dev/null
+++ b/source/blender/compositor/operations/COM_GaussianAlphaBlurBaseOperation.h
@@ -0,0 +1,62 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#pragma once
+
+#include "COM_BlurBaseOperation.h"
+
+namespace blender::compositor {
+
+class GaussianAlphaBlurBaseOperation : public BlurBaseOperation {
+ protected:
+ float *m_gausstab;
+ float *m_distbuf_inv;
+ int m_falloff; /* Falloff for #distbuf_inv. */
+ bool m_do_subtract;
+ int m_filtersize;
+ float rad_;
+ eDimension dimension_;
+
+ public:
+ GaussianAlphaBlurBaseOperation(eDimension dim);
+
+ virtual void init_data() override;
+ virtual void initExecution() override;
+ virtual void deinitExecution() override;
+
+ void get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area) final;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) final;
+
+ /**
+ * Set subtract for Dilate/Erode functionality
+ */
+ void setSubtract(bool subtract)
+ {
+ this->m_do_subtract = subtract;
+ }
+ void setFalloff(int falloff)
+ {
+ this->m_falloff = falloff;
+ }
+};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cc b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cc
index 7ca5dc4ca76..6710ed3cf5b 100644
--- a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cc
@@ -24,11 +24,9 @@
namespace blender::compositor {
-GaussianAlphaXBlurOperation::GaussianAlphaXBlurOperation() : BlurBaseOperation(DataType::Value)
+GaussianAlphaXBlurOperation::GaussianAlphaXBlurOperation()
+ : GaussianAlphaBlurBaseOperation(eDimension::X)
{
- this->m_gausstab = nullptr;
- this->m_filtersize = 0;
- this->m_falloff = -1; /* intentionally invalid, so we can detect uninitialized values */
}
void *GaussianAlphaXBlurOperation::initializeTileData(rcti * /*rect*/)
@@ -44,12 +42,11 @@ void *GaussianAlphaXBlurOperation::initializeTileData(rcti * /*rect*/)
void GaussianAlphaXBlurOperation::initExecution()
{
- /* Until we support size input - comment this. */
- // BlurBaseOperation::initExecution();
+ GaussianAlphaBlurBaseOperation::initExecution();
initMutex();
- if (this->m_sizeavailable) {
+ if (this->m_sizeavailable && execution_model_ == eExecutionModel::Tiled) {
float rad = max_ff(m_size * m_data.sizex, 0.0f);
m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS);
@@ -144,7 +141,7 @@ void GaussianAlphaXBlurOperation::executePixel(float output[4], int x, int y, vo
void GaussianAlphaXBlurOperation::deinitExecution()
{
- BlurBaseOperation::deinitExecution();
+ GaussianAlphaBlurBaseOperation::deinitExecution();
if (this->m_gausstab) {
MEM_freeN(this->m_gausstab);
diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h
index 949956fae04..2a44c639665 100644
--- a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h
+++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h
@@ -18,18 +18,13 @@
#pragma once
-#include "COM_BlurBaseOperation.h"
-#include "COM_NodeOperation.h"
+#include "COM_GaussianAlphaBlurBaseOperation.h"
namespace blender::compositor {
-class GaussianAlphaXBlurOperation : public BlurBaseOperation {
+/* TODO(manzanilla): everything to be removed with tiled implementation except the constructor. */
+class GaussianAlphaXBlurOperation : public GaussianAlphaBlurBaseOperation {
private:
- float *m_gausstab;
- float *m_distbuf_inv;
- int m_falloff; /* falloff for distbuf_inv */
- bool m_do_subtract;
- int m_filtersize;
void updateGauss();
public:
@@ -54,18 +49,6 @@ class GaussianAlphaXBlurOperation : public BlurBaseOperation {
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
rcti *output) override;
-
- /**
- * Set subtract for Dilate/Erode functionality
- */
- void setSubtract(bool subtract)
- {
- this->m_do_subtract = subtract;
- }
- void setFalloff(int falloff)
- {
- this->m_falloff = falloff;
- }
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cc b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cc
index d2385a972dd..09aeddb6573 100644
--- a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cc
@@ -24,11 +24,9 @@
namespace blender::compositor {
-GaussianAlphaYBlurOperation::GaussianAlphaYBlurOperation() : BlurBaseOperation(DataType::Value)
+GaussianAlphaYBlurOperation::GaussianAlphaYBlurOperation()
+ : GaussianAlphaBlurBaseOperation(eDimension::Y)
{
- this->m_gausstab = nullptr;
- this->m_filtersize = 0;
- this->m_falloff = -1; /* intentionally invalid, so we can detect uninitialized values */
}
void *GaussianAlphaYBlurOperation::initializeTileData(rcti * /*rect*/)
@@ -42,14 +40,14 @@ void *GaussianAlphaYBlurOperation::initializeTileData(rcti * /*rect*/)
return buffer;
}
+/* TODO(manzanilla): to be removed with tiled implementation. */
void GaussianAlphaYBlurOperation::initExecution()
{
- /* Until we support size input - comment this. */
- // BlurBaseOperation::initExecution();
+ GaussianAlphaBlurBaseOperation::initExecution();
initMutex();
- if (this->m_sizeavailable) {
+ if (this->m_sizeavailable && execution_model_ == eExecutionModel::Tiled) {
float rad = max_ff(m_size * m_data.sizey, 0.0f);
m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS);
@@ -58,6 +56,7 @@ void GaussianAlphaYBlurOperation::initExecution()
}
}
+/* TODO(manzanilla): to be removed with tiled implementation. */
void GaussianAlphaYBlurOperation::updateGauss()
{
if (this->m_gausstab == nullptr) {
@@ -143,7 +142,7 @@ void GaussianAlphaYBlurOperation::executePixel(float output[4], int x, int y, vo
void GaussianAlphaYBlurOperation::deinitExecution()
{
- BlurBaseOperation::deinitExecution();
+ GaussianAlphaBlurBaseOperation::deinitExecution();
if (this->m_gausstab) {
MEM_freeN(this->m_gausstab);
diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h
index d25770386c4..ef01f7e0f92 100644
--- a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h
+++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h
@@ -18,18 +18,13 @@
#pragma once
-#include "COM_BlurBaseOperation.h"
-#include "COM_NodeOperation.h"
+#include "COM_GaussianAlphaBlurBaseOperation.h"
namespace blender::compositor {
-class GaussianAlphaYBlurOperation : public BlurBaseOperation {
+/* TODO(manzanilla): everything to be removed with tiled implementation except the constructor. */
+class GaussianAlphaYBlurOperation : public GaussianAlphaBlurBaseOperation {
private:
- float *m_gausstab;
- float *m_distbuf_inv;
- bool m_do_subtract;
- int m_falloff;
- int m_filtersize;
void updateGauss();
public:
@@ -54,18 +49,6 @@ class GaussianAlphaYBlurOperation : public BlurBaseOperation {
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
rcti *output) override;
-
- /**
- * Set subtract for Dilate/Erode functionality
- */
- void setSubtract(bool subtract)
- {
- this->m_do_subtract = subtract;
- }
- void setFalloff(int falloff)
- {
- this->m_falloff = falloff;
- }
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianBlurBaseOperation.cc b/source/blender/compositor/operations/COM_GaussianBlurBaseOperation.cc
new file mode 100644
index 00000000000..959f599fab4
--- /dev/null
+++ b/source/blender/compositor/operations/COM_GaussianBlurBaseOperation.cc
@@ -0,0 +1,154 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#include "COM_GaussianBlurBaseOperation.h"
+
+namespace blender::compositor {
+
+GaussianBlurBaseOperation::GaussianBlurBaseOperation(eDimension dim)
+ : BlurBaseOperation(DataType::Color)
+{
+ m_gausstab = nullptr;
+#ifdef BLI_HAVE_SSE2
+ m_gausstab_sse = nullptr;
+#endif
+ m_filtersize = 0;
+ rad_ = 0.0f;
+ dimension_ = dim;
+}
+
+void GaussianBlurBaseOperation::init_data()
+{
+ BlurBaseOperation::init_data();
+ if (execution_model_ == eExecutionModel::FullFrame) {
+ rad_ = max_ff(m_size * this->get_blur_size(dimension_), 0.0f);
+ rad_ = min_ff(rad_, MAX_GAUSSTAB_RADIUS);
+ m_filtersize = min_ii(ceil(rad_), MAX_GAUSSTAB_RADIUS);
+ }
+}
+
+void GaussianBlurBaseOperation::initExecution()
+{
+ BlurBaseOperation::initExecution();
+ if (execution_model_ == eExecutionModel::FullFrame) {
+ m_gausstab = BlurBaseOperation::make_gausstab(rad_, m_filtersize);
+#ifdef BLI_HAVE_SSE2
+ m_gausstab_sse = BlurBaseOperation::convert_gausstab_sse(m_gausstab, m_filtersize);
+#endif
+ }
+}
+
+void GaussianBlurBaseOperation::deinitExecution()
+{
+ BlurBaseOperation::deinitExecution();
+
+ if (m_gausstab) {
+ MEM_freeN(m_gausstab);
+ m_gausstab = nullptr;
+ }
+#ifdef BLI_HAVE_SSE2
+ if (m_gausstab_sse) {
+ MEM_freeN(m_gausstab_sse);
+ m_gausstab_sse = nullptr;
+ }
+#endif
+}
+
+void GaussianBlurBaseOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ if (input_idx != IMAGE_INPUT_INDEX) {
+ BlurBaseOperation::get_area_of_interest(input_idx, output_area, r_input_area);
+ return;
+ }
+
+ r_input_area = output_area;
+ switch (dimension_) {
+ case eDimension::X:
+ r_input_area.xmin = output_area.xmin - m_filtersize - 1;
+ r_input_area.xmax = output_area.xmax + m_filtersize + 1;
+ break;
+ case eDimension::Y:
+ r_input_area.ymin = output_area.ymin - m_filtersize - 1;
+ r_input_area.ymax = output_area.ymax + m_filtersize + 1;
+ break;
+ }
+}
+
+void GaussianBlurBaseOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ MemoryBuffer *input = inputs[IMAGE_INPUT_INDEX];
+ const rcti &input_rect = input->get_rect();
+ BuffersIterator<float> it = output->iterate_with({input}, area);
+
+ int min_input_coord = -1;
+ int max_input_coord = -1;
+ int elem_stride = -1;
+ std::function<int()> get_current_coord;
+ switch (dimension_) {
+ case eDimension::X:
+ min_input_coord = input_rect.xmin;
+ max_input_coord = input_rect.xmax;
+ elem_stride = input->elem_stride;
+ get_current_coord = [&] { return it.x; };
+ break;
+ case eDimension::Y:
+ min_input_coord = input_rect.ymin;
+ max_input_coord = input_rect.ymax;
+ elem_stride = input->row_stride;
+ get_current_coord = [&] { return it.y; };
+ break;
+ }
+
+ for (; !it.is_end(); ++it) {
+ const int coord = get_current_coord();
+ const int coord_min = max_ii(coord - m_filtersize, min_input_coord);
+ const int coord_max = min_ii(coord + m_filtersize + 1, max_input_coord);
+
+ float ATTR_ALIGN(16) color_accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float multiplier_accum = 0.0f;
+
+ const int step = QualityStepHelper::getStep();
+ const float *in = it.in(0) + ((intptr_t)coord_min - coord) * elem_stride;
+ const int in_stride = elem_stride * step;
+ int gauss_idx = (coord_min - coord) + m_filtersize;
+ const int gauss_end = gauss_idx + (coord_max - coord_min);
+#ifdef BLI_HAVE_SSE2
+ __m128 accum_r = _mm_load_ps(color_accum);
+ for (; gauss_idx < gauss_end; in += in_stride, gauss_idx += step) {
+ __m128 reg_a = _mm_load_ps(in);
+ reg_a = _mm_mul_ps(reg_a, m_gausstab_sse[gauss_idx]);
+ accum_r = _mm_add_ps(accum_r, reg_a);
+ multiplier_accum += m_gausstab[gauss_idx];
+ }
+ _mm_store_ps(color_accum, accum_r);
+#else
+ for (; gauss_idx < gauss_end; in += in_stride, gauss_idx += step) {
+ const float multiplier = m_gausstab[gauss_idx];
+ madd_v4_v4fl(color_accum, in, multiplier);
+ multiplier_accum += multiplier;
+ }
+#endif
+ mul_v4_v4fl(it.out, color_accum, 1.0f / multiplier_accum);
+ }
+}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianBlurBaseOperation.h b/source/blender/compositor/operations/COM_GaussianBlurBaseOperation.h
new file mode 100644
index 00000000000..c0b27078a24
--- /dev/null
+++ b/source/blender/compositor/operations/COM_GaussianBlurBaseOperation.h
@@ -0,0 +1,50 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#pragma once
+
+#include "COM_BlurBaseOperation.h"
+
+namespace blender::compositor {
+
+class GaussianBlurBaseOperation : public BlurBaseOperation {
+ protected:
+ float *m_gausstab;
+#ifdef BLI_HAVE_SSE2
+ __m128 *m_gausstab_sse;
+#endif
+ int m_filtersize;
+ float rad_;
+ eDimension dimension_;
+
+ public:
+ GaussianBlurBaseOperation(eDimension dim);
+
+ virtual void init_data() override;
+ virtual void initExecution() override;
+ virtual void deinitExecution() override;
+
+ void get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area) override;
+ virtual void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
+};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cc b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cc
index b2c65ff2c96..aafc269abac 100644
--- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cc
@@ -40,6 +40,27 @@ void *GaussianBokehBlurOperation::initializeTileData(rcti * /*rect*/)
return buffer;
}
+void GaussianBokehBlurOperation::init_data()
+{
+ BlurBaseOperation::init_data();
+ const float width = this->getWidth();
+ const float height = this->getHeight();
+
+ if (!this->m_sizeavailable) {
+ updateSize();
+ }
+
+ radxf_ = this->m_size * (float)this->m_data.sizex;
+ CLAMP(radxf_, 0.0f, width / 2.0f);
+
+ /* Vertical. */
+ radyf_ = this->m_size * (float)this->m_data.sizey;
+ CLAMP(radyf_, 0.0f, height / 2.0f);
+
+ this->m_radx = ceil(radxf_);
+ this->m_rady = ceil(radyf_);
+}
+
void GaussianBokehBlurOperation::initExecution()
{
BlurBaseOperation::initExecution();
@@ -54,39 +75,17 @@ void GaussianBokehBlurOperation::initExecution()
void GaussianBokehBlurOperation::updateGauss()
{
if (this->m_gausstab == nullptr) {
- float radxf;
- float radyf;
- int n;
- float *dgauss;
- float *ddgauss;
- int j, i;
- const float width = this->getWidth();
- const float height = this->getHeight();
- if (!this->m_sizeavailable) {
- updateSize();
- }
- radxf = this->m_size * (float)this->m_data.sizex;
- CLAMP(radxf, 0.0f, width / 2.0f);
-
- /* vertical */
- radyf = this->m_size * (float)this->m_data.sizey;
- CLAMP(radyf, 0.0f, height / 2.0f);
-
- this->m_radx = ceil(radxf);
- this->m_rady = ceil(radyf);
-
int ddwidth = 2 * this->m_radx + 1;
int ddheight = 2 * this->m_rady + 1;
- n = ddwidth * ddheight;
-
+ int n = ddwidth * ddheight;
/* create a full filter image */
- ddgauss = (float *)MEM_mallocN(sizeof(float) * n, __func__);
- dgauss = ddgauss;
+ float *ddgauss = (float *)MEM_mallocN(sizeof(float) * n, __func__);
+ float *dgauss = ddgauss;
float sum = 0.0f;
- float facx = (radxf > 0.0f ? 1.0f / radxf : 0.0f);
- float facy = (radyf > 0.0f ? 1.0f / radyf : 0.0f);
- for (j = -this->m_rady; j <= this->m_rady; j++) {
- for (i = -this->m_radx; i <= this->m_radx; i++, dgauss++) {
+ float facx = (radxf_ > 0.0f ? 1.0f / radxf_ : 0.0f);
+ float facy = (radyf_ > 0.0f ? 1.0f / radyf_ : 0.0f);
+ for (int j = -this->m_rady; j <= this->m_rady; j++) {
+ for (int i = -this->m_radx; i <= this->m_radx; i++, dgauss++) {
float fj = (float)j * facy;
float fi = (float)i * facx;
float dist = sqrt(fj * fj + fi * fi);
@@ -99,7 +98,7 @@ void GaussianBokehBlurOperation::updateGauss()
if (sum > 0.0f) {
/* normalize */
float norm = 1.0f / sum;
- for (j = n - 1; j >= 0; j--) {
+ for (int j = n - 1; j >= 0; j--) {
ddgauss[j] *= norm;
}
}
@@ -196,23 +195,69 @@ bool GaussianBokehBlurOperation::determineDependingAreaOfInterest(
return BlurBaseOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+void GaussianBokehBlurOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ if (input_idx != IMAGE_INPUT_INDEX) {
+ BlurBaseOperation::get_area_of_interest(input_idx, output_area, r_input_area);
+ return;
+ }
+
+ r_input_area.xmax = output_area.xmax + m_radx;
+ r_input_area.xmin = output_area.xmin - m_radx;
+ r_input_area.ymax = output_area.ymax + m_rady;
+ r_input_area.ymin = output_area.ymin - m_rady;
+}
+
+void GaussianBokehBlurOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const MemoryBuffer *input = inputs[IMAGE_INPUT_INDEX];
+ BuffersIterator<float> it = output->iterate_with({}, area);
+ const rcti &input_rect = input->get_rect();
+ for (; !it.is_end(); ++it) {
+ const int x = it.x;
+ const int y = it.y;
+
+ const int ymin = max_ii(y - this->m_rady, input_rect.ymin);
+ const int ymax = min_ii(y + this->m_rady + 1, input_rect.ymax);
+ const int xmin = max_ii(x - this->m_radx, input_rect.xmin);
+ const int xmax = min_ii(x + this->m_radx + 1, input_rect.xmax);
+
+ float tempColor[4] = {0};
+ float multiplier_accum = 0;
+ const int step = QualityStepHelper::getStep();
+ const int elem_step = step * input->elem_stride;
+ const int add_const = (xmin - x + this->m_radx);
+ const int mul_const = (this->m_radx * 2 + 1);
+ for (int ny = ymin; ny < ymax; ny += step) {
+ const float *color = input->get_elem(xmin, ny);
+ int gauss_index = ((ny - y) + this->m_rady) * mul_const + add_const;
+ const int gauss_end = gauss_index + (xmax - xmin);
+ for (; gauss_index < gauss_end; gauss_index += step, color += elem_step) {
+ const float multiplier = this->m_gausstab[gauss_index];
+ madd_v4_v4fl(tempColor, color, multiplier);
+ multiplier_accum += multiplier;
+ }
+ }
+
+ mul_v4_v4fl(it.out, tempColor, 1.0f / multiplier_accum);
+ }
+}
+
// reference image
GaussianBlurReferenceOperation::GaussianBlurReferenceOperation()
: BlurBaseOperation(DataType::Color)
{
this->m_maintabs = nullptr;
+ use_variable_size_ = true;
}
-void *GaussianBlurReferenceOperation::initializeTileData(rcti * /*rect*/)
-{
- void *buffer = getInputOperation(0)->initializeTileData(nullptr);
- return buffer;
-}
-
-void GaussianBlurReferenceOperation::initExecution()
+void GaussianBlurReferenceOperation::init_data()
{
- BlurBaseOperation::initExecution();
- // setup gaustab
+ /* Setup variables for gausstab and area of interest. */
this->m_data.image_in_width = this->getWidth();
this->m_data.image_in_height = this->getHeight();
if (this->m_data.relative) {
@@ -232,7 +277,7 @@ void GaussianBlurReferenceOperation::initExecution()
}
}
- /* horizontal */
+ /* Horizontal. */
m_filtersizex = (float)this->m_data.sizex;
int imgx = getWidth() / 2;
if (m_filtersizex > imgx) {
@@ -243,7 +288,7 @@ void GaussianBlurReferenceOperation::initExecution()
}
m_radx = (float)m_filtersizex;
- /* vertical */
+ /* Vertical. */
m_filtersizey = (float)this->m_data.sizey;
int imgy = getHeight() / 2;
if (m_filtersizey > imgy) {
@@ -253,6 +298,18 @@ void GaussianBlurReferenceOperation::initExecution()
m_filtersizey = 1;
}
m_rady = (float)m_filtersizey;
+}
+
+void *GaussianBlurReferenceOperation::initializeTileData(rcti * /*rect*/)
+{
+ void *buffer = getInputOperation(0)->initializeTileData(nullptr);
+ return buffer;
+}
+
+void GaussianBlurReferenceOperation::initExecution()
+{
+ BlurBaseOperation::initExecution();
+
updateGauss();
}
@@ -363,4 +420,78 @@ bool GaussianBlurReferenceOperation::determineDependingAreaOfInterest(
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+void GaussianBlurReferenceOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ if (input_idx != IMAGE_INPUT_INDEX) {
+ BlurBaseOperation::get_area_of_interest(input_idx, output_area, r_input_area);
+ return;
+ }
+
+ const int add_x = this->m_data.sizex + 2;
+ const int add_y = this->m_data.sizey + 2;
+ r_input_area.xmax = output_area.xmax + add_x;
+ r_input_area.xmin = output_area.xmin - add_x;
+ r_input_area.ymax = output_area.ymax + add_y;
+ r_input_area.ymin = output_area.ymin - add_y;
+}
+
+void GaussianBlurReferenceOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const MemoryBuffer *image_input = inputs[IMAGE_INPUT_INDEX];
+ MemoryBuffer *size_input = inputs[SIZE_INPUT_INDEX];
+ for (BuffersIterator<float> it = output->iterate_with({size_input}, area); !it.is_end(); ++it) {
+ const float ref_size = *it.in(0);
+ int ref_radx = (int)(ref_size * m_radx);
+ int ref_rady = (int)(ref_size * m_rady);
+ if (ref_radx > m_filtersizex) {
+ ref_radx = m_filtersizex;
+ }
+ else if (ref_radx < 1) {
+ ref_radx = 1;
+ }
+ if (ref_rady > m_filtersizey) {
+ ref_rady = m_filtersizey;
+ }
+ else if (ref_rady < 1) {
+ ref_rady = 1;
+ }
+
+ const int x = it.x;
+ const int y = it.y;
+ if (ref_radx == 1 && ref_rady == 1) {
+ image_input->read_elem(x, y, it.out);
+ continue;
+ }
+
+ const int w = getWidth();
+ const int height = getHeight();
+ const int minxr = x - ref_radx < 0 ? -x : -ref_radx;
+ const int maxxr = x + ref_radx > w ? w - x : ref_radx;
+ const int minyr = y - ref_rady < 0 ? -y : -ref_rady;
+ const int maxyr = y + ref_rady > height ? height - y : ref_rady;
+
+ const float *gausstabx = m_maintabs[ref_radx - 1];
+ const float *gausstabcentx = gausstabx + ref_radx;
+ const float *gausstaby = m_maintabs[ref_rady - 1];
+ const float *gausstabcenty = gausstaby + ref_rady;
+
+ float gauss_sum = 0.0f;
+ float color_sum[4] = {0};
+ const float *row_color = image_input->get_elem(x + minxr, y + minyr);
+ for (int i = minyr; i < maxyr; i++, row_color += image_input->row_stride) {
+ const float *color = row_color;
+ for (int j = minxr; j < maxxr; j++, color += image_input->elem_stride) {
+ const float val = gausstabcenty[i] * gausstabcentx[j];
+ gauss_sum += val;
+ madd_v4_v4fl(color_sum, color, val);
+ }
+ }
+ mul_v4_v4fl(it.out, color_sum, 1.0f / gauss_sum);
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h
index 59ba3d06619..a64b5b327b0 100644
--- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h
+++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h
@@ -28,10 +28,13 @@ class GaussianBokehBlurOperation : public BlurBaseOperation {
private:
float *m_gausstab;
int m_radx, m_rady;
+ float radxf_;
+ float radyf_;
void updateGauss();
public:
GaussianBokehBlurOperation();
+ void init_data() override;
void initExecution() override;
void *initializeTileData(rcti *rect) override;
/**
@@ -47,6 +50,13 @@ class GaussianBokehBlurOperation : public BlurBaseOperation {
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
rcti *output) override;
+
+ void get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
class GaussianBlurReferenceOperation : public BlurBaseOperation {
@@ -61,6 +71,7 @@ class GaussianBlurReferenceOperation : public BlurBaseOperation {
public:
GaussianBlurReferenceOperation();
+ void init_data() override;
void initExecution() override;
void *initializeTileData(rcti *rect) override;
/**
@@ -76,6 +87,13 @@ class GaussianBlurReferenceOperation : public BlurBaseOperation {
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
rcti *output) override;
+
+ void get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cc b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cc
index 4b46cfc8776..8d686265231 100644
--- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cc
@@ -25,13 +25,8 @@
namespace blender::compositor {
-GaussianXBlurOperation::GaussianXBlurOperation() : BlurBaseOperation(DataType::Color)
+GaussianXBlurOperation::GaussianXBlurOperation() : GaussianBlurBaseOperation(eDimension::X)
{
- this->m_gausstab = nullptr;
-#ifdef BLI_HAVE_SSE2
- this->m_gausstab_sse = nullptr;
-#endif
- this->m_filtersize = 0;
}
void *GaussianXBlurOperation::initializeTileData(rcti * /*rect*/)
@@ -45,13 +40,14 @@ void *GaussianXBlurOperation::initializeTileData(rcti * /*rect*/)
return buffer;
}
+/* TODO(manzanilla): to be removed with tiled implementation. */
void GaussianXBlurOperation::initExecution()
{
- BlurBaseOperation::initExecution();
+ GaussianBlurBaseOperation::initExecution();
initMutex();
- if (this->m_sizeavailable) {
+ if (this->m_sizeavailable && execution_model_ == eExecutionModel::Tiled) {
float rad = max_ff(m_size * m_data.sizex, 0.0f);
m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS);
@@ -63,6 +59,7 @@ void GaussianXBlurOperation::initExecution()
}
}
+/* TODO(manzanilla): to be removed with tiled implementation. */
void GaussianXBlurOperation::updateGauss()
{
if (this->m_gausstab == nullptr) {
@@ -158,7 +155,7 @@ void GaussianXBlurOperation::executeOpenCL(OpenCLDevice *device,
void GaussianXBlurOperation::deinitExecution()
{
- BlurBaseOperation::deinitExecution();
+ GaussianBlurBaseOperation::deinitExecution();
if (this->m_gausstab) {
MEM_freeN(this->m_gausstab);
diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.h b/source/blender/compositor/operations/COM_GaussianXBlurOperation.h
index 15277f0a42d..e09e57bad67 100644
--- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.h
+++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.h
@@ -18,18 +18,13 @@
#pragma once
-#include "COM_BlurBaseOperation.h"
-#include "COM_NodeOperation.h"
+#include "COM_GaussianBlurBaseOperation.h"
namespace blender::compositor {
-class GaussianXBlurOperation : public BlurBaseOperation {
+/* TODO(manzanilla): everything to be removed with tiled implementation except the constructor. */
+class GaussianXBlurOperation : public GaussianBlurBaseOperation {
private:
- float *m_gausstab;
-#ifdef BLI_HAVE_SSE2
- __m128 *m_gausstab_sse;
-#endif
- int m_filtersize;
void updateGauss();
public:
diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cc b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cc
index 590ac5faa6a..32d469a0ae4 100644
--- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cc
@@ -25,13 +25,8 @@
namespace blender::compositor {
-GaussianYBlurOperation::GaussianYBlurOperation() : BlurBaseOperation(DataType::Color)
+GaussianYBlurOperation::GaussianYBlurOperation() : GaussianBlurBaseOperation(eDimension::Y)
{
- this->m_gausstab = nullptr;
-#ifdef BLI_HAVE_SSE2
- this->m_gausstab_sse = nullptr;
-#endif
- this->m_filtersize = 0;
}
void *GaussianYBlurOperation::initializeTileData(rcti * /*rect*/)
@@ -47,11 +42,11 @@ void *GaussianYBlurOperation::initializeTileData(rcti * /*rect*/)
void GaussianYBlurOperation::initExecution()
{
- BlurBaseOperation::initExecution();
+ GaussianBlurBaseOperation::initExecution();
initMutex();
- if (this->m_sizeavailable) {
+ if (this->m_sizeavailable && execution_model_ == eExecutionModel::Tiled) {
float rad = max_ff(m_size * m_data.sizey, 0.0f);
m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS);
@@ -158,7 +153,7 @@ void GaussianYBlurOperation::executeOpenCL(OpenCLDevice *device,
void GaussianYBlurOperation::deinitExecution()
{
- BlurBaseOperation::deinitExecution();
+ GaussianBlurBaseOperation::deinitExecution();
if (this->m_gausstab) {
MEM_freeN(this->m_gausstab);
diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.h b/source/blender/compositor/operations/COM_GaussianYBlurOperation.h
index 56d40849ba4..bb33f8b74cb 100644
--- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.h
+++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.h
@@ -18,18 +18,13 @@
#pragma once
-#include "COM_BlurBaseOperation.h"
-#include "COM_NodeOperation.h"
+#include "COM_GaussianBlurBaseOperation.h"
namespace blender::compositor {
-class GaussianYBlurOperation : public BlurBaseOperation {
+/* TODO(manzanilla): everything to be removed with tiled implementation except the constructor. */
+class GaussianYBlurOperation : public GaussianBlurBaseOperation {
private:
- float *m_gausstab;
-#ifdef BLI_HAVE_SSE2
- __m128 *m_gausstab_sse;
-#endif
- int m_filtersize;
void updateGauss();
public:
diff --git a/source/blender/compositor/operations/COM_KeyingBlurOperation.cc b/source/blender/compositor/operations/COM_KeyingBlurOperation.cc
index 994b00cd3f4..d5ebd5e9df7 100644
--- a/source/blender/compositor/operations/COM_KeyingBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_KeyingBlurOperation.cc
@@ -96,4 +96,67 @@ bool KeyingBlurOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+void KeyingBlurOperation::get_area_of_interest(const int UNUSED(input_idx),
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ switch (m_axis) {
+ case BLUR_AXIS_X:
+ r_input_area.xmin = output_area.xmin - m_size;
+ r_input_area.ymin = output_area.ymin;
+ r_input_area.xmax = output_area.xmax + m_size;
+ r_input_area.ymax = output_area.ymax;
+ break;
+ case BLUR_AXIS_Y:
+ r_input_area.xmin = output_area.xmin;
+ r_input_area.ymin = output_area.ymin - m_size;
+ r_input_area.xmax = output_area.xmax;
+ r_input_area.ymax = output_area.ymax + m_size;
+ break;
+ default:
+ BLI_assert_msg(0, "Unknown axis");
+ break;
+ }
+}
+
+void KeyingBlurOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const MemoryBuffer *input = inputs[0];
+ BuffersIterator<float> it = output->iterate_with(inputs, area);
+
+ int coord_max;
+ int elem_stride;
+ std::function<int()> get_current_coord;
+ switch (m_axis) {
+ case BLUR_AXIS_X:
+ get_current_coord = [&] { return it.x; };
+ coord_max = this->getWidth();
+ elem_stride = input->elem_stride;
+ break;
+ case BLUR_AXIS_Y:
+ get_current_coord = [&] { return it.y; };
+ coord_max = this->getHeight();
+ elem_stride = input->row_stride;
+ break;
+ }
+
+ for (; !it.is_end(); ++it) {
+ const int coord = get_current_coord();
+ const int start_coord = MAX2(0, coord - m_size + 1);
+ const int end_coord = MIN2(coord_max, coord + m_size);
+ const int count = end_coord - start_coord;
+
+ float sum = 0.0f;
+ const float *start = it.in(0) + (start_coord - coord) * elem_stride;
+ const float *end = start + count * elem_stride;
+ for (const float *elem = start; elem < end; elem += elem_stride) {
+ sum += *elem;
+ }
+
+ *it.out = sum / count;
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingBlurOperation.h b/source/blender/compositor/operations/COM_KeyingBlurOperation.h
index b055d7713f1..b290b905e63 100644
--- a/source/blender/compositor/operations/COM_KeyingBlurOperation.h
+++ b/source/blender/compositor/operations/COM_KeyingBlurOperation.h
@@ -18,14 +18,14 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
/**
* Class with implementation of blurring for keying node
*/
-class KeyingBlurOperation : public NodeOperation {
+class KeyingBlurOperation : public MultiThreadedOperation {
protected:
int m_size;
int m_axis;
@@ -54,6 +54,13 @@ class KeyingBlurOperation : public NodeOperation {
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
rcti *output) override;
+
+ void get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingClipOperation.cc b/source/blender/compositor/operations/COM_KeyingClipOperation.cc
index 4029be4e077..817c920ed91 100644
--- a/source/blender/compositor/operations/COM_KeyingClipOperation.cc
+++ b/source/blender/compositor/operations/COM_KeyingClipOperation.cc
@@ -130,4 +130,89 @@ bool KeyingClipOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+void KeyingClipOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ BLI_assert(input_idx == 0);
+ UNUSED_VARS_NDEBUG(input_idx);
+ r_input_area.xmin = output_area.xmin - m_kernelRadius;
+ r_input_area.xmax = output_area.xmax + m_kernelRadius;
+ r_input_area.ymin = output_area.ymin - m_kernelRadius;
+ r_input_area.ymax = output_area.ymax + m_kernelRadius;
+}
+
+void KeyingClipOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const MemoryBuffer *input = inputs[0];
+ BuffersIterator<float> it = output->iterate_with(inputs, area);
+
+ const int delta = m_kernelRadius;
+ const float tolerance = m_kernelTolerance;
+ const int width = this->getWidth();
+ const int height = this->getHeight();
+ const int row_stride = input->row_stride;
+ const int elem_stride = input->elem_stride;
+ for (; !it.is_end(); ++it) {
+ const int x = it.x;
+ const int y = it.y;
+
+ const int start_x = MAX2(0, x - delta + 1);
+ const int start_y = MAX2(0, y - delta + 1);
+ const int end_x = MIN2(x + delta, width);
+ const int end_y = MIN2(y + delta, height);
+ const int x_len = end_x - start_x;
+ const int y_len = end_y - start_y;
+
+ const int total_count = x_len * y_len - 1;
+ const int threshold_count = ceil((float)total_count * 0.9f);
+ bool ok = false;
+ if (delta == 0) {
+ ok = true;
+ }
+
+ const float *main_elem = it.in(0);
+ const float value = *main_elem;
+ const float *row = input->get_elem(start_x, start_y);
+ const float *end_row = row + y_len * row_stride;
+ int count = 0;
+ for (; ok == false && row < end_row; row += row_stride) {
+ const float *end_elem = row + x_len * elem_stride;
+ for (const float *elem = row; ok == false && elem < end_elem; elem += elem_stride) {
+ if (UNLIKELY(elem == main_elem)) {
+ continue;
+ }
+
+ const float current_value = *elem;
+ if (fabsf(current_value - value) < tolerance) {
+ count++;
+ if (count >= threshold_count) {
+ ok = true;
+ }
+ }
+ }
+ }
+
+ if (m_isEdgeMatte) {
+ *it.out = ok ? 0.0f : 1.0f;
+ }
+ else {
+ if (!ok) {
+ *it.out = value;
+ }
+ else if (value < m_clipBlack) {
+ *it.out = 0.0f;
+ }
+ else if (value >= m_clipWhite) {
+ *it.out = 1.0f;
+ }
+ else {
+ *it.out = (value - m_clipBlack) / (m_clipWhite - m_clipBlack);
+ }
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingClipOperation.h b/source/blender/compositor/operations/COM_KeyingClipOperation.h
index 0a21fb48c99..1a17d591781 100644
--- a/source/blender/compositor/operations/COM_KeyingClipOperation.h
+++ b/source/blender/compositor/operations/COM_KeyingClipOperation.h
@@ -18,14 +18,14 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
/**
* Class with implementation of black/white clipping for keying node
*/
-class KeyingClipOperation : public NodeOperation {
+class KeyingClipOperation : public MultiThreadedOperation {
protected:
float m_clipBlack;
float m_clipWhite;
@@ -68,6 +68,13 @@ class KeyingClipOperation : public NodeOperation {
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
rcti *output) override;
+
+ void get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingDespillOperation.cc b/source/blender/compositor/operations/COM_KeyingDespillOperation.cc
index d31a88cb91e..620b767e584 100644
--- a/source/blender/compositor/operations/COM_KeyingDespillOperation.cc
+++ b/source/blender/compositor/operations/COM_KeyingDespillOperation.cc
@@ -36,6 +36,7 @@ KeyingDespillOperation::KeyingDespillOperation()
this->m_pixelReader = nullptr;
this->m_screenReader = nullptr;
+ flags.can_be_constant = true;
}
void KeyingDespillOperation::initExecution()
@@ -82,4 +83,32 @@ void KeyingDespillOperation::executePixelSampled(float output[4],
}
}
+void KeyingDespillOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const float *pixel_color = it.in(0);
+ const float *screen_color = it.in(1);
+
+ const int screen_primary_channel = max_axis_v3(screen_color);
+ const int other_1 = (screen_primary_channel + 1) % 3;
+ const int other_2 = (screen_primary_channel + 2) % 3;
+
+ const int min_channel = MIN2(other_1, other_2);
+ const int max_channel = MAX2(other_1, other_2);
+
+ const float average_value = m_colorBalance * pixel_color[min_channel] +
+ (1.0f - m_colorBalance) * pixel_color[max_channel];
+ const float amount = (pixel_color[screen_primary_channel] - average_value);
+
+ copy_v4_v4(it.out, pixel_color);
+
+ const float amount_despill = m_despillFactor * amount;
+ if (amount_despill > 0.0f) {
+ it.out[screen_primary_channel] = pixel_color[screen_primary_channel] - amount_despill;
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingDespillOperation.h b/source/blender/compositor/operations/COM_KeyingDespillOperation.h
index 279ac60e6e9..16bed651d3a 100644
--- a/source/blender/compositor/operations/COM_KeyingDespillOperation.h
+++ b/source/blender/compositor/operations/COM_KeyingDespillOperation.h
@@ -18,14 +18,14 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
/**
* Class with implementation of keying despill node
*/
-class KeyingDespillOperation : public NodeOperation {
+class KeyingDespillOperation : public MultiThreadedOperation {
protected:
SocketReader *m_pixelReader;
SocketReader *m_screenReader;
@@ -48,6 +48,10 @@ class KeyingDespillOperation : public NodeOperation {
}
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingOperation.cc b/source/blender/compositor/operations/COM_KeyingOperation.cc
index e786e4b8219..3edb5a5d34e 100644
--- a/source/blender/compositor/operations/COM_KeyingOperation.cc
+++ b/source/blender/compositor/operations/COM_KeyingOperation.cc
@@ -110,4 +110,49 @@ void KeyingOperation::executePixelSampled(float output[4], float x, float y, Pix
}
}
+void KeyingOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const float *pixel_color = it.in(0);
+ const float *screen_color = it.in(1);
+
+ const int primary_channel = max_axis_v3(screen_color);
+ const float min_pixel_color = min_fff(pixel_color[0], pixel_color[1], pixel_color[2]);
+
+ if (min_pixel_color > 1.0f) {
+ /* Overexposure doesn't happen on screen itself and usually happens
+ * on light sources in the shot, this need to be checked separately
+ * because saturation and falloff calculation is based on the fact
+ * that pixels are not overexposed.
+ */
+ it.out[0] = 1.0f;
+ }
+ else {
+ const float saturation = get_pixel_saturation(pixel_color, m_screenBalance, primary_channel);
+ const float screen_saturation = get_pixel_saturation(
+ screen_color, m_screenBalance, primary_channel);
+
+ if (saturation < 0) {
+ /* Means main channel of pixel is different from screen,
+ * assume this is completely a foreground.
+ */
+ it.out[0] = 1.0f;
+ }
+ else if (saturation >= screen_saturation) {
+ /* Matched main channels and higher saturation on pixel
+ * is treated as completely background.
+ */
+ it.out[0] = 0.0f;
+ }
+ else {
+ /* Nice alpha falloff on edges. */
+ const float distance = 1.0f - saturation / screen_saturation;
+ it.out[0] = distance;
+ }
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingOperation.h b/source/blender/compositor/operations/COM_KeyingOperation.h
index 3d41ecaa0f6..e134ad54896 100644
--- a/source/blender/compositor/operations/COM_KeyingOperation.h
+++ b/source/blender/compositor/operations/COM_KeyingOperation.h
@@ -20,7 +20,7 @@
#include <string.h>
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
#include "BLI_listbase.h"
@@ -29,7 +29,7 @@ namespace blender::compositor {
/**
* Class with implementation of keying node
*/
-class KeyingOperation : public NodeOperation {
+class KeyingOperation : public MultiThreadedOperation {
protected:
SocketReader *m_pixelReader;
SocketReader *m_screenReader;
@@ -48,6 +48,10 @@ class KeyingOperation : public NodeOperation {
}
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.cc b/source/blender/compositor/operations/COM_KeyingScreenOperation.cc
index 17b613246ad..c00aafc19a2 100644
--- a/source/blender/compositor/operations/COM_KeyingScreenOperation.cc
+++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.cc
@@ -39,12 +39,21 @@ KeyingScreenOperation::KeyingScreenOperation()
this->m_framenumber = 0;
this->m_trackingObject[0] = 0;
flags.complex = true;
+ m_cachedTriangulation = nullptr;
}
void KeyingScreenOperation::initExecution()
{
initMutex();
- this->m_cachedTriangulation = nullptr;
+ if (execution_model_ == eExecutionModel::FullFrame) {
+ BLI_assert(m_cachedTriangulation == nullptr);
+ if (m_movieClip) {
+ m_cachedTriangulation = buildVoronoiTriangulation();
+ }
+ }
+ else {
+ this->m_cachedTriangulation = nullptr;
+ }
}
void KeyingScreenOperation::deinitExecution()
@@ -226,7 +235,7 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri
return triangulation;
}
-void *KeyingScreenOperation::initializeTileData(rcti *rect)
+KeyingScreenOperation::TileData *KeyingScreenOperation::triangulate(const rcti *rect)
{
TileData *tile_data;
TriangulationData *triangulation;
@@ -234,18 +243,6 @@ void *KeyingScreenOperation::initializeTileData(rcti *rect)
int chunk_size = 20;
int i;
- if (this->m_movieClip == nullptr) {
- return nullptr;
- }
-
- if (!this->m_cachedTriangulation) {
- lockMutex();
- if (this->m_cachedTriangulation == nullptr) {
- this->m_cachedTriangulation = buildVoronoiTriangulation();
- }
- unlockMutex();
- }
-
triangulation = this->m_cachedTriangulation;
if (!triangulation) {
@@ -278,6 +275,23 @@ void *KeyingScreenOperation::initializeTileData(rcti *rect)
return tile_data;
}
+void *KeyingScreenOperation::initializeTileData(rcti *rect)
+{
+ if (this->m_movieClip == nullptr) {
+ return nullptr;
+ }
+
+ if (!this->m_cachedTriangulation) {
+ lockMutex();
+ if (this->m_cachedTriangulation == nullptr) {
+ this->m_cachedTriangulation = buildVoronoiTriangulation();
+ }
+ unlockMutex();
+ }
+
+ return triangulate(rect);
+}
+
void KeyingScreenOperation::deinitializeTileData(rcti * /*rect*/, void *data)
{
TileData *tile_data = (TileData *)data;
@@ -347,4 +361,57 @@ void KeyingScreenOperation::executePixel(float output[4], int x, int y, void *da
}
}
+void KeyingScreenOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ if (m_movieClip == nullptr) {
+ output->fill(area, COM_COLOR_BLACK);
+ return;
+ }
+
+ TileData *tri_area = this->triangulate(&area);
+ BLI_assert(tri_area != nullptr);
+
+ const int *triangles = tri_area->triangles;
+ const int num_triangles = tri_area->triangles_total;
+ const TriangulationData *triangulation = m_cachedTriangulation;
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ copy_v4_v4(it.out, COM_COLOR_BLACK);
+
+ const float co[2] = {(float)it.x, (float)it.y};
+ for (int i = 0; i < num_triangles; i++) {
+ const int triangle_idx = triangles[i];
+ const rcti *rect = &triangulation->triangles_AABB[triangle_idx];
+
+ if (!BLI_rcti_isect_pt(rect, it.x, it.y)) {
+ continue;
+ }
+
+ const int *triangle = triangulation->triangles[triangle_idx];
+ const VoronoiTriangulationPoint &a = triangulation->triangulated_points[triangle[0]];
+ const VoronoiTriangulationPoint &b = triangulation->triangulated_points[triangle[1]];
+ const VoronoiTriangulationPoint &c = triangulation->triangulated_points[triangle[2]];
+
+ float w[3];
+ if (!barycentric_coords_v2(a.co, b.co, c.co, co, w)) {
+ continue;
+ }
+
+ if (barycentric_inside_triangle_v2(w)) {
+ it.out[0] = a.color[0] * w[0] + b.color[0] * w[1] + c.color[0] * w[2];
+ it.out[1] = a.color[1] * w[0] + b.color[1] * w[1] + c.color[1] * w[2];
+ it.out[2] = a.color[2] * w[0] + b.color[2] * w[1] + c.color[2] * w[2];
+ break;
+ }
+ }
+ }
+
+ if (tri_area->triangles) {
+ MEM_freeN(tri_area->triangles);
+ }
+
+ MEM_freeN(tri_area);
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.h b/source/blender/compositor/operations/COM_KeyingScreenOperation.h
index 4118d229be9..0bc47dbea30 100644
--- a/source/blender/compositor/operations/COM_KeyingScreenOperation.h
+++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.h
@@ -20,7 +20,7 @@
#include <string.h>
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
#include "DNA_movieclip_types.h"
@@ -34,7 +34,7 @@ namespace blender::compositor {
/**
* Class with implementation of green screen gradient rasterization
*/
-class KeyingScreenOperation : public NodeOperation {
+class KeyingScreenOperation : public MultiThreadedOperation {
protected:
typedef struct TriangulationData {
VoronoiTriangulationPoint *triangulated_points;
@@ -43,6 +43,7 @@ class KeyingScreenOperation : public NodeOperation {
rcti *triangles_AABB;
} TriangulationData;
+ /* TODO(manzanilla): rename to #TrianguledArea on removing tiled implementation. */
typedef struct TileData {
int *triangles;
int triangles_total;
@@ -84,6 +85,13 @@ class KeyingScreenOperation : public NodeOperation {
}
void executePixel(float output[4], int x, int y, void *data) override;
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
+
+ private:
+ TileData *triangulate(const rcti *rect);
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_LuminanceMatteOperation.cc b/source/blender/compositor/operations/COM_LuminanceMatteOperation.cc
index 5ca16e40ce3..c642c60b912 100644
--- a/source/blender/compositor/operations/COM_LuminanceMatteOperation.cc
+++ b/source/blender/compositor/operations/COM_LuminanceMatteOperation.cc
@@ -29,6 +29,7 @@ LuminanceMatteOperation::LuminanceMatteOperation()
addOutputSocket(DataType::Value);
this->m_inputImageProgram = nullptr;
+ flags.can_be_constant = true;
}
void LuminanceMatteOperation::initExecution()
@@ -78,4 +79,39 @@ void LuminanceMatteOperation::executePixelSampled(float output[4],
output[0] = min_ff(alpha, inColor[3]);
}
+void LuminanceMatteOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const float *color = it.in(0);
+ const float luminance = IMB_colormanagement_get_luminance(color);
+
+ /* One line thread-friend algorithm:
+ * `it.out[0] = MIN2(color[3], MIN2(1.0f, MAX2(0.0f, ((luminance - low) / (high - low))));`
+ */
+
+ /* Test range. */
+ const float high = m_settings->t1;
+ const float low = m_settings->t2;
+ float alpha;
+ if (luminance > high) {
+ alpha = 1.0f;
+ }
+ else if (luminance < low) {
+ alpha = 0.0f;
+ }
+ else { /* Blend. */
+ alpha = (luminance - low) / (high - low);
+ }
+
+ /* Store matte(alpha) value in [0] to go with
+ * COM_SetAlphaMultiplyOperation and the Value output.
+ */
+
+ /* Don't make something that was more transparent less transparent. */
+ it.out[0] = MIN2(alpha, color[3]);
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_LuminanceMatteOperation.h b/source/blender/compositor/operations/COM_LuminanceMatteOperation.h
index 035c68b9d59..aedfc715382 100644
--- a/source/blender/compositor/operations/COM_LuminanceMatteOperation.h
+++ b/source/blender/compositor/operations/COM_LuminanceMatteOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_MixOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
@@ -26,7 +26,7 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
-class LuminanceMatteOperation : public NodeOperation {
+class LuminanceMatteOperation : public MultiThreadedOperation {
private:
NodeChroma *m_settings;
SocketReader *m_inputImageProgram;
@@ -49,6 +49,10 @@ class LuminanceMatteOperation : public NodeOperation {
{
this->m_settings = nodeChroma;
}
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MapUVOperation.cc b/source/blender/compositor/operations/COM_MapUVOperation.cc
index 74e3d965d41..ad047c619f8 100644
--- a/source/blender/compositor/operations/COM_MapUVOperation.cc
+++ b/source/blender/compositor/operations/COM_MapUVOperation.cc
@@ -34,10 +34,26 @@ MapUVOperation::MapUVOperation()
this->m_inputColorProgram = nullptr;
}
+void MapUVOperation::init_data()
+{
+ NodeOperation *image_input = get_input_operation(0);
+ image_width_ = image_input->getWidth();
+ image_height_ = image_input->getHeight();
+
+ NodeOperation *uv_input = get_input_operation(1);
+ uv_width_ = uv_input->getWidth();
+ uv_height_ = uv_input->getHeight();
+}
+
void MapUVOperation::initExecution()
{
this->m_inputColorProgram = this->getInputSocketReader(0);
this->m_inputUVProgram = this->getInputSocketReader(1);
+ if (execution_model_ == eExecutionModel::Tiled) {
+ uv_input_read_fn_ = [=](float x, float y, float *out) {
+ this->m_inputUVProgram->readSampled(out, x, y, PixelSampler::Bilinear);
+ };
+ }
}
void MapUVOperation::executePixelSampled(float output[4],
@@ -81,9 +97,7 @@ void MapUVOperation::executePixelSampled(float output[4],
bool MapUVOperation::read_uv(float x, float y, float &r_u, float &r_v, float &r_alpha)
{
- float width = m_inputUVProgram->getWidth();
- float height = m_inputUVProgram->getHeight();
- if (x < 0.0f || x >= width || y < 0.0f || y >= height) {
+ if (x < 0.0f || x >= uv_width_ || y < 0.0f || y >= uv_height_) {
r_u = 0.0f;
r_v = 0.0f;
r_alpha = 0.0f;
@@ -91,9 +105,9 @@ bool MapUVOperation::read_uv(float x, float y, float &r_u, float &r_v, float &r_
}
float vector[3];
- m_inputUVProgram->readSampled(vector, x, y, PixelSampler::Bilinear);
- r_u = vector[0] * m_inputColorProgram->getWidth();
- r_v = vector[1] * m_inputColorProgram->getHeight();
+ uv_input_read_fn_(x, y, vector);
+ r_u = vector[0] * image_width_;
+ r_v = vector[1] * image_height_;
r_alpha = vector[2];
return true;
}
@@ -186,4 +200,75 @@ bool MapUVOperation::determineDependingAreaOfInterest(rcti *input,
return false;
}
+void MapUVOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ switch (input_idx) {
+ case 0: {
+ r_input_area.xmin = 0;
+ r_input_area.xmax = image_width_;
+ r_input_area.ymin = 0;
+ r_input_area.ymax = image_height_;
+ break;
+ }
+ case 1: {
+ r_input_area = output_area;
+ expand_area_for_sampler(r_input_area, PixelSampler::Bilinear);
+ break;
+ }
+ }
+}
+
+void MapUVOperation::update_memory_buffer_started(MemoryBuffer *UNUSED(output),
+ const rcti &UNUSED(area),
+ Span<MemoryBuffer *> inputs)
+{
+ const MemoryBuffer *uv_input = inputs[1];
+ uv_input_read_fn_ = [=](float x, float y, float *out) {
+ uv_input->read_elem_bilinear(x, y, out);
+ };
+}
+
+void MapUVOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const MemoryBuffer *input_image = inputs[0];
+ for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
+ float xy[2] = {(float)it.x, (float)it.y};
+ float uv[2];
+ float deriv[2][2];
+ float alpha;
+ pixelTransform(xy, uv, deriv, alpha);
+ if (alpha == 0.0f) {
+ zero_v4(it.out);
+ continue;
+ }
+
+ /* EWA filtering. */
+ input_image->read_elem_filtered(uv[0], uv[1], deriv[0], deriv[1], it.out);
+
+ /* UV to alpha threshold. */
+ const float threshold = this->m_alpha * 0.05f;
+ /* XXX alpha threshold is used to fade out pixels on boundaries with invalid derivatives.
+ * this calculation is not very well defined, should be looked into if it becomes a problem ...
+ */
+ const float du = len_v2(deriv[0]);
+ const float dv = len_v2(deriv[1]);
+ const float factor = 1.0f - threshold * (du / image_width_ + dv / image_height_);
+ if (factor < 0.0f) {
+ alpha = 0.0f;
+ }
+ else {
+ alpha *= factor;
+ }
+
+ /* "premul" */
+ if (alpha < 1.0f) {
+ mul_v4_fl(it.out, alpha);
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MapUVOperation.h b/source/blender/compositor/operations/COM_MapUVOperation.h
index eb5f7d49122..65fbcb461c9 100644
--- a/source/blender/compositor/operations/COM_MapUVOperation.h
+++ b/source/blender/compositor/operations/COM_MapUVOperation.h
@@ -18,11 +18,11 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
-class MapUVOperation : public NodeOperation {
+class MapUVOperation : public MultiThreadedOperation {
private:
/**
* Cached reference to the inputProgram
@@ -30,8 +30,15 @@ class MapUVOperation : public NodeOperation {
SocketReader *m_inputUVProgram;
SocketReader *m_inputColorProgram;
+ int uv_width_;
+ int uv_height_;
+ int image_width_;
+ int image_height_;
+
float m_alpha;
+ std::function<void(float x, float y, float *out)> uv_input_read_fn_;
+
public:
MapUVOperation();
@@ -49,6 +56,8 @@ class MapUVOperation : public NodeOperation {
void pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2], float &r_alpha);
+ void init_data() override;
+
/**
* Initialize the execution
*/
@@ -64,6 +73,14 @@ class MapUVOperation : public NodeOperation {
this->m_alpha = alpha;
}
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+ void update_memory_buffer_started(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
+
private:
bool read_uv(float x, float y, float &r_u, float &r_v, float &r_alpha);
};
diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.cc b/source/blender/compositor/operations/COM_MathBaseOperation.cc
index a94c14347fb..2256dce011b 100644
--- a/source/blender/compositor/operations/COM_MathBaseOperation.cc
+++ b/source/blender/compositor/operations/COM_MathBaseOperation.cc
@@ -24,6 +24,8 @@ namespace blender::compositor {
MathBaseOperation::MathBaseOperation()
{
+ /* TODO(manzanilla): after removing tiled implementation, template this class to only add needed
+ * number of inputs. */
this->addInputSocket(DataType::Value);
this->addInputSocket(DataType::Value);
this->addInputSocket(DataType::Value);
@@ -32,6 +34,7 @@ MathBaseOperation::MathBaseOperation()
this->m_inputValue2Operation = nullptr;
this->m_inputValue3Operation = nullptr;
this->m_useClamp = false;
+ this->flags.can_be_constant = true;
}
void MathBaseOperation::initExecution()
@@ -73,6 +76,14 @@ void MathBaseOperation::clampIfNeeded(float *color)
}
}
+void MathBaseOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ BuffersIterator<float> it = output->iterate_with(inputs, area);
+ update_memory_buffer_partial(it);
+}
+
void MathAddOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
float inputValue1[4];
@@ -139,6 +150,14 @@ void MathDivideOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathDivideOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float divisor = *it.in(1);
+ *it.out = clamp_when_enabled((divisor == 0) ? 0 : *it.in(0) / divisor);
+ }
+}
+
void MathSineOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -155,6 +174,14 @@ void MathSineOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathSineOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = sin(*it.in(0));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathCosineOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -171,6 +198,14 @@ void MathCosineOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathCosineOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = cos(*it.in(0));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathTangentOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -187,6 +222,14 @@ void MathTangentOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathTangentOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = tan(*it.in(0));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathHyperbolicSineOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -203,6 +246,14 @@ void MathHyperbolicSineOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathHyperbolicSineOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = sinh(*it.in(0));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathHyperbolicCosineOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -219,6 +270,14 @@ void MathHyperbolicCosineOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathHyperbolicCosineOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = cosh(*it.in(0));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathHyperbolicTangentOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -235,6 +294,14 @@ void MathHyperbolicTangentOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathHyperbolicTangentOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = tanh(*it.in(0));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathArcSineOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -256,6 +323,14 @@ void MathArcSineOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathArcSineOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ float value1 = *it.in(0);
+ *it.out = clamp_when_enabled((value1 <= 1 && value1 >= -1) ? asin(value1) : 0.0f);
+ }
+}
+
void MathArcCosineOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -277,6 +352,14 @@ void MathArcCosineOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathArcCosineOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ float value1 = *it.in(0);
+ *it.out = clamp_when_enabled((value1 <= 1 && value1 >= -1) ? acos(value1) : 0.0f);
+ }
+}
+
void MathArcTangentOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -293,6 +376,14 @@ void MathArcTangentOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathArcTangentOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = atan(*it.in(0));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathPowerOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -321,6 +412,29 @@ void MathPowerOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathPowerOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float value1 = *it.in(0);
+ const float value2 = *it.in(1);
+ if (value1 >= 0) {
+ *it.out = pow(value1, value2);
+ }
+ else {
+ const float y_mod_1 = fmod(value2, 1);
+ /* If input value is not nearly an integer, fall back to zero, nicer than straight rounding.
+ */
+ if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) {
+ *it.out = pow(value1, floorf(value2 + 0.5f));
+ }
+ else {
+ *it.out = 0.0f;
+ }
+ }
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathLogarithmOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -342,6 +456,21 @@ void MathLogarithmOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathLogarithmOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float value1 = *it.in(0);
+ const float value2 = *it.in(1);
+ if (value1 > 0 && value2 > 0) {
+ *it.out = log(value1) / log(value2);
+ }
+ else {
+ *it.out = 0.0;
+ }
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathMinimumOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -358,6 +487,14 @@ void MathMinimumOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathMinimumOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = MIN2(*it.in(0), *it.in(1));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathMaximumOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -374,6 +511,14 @@ void MathMaximumOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathMaximumOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = MAX2(*it.in(0), *it.in(1));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathRoundOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -390,6 +535,14 @@ void MathRoundOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathRoundOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = round(*it.in(0));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathLessThanOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -443,6 +596,15 @@ void MathModuloOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathModuloOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float value2 = *it.in(1);
+ *it.out = (value2 == 0) ? 0 : fmod(*it.in(0), value2);
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathAbsoluteOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -457,6 +619,14 @@ void MathAbsoluteOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathAbsoluteOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = fabs(*it.in(0));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathRadiansOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -471,6 +641,14 @@ void MathRadiansOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathRadiansOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = DEG2RADF(*it.in(0));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathDegreesOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -485,6 +663,14 @@ void MathDegreesOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathDegreesOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = RAD2DEGF(*it.in(0));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathArcTan2Operation::executePixelSampled(float output[4],
float x,
float y,
@@ -501,6 +687,14 @@ void MathArcTan2Operation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathArcTan2Operation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = atan2(*it.in(0), *it.in(1));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathFloorOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -515,6 +709,14 @@ void MathFloorOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathFloorOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = floor(*it.in(0));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathCeilOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -529,6 +731,14 @@ void MathCeilOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathCeilOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = ceil(*it.in(0));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathFractOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -543,6 +753,14 @@ void MathFractOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathFractOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float value = *it.in(0);
+ *it.out = clamp_when_enabled(value - floor(value));
+ }
+}
+
void MathSqrtOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -562,6 +780,14 @@ void MathSqrtOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathSqrtOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float value = *it.in(0);
+ *it.out = clamp_when_enabled(value > 0 ? sqrt(value) : 0.0f);
+ }
+}
+
void MathInverseSqrtOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -581,6 +807,14 @@ void MathInverseSqrtOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathInverseSqrtOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float value = *it.in(0);
+ *it.out = clamp_when_enabled(value > 0 ? 1.0f / sqrt(value) : 0.0f);
+ }
+}
+
void MathSignOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -595,6 +829,14 @@ void MathSignOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathSignOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = compatible_signf(*it.in(0));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathExponentOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -609,6 +851,14 @@ void MathExponentOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathExponentOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = expf(*it.in(0));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathTruncOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -623,6 +873,15 @@ void MathTruncOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathTruncOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float value = *it.in(0);
+ *it.out = (value >= 0.0f) ? floor(value) : ceil(value);
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathSnapOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -644,6 +903,21 @@ void MathSnapOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathSnapOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float value1 = *it.in(0);
+ const float value2 = *it.in(1);
+ if (value1 == 0 || value2 == 0) { /* Avoid dividing by zero. */
+ *it.out = 0.0f;
+ }
+ else {
+ *it.out = floorf(value1 / value2) * value2;
+ }
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathWrapOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -662,6 +936,14 @@ void MathWrapOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathWrapOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = wrapf(*it.in(0), *it.in(1), *it.in(2));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathPingpongOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -678,6 +960,14 @@ void MathPingpongOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathPingpongOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = pingpongf(*it.in(0), *it.in(1));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathCompareOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -697,6 +987,14 @@ void MathCompareOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathCompareOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = (fabsf(*it.in(0) - *it.in(1)) <= MAX2(*it.in(2), 1e-5f)) ? 1.0f : 0.0f;
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathMultiplyAddOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -715,6 +1013,14 @@ void MathMultiplyAddOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathMultiplyAddOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = it.in(0)[0] * it.in(1)[0] + it.in(2)[0];
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathSmoothMinOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -733,6 +1039,14 @@ void MathSmoothMinOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathSmoothMinOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = smoothminf(*it.in(0), *it.in(1), *it.in(2));
+ clamp_when_enabled(it.out);
+ }
+}
+
void MathSmoothMaxOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -751,4 +1065,12 @@ void MathSmoothMaxOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+void MathSmoothMaxOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ *it.out = -smoothminf(-it.in(0)[0], -it.in(1)[0], it.in(2)[0]);
+ clamp_when_enabled(it.out);
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.h b/source/blender/compositor/operations/COM_MathBaseOperation.h
index 08794c8db22..d2da05db68e 100644
--- a/source/blender/compositor/operations/COM_MathBaseOperation.h
+++ b/source/blender/compositor/operations/COM_MathBaseOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
@@ -26,7 +26,7 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
-class MathBaseOperation : public NodeOperation {
+class MathBaseOperation : public MultiThreadedOperation {
protected:
/**
* Prefetched reference to the inputProgram
@@ -43,8 +43,24 @@ class MathBaseOperation : public NodeOperation {
*/
MathBaseOperation();
+ /* TODO(manzanilla): to be removed with tiled implementation. */
void clampIfNeeded(float color[4]);
+ float clamp_when_enabled(float value)
+ {
+ if (this->m_useClamp) {
+ return CLAMPIS(value, 0.0f, 1.0f);
+ }
+ return value;
+ }
+
+ void clamp_when_enabled(float *out)
+ {
+ if (this->m_useClamp) {
+ CLAMP(*out, 0.0f, 1.0f);
+ }
+ }
+
public:
/**
* Initialize the execution
@@ -66,87 +82,151 @@ class MathBaseOperation : public NodeOperation {
{
this->m_useClamp = value;
}
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) final;
+
+ protected:
+ virtual void update_memory_buffer_partial(BuffersIterator<float> &it) = 0;
};
-class MathAddOperation : public MathBaseOperation {
+template<template<typename> typename TFunctor>
+class MathFunctor2Operation : public MathBaseOperation {
+ void update_memory_buffer_partial(BuffersIterator<float> &it) final
+ {
+ TFunctor functor;
+ for (; !it.is_end(); ++it) {
+ *it.out = functor(*it.in(0), *it.in(1));
+ clamp_when_enabled(it.out);
+ }
+ }
+};
+
+class MathAddOperation : public MathFunctor2Operation<std::plus> {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
-class MathSubtractOperation : public MathBaseOperation {
+class MathSubtractOperation : public MathFunctor2Operation<std::minus> {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
-class MathMultiplyOperation : public MathBaseOperation {
+class MathMultiplyOperation : public MathFunctor2Operation<std::multiplies> {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathDivideOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathSineOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathCosineOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathTangentOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathHyperbolicSineOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathHyperbolicCosineOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathHyperbolicTangentOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathArcSineOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathArcCosineOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathArcTangentOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathPowerOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathLogarithmOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathMinimumOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathMaximumOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathRoundOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
-class MathLessThanOperation : public MathBaseOperation {
+class MathLessThanOperation : public MathFunctor2Operation<std::less> {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
-class MathGreaterThanOperation : public MathBaseOperation {
+class MathGreaterThanOperation : public MathFunctor2Operation<std::greater> {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
@@ -154,101 +234,161 @@ class MathGreaterThanOperation : public MathBaseOperation {
class MathModuloOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathAbsoluteOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathRadiansOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathDegreesOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathArcTan2Operation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathFloorOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathCeilOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathFractOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathSqrtOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathInverseSqrtOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathSignOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathExponentOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathTruncOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathSnapOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathWrapOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathPingpongOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathCompareOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathMultiplyAddOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathSmoothMinOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class MathSmoothMaxOperation : public MathBaseOperation {
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cc b/source/blender/compositor/operations/COM_MovieDistortionOperation.cc
index c8e045ea117..d3424959061 100644
--- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cc
+++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cc
@@ -128,4 +128,51 @@ bool MovieDistortionOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+void MovieDistortionOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ BLI_assert(input_idx == 0);
+ UNUSED_VARS_NDEBUG(input_idx);
+ r_input_area.xmin = output_area.xmin - m_margin[0];
+ r_input_area.ymin = output_area.ymin - m_margin[1];
+ r_input_area.xmax = output_area.xmax + m_margin[0];
+ r_input_area.ymax = output_area.ymax + m_margin[1];
+}
+
+void MovieDistortionOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const MemoryBuffer *input_img = inputs[0];
+ if (this->m_distortion == nullptr) {
+ output->copy_from(input_img, area);
+ return;
+ }
+
+ /* `float overscan = 0.0f;` */
+ const float pixel_aspect = this->m_pixel_aspect;
+ const float w = (float)this->m_width /* `/ (1 + overscan)` */;
+ const float h = (float)this->m_height /* `/ (1 + overscan)` */;
+ const float aspx = w / (float)this->m_calibration_width;
+ const float aspy = h / (float)this->m_calibration_height;
+ float xy[2];
+ float distorted_xy[2];
+ for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
+ xy[0] = (it.x /* `- 0.5 * overscan * w` */) / aspx;
+ xy[1] = (it.y /* `- 0.5 * overscan * h` */) / aspy / pixel_aspect;
+
+ if (this->m_apply) {
+ BKE_tracking_distortion_undistort_v2(this->m_distortion, xy, distorted_xy);
+ }
+ else {
+ BKE_tracking_distortion_distort_v2(this->m_distortion, xy, distorted_xy);
+ }
+
+ const float u = distorted_xy[0] * aspx /* `+ 0.5 * overscan * w` */;
+ const float v = (distorted_xy[1] * aspy /* `+ 0.5 * overscan * h` */) * pixel_aspect;
+ input_img->read_elem_bilinear(u, v, it.out);
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.h b/source/blender/compositor/operations/COM_MovieDistortionOperation.h
index 631a62f7ebf..69c2f9c269c 100644
--- a/source/blender/compositor/operations/COM_MovieDistortionOperation.h
+++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
#include "DNA_movieclip_types.h"
#include "MEM_guardedalloc.h"
@@ -26,7 +26,7 @@
namespace blender::compositor {
-class MovieDistortionOperation : public NodeOperation {
+class MovieDistortionOperation : public MultiThreadedOperation {
private:
SocketReader *m_inputOperation;
MovieClip *m_movieClip;
@@ -58,6 +58,11 @@ class MovieDistortionOperation : public NodeOperation {
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
rcti *output) override;
+
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cc b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cc
index 3577860b93d..d2a06ddd7c4 100644
--- a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cc
+++ b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cc
@@ -16,6 +16,7 @@
*/
#include "COM_PlaneCornerPinOperation.h"
+#include "COM_ConstantOperation.h"
#include "COM_ReadBufferOperation.h"
#include "MEM_guardedalloc.h"
@@ -28,6 +29,11 @@
namespace blender::compositor {
+constexpr int LOWER_LEFT_CORNER_INDEX = 0;
+constexpr int LOWER_RIGHT_CORNER_INDEX = 1;
+constexpr int UPPER_RIGHT_CORNER_INDEX = 2;
+constexpr int UPPER_LEFT_CORNER_INDEX = 3;
+
static bool check_corners(float corners[4][2])
{
int i, next, prev;
@@ -58,6 +64,7 @@ static bool check_corners(float corners[4][2])
return true;
}
+/* TODO(manzanilla): to be removed with tiled implementation. */
static void readCornersFromSockets(rcti *rect, SocketReader *readers[4], float corners[4][2])
{
for (int i = 0; i < 4; i++) {
@@ -87,6 +94,53 @@ static void readCornersFromSockets(rcti *rect, SocketReader *readers[4], float c
}
}
+static void set_default_corner(const int corner_idx, float r_corner[2])
+{
+ BLI_assert(corner_idx >= 0 && corner_idx < 4);
+ switch (corner_idx) {
+ case LOWER_LEFT_CORNER_INDEX:
+ r_corner[0] = 0.0f;
+ r_corner[1] = 0.0f;
+ break;
+ case LOWER_RIGHT_CORNER_INDEX:
+ r_corner[0] = 1.0f;
+ r_corner[1] = 0.0f;
+ break;
+ case UPPER_RIGHT_CORNER_INDEX:
+ r_corner[0] = 1.0f;
+ r_corner[1] = 1.0f;
+ break;
+ case UPPER_LEFT_CORNER_INDEX:
+ r_corner[0] = 0.0f;
+ r_corner[1] = 1.0f;
+ break;
+ }
+}
+
+static void read_input_corners(NodeOperation *op, const int first_input_idx, float r_corners[4][2])
+{
+ for (const int i : IndexRange(4)) {
+ NodeOperation *input = op->get_input_operation(i + first_input_idx);
+ if (input->get_flags().is_constant_operation) {
+ ConstantOperation *corner_input = static_cast<ConstantOperation *>(input);
+ copy_v2_v2(r_corners[i], corner_input->get_constant_elem());
+ }
+ else {
+ set_default_corner(i, r_corners[i]);
+ }
+ }
+
+ /* Convexity check: concave corners need to be prevented, otherwise
+ * #BKE_tracking_homography_between_two_quads will freeze. */
+ if (!check_corners(r_corners)) {
+ /* Revert to default corners. There could be a more elegant solution,
+ * this prevents freezing at least. */
+ for (const int i : IndexRange(4)) {
+ set_default_corner(i, r_corners[i]);
+ }
+ }
+}
+
/* ******** PlaneCornerPinMaskOperation ******** */
PlaneCornerPinMaskOperation::PlaneCornerPinMaskOperation() : m_corners_ready(false)
@@ -103,6 +157,17 @@ PlaneCornerPinMaskOperation::PlaneCornerPinMaskOperation() : m_corners_ready(fal
flags.complex = true;
}
+void PlaneCornerPinMaskOperation::init_data()
+{
+ if (execution_model_ == eExecutionModel::FullFrame) {
+ float corners[4][2];
+ read_input_corners(this, 0, corners);
+ calculateCorners(corners, true, 0);
+ }
+}
+
+/* TODO(manzanilla): to be removed with tiled implementation. Same for #deinitExecution and do the
+ * same on #PlaneCornerPinWarpImageOperation. */
void PlaneCornerPinMaskOperation::initExecution()
{
PlaneDistortMaskOperation::initExecution();
@@ -147,10 +212,22 @@ void *PlaneCornerPinMaskOperation::initializeTileData(rcti *rect)
void PlaneCornerPinMaskOperation::determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2])
{
+ if (execution_model_ == eExecutionModel::FullFrame) {
+ /* Determine inputs resolution. */
+ PlaneDistortMaskOperation::determineResolution(resolution, preferredResolution);
+ }
resolution[0] = preferredResolution[0];
resolution[1] = preferredResolution[1];
}
+void PlaneCornerPinMaskOperation::get_area_of_interest(const int UNUSED(input_idx),
+ const rcti &UNUSED(output_area),
+ rcti &r_input_area)
+{
+ /* All corner inputs are used as constants. */
+ r_input_area = COM_SINGLE_ELEM_AREA;
+}
+
/* ******** PlaneCornerPinWarpImageOperation ******** */
PlaneCornerPinWarpImageOperation::PlaneCornerPinWarpImageOperation() : m_corners_ready(false)
@@ -161,6 +238,15 @@ PlaneCornerPinWarpImageOperation::PlaneCornerPinWarpImageOperation() : m_corners
addInputSocket(DataType::Vector);
}
+void PlaneCornerPinWarpImageOperation::init_data()
+{
+ if (execution_model_ == eExecutionModel::FullFrame) {
+ float corners[4][2];
+ read_input_corners(this, 1, corners);
+ calculateCorners(corners, true, 0);
+ }
+}
+
void PlaneCornerPinWarpImageOperation::initExecution()
{
PlaneDistortWarpImageOperation::initExecution();
@@ -227,4 +313,17 @@ bool PlaneCornerPinWarpImageOperation::determineDependingAreaOfInterest(
#endif
}
+void PlaneCornerPinWarpImageOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ if (input_idx == 0) {
+ PlaneDistortWarpImageOperation::get_area_of_interest(input_idx, output_area, r_input_area);
+ }
+ else {
+ /* Corner inputs are used as constants. */
+ r_input_area = COM_SINGLE_ELEM_AREA;
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h
index 91c0cd9e16b..2831e937147 100644
--- a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h
+++ b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h
@@ -31,11 +31,13 @@ namespace blender::compositor {
class PlaneCornerPinMaskOperation : public PlaneDistortMaskOperation {
private:
+ /* TODO(manzanilla): to be removed with tiled implementation. */
bool m_corners_ready;
public:
PlaneCornerPinMaskOperation();
+ void init_data() override;
void initExecution() override;
void deinitExecution() override;
@@ -43,6 +45,8 @@ class PlaneCornerPinMaskOperation : public PlaneDistortMaskOperation {
void determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2]) override;
+
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
};
class PlaneCornerPinWarpImageOperation : public PlaneDistortWarpImageOperation {
@@ -52,6 +56,7 @@ class PlaneCornerPinWarpImageOperation : public PlaneDistortWarpImageOperation {
public:
PlaneCornerPinWarpImageOperation();
+ void init_data() override;
void initExecution() override;
void deinitExecution() override;
@@ -60,6 +65,8 @@ class PlaneCornerPinWarpImageOperation : public PlaneDistortWarpImageOperation {
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
rcti *output) override;
+
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cc b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cc
index 4edcc206f5b..ccabb3cf11c 100644
--- a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cc
+++ b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cc
@@ -85,8 +85,9 @@ void PlaneDistortWarpImageOperation::calculateCorners(const float corners[4][2],
{
PlaneDistortBaseOperation::calculateCorners(corners, normalized, sample);
- const int width = this->m_pixelReader->getWidth();
- const int height = this->m_pixelReader->getHeight();
+ const NodeOperation *image = get_input_operation(0);
+ const int width = image->getWidth();
+ const int height = image->getHeight();
float frame_corners[4][2] = {
{0.0f, 0.0f}, {(float)width, 0.0f}, {(float)width, (float)height}, {0.0f, (float)height}};
MotionSample *sample_data = &this->m_samples[sample];
@@ -127,6 +128,34 @@ void PlaneDistortWarpImageOperation::executePixelSampled(float output[4],
}
}
+void PlaneDistortWarpImageOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const MemoryBuffer *input_img = inputs[0];
+ float uv[2];
+ float deriv[2][2];
+ BuffersIterator<float> it = output->iterate_with({}, area);
+ if (this->m_motion_blur_samples == 1) {
+ for (; !it.is_end(); ++it) {
+ warpCoord(it.x, it.y, this->m_samples[0].perspectiveMatrix, uv, deriv);
+ input_img->read_elem_filtered(uv[0], uv[1], deriv[0], deriv[1], it.out);
+ }
+ }
+ else {
+ for (; !it.is_end(); ++it) {
+ zero_v4(it.out);
+ for (const int sample : IndexRange(this->m_motion_blur_samples)) {
+ float color[4];
+ warpCoord(it.x, it.y, this->m_samples[sample].perspectiveMatrix, uv, deriv);
+ input_img->read_elem_filtered(uv[0], uv[1], deriv[0], deriv[1], color);
+ add_v4_v4(it.out, color);
+ }
+ mul_v4_fl(it.out, 1.0f / (float)this->m_motion_blur_samples);
+ }
+ }
+}
+
bool PlaneDistortWarpImageOperation::determineDependingAreaOfInterest(
rcti *input, ReadBufferOperation *readOperation, rcti *output)
{
@@ -157,6 +186,51 @@ bool PlaneDistortWarpImageOperation::determineDependingAreaOfInterest(
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+void PlaneDistortWarpImageOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ if (input_idx != 0) {
+ r_input_area = output_area;
+ return;
+ }
+
+ /* TODO: figure out the area needed for warping and EWA filtering. */
+ r_input_area.xmin = 0;
+ r_input_area.ymin = 0;
+ r_input_area.xmax = get_input_operation(0)->getWidth();
+ r_input_area.ymax = get_input_operation(0)->getHeight();
+
+/* Old implementation but resulting coordinates are way out of input operation bounds and in some
+ * cases the area result may incorrectly cause cropping. */
+#if 0
+ float min[2], max[2];
+ INIT_MINMAX2(min, max);
+ for (int sample = 0; sample < this->m_motion_blur_samples; sample++) {
+ float UVs[4][2];
+ float deriv[2][2];
+ MotionSample *sample_data = &this->m_samples[sample];
+ /* TODO(sergey): figure out proper way to do this. */
+ warpCoord(
+ output_area.xmin - 2, output_area.ymin - 2, sample_data->perspectiveMatrix, UVs[0], deriv);
+ warpCoord(
+ output_area.xmax + 2, output_area.ymin - 2, sample_data->perspectiveMatrix, UVs[1], deriv);
+ warpCoord(
+ output_area.xmax + 2, output_area.ymax + 2, sample_data->perspectiveMatrix, UVs[2], deriv);
+ warpCoord(
+ output_area.xmin - 2, output_area.ymax + 2, sample_data->perspectiveMatrix, UVs[3], deriv);
+ for (int i = 0; i < 4; i++) {
+ minmax_v2v2_v2(min, max, UVs[i]);
+ }
+ }
+
+ r_input_area.xmin = min[0] - 1;
+ r_input_area.ymin = min[1] - 1;
+ r_input_area.xmax = max[0] + 1;
+ r_input_area.ymax = max[1] + 1;
+#endif
+}
+
/* ******** PlaneDistort Mask ******** */
PlaneDistortMaskOperation::PlaneDistortMaskOperation() : PlaneDistortBaseOperation()
@@ -219,4 +293,41 @@ void PlaneDistortMaskOperation::executePixelSampled(float output[4],
}
}
+void PlaneDistortMaskOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> UNUSED(inputs))
+{
+ for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
+ int inside_count = 0;
+ for (const int motion_sample : IndexRange(this->m_motion_blur_samples)) {
+ MotionSample &sample = this->m_samples[motion_sample];
+ inside_count += get_jitter_samples_inside_count(it.x, it.y, sample);
+ }
+ *it.out = (float)inside_count / (this->m_osa * this->m_motion_blur_samples);
+ }
+}
+
+int PlaneDistortMaskOperation::get_jitter_samples_inside_count(int x,
+ int y,
+ MotionSample &sample_data)
+{
+ float point[2];
+ int inside_count = 0;
+ for (int sample = 0; sample < this->m_osa; sample++) {
+ point[0] = x + this->m_jitter[sample][0];
+ point[1] = y + this->m_jitter[sample][1];
+ if (isect_point_tri_v2(point,
+ sample_data.frameSpaceCorners[0],
+ sample_data.frameSpaceCorners[1],
+ sample_data.frameSpaceCorners[2]) ||
+ isect_point_tri_v2(point,
+ sample_data.frameSpaceCorners[0],
+ sample_data.frameSpaceCorners[2],
+ sample_data.frameSpaceCorners[3])) {
+ inside_count++;
+ }
+ }
+ return inside_count;
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h
index cc6e4d00d71..3ef9c1dfab8 100644
--- a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h
+++ b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h
@@ -20,7 +20,7 @@
#include <string.h>
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
#include "DNA_movieclip_types.h"
#include "DNA_tracking_types.h"
@@ -32,7 +32,7 @@ namespace blender::compositor {
#define PLANE_DISTORT_MAX_SAMPLES 64
-class PlaneDistortBaseOperation : public NodeOperation {
+class PlaneDistortBaseOperation : public MultiThreadedOperation {
protected:
struct MotionSample {
float frameSpaceCorners[4][2]; /* Corners coordinates in pixel space. */
@@ -78,6 +78,11 @@ class PlaneDistortWarpImageOperation : public PlaneDistortBaseOperation {
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
rcti *output) override;
+
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
class PlaneDistortMaskOperation : public PlaneDistortBaseOperation {
@@ -91,6 +96,13 @@ class PlaneDistortMaskOperation : public PlaneDistortBaseOperation {
void initExecution() override;
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
+
+ private:
+ int get_jitter_samples_inside_count(int x, int y, MotionSample &sample_data);
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_PlaneTrackOperation.cc b/source/blender/compositor/operations/COM_PlaneTrackOperation.cc
index 0884f2ad979..bf24f843ca2 100644
--- a/source/blender/compositor/operations/COM_PlaneTrackOperation.cc
+++ b/source/blender/compositor/operations/COM_PlaneTrackOperation.cc
@@ -101,18 +101,40 @@ void PlaneTrackCommon::determineResolution(unsigned int resolution[2],
/* ******** PlaneTrackMaskOperation ******** */
+void PlaneTrackMaskOperation::init_data()
+{
+ PlaneDistortMaskOperation::init_data();
+ if (execution_model_ == eExecutionModel::FullFrame) {
+ PlaneTrackCommon::read_and_calculate_corners(this);
+ }
+}
+
+/* TODO(manzanilla): to be removed with tiled implementation. */
void PlaneTrackMaskOperation::initExecution()
{
PlaneDistortMaskOperation::initExecution();
- PlaneTrackCommon::read_and_calculate_corners(this);
+ if (execution_model_ == eExecutionModel::Tiled) {
+ PlaneTrackCommon::read_and_calculate_corners(this);
+ }
}
/* ******** PlaneTrackWarpImageOperation ******** */
+void PlaneTrackWarpImageOperation::init_data()
+{
+ PlaneDistortWarpImageOperation::init_data();
+ if (execution_model_ == eExecutionModel::FullFrame) {
+ PlaneTrackCommon::read_and_calculate_corners(this);
+ }
+}
+
+/* TODO(manzanilla): to be removed with tiled implementation. */
void PlaneTrackWarpImageOperation::initExecution()
{
PlaneDistortWarpImageOperation::initExecution();
- PlaneTrackCommon::read_and_calculate_corners(this);
+ if (execution_model_ == eExecutionModel::Tiled) {
+ PlaneTrackCommon::read_and_calculate_corners(this);
+ }
}
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_PlaneTrackOperation.h b/source/blender/compositor/operations/COM_PlaneTrackOperation.h
index 3bae230aa06..d2027755162 100644
--- a/source/blender/compositor/operations/COM_PlaneTrackOperation.h
+++ b/source/blender/compositor/operations/COM_PlaneTrackOperation.h
@@ -73,6 +73,8 @@ class PlaneTrackMaskOperation : public PlaneDistortMaskOperation, public PlaneTr
{
}
+ void init_data() override;
+
void initExecution() override;
void determineResolution(unsigned int resolution[2],
@@ -92,6 +94,8 @@ class PlaneTrackWarpImageOperation : public PlaneDistortWarpImageOperation,
{
}
+ void init_data() override;
+
void initExecution() override;
void determineResolution(unsigned int resolution[2],
diff --git a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cc b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cc
index 93702d3f0cf..fcab5dd5751 100644
--- a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cc
+++ b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cc
@@ -17,6 +17,8 @@
*/
#include "COM_ProjectorLensDistortionOperation.h"
+#include "COM_ConstantOperation.h"
+
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -32,6 +34,20 @@ ProjectorLensDistortionOperation::ProjectorLensDistortionOperation()
this->m_dispersionAvailable = false;
this->m_dispersion = 0.0f;
}
+
+void ProjectorLensDistortionOperation::init_data()
+{
+ if (execution_model_ == eExecutionModel::FullFrame) {
+ NodeOperation *dispersion_input = get_input_operation(1);
+ if (dispersion_input->get_flags().is_constant_operation) {
+ this->m_dispersion =
+ static_cast<ConstantOperation *>(dispersion_input)->get_constant_elem()[0];
+ }
+ this->m_kr = 0.25f * max_ff(min_ff(this->m_dispersion, 1.0f), 0.0f);
+ this->m_kr2 = this->m_kr * 20;
+ }
+}
+
void ProjectorLensDistortionOperation::initExecution()
{
this->initMutex();
@@ -97,6 +113,7 @@ bool ProjectorLensDistortionOperation::determineDependingAreaOfInterest(
return false;
}
+/* TODO(manzanilla): to be removed with tiled implementation. */
void ProjectorLensDistortionOperation::updateDispersion()
{
if (this->m_dispersionAvailable) {
@@ -114,4 +131,41 @@ void ProjectorLensDistortionOperation::updateDispersion()
this->unlockMutex();
}
+void ProjectorLensDistortionOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ if (input_idx == 1) {
+ /* Dispersion input is used as constant only. */
+ r_input_area = COM_SINGLE_ELEM_AREA;
+ return;
+ }
+
+ r_input_area.ymax = output_area.ymax;
+ r_input_area.ymin = output_area.ymin;
+ r_input_area.xmin = output_area.xmin - this->m_kr2 - 2;
+ r_input_area.xmax = output_area.xmax + this->m_kr2 + 2;
+}
+
+void ProjectorLensDistortionOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const MemoryBuffer *input_image = inputs[0];
+ const float height = this->getHeight();
+ const float width = this->getWidth();
+ float color[4];
+ for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
+ const float v = (it.y + 0.5f) / height;
+ const float u = (it.x + 0.5f) / width;
+ input_image->read_elem_bilinear((u * width + this->m_kr2) - 0.5f, v * height - 0.5f, color);
+ it.out[0] = color[0];
+ input_image->read_elem(it.x, it.y, color);
+ it.out[1] = color[1];
+ input_image->read_elem_bilinear((u * width - this->m_kr2) - 0.5f, v * height - 0.5f, color);
+ it.out[2] = color[2];
+ it.out[3] = 1.0f;
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h
index bce61d3de15..7c7626bf271 100644
--- a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h
+++ b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h
@@ -18,12 +18,12 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
#include "DNA_node_types.h"
namespace blender::compositor {
-class ProjectorLensDistortionOperation : public NodeOperation {
+class ProjectorLensDistortionOperation : public MultiThreadedOperation {
private:
/**
* Cached reference to the inputProgram
@@ -31,6 +31,7 @@ class ProjectorLensDistortionOperation : public NodeOperation {
SocketReader *m_inputProgram;
float m_dispersion;
+ /* TODO(manzanilla): to be removed with tiled implementation. */
bool m_dispersionAvailable;
float m_kr, m_kr2;
@@ -43,6 +44,7 @@ class ProjectorLensDistortionOperation : public NodeOperation {
*/
void executePixel(float output[4], int x, int y, void *data) override;
+ void init_data() override;
/**
* Initialize the execution
*/
@@ -59,6 +61,11 @@ class ProjectorLensDistortionOperation : public NodeOperation {
rcti *output) override;
void updateDispersion();
+
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_RotateOperation.cc b/source/blender/compositor/operations/COM_RotateOperation.cc
index 4fb3d324992..e3c482c15cb 100644
--- a/source/blender/compositor/operations/COM_RotateOperation.cc
+++ b/source/blender/compositor/operations/COM_RotateOperation.cc
@@ -17,6 +17,8 @@
*/
#include "COM_RotateOperation.h"
+#include "COM_ConstantOperation.h"
+
#include "BLI_math.h"
namespace blender::compositor {
@@ -31,13 +33,50 @@ RotateOperation::RotateOperation()
this->m_degreeSocket = nullptr;
this->m_doDegree2RadConversion = false;
this->m_isDegreeSet = false;
+ sampler_ = PixelSampler::Bilinear;
+}
+
+void RotateOperation::get_area_rotation_bounds(const rcti &area,
+ const float center_x,
+ const float center_y,
+ const float sine,
+ const float cosine,
+ rcti &r_bounds)
+{
+ const float dxmin = area.xmin - center_x;
+ const float dymin = area.ymin - center_y;
+ const float dxmax = area.xmax - center_x;
+ const float dymax = area.ymax - center_y;
+
+ const float x1 = center_x + (cosine * dxmin + sine * dymin);
+ const float x2 = center_x + (cosine * dxmax + sine * dymin);
+ const float x3 = center_x + (cosine * dxmin + sine * dymax);
+ const float x4 = center_x + (cosine * dxmax + sine * dymax);
+ const float y1 = center_y + (-sine * dxmin + cosine * dymin);
+ const float y2 = center_y + (-sine * dxmax + cosine * dymin);
+ const float y3 = center_y + (-sine * dxmin + cosine * dymax);
+ const float y4 = center_y + (-sine * dxmax + cosine * dymax);
+ const float minx = MIN2(x1, MIN2(x2, MIN2(x3, x4)));
+ const float maxx = MAX2(x1, MAX2(x2, MAX2(x3, x4)));
+ const float miny = MIN2(y1, MIN2(y2, MIN2(y3, y4)));
+ const float maxy = MAX2(y1, MAX2(y2, MAX2(y3, y4)));
+
+ r_bounds.xmin = floor(minx);
+ r_bounds.xmax = ceil(maxx);
+ r_bounds.ymin = floor(miny);
+ r_bounds.ymax = ceil(maxy);
+}
+
+void RotateOperation::init_data()
+{
+ this->m_centerX = (getWidth() - 1) / 2.0;
+ this->m_centerY = (getHeight() - 1) / 2.0;
}
+
void RotateOperation::initExecution()
{
this->m_imageSocket = this->getInputSocketReader(0);
this->m_degreeSocket = this->getInputSocketReader(1);
- this->m_centerX = (getWidth() - 1) / 2.0;
- this->m_centerY = (getHeight() - 1) / 2.0;
}
void RotateOperation::deinitExecution()
@@ -50,7 +89,19 @@ inline void RotateOperation::ensureDegree()
{
if (!this->m_isDegreeSet) {
float degree[4];
- this->m_degreeSocket->readSampled(degree, 0, 0, PixelSampler::Nearest);
+ switch (execution_model_) {
+ case eExecutionModel::Tiled:
+ this->m_degreeSocket->readSampled(degree, 0, 0, PixelSampler::Nearest);
+ break;
+ case eExecutionModel::FullFrame:
+ NodeOperation *degree_op = getInputOperation(DEGREE_INPUT_INDEX);
+ const bool is_constant_degree = degree_op->get_flags().is_constant_operation;
+ degree[0] = is_constant_degree ?
+ static_cast<ConstantOperation *>(degree_op)->get_constant_elem()[0] :
+ 0.0f;
+ break;
+ }
+
double rad;
if (this->m_doDegree2RadConversion) {
rad = DEG2RAD((double)degree[0]);
@@ -108,4 +159,33 @@ bool RotateOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+void RotateOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ if (input_idx == DEGREE_INPUT_INDEX) {
+ /* Degrees input is always used as constant. */
+ r_input_area = COM_SINGLE_ELEM_AREA;
+ return;
+ }
+
+ ensureDegree();
+ get_area_rotation_bounds(output_area, m_centerX, m_centerY, m_sine, m_cosine, r_input_area);
+ expand_area_for_sampler(r_input_area, sampler_);
+}
+
+void RotateOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ ensureDegree();
+ const MemoryBuffer *input_img = inputs[IMAGE_INPUT_INDEX];
+ for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
+ float x = it.x;
+ float y = it.y;
+ rotate_coords(x, y, m_centerX, m_centerY, m_sine, m_cosine);
+ input_img->read_elem_sampled(x, y, sampler_, it.out);
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_RotateOperation.h b/source/blender/compositor/operations/COM_RotateOperation.h
index d76507f9816..f0de699f9ce 100644
--- a/source/blender/compositor/operations/COM_RotateOperation.h
+++ b/source/blender/compositor/operations/COM_RotateOperation.h
@@ -18,12 +18,15 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
-class RotateOperation : public NodeOperation {
+class RotateOperation : public MultiThreadedOperation {
private:
+ constexpr static int IMAGE_INPUT_INDEX = 0;
+ constexpr static int DEGREE_INPUT_INDEX = 1;
+
SocketReader *m_imageSocket;
SocketReader *m_degreeSocket;
float m_centerX;
@@ -32,21 +35,51 @@ class RotateOperation : public NodeOperation {
float m_sine;
bool m_doDegree2RadConversion;
bool m_isDegreeSet;
+ PixelSampler sampler_;
public:
RotateOperation();
+
+ static void rotate_coords(
+ float &x, float &y, float center_x, float center_y, float sine, float cosine)
+ {
+ const float dx = x - center_x;
+ const float dy = y - center_y;
+ x = center_x + (cosine * dx + sine * dy);
+ y = center_y + (-sine * dx + cosine * dy);
+ }
+
+ static void get_area_rotation_bounds(const rcti &area,
+ const float center_x,
+ const float center_y,
+ const float sine,
+ const float cosine,
+ rcti &r_bounds);
+
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
rcti *output) override;
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+ void init_data() override;
void initExecution() override;
void deinitExecution() override;
+
void setDoDegree2RadConversion(bool abool)
{
this->m_doDegree2RadConversion = abool;
}
+ void set_sampler(PixelSampler sampler)
+ {
+ sampler_ = sampler;
+ }
+
void ensureDegree();
+
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ScaleOperation.cc b/source/blender/compositor/operations/COM_ScaleOperation.cc
index 5410b2c832a..ef34bc7bee6 100644
--- a/source/blender/compositor/operations/COM_ScaleOperation.cc
+++ b/source/blender/compositor/operations/COM_ScaleOperation.cc
@@ -74,17 +74,18 @@ float ScaleOperation::get_constant_scale_y()
return get_constant_scale(2, get_relative_scale_y_factor());
}
-BLI_INLINE float scale_coord(const int coord, const float center, const float relative_scale)
+void ScaleOperation::scale_area(
+ rcti &rect, float center_x, float center_y, float scale_x, float scale_y)
{
- return center + (coord - center) / relative_scale;
+ rect.xmin = scale_coord(rect.xmin, center_x, scale_x);
+ rect.xmax = scale_coord(rect.xmax, center_x, scale_x);
+ rect.ymin = scale_coord(rect.ymin, center_y, scale_y);
+ rect.ymax = scale_coord(rect.ymax, center_y, scale_y);
}
void ScaleOperation::scale_area(rcti &rect, float scale_x, float scale_y)
{
- rect.xmin = scale_coord(rect.xmin, m_centerX, scale_x);
- rect.xmax = scale_coord(rect.xmax, m_centerX, scale_x);
- rect.ymin = scale_coord(rect.ymin, m_centerY, scale_y);
- rect.ymax = scale_coord(rect.ymax, m_centerY, scale_y);
+ scale_area(rect, m_centerX, m_centerY, scale_x, scale_y);
}
void ScaleOperation::init_data()
diff --git a/source/blender/compositor/operations/COM_ScaleOperation.h b/source/blender/compositor/operations/COM_ScaleOperation.h
index 62a2cabc8e6..65762d1ce62 100644
--- a/source/blender/compositor/operations/COM_ScaleOperation.h
+++ b/source/blender/compositor/operations/COM_ScaleOperation.h
@@ -46,6 +46,9 @@ class BaseScaleOperation : public MultiThreadedOperation {
};
class ScaleOperation : public BaseScaleOperation {
+ public:
+ static constexpr float MIN_SCALE = 0.0001f;
+
protected:
SocketReader *m_inputOperation;
SocketReader *m_inputXOperation;
@@ -57,6 +60,12 @@ class ScaleOperation : public BaseScaleOperation {
ScaleOperation();
ScaleOperation(DataType data_type);
+ static float scale_coord(const float coord, const float center, const float relative_scale)
+ {
+ return center + (coord - center) / MAX2(relative_scale, MIN_SCALE);
+ }
+ static void scale_area(rcti &rect, float center_x, float center_y, float scale_x, float scale_y);
+
void init_data() override;
void initExecution() override;
void deinitExecution() override;
diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cc b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cc
index 634fe66b0dd..1f503051349 100644
--- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cc
+++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cc
@@ -17,6 +17,7 @@
*/
#include "COM_ScreenLensDistortionOperation.h"
+#include "COM_ConstantOperation.h"
#include "BLI_math.h"
#include "BLI_rand.h"
@@ -53,6 +54,35 @@ void ScreenLensDistortionOperation::setDispersion(float dispersion)
m_dispersion_const = true;
}
+void ScreenLensDistortionOperation::init_data()
+{
+ this->m_cx = 0.5f * (float)getWidth();
+ this->m_cy = 0.5f * (float)getHeight();
+
+ switch (execution_model_) {
+ case eExecutionModel::FullFrame: {
+ NodeOperation *distortion_op = get_input_operation(1);
+ NodeOperation *dispersion_op = get_input_operation(2);
+ if (!m_distortion_const && distortion_op->get_flags().is_constant_operation) {
+ m_distortion = static_cast<ConstantOperation *>(distortion_op)->get_constant_elem()[0];
+ }
+ if (!m_dispersion_const && distortion_op->get_flags().is_constant_operation) {
+ m_dispersion = static_cast<ConstantOperation *>(dispersion_op)->get_constant_elem()[0];
+ }
+ updateVariables(m_distortion, m_dispersion);
+ break;
+ }
+ case eExecutionModel::Tiled: {
+ /* If both are constant, init variables once. */
+ if (m_distortion_const && m_dispersion_const) {
+ updateVariables(m_distortion, m_dispersion);
+ m_variables_ready = true;
+ }
+ break;
+ }
+ }
+}
+
void ScreenLensDistortionOperation::initExecution()
{
this->m_inputProgram = this->getInputSocketReader(0);
@@ -61,15 +91,6 @@ void ScreenLensDistortionOperation::initExecution()
uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
rng_seed ^= (uint)POINTER_AS_INT(m_inputProgram);
this->m_rng = BLI_rng_new(rng_seed);
-
- this->m_cx = 0.5f * (float)getWidth();
- this->m_cy = 0.5f * (float)getHeight();
-
- /* if both are constant, init variables once */
- if (m_distortion_const && m_dispersion_const) {
- updateVariables(m_distortion, m_dispersion);
- m_variables_ready = true;
- }
}
void *ScreenLensDistortionOperation::initializeTileData(rcti * /*rect*/)
@@ -130,7 +151,7 @@ bool ScreenLensDistortionOperation::get_delta(float r_sq,
return false;
}
-void ScreenLensDistortionOperation::accumulate(MemoryBuffer *buffer,
+void ScreenLensDistortionOperation::accumulate(const MemoryBuffer *buffer,
int a,
int b,
float r_sq,
@@ -154,7 +175,14 @@ void ScreenLensDistortionOperation::accumulate(MemoryBuffer *buffer,
float xy[2];
distort_uv(uv, t, xy);
- buffer->readBilinear(color, xy[0], xy[1]);
+ switch (execution_model_) {
+ case eExecutionModel::Tiled:
+ buffer->readBilinear(color, xy[0], xy[1]);
+ break;
+ case eExecutionModel::FullFrame:
+ buffer->read_elem_bilinear(xy[0], xy[1], color);
+ break;
+ }
sum[a] += (1.0f - tz) * color[a];
sum[b] += (tz)*color[b];
@@ -354,4 +382,143 @@ void ScreenLensDistortionOperation::updateVariables(float distortion, float disp
mul_v3_v3fl(m_k4, m_k, 4.0f);
}
+void ScreenLensDistortionOperation::get_area_of_interest(const int input_idx,
+ const rcti &UNUSED(output_area),
+ rcti &r_input_area)
+{
+ if (input_idx != 0) {
+ /* Dispersion and distortion inputs are used as constants only. */
+ r_input_area = COM_SINGLE_ELEM_AREA;
+ }
+
+ /* XXX the original method of estimating the area-of-interest does not work
+ * it assumes a linear increase/decrease of mapped coordinates, which does not
+ * yield correct results for the area and leaves uninitialized buffer areas.
+ * So now just use the full image area, which may not be as efficient but works at least ...
+ */
+#if 1
+ NodeOperation *image = getInputOperation(0);
+ r_input_area.xmax = image->getWidth();
+ r_input_area.xmin = 0;
+ r_input_area.ymax = image->getHeight();
+ r_input_area.ymin = 0;
+
+#else /* Original method in tiled implementation. */
+ rcti newInput;
+ const float margin = 2;
+
+ BLI_rcti_init_minmax(&newInput);
+
+ if (m_dispersion_const && m_distortion_const) {
+ /* update from fixed distortion/dispersion */
+# define UPDATE_INPUT(x, y) \
+ { \
+ float coords[6]; \
+ determineUV(coords, x, y); \
+ newInput.xmin = min_ffff(newInput.xmin, coords[0], coords[2], coords[4]); \
+ newInput.ymin = min_ffff(newInput.ymin, coords[1], coords[3], coords[5]); \
+ newInput.xmax = max_ffff(newInput.xmax, coords[0], coords[2], coords[4]); \
+ newInput.ymax = max_ffff(newInput.ymax, coords[1], coords[3], coords[5]); \
+ } \
+ (void)0
+
+ UPDATE_INPUT(input->xmin, input->xmax);
+ UPDATE_INPUT(input->xmin, input->ymax);
+ UPDATE_INPUT(input->xmax, input->ymax);
+ UPDATE_INPUT(input->xmax, input->ymin);
+
+# undef UPDATE_INPUT
+ }
+ else {
+ /* use maximum dispersion 1.0 if not const */
+ float dispersion = m_dispersion_const ? m_dispersion : 1.0f;
+
+# define UPDATE_INPUT(x, y, distortion) \
+ { \
+ float coords[6]; \
+ updateVariables(distortion, dispersion); \
+ determineUV(coords, x, y); \
+ newInput.xmin = min_ffff(newInput.xmin, coords[0], coords[2], coords[4]); \
+ newInput.ymin = min_ffff(newInput.ymin, coords[1], coords[3], coords[5]); \
+ newInput.xmax = max_ffff(newInput.xmax, coords[0], coords[2], coords[4]); \
+ newInput.ymax = max_ffff(newInput.ymax, coords[1], coords[3], coords[5]); \
+ } \
+ (void)0
+
+ if (m_distortion_const) {
+ /* update from fixed distortion */
+ UPDATE_INPUT(input->xmin, input->xmax, m_distortion);
+ UPDATE_INPUT(input->xmin, input->ymax, m_distortion);
+ UPDATE_INPUT(input->xmax, input->ymax, m_distortion);
+ UPDATE_INPUT(input->xmax, input->ymin, m_distortion);
+ }
+ else {
+ /* update from min/max distortion (-1..1) */
+ UPDATE_INPUT(input->xmin, input->xmax, -1.0f);
+ UPDATE_INPUT(input->xmin, input->ymax, -1.0f);
+ UPDATE_INPUT(input->xmax, input->ymax, -1.0f);
+ UPDATE_INPUT(input->xmax, input->ymin, -1.0f);
+
+ UPDATE_INPUT(input->xmin, input->xmax, 1.0f);
+ UPDATE_INPUT(input->xmin, input->ymax, 1.0f);
+ UPDATE_INPUT(input->xmax, input->ymax, 1.0f);
+ UPDATE_INPUT(input->xmax, input->ymin, 1.0f);
+
+# undef UPDATE_INPUT
+ }
+ }
+
+ newInput.xmin -= margin;
+ newInput.ymin -= margin;
+ newInput.xmax += margin;
+ newInput.ymax += margin;
+
+ operation = getInputOperation(0);
+ if (operation->determineDependingAreaOfInterest(&newInput, readOperation, output)) {
+ return true;
+ }
+ return false;
+#endif
+}
+
+void ScreenLensDistortionOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const MemoryBuffer *input_image = inputs[0];
+ for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
+ float xy[2] = {(float)it.x, (float)it.y};
+ float uv[2];
+ get_uv(xy, uv);
+ const float uv_dot = len_squared_v2(uv);
+
+ float delta[3][2];
+ const bool valid_r = get_delta(uv_dot, m_k4[0], uv, delta[0]);
+ const bool valid_g = get_delta(uv_dot, m_k4[1], uv, delta[1]);
+ const bool valid_b = get_delta(uv_dot, m_k4[2], uv, delta[2]);
+ if (!(valid_r && valid_g && valid_b)) {
+ zero_v4(it.out);
+ continue;
+ }
+
+ int count[3] = {0, 0, 0};
+ float sum[4] = {0, 0, 0, 0};
+ accumulate(input_image, 0, 1, uv_dot, uv, delta, sum, count);
+ accumulate(input_image, 1, 2, uv_dot, uv, delta, sum, count);
+
+ if (count[0]) {
+ it.out[0] = 2.0f * sum[0] / (float)count[0];
+ }
+ if (count[1]) {
+ it.out[1] = 2.0f * sum[1] / (float)count[1];
+ }
+ if (count[2]) {
+ it.out[2] = 2.0f * sum[2] / (float)count[2];
+ }
+
+ /* Set alpha. */
+ it.out[3] = 1.0f;
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h
index 98872bfe142..616fc8883b0 100644
--- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h
+++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h
@@ -18,14 +18,14 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
#include "DNA_node_types.h"
struct RNG;
namespace blender::compositor {
-class ScreenLensDistortionOperation : public NodeOperation {
+class ScreenLensDistortionOperation : public MultiThreadedOperation {
private:
/**
* Cached reference to the inputProgram
@@ -50,6 +50,8 @@ class ScreenLensDistortionOperation : public NodeOperation {
public:
ScreenLensDistortionOperation();
+ void init_data() override;
+
/**
* The inner loop of this operation.
*/
@@ -84,6 +86,11 @@ class ScreenLensDistortionOperation : public NodeOperation {
ReadBufferOperation *readOperation,
rcti *output) override;
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
+
private:
void determineUV(float result[6], float x, float y) const;
void updateVariables(float distortion, float dispersion);
@@ -91,7 +98,7 @@ class ScreenLensDistortionOperation : public NodeOperation {
void get_uv(const float xy[2], float uv[2]) const;
void distort_uv(const float uv[2], float t, float xy[2]) const;
bool get_delta(float r_sq, float k4, const float uv[2], float delta[2]) const;
- void accumulate(MemoryBuffer *buffer,
+ void accumulate(const MemoryBuffer *buffer,
int a,
int b,
float r_sq,
diff --git a/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.cc b/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.cc
index 24edbc61d40..e4686ffa76d 100644
--- a/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.cc
+++ b/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.cc
@@ -28,6 +28,7 @@ SetAlphaMultiplyOperation::SetAlphaMultiplyOperation()
this->m_inputColor = nullptr;
this->m_inputAlpha = nullptr;
+ this->flags.can_be_constant = true;
}
void SetAlphaMultiplyOperation::initExecution()
@@ -56,4 +57,15 @@ void SetAlphaMultiplyOperation::deinitExecution()
this->m_inputAlpha = nullptr;
}
+void SetAlphaMultiplyOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const float *color = it.in(0);
+ const float alpha = *it.in(1);
+ mul_v4_v4fl(it.out, color, alpha);
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.h b/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.h
index b4eea659fa2..44885318901 100644
--- a/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.h
+++ b/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
@@ -27,7 +27,7 @@ namespace blender::compositor {
*
* `output color.rgba = input color.rgba * input alpha`
*/
-class SetAlphaMultiplyOperation : public NodeOperation {
+class SetAlphaMultiplyOperation : public MultiThreadedOperation {
private:
SocketReader *m_inputColor;
SocketReader *m_inputAlpha;
@@ -39,6 +39,10 @@ class SetAlphaMultiplyOperation : public NodeOperation {
void initExecution() override;
void deinitExecution() override;
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.cc b/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.cc
index 90bfc814b09..434f5d9b63c 100644
--- a/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.cc
+++ b/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.cc
@@ -28,6 +28,7 @@ SetAlphaReplaceOperation::SetAlphaReplaceOperation()
this->m_inputColor = nullptr;
this->m_inputAlpha = nullptr;
+ this->flags.can_be_constant = true;
}
void SetAlphaReplaceOperation::initExecution()
@@ -54,4 +55,16 @@ void SetAlphaReplaceOperation::deinitExecution()
this->m_inputAlpha = nullptr;
}
+void SetAlphaReplaceOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const float *color = it.in(0);
+ const float alpha = *it.in(1);
+ copy_v3_v3(it.out, color);
+ it.out[3] = alpha;
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.h b/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.h
index c84299b6d82..2c2d4cddf5b 100644
--- a/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.h
+++ b/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
@@ -26,7 +26,7 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
-class SetAlphaReplaceOperation : public NodeOperation {
+class SetAlphaReplaceOperation : public MultiThreadedOperation {
private:
SocketReader *m_inputColor;
SocketReader *m_inputAlpha;
@@ -44,6 +44,10 @@ class SetAlphaReplaceOperation : public NodeOperation {
void initExecution() override;
void deinitExecution() override;
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_TransformOperation.cc b/source/blender/compositor/operations/COM_TransformOperation.cc
new file mode 100644
index 00000000000..2feaa0ae16d
--- /dev/null
+++ b/source/blender/compositor/operations/COM_TransformOperation.cc
@@ -0,0 +1,156 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#include "COM_TransformOperation.h"
+#include "COM_ConstantOperation.h"
+#include "COM_RotateOperation.h"
+#include "COM_ScaleOperation.h"
+
+#include "BLI_math.h"
+
+namespace blender::compositor {
+
+TransformOperation::TransformOperation()
+{
+ addInputSocket(DataType::Color);
+ addInputSocket(DataType::Value);
+ addInputSocket(DataType::Value);
+ addInputSocket(DataType::Value);
+ addInputSocket(DataType::Value);
+ addOutputSocket(DataType::Color);
+ translate_factor_x_ = 1.0f;
+ translate_factor_y_ = 1.0f;
+ convert_degree_to_rad_ = false;
+ sampler_ = PixelSampler::Bilinear;
+ invert_ = false;
+}
+
+void TransformOperation::init_data()
+{
+ /* Translation. */
+ translate_x_ = 0;
+ NodeOperation *x_op = getInputOperation(X_INPUT_INDEX);
+ if (x_op->get_flags().is_constant_operation) {
+ translate_x_ = static_cast<ConstantOperation *>(x_op)->get_constant_elem()[0] *
+ translate_factor_x_;
+ }
+ translate_y_ = 0;
+ NodeOperation *y_op = getInputOperation(Y_INPUT_INDEX);
+ if (y_op->get_flags().is_constant_operation) {
+ translate_y_ = static_cast<ConstantOperation *>(y_op)->get_constant_elem()[0] *
+ translate_factor_y_;
+ }
+
+ /* Scaling. */
+ scale_center_x_ = getWidth() / 2.0;
+ scale_center_y_ = getHeight() / 2.0;
+ constant_scale_ = 1.0f;
+ NodeOperation *scale_op = getInputOperation(SCALE_INPUT_INDEX);
+ if (scale_op->get_flags().is_constant_operation) {
+ constant_scale_ = static_cast<ConstantOperation *>(scale_op)->get_constant_elem()[0];
+ }
+
+ /* Rotation. */
+ rotate_center_x_ = (getWidth() - 1.0) / 2.0;
+ rotate_center_y_ = (getHeight() - 1.0) / 2.0;
+ NodeOperation *degree_op = getInputOperation(DEGREE_INPUT_INDEX);
+ const bool is_constant_degree = degree_op->get_flags().is_constant_operation;
+ const float degree = is_constant_degree ?
+ static_cast<ConstantOperation *>(degree_op)->get_constant_elem()[0] :
+ 0.0f;
+ const double rad = convert_degree_to_rad_ ? DEG2RAD((double)degree) : degree;
+ rotate_cosine_ = cos(rad);
+ rotate_sine_ = sin(rad);
+}
+
+void TransformOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ switch (input_idx) {
+ case IMAGE_INPUT_INDEX: {
+ BLI_rcti_translate(&r_input_area, translate_x_, translate_y_);
+ ScaleOperation::scale_area(
+ r_input_area, scale_center_x_, scale_center_y_, constant_scale_, constant_scale_);
+ RotateOperation::get_area_rotation_bounds(r_input_area,
+ rotate_center_x_,
+ rotate_center_y_,
+ rotate_sine_,
+ rotate_cosine_,
+ r_input_area);
+ expand_area_for_sampler(r_input_area, sampler_);
+ break;
+ }
+ case X_INPUT_INDEX:
+ case Y_INPUT_INDEX:
+ case DEGREE_INPUT_INDEX: {
+ r_input_area = COM_SINGLE_ELEM_AREA;
+ break;
+ }
+ case SCALE_INPUT_INDEX: {
+ r_input_area = output_area;
+ break;
+ }
+ }
+}
+
+void TransformOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const MemoryBuffer *input_img = inputs[IMAGE_INPUT_INDEX];
+ MemoryBuffer *input_scale = inputs[SCALE_INPUT_INDEX];
+ BuffersIterator<float> it = output->iterate_with({input_scale}, area);
+ if (invert_) {
+ transform_inverted(it, input_img);
+ }
+ else {
+ transform(it, input_img);
+ }
+}
+
+void TransformOperation::transform(BuffersIterator<float> &it, const MemoryBuffer *input_img)
+{
+ for (; !it.is_end(); ++it) {
+ const float scale = *it.in(0);
+ float x = it.x - translate_x_;
+ float y = it.y - translate_y_;
+ RotateOperation::rotate_coords(
+ x, y, rotate_center_x_, rotate_center_y_, rotate_sine_, rotate_cosine_);
+ x = ScaleOperation::scale_coord(x, scale_center_x_, scale);
+ y = ScaleOperation::scale_coord(y, scale_center_y_, scale);
+ input_img->read_elem_sampled(x, y, sampler_, it.out);
+ }
+}
+
+void TransformOperation::transform_inverted(BuffersIterator<float> &it,
+ const MemoryBuffer *input_img)
+{
+ for (; !it.is_end(); ++it) {
+ const float scale = *it.in(0);
+ float x = ScaleOperation::scale_coord(it.x, scale_center_x_, scale);
+ float y = ScaleOperation::scale_coord(it.y, scale_center_y_, scale);
+ RotateOperation::rotate_coords(
+ x, y, rotate_center_x_, rotate_center_y_, rotate_sine_, rotate_cosine_);
+ x -= translate_x_;
+ y -= translate_y_;
+ input_img->read_elem_sampled(x, y, sampler_, it.out);
+ }
+}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_TransformOperation.h b/source/blender/compositor/operations/COM_TransformOperation.h
new file mode 100644
index 00000000000..480998a0207
--- /dev/null
+++ b/source/blender/compositor/operations/COM_TransformOperation.h
@@ -0,0 +1,87 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#pragma once
+
+#include "COM_MultiThreadedOperation.h"
+
+namespace blender::compositor {
+
+class TransformOperation : public MultiThreadedOperation {
+ private:
+ constexpr static int IMAGE_INPUT_INDEX = 0;
+ constexpr static int X_INPUT_INDEX = 1;
+ constexpr static int Y_INPUT_INDEX = 2;
+ constexpr static int DEGREE_INPUT_INDEX = 3;
+ constexpr static int SCALE_INPUT_INDEX = 4;
+
+ float scale_center_x_;
+ float scale_center_y_;
+ float rotate_center_x_;
+ float rotate_center_y_;
+ float rotate_cosine_;
+ float rotate_sine_;
+ float translate_x_;
+ float translate_y_;
+ float constant_scale_;
+
+ /* Set variables. */
+ PixelSampler sampler_;
+ bool convert_degree_to_rad_;
+ float translate_factor_x_;
+ float translate_factor_y_;
+ bool invert_;
+
+ public:
+ TransformOperation();
+
+ void set_translate_factor_xy(float x, float y)
+ {
+ translate_factor_x_ = x;
+ translate_factor_y_ = y;
+ }
+
+ void set_convert_rotate_degree_to_rad(bool value)
+ {
+ convert_degree_to_rad_ = value;
+ }
+
+ void set_sampler(PixelSampler sampler)
+ {
+ sampler_ = sampler;
+ }
+
+ void set_invert(bool value)
+ {
+ invert_ = value;
+ }
+
+ void init_data() override;
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
+
+ private:
+ /** Translate -> Rotate -> Scale. */
+ void transform(BuffersIterator<float> &it, const MemoryBuffer *input_img);
+ /** Scale -> Rotate -> Translate. */
+ void transform_inverted(BuffersIterator<float> &it, const MemoryBuffer *input_img);
+};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cc b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cc
index 19cd5a53084..6af6f5a6244 100644
--- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cc
@@ -18,6 +18,7 @@
#include "COM_VariableSizeBokehBlurOperation.h"
#include "BLI_math.h"
+#include "COM_ExecutionSystem.h"
#include "COM_OpenCLDevice.h"
#include "RE_pipeline.h"
@@ -276,6 +277,166 @@ bool VariableSizeBokehBlurOperation::determineDependingAreaOfInterest(
return false;
}
+void VariableSizeBokehBlurOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ switch (input_idx) {
+ case IMAGE_INPUT_INDEX:
+ case SIZE_INPUT_INDEX: {
+ const float max_dim = MAX2(getWidth(), getHeight());
+ const float scalar = m_do_size_scale ? (max_dim / 100.0f) : 1.0f;
+ const int max_blur_scalar = m_maxBlur * scalar;
+ r_input_area.xmax = output_area.xmax + max_blur_scalar + 2;
+ r_input_area.xmin = output_area.xmin - max_blur_scalar - 2;
+ r_input_area.ymax = output_area.ymax + max_blur_scalar + 2;
+ r_input_area.ymin = output_area.ymin - max_blur_scalar - 2;
+ break;
+ }
+ case BOKEH_INPUT_INDEX: {
+ r_input_area.xmax = COM_BLUR_BOKEH_PIXELS;
+ r_input_area.xmin = 0;
+ r_input_area.ymax = COM_BLUR_BOKEH_PIXELS;
+ r_input_area.ymin = 0;
+ break;
+ }
+#ifdef COM_DEFOCUS_SEARCH
+ case DEFOCUS_INPUT_INDEX: {
+ r_input_area.xmax = (output_area.xmax / InverseSearchRadiusOperation::DIVIDER) + 1;
+ r_input_area.xmin = (output_area.xmin / InverseSearchRadiusOperation::DIVIDER) - 1;
+ r_input_area.ymax = (output_area.ymax / InverseSearchRadiusOperation::DIVIDER) + 1;
+ r_input_area.ymin = (output_area.ymin / InverseSearchRadiusOperation::DIVIDER) - 1;
+ break;
+ }
+#endif
+ }
+}
+
+struct PixelData {
+ float multiplier_accum[4];
+ float color_accum[4];
+ float threshold;
+ float scalar;
+ float size_center;
+ int max_blur_scalar;
+ int step;
+ MemoryBuffer *bokeh_input;
+ MemoryBuffer *size_input;
+ MemoryBuffer *image_input;
+ int image_width;
+ int image_height;
+};
+
+static void blur_pixel(int x, int y, PixelData &p)
+{
+ BLI_assert(p.bokeh_input->getWidth() == COM_BLUR_BOKEH_PIXELS);
+ BLI_assert(p.bokeh_input->getHeight() == COM_BLUR_BOKEH_PIXELS);
+
+#ifdef COM_DEFOCUS_SEARCH
+ float search[4];
+ inputs[DEFOCUS_INPUT_INDEX]->read_elem_checked(x / InverseSearchRadiusOperation::DIVIDER,
+ y / InverseSearchRadiusOperation::DIVIDER,
+ search);
+ const int minx = search[0];
+ const int miny = search[1];
+ const int maxx = search[2];
+ const int maxy = search[3];
+#else
+ const int minx = MAX2(x - p.max_blur_scalar, 0);
+ const int miny = MAX2(y - p.max_blur_scalar, 0);
+ const int maxx = MIN2(x + p.max_blur_scalar, p.image_width);
+ const int maxy = MIN2(y + p.max_blur_scalar, p.image_height);
+#endif
+
+ const int color_row_stride = p.image_input->row_stride * p.step;
+ const int color_elem_stride = p.image_input->elem_stride * p.step;
+ const int size_row_stride = p.size_input->row_stride * p.step;
+ const int size_elem_stride = p.size_input->elem_stride * p.step;
+ const float *row_color = p.image_input->get_elem(minx, miny);
+ const float *row_size = p.size_input->get_elem(minx, miny);
+ for (int ny = miny; ny < maxy;
+ ny += p.step, row_size += size_row_stride, row_color += color_row_stride) {
+ const float dy = ny - y;
+ const float *size_elem = row_size;
+ const float *color = row_color;
+ for (int nx = minx; nx < maxx;
+ nx += p.step, size_elem += size_elem_stride, color += color_elem_stride) {
+ if (nx == x && ny == y) {
+ continue;
+ }
+ const float size = MIN2(size_elem[0] * p.scalar, p.size_center);
+ if (size <= p.threshold) {
+ continue;
+ }
+ const float dx = nx - x;
+ if (size <= fabsf(dx) || size <= fabsf(dy)) {
+ continue;
+ }
+
+ /* XXX: There is no way to ensure bokeh input is an actual bokeh with #COM_BLUR_BOKEH_PIXELS
+ * size, anything may be connected. Use the real input size and remove asserts? */
+ const float u = (float)(COM_BLUR_BOKEH_PIXELS / 2) +
+ (dx / size) * (float)((COM_BLUR_BOKEH_PIXELS / 2) - 1);
+ const float v = (float)(COM_BLUR_BOKEH_PIXELS / 2) +
+ (dy / size) * (float)((COM_BLUR_BOKEH_PIXELS / 2) - 1);
+ float bokeh[4];
+ p.bokeh_input->read_elem_checked(u, v, bokeh);
+ madd_v4_v4v4(p.color_accum, bokeh, color);
+ add_v4_v4(p.multiplier_accum, bokeh);
+ }
+ }
+}
+
+void VariableSizeBokehBlurOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ PixelData p;
+ p.bokeh_input = inputs[BOKEH_INPUT_INDEX];
+ p.size_input = inputs[SIZE_INPUT_INDEX];
+ p.image_input = inputs[IMAGE_INPUT_INDEX];
+ p.step = QualityStepHelper::getStep();
+ p.threshold = m_threshold;
+ p.image_width = this->getWidth();
+ p.image_height = this->getHeight();
+
+ rcti scalar_area;
+ this->get_area_of_interest(SIZE_INPUT_INDEX, area, scalar_area);
+ BLI_rcti_isect(&scalar_area, &p.size_input->get_rect(), &scalar_area);
+ const float max_size = p.size_input->get_max_value(scalar_area);
+
+ const float max_dim = MAX2(this->getWidth(), this->getHeight());
+ p.scalar = m_do_size_scale ? (max_dim / 100.0f) : 1.0f;
+ p.max_blur_scalar = static_cast<int>(max_size * p.scalar);
+ CLAMP(p.max_blur_scalar, 1, m_maxBlur);
+
+ for (BuffersIterator<float> it = output->iterate_with({p.image_input, p.size_input}, area);
+ !it.is_end();
+ ++it) {
+ const float *color = it.in(0);
+ const float size = *it.in(1);
+ copy_v4_v4(p.color_accum, color);
+ copy_v4_fl(p.multiplier_accum, 1.0f);
+ p.size_center = size * p.scalar;
+
+ if (p.size_center > p.threshold) {
+ blur_pixel(it.x, it.y, p);
+ }
+
+ it.out[0] = p.color_accum[0] / p.multiplier_accum[0];
+ it.out[1] = p.color_accum[1] / p.multiplier_accum[1];
+ it.out[2] = p.color_accum[2] / p.multiplier_accum[2];
+ it.out[3] = p.color_accum[3] / p.multiplier_accum[3];
+
+ /* Blend in out values over the threshold, otherwise we get sharp, ugly transitions. */
+ if ((p.size_center > p.threshold) && (p.size_center < p.threshold * 2.0f)) {
+ /* Factor from 0-1. */
+ const float fac = (p.size_center - p.threshold) / p.threshold;
+ interp_v4_v4v4(it.out, color, it.out, fac);
+ }
+ }
+}
+
#ifdef COM_DEFOCUS_SEARCH
// InverseSearchRadiusOperation
InverseSearchRadiusOperation::InverseSearchRadiusOperation()
diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h
index baeab6a646e..56b4677087b 100644
--- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h
+++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h
@@ -18,15 +18,22 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
#include "COM_QualityStepHelper.h"
namespace blender::compositor {
//#define COM_DEFOCUS_SEARCH
-class VariableSizeBokehBlurOperation : public NodeOperation, public QualityStepHelper {
+class VariableSizeBokehBlurOperation : public MultiThreadedOperation, public QualityStepHelper {
private:
+ static constexpr int IMAGE_INPUT_INDEX = 0;
+ static constexpr int BOKEH_INPUT_INDEX = 1;
+ static constexpr int SIZE_INPUT_INDEX = 2;
+#ifdef COM_DEFOCUS_SEARCH
+ static constexpr int DEFOCUS_INPUT_INDEX = 3;
+#endif
+
int m_maxBlur;
float m_threshold;
bool m_do_size_scale; /* scale size, matching 'BokehBlurNode' */
@@ -84,8 +91,14 @@ class VariableSizeBokehBlurOperation : public NodeOperation, public QualityStepH
MemoryBuffer **inputMemoryBuffers,
std::list<cl_mem> *clMemToCleanUp,
std::list<cl_kernel> *clKernelsToCleanUp) override;
+
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
+/* Currently unused. If ever used, it needs full-frame implementation. */
#ifdef COM_DEFOCUS_SEARCH
class InverseSearchRadiusOperation : public NodeOperation {
private:
diff --git a/source/blender/draw/engines/image/image_engine.c b/source/blender/draw/engines/image/image_engine.c
index 395d50fbc6b..b4c0ade380e 100644
--- a/source/blender/draw/engines/image/image_engine.c
+++ b/source/blender/draw/engines/image/image_engine.c
@@ -111,35 +111,52 @@ static void space_image_gpu_texture_get(Image *image,
/* Update multi-index and pass for the current eye. */
BKE_image_multilayer_index(image->rr, &sima->iuser);
}
- BKE_image_multiview_index(image, &sima->iuser);
+ else {
+ BKE_image_multiview_index(image, &sima->iuser);
+ }
- if (ibuf) {
- const int sima_flag = sima->flag & ED_space_image_get_display_channel_mask(ibuf);
- if (sima_flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) {
- if (ibuf->zbuf) {
- BLI_assert_msg(0, "Integer based depth buffers not supported");
- }
- else if (ibuf->zbuf_float) {
- *r_gpu_texture = GPU_texture_create_2d(
- __func__, ibuf->x, ibuf->y, 0, GPU_R16F, ibuf->zbuf_float);
- *r_owns_texture = true;
- }
- else if (ibuf->rect_float && ibuf->channels == 1) {
- *r_gpu_texture = GPU_texture_create_2d(
- __func__, ibuf->x, ibuf->y, 0, GPU_R16F, ibuf->rect_float);
- *r_owns_texture = true;
- }
+ if (ibuf == NULL) {
+ return;
+ }
+
+ if (ibuf->rect == NULL && ibuf->rect_float == NULL) {
+ /* This codepath is only supposed to happen when drawing a lazily-allocatable render result.
+ * In all the other cases the `ED_space_image_acquire_buffer()` is expected to return NULL as
+ * an image buffer when it has no pixels. */
+
+ BLI_assert(image->type == IMA_TYPE_R_RESULT);
+
+ float zero[4] = {0, 0, 0, 0};
+ *r_gpu_texture = GPU_texture_create_2d(__func__, 1, 1, 0, GPU_RGBA16F, zero);
+ *r_owns_texture = true;
+ return;
+ }
+
+ const int sima_flag = sima->flag & ED_space_image_get_display_channel_mask(ibuf);
+ if (sima_flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) {
+ if (ibuf->zbuf) {
+ BLI_assert_msg(0, "Integer based depth buffers not supported");
}
- else if (image->source == IMA_SRC_TILED) {
- *r_gpu_texture = BKE_image_get_gpu_tiles(image, iuser, ibuf);
- *r_tex_tile_data = BKE_image_get_gpu_tilemap(image, iuser, NULL);
- *r_owns_texture = false;
+ else if (ibuf->zbuf_float) {
+ *r_gpu_texture = GPU_texture_create_2d(
+ __func__, ibuf->x, ibuf->y, 0, GPU_R16F, ibuf->zbuf_float);
+ *r_owns_texture = true;
}
- else {
- *r_gpu_texture = BKE_image_get_gpu_texture(image, iuser, ibuf);
- *r_owns_texture = false;
+ else if (ibuf->rect_float && ibuf->channels == 1) {
+ *r_gpu_texture = GPU_texture_create_2d(
+ __func__, ibuf->x, ibuf->y, 0, GPU_R16F, ibuf->rect_float);
+ *r_owns_texture = true;
}
}
+ else if (image->source == IMA_SRC_TILED) {
+ *r_gpu_texture = BKE_image_get_gpu_tiles(image, iuser, ibuf);
+ *r_tex_tile_data = BKE_image_get_gpu_tilemap(image, iuser, NULL);
+ *r_owns_texture = false;
+ }
+ else {
+ *r_gpu_texture = BKE_image_get_gpu_texture(image, iuser, ibuf);
+ *r_owns_texture = false;
+ }
}
static void space_node_gpu_texture_get(Image *image,
diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index 2a9080eb217..04d90919a20 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -864,7 +864,6 @@ typedef union OVERLAY_CameraInstanceData {
static void camera_view3d_reconstruction(OVERLAY_ExtraCallBuffers *cb,
Scene *scene,
View3D *v3d,
- Object *camera_object,
Object *ob,
const float color[4])
{
@@ -943,7 +942,7 @@ static void camera_view3d_reconstruction(OVERLAY_ExtraCallBuffers *cb,
}
if (is_select) {
- DRW_select_load_id(camera_object->runtime.select_id | (track_index << 16));
+ DRW_select_load_id(ob->runtime.select_id | (track_index << 16));
track_index++;
}
@@ -1251,7 +1250,7 @@ void OVERLAY_camera_cache_populate(OVERLAY_Data *vedata, Object *ob)
/* Motion Tracking. */
if ((v3d->flag2 & V3D_SHOW_RECONSTRUCTION) != 0) {
- camera_view3d_reconstruction(cb, scene, v3d, camera_object, ob, color_p);
+ camera_view3d_reconstruction(cb, scene, v3d, ob, color_p);
}
/* Background images. */
diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h
index 7dc468d1a73..db96d6a774f 100644
--- a/source/blender/draw/intern/draw_cache_extract.h
+++ b/source/blender/draw/intern/draw_cache_extract.h
@@ -101,7 +101,7 @@ BLI_INLINE int mesh_render_mat_len_get(const Mesh *me)
return MAX2(1, me->totcol);
}
-typedef struct MeshBufferCache {
+typedef struct MeshBufferList {
/* Every VBO below contains at least enough
* data for every loops in the mesh (except fdots and skin roots).
* For some VBOs, it extends to (in this exact order) :
@@ -152,16 +152,91 @@ typedef struct MeshBufferCache {
GPUIndexBuf *edituv_points;
GPUIndexBuf *edituv_fdots;
} ibo;
- /* Index buffer per material. These are subranges of `ibo.tris` */
- GPUIndexBuf **tris_per_mat;
-} MeshBufferCache;
+} MeshBufferList;
+
+typedef struct MeshBatchList {
+ /* Surfaces / Render */
+ GPUBatch *surface;
+ GPUBatch *surface_weights;
+ /* Edit mode */
+ GPUBatch *edit_triangles;
+ GPUBatch *edit_vertices;
+ GPUBatch *edit_edges;
+ GPUBatch *edit_vnor;
+ GPUBatch *edit_lnor;
+ GPUBatch *edit_fdots;
+ GPUBatch *edit_mesh_analysis;
+ GPUBatch *edit_skin_roots;
+ /* Edit UVs */
+ GPUBatch *edituv_faces_stretch_area;
+ GPUBatch *edituv_faces_stretch_angle;
+ GPUBatch *edituv_faces;
+ GPUBatch *edituv_edges;
+ GPUBatch *edituv_verts;
+ GPUBatch *edituv_fdots;
+ /* Edit selection */
+ GPUBatch *edit_selection_verts;
+ GPUBatch *edit_selection_edges;
+ GPUBatch *edit_selection_faces;
+ GPUBatch *edit_selection_fdots;
+ /* Common display / Other */
+ GPUBatch *all_verts;
+ GPUBatch *all_edges;
+ GPUBatch *loose_edges;
+ GPUBatch *edge_detection;
+ GPUBatch *wire_edges; /* Individual edges with face normals. */
+ GPUBatch *wire_loops; /* Loops around faces. no edges between selected faces */
+ GPUBatch *wire_loops_uvs; /* Same as wire_loops but only has uvs. */
+ GPUBatch *sculpt_overlays;
+} MeshBatchList;
+
+#define MBC_BATCH_LEN (sizeof(MeshBatchList) / sizeof(void *))
+#define MBC_VBO_LEN (sizeof(((MeshBufferList){0}).vbo) / sizeof(void *))
+#define MBC_IBO_LEN (sizeof(((MeshBufferList){0}).ibo) / sizeof(void *))
+
+#define MBC_BATCH_INDEX(batch) (offsetof(MeshBatchList, batch) / sizeof(void *))
+
+typedef enum DRWBatchFlag {
+ MBC_SURFACE = (1u << MBC_BATCH_INDEX(surface)),
+ MBC_SURFACE_WEIGHTS = (1u << MBC_BATCH_INDEX(surface_weights)),
+ MBC_EDIT_TRIANGLES = (1u << MBC_BATCH_INDEX(edit_triangles)),
+ MBC_EDIT_VERTICES = (1u << MBC_BATCH_INDEX(edit_vertices)),
+ MBC_EDIT_EDGES = (1u << MBC_BATCH_INDEX(edit_edges)),
+ MBC_EDIT_VNOR = (1u << MBC_BATCH_INDEX(edit_vnor)),
+ MBC_EDIT_LNOR = (1u << MBC_BATCH_INDEX(edit_lnor)),
+ MBC_EDIT_FACEDOTS = (1u << MBC_BATCH_INDEX(edit_fdots)),
+ MBC_EDIT_MESH_ANALYSIS = (1u << MBC_BATCH_INDEX(edit_mesh_analysis)),
+ MBC_SKIN_ROOTS = (1u << MBC_BATCH_INDEX(edit_skin_roots)),
+ MBC_EDITUV_FACES_STRETCH_AREA = (1u << MBC_BATCH_INDEX(edituv_faces_stretch_area)),
+ MBC_EDITUV_FACES_STRETCH_ANGLE = (1u << MBC_BATCH_INDEX(edituv_faces_stretch_angle)),
+ MBC_EDITUV_FACES = (1u << MBC_BATCH_INDEX(edituv_faces)),
+ MBC_EDITUV_EDGES = (1u << MBC_BATCH_INDEX(edituv_edges)),
+ MBC_EDITUV_VERTS = (1u << MBC_BATCH_INDEX(edituv_verts)),
+ MBC_EDITUV_FACEDOTS = (1u << MBC_BATCH_INDEX(edituv_fdots)),
+ MBC_EDIT_SELECTION_VERTS = (1u << MBC_BATCH_INDEX(edit_selection_verts)),
+ MBC_EDIT_SELECTION_EDGES = (1u << MBC_BATCH_INDEX(edit_selection_edges)),
+ MBC_EDIT_SELECTION_FACES = (1u << MBC_BATCH_INDEX(edit_selection_faces)),
+ MBC_EDIT_SELECTION_FACEDOTS = (1u << MBC_BATCH_INDEX(edit_selection_fdots)),
+ MBC_ALL_VERTS = (1u << MBC_BATCH_INDEX(all_verts)),
+ MBC_ALL_EDGES = (1u << MBC_BATCH_INDEX(all_edges)),
+ MBC_LOOSE_EDGES = (1u << MBC_BATCH_INDEX(loose_edges)),
+ MBC_EDGE_DETECTION = (1u << MBC_BATCH_INDEX(edge_detection)),
+ MBC_WIRE_EDGES = (1u << MBC_BATCH_INDEX(wire_edges)),
+ MBC_WIRE_LOOPS = (1u << MBC_BATCH_INDEX(wire_loops)),
+ MBC_WIRE_LOOPS_UVS = (1u << MBC_BATCH_INDEX(wire_loops_uvs)),
+ MBC_SCULPT_OVERLAYS = (1u << MBC_BATCH_INDEX(sculpt_overlays)),
+} DRWBatchFlag;
+
+BLI_STATIC_ASSERT(MBC_BATCH_LEN < 32, "Number of batches exceeded the limit of bit fields");
/**
* Data that are kept around between extractions to reduce rebuilding time.
*
* - Loose geometry.
*/
-typedef struct MeshBufferExtractionCache {
+typedef struct MeshBufferCache {
+ MeshBufferList buff;
+
struct {
int edge_len;
int vert_len;
@@ -174,7 +249,7 @@ typedef struct MeshBufferExtractionCache {
int *mat_tri_len;
int visible_tri_len;
} poly_sorted;
-} MeshBufferExtractionCache;
+} MeshBufferCache;
#define FOREACH_MESH_BUFFER_CACHE(batch_cache, mbc) \
for (MeshBufferCache *mbc = &batch_cache->final; \
@@ -186,50 +261,15 @@ typedef struct MeshBufferExtractionCache {
typedef struct MeshBatchCache {
MeshBufferCache final, cage, uv_cage;
- MeshBufferExtractionCache final_extraction_cache;
- MeshBufferExtractionCache cage_extraction_cache;
- MeshBufferExtractionCache uv_cage_extraction_cache;
+ MeshBatchList batch;
- struct {
- /* Surfaces / Render */
- GPUBatch *surface;
- GPUBatch *surface_weights;
- /* Edit mode */
- GPUBatch *edit_triangles;
- GPUBatch *edit_vertices;
- GPUBatch *edit_edges;
- GPUBatch *edit_vnor;
- GPUBatch *edit_lnor;
- GPUBatch *edit_fdots;
- GPUBatch *edit_mesh_analysis;
- GPUBatch *edit_skin_roots;
- /* Edit UVs */
- GPUBatch *edituv_faces_stretch_area;
- GPUBatch *edituv_faces_stretch_angle;
- GPUBatch *edituv_faces;
- GPUBatch *edituv_edges;
- GPUBatch *edituv_verts;
- GPUBatch *edituv_fdots;
- /* Edit selection */
- GPUBatch *edit_selection_verts;
- GPUBatch *edit_selection_edges;
- GPUBatch *edit_selection_faces;
- GPUBatch *edit_selection_fdots;
- /* Common display / Other */
- GPUBatch *all_verts;
- GPUBatch *all_edges;
- GPUBatch *loose_edges;
- GPUBatch *edge_detection;
- GPUBatch *wire_edges; /* Individual edges with face normals. */
- GPUBatch *wire_loops; /* Loops around faces. no edges between selected faces */
- GPUBatch *wire_loops_uvs; /* Same as wire_loops but only has uvs. */
- GPUBatch *sculpt_overlays;
- } batch;
+ /* Index buffer per material. These are subranges of `ibo.tris` */
+ GPUIndexBuf **tris_per_mat;
GPUBatch **surface_per_mat;
- uint32_t batch_requested; /* DRWBatchFlag */
- uint32_t batch_ready; /* DRWBatchFlag */
+ DRWBatchFlag batch_requested; /* DRWBatchFlag */
+ DRWBatchFlag batch_ready; /* DRWBatchFlag */
/* settings to determine if cache is invalid */
int edge_len;
@@ -259,55 +299,13 @@ typedef struct MeshBatchCache {
bool no_loose_wire;
} MeshBatchCache;
-#define MBC_BATCH_LEN (sizeof(((MeshBatchCache){0}).batch) / sizeof(void *))
-#define MBC_VBO_LEN (sizeof(((MeshBufferCache){0}).vbo) / sizeof(void *))
-#define MBC_IBO_LEN (sizeof(((MeshBufferCache){0}).ibo) / sizeof(void *))
-
-#define MBC_BATCH_INDEX(batch_name) \
- ((offsetof(MeshBatchCache, batch_name) - offsetof(MeshBatchCache, batch)) / sizeof(void *))
-
-typedef enum DRWBatchFlag {
- MBC_SURFACE = (1u << MBC_BATCH_INDEX(batch.surface)),
- MBC_SURFACE_WEIGHTS = (1u << MBC_BATCH_INDEX(batch.surface_weights)),
- MBC_EDIT_TRIANGLES = (1u << MBC_BATCH_INDEX(batch.edit_triangles)),
- MBC_EDIT_VERTICES = (1u << MBC_BATCH_INDEX(batch.edit_vertices)),
- MBC_EDIT_EDGES = (1u << MBC_BATCH_INDEX(batch.edit_edges)),
- MBC_EDIT_VNOR = (1u << MBC_BATCH_INDEX(batch.edit_vnor)),
- MBC_EDIT_LNOR = (1u << MBC_BATCH_INDEX(batch.edit_lnor)),
- MBC_EDIT_FACEDOTS = (1u << MBC_BATCH_INDEX(batch.edit_fdots)),
- MBC_EDIT_MESH_ANALYSIS = (1u << MBC_BATCH_INDEX(batch.edit_mesh_analysis)),
- MBC_SKIN_ROOTS = (1u << MBC_BATCH_INDEX(batch.edit_skin_roots)),
- MBC_EDITUV_FACES_STRETCH_AREA = (1u << MBC_BATCH_INDEX(batch.edituv_faces_stretch_area)),
- MBC_EDITUV_FACES_STRETCH_ANGLE = (1u << MBC_BATCH_INDEX(batch.edituv_faces_stretch_angle)),
- MBC_EDITUV_FACES = (1u << MBC_BATCH_INDEX(batch.edituv_faces)),
- MBC_EDITUV_EDGES = (1u << MBC_BATCH_INDEX(batch.edituv_edges)),
- MBC_EDITUV_VERTS = (1u << MBC_BATCH_INDEX(batch.edituv_verts)),
- MBC_EDITUV_FACEDOTS = (1u << MBC_BATCH_INDEX(batch.edituv_fdots)),
- MBC_EDIT_SELECTION_VERTS = (1u << MBC_BATCH_INDEX(batch.edit_selection_verts)),
- MBC_EDIT_SELECTION_EDGES = (1u << MBC_BATCH_INDEX(batch.edit_selection_edges)),
- MBC_EDIT_SELECTION_FACES = (1u << MBC_BATCH_INDEX(batch.edit_selection_faces)),
- MBC_EDIT_SELECTION_FACEDOTS = (1u << MBC_BATCH_INDEX(batch.edit_selection_fdots)),
- MBC_ALL_VERTS = (1u << MBC_BATCH_INDEX(batch.all_verts)),
- MBC_ALL_EDGES = (1u << MBC_BATCH_INDEX(batch.all_edges)),
- MBC_LOOSE_EDGES = (1u << MBC_BATCH_INDEX(batch.loose_edges)),
- MBC_EDGE_DETECTION = (1u << MBC_BATCH_INDEX(batch.edge_detection)),
- MBC_WIRE_EDGES = (1u << MBC_BATCH_INDEX(batch.wire_edges)),
- MBC_WIRE_LOOPS = (1u << MBC_BATCH_INDEX(batch.wire_loops)),
- MBC_WIRE_LOOPS_UVS = (1u << MBC_BATCH_INDEX(batch.wire_loops_uvs)),
- MBC_SCULPT_OVERLAYS = (1u << MBC_BATCH_INDEX(batch.sculpt_overlays)),
-} DRWBatchFlag;
-
-BLI_STATIC_ASSERT(MBC_BATCH_INDEX(surface_per_mat) < 32,
- "Number of batches exceeded the limit of bit fields");
-
#define MBC_EDITUV \
(MBC_EDITUV_FACES_STRETCH_AREA | MBC_EDITUV_FACES_STRETCH_ANGLE | MBC_EDITUV_FACES | \
MBC_EDITUV_EDGES | MBC_EDITUV_VERTS | MBC_EDITUV_FACEDOTS | MBC_WIRE_LOOPS_UVS)
void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
- MeshBatchCache *cache,
- MeshBufferCache *mbc,
- MeshBufferExtractionCache *extraction_cache,
+ MeshBatchCache *mbc,
+ MeshBufferCache *extraction_cache,
Mesh *me,
const bool is_editmode,
const bool is_paint_mode,
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc
index 1bc2b8a9def..06c449fe590 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh.cc
+++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc
@@ -162,7 +162,7 @@ struct ExtractTaskData {
const MeshRenderData *mr = nullptr;
MeshBatchCache *cache = nullptr;
ExtractorRunDatas *extractors = nullptr;
- MeshBufferCache *mbc = nullptr;
+ MeshBufferList *mbuflist = nullptr;
eMRIterType iter_type;
bool use_threading = false;
@@ -170,9 +170,13 @@ struct ExtractTaskData {
ExtractTaskData(const MeshRenderData *mr,
struct MeshBatchCache *cache,
ExtractorRunDatas *extractors,
- MeshBufferCache *mbc,
+ MeshBufferList *mbuflist,
const bool use_threading)
- : mr(mr), cache(cache), extractors(extractors), mbc(mbc), use_threading(use_threading)
+ : mr(mr),
+ cache(cache),
+ extractors(extractors),
+ mbuflist(mbuflist),
+ use_threading(use_threading)
{
iter_type = extractors->iter_types();
};
@@ -204,13 +208,13 @@ static void extract_task_data_free(void *data)
BLI_INLINE void extract_init(const MeshRenderData *mr,
struct MeshBatchCache *cache,
ExtractorRunDatas &extractors,
- MeshBufferCache *mbc,
+ MeshBufferList *mbuflist,
void *data_stack)
{
uint32_t data_offset = 0;
for (ExtractorRunData &run_data : extractors) {
const MeshExtract *extractor = run_data.extractor;
- run_data.buffer = mesh_extract_buffer_get(extractor, mbc);
+ run_data.buffer = mesh_extract_buffer_get(extractor, mbuflist);
run_data.data_offset = data_offset;
extractor->init(mr, cache, run_data.buffer, POINTER_OFFSET(data_stack, data_offset));
data_offset += (uint32_t)extractor->data_size;
@@ -445,7 +449,7 @@ static void extract_task_range_run(void *__restrict taskdata)
settings.func_reduce = extract_task_reduce;
settings.min_iter_per_thread = MIN_RANGE_LEN;
- extract_init(data->mr, data->cache, *data->extractors, data->mbc, userdata_chunk);
+ extract_init(data->mr, data->cache, *data->extractors, data->mbuflist, userdata_chunk);
if (iter_type & MR_ITER_LOOPTRI) {
extract_task_range_run_iter(data->mr, data->extractors, MR_ITER_LOOPTRI, is_mesh, &settings);
@@ -474,10 +478,10 @@ static struct TaskNode *extract_task_node_create(struct TaskGraph *task_graph,
const MeshRenderData *mr,
MeshBatchCache *cache,
ExtractorRunDatas *extractors,
- MeshBufferCache *mbc,
+ MeshBufferList *mbuflist,
const bool use_threading)
{
- ExtractTaskData *taskdata = new ExtractTaskData(mr, cache, extractors, mbc, use_threading);
+ ExtractTaskData *taskdata = new ExtractTaskData(mr, cache, extractors, mbuflist, use_threading);
struct TaskNode *task_node = BLI_task_graph_node_create(
task_graph,
extract_task_range_run,
@@ -493,12 +497,12 @@ static struct TaskNode *extract_task_node_create(struct TaskGraph *task_graph,
* \{ */
struct MeshRenderDataUpdateTaskData {
MeshRenderData *mr = nullptr;
- MeshBufferExtractionCache *cache = nullptr;
+ MeshBufferCache *cache = nullptr;
eMRIterType iter_type;
eMRDataType data_flag;
MeshRenderDataUpdateTaskData(MeshRenderData *mr,
- MeshBufferExtractionCache *cache,
+ MeshBufferCache *cache,
eMRIterType iter_type,
eMRDataType data_flag)
: mr(mr), cache(cache), iter_type(iter_type), data_flag(data_flag)
@@ -538,7 +542,7 @@ static void mesh_extract_render_data_node_exec(void *__restrict task_data)
static struct TaskNode *mesh_extract_render_data_node_create(struct TaskGraph *task_graph,
MeshRenderData *mr,
- MeshBufferExtractionCache *cache,
+ MeshBufferCache *cache,
const eMRIterType iter_type,
const eMRDataType data_flag)
{
@@ -562,7 +566,6 @@ static struct TaskNode *mesh_extract_render_data_node_create(struct TaskGraph *t
static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
MeshBatchCache *cache,
MeshBufferCache *mbc,
- MeshBufferExtractionCache *extraction_cache,
Mesh *me,
const bool is_editmode,
@@ -613,9 +616,11 @@ static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
/* Create an array containing all the extractors that needs to be executed. */
ExtractorRunDatas extractors;
+ MeshBufferList *mbuflist = &mbc->buff;
+
#define EXTRACT_ADD_REQUESTED(type, name) \
do { \
- if (DRW_##type##_requested(mbc->type.name)) { \
+ if (DRW_##type##_requested(mbuflist->type.name)) { \
const MeshExtract *extractor = mesh_extract_override_get( \
&extract_##name, do_hq_normals, override_single_mat); \
extractors.append(extractor); \
@@ -647,19 +652,19 @@ static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
EXTRACT_ADD_REQUESTED(vbo, skin_roots);
EXTRACT_ADD_REQUESTED(ibo, tris);
- if (DRW_ibo_requested(mbc->ibo.lines_loose)) {
+ if (DRW_ibo_requested(mbuflist->ibo.lines_loose)) {
/* `ibo.lines_loose` require the `ibo.lines` buffer. */
- if (mbc->ibo.lines == nullptr) {
- DRW_ibo_request(nullptr, &mbc->ibo.lines);
+ if (mbuflist->ibo.lines == nullptr) {
+ DRW_ibo_request(nullptr, &mbuflist->ibo.lines);
}
- const MeshExtract *extractor = DRW_ibo_requested(mbc->ibo.lines) ?
+ const MeshExtract *extractor = DRW_ibo_requested(mbuflist->ibo.lines) ?
&extract_lines_with_lines_loose :
&extract_lines_loose_only;
extractors.append(extractor);
}
- else if (DRW_ibo_requested(mbc->ibo.lines)) {
+ else if (DRW_ibo_requested(mbuflist->ibo.lines)) {
const MeshExtract *extractor;
- if (mbc->ibo.lines_loose != nullptr) {
+ if (mbuflist->ibo.lines_loose != nullptr) {
/* Update `ibo.lines_loose` as it depends on `ibo.lines`. */
extractor = &extract_lines_with_lines_loose;
}
@@ -701,7 +706,7 @@ static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
eMRDataType data_flag = extractors.data_types();
struct TaskNode *task_node_mesh_render_data = mesh_extract_render_data_node_create(
- task_graph, mr, extraction_cache, iter_type, data_flag);
+ task_graph, mr, mbc, iter_type, data_flag);
/* Simple heuristic. */
const bool use_thread = (mr->loop_len + mr->loop_loose_len) > MIN_RANGE_LEN;
@@ -714,7 +719,7 @@ static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
ExtractorRunDatas *single_threaded_extractors = new ExtractorRunDatas();
single_threaded_extractors->append(extractor);
struct TaskNode *task_node = extract_task_node_create(
- task_graph, mr, cache, single_threaded_extractors, mbc, false);
+ task_graph, mr, cache, single_threaded_extractors, mbuflist, false);
BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
}
@@ -725,7 +730,7 @@ static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
extractors.filter_threaded_extractors_into(*multi_threaded_extractors);
if (!multi_threaded_extractors->is_empty()) {
struct TaskNode *task_node = extract_task_node_create(
- task_graph, mr, cache, multi_threaded_extractors, mbc, true);
+ task_graph, mr, cache, multi_threaded_extractors, mbuflist, true);
BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
}
@@ -738,7 +743,7 @@ static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
/* Run all requests on the same thread. */
ExtractorRunDatas *extractors_copy = new ExtractorRunDatas(extractors);
struct TaskNode *task_node = extract_task_node_create(
- task_graph, mr, cache, extractors_copy, mbc, false);
+ task_graph, mr, cache, extractors_copy, mbuflist, false);
BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
}
@@ -776,7 +781,6 @@ extern "C" {
void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
MeshBatchCache *cache,
MeshBufferCache *mbc,
- MeshBufferExtractionCache *extraction_cache,
Mesh *me,
const bool is_editmode,
@@ -793,7 +797,6 @@ void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
blender::draw::mesh_buffer_cache_create_requested(task_graph,
cache,
mbc,
- extraction_cache,
me,
is_editmode,
is_paint_mode,
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c
index 27fd6ca9134..abfbeabef6b 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c
+++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c
@@ -45,17 +45,15 @@
* \{ */
static void mesh_render_data_lverts_bm(const MeshRenderData *mr,
- MeshBufferExtractionCache *cache,
+ MeshBufferCache *cache,
BMesh *bm);
static void mesh_render_data_ledges_bm(const MeshRenderData *mr,
- MeshBufferExtractionCache *cache,
+ MeshBufferCache *cache,
BMesh *bm);
-static void mesh_render_data_loose_geom_mesh(const MeshRenderData *mr,
- MeshBufferExtractionCache *cache);
-static void mesh_render_data_loose_geom_build(const MeshRenderData *mr,
- MeshBufferExtractionCache *cache);
+static void mesh_render_data_loose_geom_mesh(const MeshRenderData *mr, MeshBufferCache *cache);
+static void mesh_render_data_loose_geom_build(const MeshRenderData *mr, MeshBufferCache *cache);
-static void mesh_render_data_loose_geom_load(MeshRenderData *mr, MeshBufferExtractionCache *cache)
+static void mesh_render_data_loose_geom_load(MeshRenderData *mr, MeshBufferCache *cache)
{
mr->ledges = cache->loose_geom.edges;
mr->lverts = cache->loose_geom.verts;
@@ -65,8 +63,7 @@ static void mesh_render_data_loose_geom_load(MeshRenderData *mr, MeshBufferExtra
mr->loop_loose_len = mr->vert_loose_len + (mr->edge_loose_len * 2);
}
-static void mesh_render_data_loose_geom_ensure(const MeshRenderData *mr,
- MeshBufferExtractionCache *cache)
+static void mesh_render_data_loose_geom_ensure(const MeshRenderData *mr, MeshBufferCache *cache)
{
/* Early exit: Are loose geometry already available.
* Only checking for loose verts as loose edges and verts are calculated at the same time. */
@@ -76,8 +73,7 @@ static void mesh_render_data_loose_geom_ensure(const MeshRenderData *mr,
mesh_render_data_loose_geom_build(mr, cache);
}
-static void mesh_render_data_loose_geom_build(const MeshRenderData *mr,
- MeshBufferExtractionCache *cache)
+static void mesh_render_data_loose_geom_build(const MeshRenderData *mr, MeshBufferCache *cache)
{
cache->loose_geom.vert_len = 0;
cache->loose_geom.edge_len = 0;
@@ -94,8 +90,7 @@ static void mesh_render_data_loose_geom_build(const MeshRenderData *mr,
}
}
-static void mesh_render_data_loose_geom_mesh(const MeshRenderData *mr,
- MeshBufferExtractionCache *cache)
+static void mesh_render_data_loose_geom_mesh(const MeshRenderData *mr, MeshBufferCache *cache)
{
BLI_bitmap *lvert_map = BLI_BITMAP_NEW(mr->vert_len, __func__);
@@ -128,9 +123,7 @@ static void mesh_render_data_loose_geom_mesh(const MeshRenderData *mr,
MEM_freeN(lvert_map);
}
-static void mesh_render_data_lverts_bm(const MeshRenderData *mr,
- MeshBufferExtractionCache *cache,
- BMesh *bm)
+static void mesh_render_data_lverts_bm(const MeshRenderData *mr, MeshBufferCache *cache, BMesh *bm)
{
int elem_id;
BMIter iter;
@@ -147,9 +140,7 @@ static void mesh_render_data_lverts_bm(const MeshRenderData *mr,
}
}
-static void mesh_render_data_ledges_bm(const MeshRenderData *mr,
- MeshBufferExtractionCache *cache,
- BMesh *bm)
+static void mesh_render_data_ledges_bm(const MeshRenderData *mr, MeshBufferCache *cache, BMesh *bm)
{
int elem_id;
BMIter iter;
@@ -167,7 +158,7 @@ static void mesh_render_data_ledges_bm(const MeshRenderData *mr,
}
void mesh_render_data_update_loose_geom(MeshRenderData *mr,
- MeshBufferExtractionCache *cache,
+ MeshBufferCache *cache,
const eMRIterType iter_type,
const eMRDataType data_flag)
{
@@ -185,16 +176,13 @@ void mesh_render_data_update_loose_geom(MeshRenderData *mr,
* Contains polygon indices sorted based on their material.
*
* \{ */
-static void mesh_render_data_polys_sorted_load(MeshRenderData *mr,
- const MeshBufferExtractionCache *cache);
-static void mesh_render_data_polys_sorted_ensure(MeshRenderData *mr,
- MeshBufferExtractionCache *cache);
-static void mesh_render_data_polys_sorted_build(MeshRenderData *mr,
- MeshBufferExtractionCache *cache);
+static void mesh_render_data_polys_sorted_load(MeshRenderData *mr, const MeshBufferCache *cache);
+static void mesh_render_data_polys_sorted_ensure(MeshRenderData *mr, MeshBufferCache *cache);
+static void mesh_render_data_polys_sorted_build(MeshRenderData *mr, MeshBufferCache *cache);
static int *mesh_render_data_mat_tri_len_build(MeshRenderData *mr);
void mesh_render_data_update_polys_sorted(MeshRenderData *mr,
- MeshBufferExtractionCache *cache,
+ MeshBufferCache *cache,
const eMRDataType data_flag)
{
if (data_flag & MR_DATA_POLYS_SORTED) {
@@ -203,16 +191,14 @@ void mesh_render_data_update_polys_sorted(MeshRenderData *mr,
}
}
-static void mesh_render_data_polys_sorted_load(MeshRenderData *mr,
- const MeshBufferExtractionCache *cache)
+static void mesh_render_data_polys_sorted_load(MeshRenderData *mr, const MeshBufferCache *cache)
{
mr->poly_sorted.tri_first_index = cache->poly_sorted.tri_first_index;
mr->poly_sorted.mat_tri_len = cache->poly_sorted.mat_tri_len;
mr->poly_sorted.visible_tri_len = cache->poly_sorted.visible_tri_len;
}
-static void mesh_render_data_polys_sorted_ensure(MeshRenderData *mr,
- MeshBufferExtractionCache *cache)
+static void mesh_render_data_polys_sorted_ensure(MeshRenderData *mr, MeshBufferCache *cache)
{
if (cache->poly_sorted.tri_first_index) {
return;
@@ -220,8 +206,7 @@ static void mesh_render_data_polys_sorted_ensure(MeshRenderData *mr,
mesh_render_data_polys_sorted_build(mr, cache);
}
-static void mesh_render_data_polys_sorted_build(MeshRenderData *mr,
- MeshBufferExtractionCache *cache)
+static void mesh_render_data_polys_sorted_build(MeshRenderData *mr, MeshBufferCache *cache)
{
int *tri_first_index = MEM_mallocN(sizeof(*tri_first_index) * mr->poly_len, __func__);
int *mat_tri_len = mesh_render_data_mat_tri_len_build(mr);
@@ -584,7 +569,7 @@ void mesh_render_data_free(MeshRenderData *mr)
MEM_SAFE_FREE(mr->mlooptri);
MEM_SAFE_FREE(mr->loop_normals);
- /* Loose geometry are owned by #MeshBufferExtractionCache. */
+ /* Loose geometry are owned by #MeshBufferCache. */
mr->ledges = NULL;
mr->lverts = NULL;
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 52b76733b78..18664498d00 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -79,39 +79,42 @@
/* clang-format off */
-#define _BUFFER_INDEX(buff_name) ((offsetof(MeshBufferCache, buff_name) - offsetof(MeshBufferCache, vbo)) / sizeof(void *))
-
-#define _MDEPS_CREATE1(b) (1u << MBC_BATCH_INDEX(b))
-#define _MDEPS_CREATE2(b1, b2) _MDEPS_CREATE1(b1) | _MDEPS_CREATE1(b2)
-#define _MDEPS_CREATE3(b1, b2, b3) _MDEPS_CREATE2(b1, b2) | _MDEPS_CREATE1(b3)
-#define _MDEPS_CREATE4(b1, b2, b3, b4) _MDEPS_CREATE3(b1, b2, b3) | _MDEPS_CREATE1(b4)
-#define _MDEPS_CREATE5(b1, b2, b3, b4, b5) _MDEPS_CREATE4(b1, b2, b3, b4) | _MDEPS_CREATE1(b5)
-#define _MDEPS_CREATE6(b1, b2, b3, b4, b5, b6) _MDEPS_CREATE5(b1, b2, b3, b4, b5) | _MDEPS_CREATE1(b6)
-#define _MDEPS_CREATE7(b1, b2, b3, b4, b5, b6, b7) _MDEPS_CREATE6(b1, b2, b3, b4, b5, b6) | _MDEPS_CREATE1(b7)
-#define _MDEPS_CREATE8(b1, b2, b3, b4, b5, b6, b7, b8) _MDEPS_CREATE7(b1, b2, b3, b4, b5, b6, b7) | _MDEPS_CREATE1(b8)
-#define _MDEPS_CREATE9(b1, b2, b3, b4, b5, b6, b7, b8, b9) _MDEPS_CREATE8(b1, b2, b3, b4, b5, b6, b7, b8) | _MDEPS_CREATE1(b9)
-#define _MDEPS_CREATE10(b1, b2, b3, b4, b5, b6, b7, b8, b9, b10) _MDEPS_CREATE9(b1, b2, b3, b4, b5, b6, b7, b8, b9) | _MDEPS_CREATE1(b10)
-#define _MDEPS_CREATE19(b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17, b18, b19) _MDEPS_CREATE10(b1, b2, b3, b4, b5, b6, b7, b8, b9, b10) | _MDEPS_CREATE9(b11, b12, b13, b14, b15, b16, b17, b18, b19)
-
-#define MDEPS_CREATE(buff_name, ...) [_BUFFER_INDEX(buff_name)] = VA_NARGS_CALL_OVERLOAD(_MDEPS_CREATE, __VA_ARGS__)
-
-#define _MDEPS_CREATE_MAP1(a) g_buffer_deps[_BUFFER_INDEX(a)]
-#define _MDEPS_CREATE_MAP2(a, b) _MDEPS_CREATE_MAP1(a) | _MDEPS_CREATE_MAP1(b)
-#define _MDEPS_CREATE_MAP3(a, b, c) _MDEPS_CREATE_MAP2(a, b) | _MDEPS_CREATE_MAP1(c)
-#define _MDEPS_CREATE_MAP4(a, b, c, d) _MDEPS_CREATE_MAP3(a, b, c) | _MDEPS_CREATE_MAP1(d)
-#define _MDEPS_CREATE_MAP5(a, b, c, d, e) _MDEPS_CREATE_MAP4(a, b, c, d) | _MDEPS_CREATE_MAP1(e)
-#define _MDEPS_CREATE_MAP6(a, b, c, d, e, f) _MDEPS_CREATE_MAP5(a, b, c, d, e) | _MDEPS_CREATE_MAP1(f)
-#define _MDEPS_CREATE_MAP7(a, b, c, d, e, f, g) _MDEPS_CREATE_MAP6(a, b, c, d, e, f) | _MDEPS_CREATE_MAP1(g)
-#define _MDEPS_CREATE_MAP8(a, b, c, d, e, f, g, h) _MDEPS_CREATE_MAP7(a, b, c, d, e, f, g) | _MDEPS_CREATE_MAP1(h)
-#define _MDEPS_CREATE_MAP9(a, b, c, d, e, f, g, h, i) _MDEPS_CREATE_MAP8(a, b, c, d, e, f, g, h) | _MDEPS_CREATE_MAP1(i)
-#define _MDEPS_CREATE_MAP10(a, b, c, d, e, f, g, h, i, j) _MDEPS_CREATE_MAP9(a, b, c, d, e, f, g, h, i) | _MDEPS_CREATE_MAP1(j)
-
-#define MDEPS_CREATE_MAP(...) VA_NARGS_CALL_OVERLOAD(_MDEPS_CREATE_MAP, __VA_ARGS__)
+#define BUFFER_INDEX(buff_name) ((offsetof(MeshBufferList, buff_name) - offsetof(MeshBufferList, vbo)) / sizeof(void *))
+#define BUFFER_LEN (sizeof(MeshBufferList) / sizeof(void *))
+
+#define _BATCH_FLAG1(b) (1u << MBC_BATCH_INDEX(b))
+#define _BATCH_FLAG2(b1, b2) _BATCH_FLAG1(b1) | _BATCH_FLAG1(b2)
+#define _BATCH_FLAG3(b1, b2, b3) _BATCH_FLAG2(b1, b2) | _BATCH_FLAG1(b3)
+#define _BATCH_FLAG4(b1, b2, b3, b4) _BATCH_FLAG3(b1, b2, b3) | _BATCH_FLAG1(b4)
+#define _BATCH_FLAG5(b1, b2, b3, b4, b5) _BATCH_FLAG4(b1, b2, b3, b4) | _BATCH_FLAG1(b5)
+#define _BATCH_FLAG6(b1, b2, b3, b4, b5, b6) _BATCH_FLAG5(b1, b2, b3, b4, b5) | _BATCH_FLAG1(b6)
+#define _BATCH_FLAG7(b1, b2, b3, b4, b5, b6, b7) _BATCH_FLAG6(b1, b2, b3, b4, b5, b6) | _BATCH_FLAG1(b7)
+#define _BATCH_FLAG8(b1, b2, b3, b4, b5, b6, b7, b8) _BATCH_FLAG7(b1, b2, b3, b4, b5, b6, b7) | _BATCH_FLAG1(b8)
+#define _BATCH_FLAG9(b1, b2, b3, b4, b5, b6, b7, b8, b9) _BATCH_FLAG8(b1, b2, b3, b4, b5, b6, b7, b8) | _BATCH_FLAG1(b9)
+#define _BATCH_FLAG10(b1, b2, b3, b4, b5, b6, b7, b8, b9, b10) _BATCH_FLAG9(b1, b2, b3, b4, b5, b6, b7, b8, b9) | _BATCH_FLAG1(b10)
+#define _BATCH_FLAG18(b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17, b18) _BATCH_FLAG10(b1, b2, b3, b4, b5, b6, b7, b8, b9, b10) | _BATCH_FLAG8(b11, b12, b13, b14, b15, b16, b17, b18)
+
+#define BATCH_FLAG(...) VA_NARGS_CALL_OVERLOAD(_BATCH_FLAG, __VA_ARGS__)
+
+#define _BATCH_MAP1(a) g_buffer_deps[BUFFER_INDEX(a)]
+#define _BATCH_MAP2(a, b) _BATCH_MAP1(a) | _BATCH_MAP1(b)
+#define _BATCH_MAP3(a, b, c) _BATCH_MAP2(a, b) | _BATCH_MAP1(c)
+#define _BATCH_MAP4(a, b, c, d) _BATCH_MAP3(a, b, c) | _BATCH_MAP1(d)
+#define _BATCH_MAP5(a, b, c, d, e) _BATCH_MAP4(a, b, c, d) | _BATCH_MAP1(e)
+#define _BATCH_MAP6(a, b, c, d, e, f) _BATCH_MAP5(a, b, c, d, e) | _BATCH_MAP1(f)
+#define _BATCH_MAP7(a, b, c, d, e, f, g) _BATCH_MAP6(a, b, c, d, e, f) | _BATCH_MAP1(g)
+#define _BATCH_MAP8(a, b, c, d, e, f, g, h) _BATCH_MAP7(a, b, c, d, e, f, g) | _BATCH_MAP1(h)
+#define _BATCH_MAP9(a, b, c, d, e, f, g, h, i) _BATCH_MAP8(a, b, c, d, e, f, g, h) | _BATCH_MAP1(i)
+#define _BATCH_MAP10(a, b, c, d, e, f, g, h, i, j) _BATCH_MAP9(a, b, c, d, e, f, g, h, i) | _BATCH_MAP1(j)
+
+#define BATCH_MAP(...) VA_NARGS_CALL_OVERLOAD(_BATCH_MAP, __VA_ARGS__)
#ifndef NDEBUG
-# define _MDEPS_ASSERT2(b, name) \
- g_buffer_deps_d[_BUFFER_INDEX(name)] |= _MDEPS_CREATE1(b); \
- BLI_assert(g_buffer_deps[_BUFFER_INDEX(name)] & _MDEPS_CREATE1(b))
+# define MDEPS_ASSERT_INDEX(buffer_index, batch_flag) \
+ g_buffer_deps_d[buffer_index] |= batch_flag; \
+ BLI_assert(g_buffer_deps[buffer_index] & batch_flag)
+
+# define _MDEPS_ASSERT2(b, n1) MDEPS_ASSERT_INDEX(BUFFER_INDEX(n1), b)
# define _MDEPS_ASSERT3(b, n1, n2) _MDEPS_ASSERT2(b, n1); _MDEPS_ASSERT2(b, n2)
# define _MDEPS_ASSERT4(b, n1, n2, n3) _MDEPS_ASSERT3(b, n1, n2); _MDEPS_ASSERT2(b, n3)
# define _MDEPS_ASSERT5(b, n1, n2, n3, n4) _MDEPS_ASSERT4(b, n1, n2, n3); _MDEPS_ASSERT2(b, n4)
@@ -119,99 +122,97 @@
# define _MDEPS_ASSERT7(b, n1, n2, n3, n4, n5, n6) _MDEPS_ASSERT6(b, n1, n2, n3, n4, n5); _MDEPS_ASSERT2(b, n6)
# define _MDEPS_ASSERT8(b, n1, n2, n3, n4, n5, n6, n7) _MDEPS_ASSERT7(b, n1, n2, n3, n4, n5, n6); _MDEPS_ASSERT2(b, n7)
-# define MDEPS_ASSERT(...) VA_NARGS_CALL_OVERLOAD(_MDEPS_ASSERT, __VA_ARGS__)
-# define MDEPS_ASSERT_MAP(name) BLI_assert(g_buffer_deps_d[_BUFFER_INDEX(name)] == g_buffer_deps[_BUFFER_INDEX(name)])
+# define MDEPS_ASSERT_FLAG(...) VA_NARGS_CALL_OVERLOAD(_MDEPS_ASSERT, __VA_ARGS__)
+# define MDEPS_ASSERT(batch_name, ...) MDEPS_ASSERT_FLAG(BATCH_FLAG(batch_name), __VA_ARGS__)
+# define MDEPS_ASSERT_MAP_INDEX(buff_index) BLI_assert(g_buffer_deps_d[buff_index] == g_buffer_deps[buff_index])
+# define MDEPS_ASSERT_MAP(buff_name) MDEPS_ASSERT_MAP_INDEX(BUFFER_INDEX(buff_name))
#else
-# define MDEPS_ASSERT(...)
-# define MDEPS_ASSERT_MAP(name)
+# define MDEPS_ASSERT_INDEX(buffer_index, batch_flag)
+# define MDEPS_ASSERT_FLAG(...)
+# define MDEPS_ASSERT(batch_name, ...)
+# define MDEPS_ASSERT_MAP_INDEX(buff_index)
+# define MDEPS_ASSERT_MAP(buff_name)
#endif
/* clang-format on */
+#define TRIS_PER_MAT_INDEX BUFFER_LEN
+#define SURFACE_PER_MAT_FLAG (1u << MBC_BATCH_LEN)
+
static const DRWBatchFlag g_buffer_deps[] = {
- MDEPS_CREATE(vbo.pos_nor,
- batch.surface,
- batch.surface_weights,
- batch.edit_triangles,
- batch.edit_vertices,
- batch.edit_edges,
- batch.edit_vnor,
- batch.edit_lnor,
- batch.edit_mesh_analysis,
- batch.edit_selection_verts,
- batch.edit_selection_edges,
- batch.edit_selection_faces,
- batch.all_verts,
- batch.all_edges,
- batch.loose_edges,
- batch.edge_detection,
- batch.wire_edges,
- batch.wire_loops,
- batch.sculpt_overlays,
- surface_per_mat),
- MDEPS_CREATE(vbo.lnor, batch.surface, batch.edit_lnor, batch.wire_loops, surface_per_mat),
- MDEPS_CREATE(vbo.edge_fac, batch.wire_edges),
- MDEPS_CREATE(vbo.weights, batch.surface_weights),
- MDEPS_CREATE(vbo.uv,
- batch.surface,
- batch.edituv_faces_stretch_area,
- batch.edituv_faces_stretch_angle,
- batch.edituv_faces,
- batch.edituv_edges,
- batch.edituv_verts,
- batch.wire_loops_uvs,
- surface_per_mat),
- MDEPS_CREATE(vbo.tan, surface_per_mat),
- MDEPS_CREATE(vbo.vcol, batch.surface, surface_per_mat),
- MDEPS_CREATE(vbo.sculpt_data, batch.sculpt_overlays),
- MDEPS_CREATE(vbo.orco, surface_per_mat),
- MDEPS_CREATE(vbo.edit_data, batch.edit_triangles, batch.edit_edges, batch.edit_vertices),
- MDEPS_CREATE(vbo.edituv_data,
- batch.edituv_faces,
- batch.edituv_faces_stretch_area,
- batch.edituv_faces_stretch_angle,
- batch.edituv_edges,
- batch.edituv_verts),
- MDEPS_CREATE(vbo.edituv_stretch_area, batch.edituv_faces_stretch_area),
- MDEPS_CREATE(vbo.edituv_stretch_angle, batch.edituv_faces_stretch_angle),
- MDEPS_CREATE(vbo.mesh_analysis, batch.edit_mesh_analysis),
- MDEPS_CREATE(vbo.fdots_pos, batch.edit_fdots, batch.edit_selection_fdots),
- MDEPS_CREATE(vbo.fdots_nor, batch.edit_fdots),
- MDEPS_CREATE(vbo.fdots_uv, batch.edituv_fdots),
- MDEPS_CREATE(vbo.fdots_edituv_data, batch.edituv_fdots),
- MDEPS_CREATE(vbo.skin_roots, batch.edit_skin_roots),
- MDEPS_CREATE(vbo.vert_idx, batch.edit_selection_verts),
- MDEPS_CREATE(vbo.edge_idx, batch.edit_selection_edges),
- MDEPS_CREATE(vbo.poly_idx, batch.edit_selection_faces),
- MDEPS_CREATE(vbo.fdot_idx, batch.edit_selection_fdots),
-
- MDEPS_CREATE(ibo.tris,
- batch.surface,
- batch.surface_weights,
- batch.edit_triangles,
- batch.edit_lnor,
- batch.edit_mesh_analysis,
- batch.edit_selection_faces,
- batch.sculpt_overlays),
- MDEPS_CREATE(ibo.lines,
- batch.edit_edges,
- batch.edit_selection_edges,
- batch.all_edges,
- batch.wire_edges),
- MDEPS_CREATE(ibo.lines_loose, batch.loose_edges),
- MDEPS_CREATE(ibo.points, batch.edit_vnor, batch.edit_vertices, batch.edit_selection_verts),
- MDEPS_CREATE(ibo.fdots, batch.edit_fdots, batch.edit_selection_fdots),
- MDEPS_CREATE(ibo.lines_paint_mask, batch.wire_loops),
- MDEPS_CREATE(ibo.lines_adjacency, batch.edge_detection),
- MDEPS_CREATE(ibo.edituv_tris,
- batch.edituv_faces,
- batch.edituv_faces_stretch_area,
- batch.edituv_faces_stretch_angle),
- MDEPS_CREATE(ibo.edituv_lines, batch.edituv_edges, batch.wire_loops_uvs),
- MDEPS_CREATE(ibo.edituv_points, batch.edituv_verts),
- MDEPS_CREATE(ibo.edituv_fdots, batch.edituv_fdots),
-
- MDEPS_CREATE(tris_per_mat, surface_per_mat),
+ [BUFFER_INDEX(vbo.pos_nor)] = BATCH_FLAG(surface,
+ surface_weights,
+ edit_triangles,
+ edit_vertices,
+ edit_edges,
+ edit_vnor,
+ edit_lnor,
+ edit_mesh_analysis,
+ edit_selection_verts,
+ edit_selection_edges,
+ edit_selection_faces,
+ all_verts,
+ all_edges,
+ loose_edges,
+ edge_detection,
+ wire_edges,
+ wire_loops,
+ sculpt_overlays) |
+ SURFACE_PER_MAT_FLAG,
+ [BUFFER_INDEX(vbo.lnor)] = BATCH_FLAG(surface, edit_lnor, wire_loops) | SURFACE_PER_MAT_FLAG,
+ [BUFFER_INDEX(vbo.edge_fac)] = BATCH_FLAG(wire_edges),
+ [BUFFER_INDEX(vbo.weights)] = BATCH_FLAG(surface_weights),
+ [BUFFER_INDEX(vbo.uv)] = BATCH_FLAG(surface,
+ edituv_faces_stretch_area,
+ edituv_faces_stretch_angle,
+ edituv_faces,
+ edituv_edges,
+ edituv_verts,
+ wire_loops_uvs) |
+ SURFACE_PER_MAT_FLAG,
+ [BUFFER_INDEX(vbo.tan)] = SURFACE_PER_MAT_FLAG,
+ [BUFFER_INDEX(vbo.vcol)] = BATCH_FLAG(surface) | SURFACE_PER_MAT_FLAG,
+ [BUFFER_INDEX(vbo.sculpt_data)] = BATCH_FLAG(sculpt_overlays),
+ [BUFFER_INDEX(vbo.orco)] = SURFACE_PER_MAT_FLAG,
+ [BUFFER_INDEX(vbo.edit_data)] = BATCH_FLAG(edit_triangles, edit_edges, edit_vertices),
+ [BUFFER_INDEX(vbo.edituv_data)] = BATCH_FLAG(edituv_faces,
+ edituv_faces_stretch_area,
+ edituv_faces_stretch_angle,
+ edituv_edges,
+ edituv_verts),
+ [BUFFER_INDEX(vbo.edituv_stretch_area)] = BATCH_FLAG(edituv_faces_stretch_area),
+ [BUFFER_INDEX(vbo.edituv_stretch_angle)] = BATCH_FLAG(edituv_faces_stretch_angle),
+ [BUFFER_INDEX(vbo.mesh_analysis)] = BATCH_FLAG(edit_mesh_analysis),
+ [BUFFER_INDEX(vbo.fdots_pos)] = BATCH_FLAG(edit_fdots, edit_selection_fdots),
+ [BUFFER_INDEX(vbo.fdots_nor)] = BATCH_FLAG(edit_fdots),
+ [BUFFER_INDEX(vbo.fdots_uv)] = BATCH_FLAG(edituv_fdots),
+ [BUFFER_INDEX(vbo.fdots_edituv_data)] = BATCH_FLAG(edituv_fdots),
+ [BUFFER_INDEX(vbo.skin_roots)] = BATCH_FLAG(edit_skin_roots),
+ [BUFFER_INDEX(vbo.vert_idx)] = BATCH_FLAG(edit_selection_verts),
+ [BUFFER_INDEX(vbo.edge_idx)] = BATCH_FLAG(edit_selection_edges),
+ [BUFFER_INDEX(vbo.poly_idx)] = BATCH_FLAG(edit_selection_faces),
+ [BUFFER_INDEX(vbo.fdot_idx)] = BATCH_FLAG(edit_selection_fdots),
+
+ [BUFFER_INDEX(ibo.tris)] = BATCH_FLAG(surface,
+ surface_weights,
+ edit_triangles,
+ edit_lnor,
+ edit_mesh_analysis,
+ edit_selection_faces,
+ sculpt_overlays),
+ [BUFFER_INDEX(ibo.lines)] = BATCH_FLAG(
+ edit_edges, edit_selection_edges, all_edges, wire_edges),
+ [BUFFER_INDEX(ibo.lines_loose)] = BATCH_FLAG(loose_edges),
+ [BUFFER_INDEX(ibo.points)] = BATCH_FLAG(edit_vnor, edit_vertices, edit_selection_verts),
+ [BUFFER_INDEX(ibo.fdots)] = BATCH_FLAG(edit_fdots, edit_selection_fdots),
+ [BUFFER_INDEX(ibo.lines_paint_mask)] = BATCH_FLAG(wire_loops),
+ [BUFFER_INDEX(ibo.lines_adjacency)] = BATCH_FLAG(edge_detection),
+ [BUFFER_INDEX(ibo.edituv_tris)] = BATCH_FLAG(
+ edituv_faces, edituv_faces_stretch_area, edituv_faces_stretch_angle),
+ [BUFFER_INDEX(ibo.edituv_lines)] = BATCH_FLAG(edituv_edges, wire_loops_uvs),
+ [BUFFER_INDEX(ibo.edituv_points)] = BATCH_FLAG(edituv_verts),
+ [BUFFER_INDEX(ibo.edituv_fdots)] = BATCH_FLAG(edituv_fdots),
+ [TRIS_PER_MAT_INDEX] = SURFACE_PER_MAT_FLAG,
};
#ifndef NDEBUG
@@ -231,7 +232,7 @@ static void mesh_batch_cache_discard_batch(MeshBatchCache *cache, const DRWBatch
}
}
- if (batch_map & (1u << MBC_BATCH_INDEX(surface_per_mat))) {
+ if (batch_map & SURFACE_PER_MAT_FLAG) {
mesh_batch_cache_discard_surface_batches(cache);
}
}
@@ -661,8 +662,7 @@ static void mesh_batch_cache_init(Mesh *me)
cache->mat_len = mesh_render_mat_len_get(me);
cache->surface_per_mat = MEM_callocN(sizeof(*cache->surface_per_mat) * cache->mat_len, __func__);
- cache->final.tris_per_mat = MEM_callocN(sizeof(*cache->final.tris_per_mat) * cache->mat_len,
- __func__);
+ cache->tris_per_mat = MEM_callocN(sizeof(*cache->tris_per_mat) * cache->mat_len, __func__);
cache->is_dirty = false;
cache->batch_ready = 0;
@@ -688,8 +688,8 @@ static void mesh_batch_cache_check_vertex_group(MeshBatchCache *cache,
const struct DRW_MeshWeightState *wstate)
{
if (!drw_mesh_weight_state_compare(&cache->weight_state, wstate)) {
- FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.weights);
+ FOREACH_MESH_BUFFER_CACHE (cache, mbc) {
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.weights);
}
GPU_BATCH_CLEAR_SAFE(cache->batch.surface_weights);
@@ -708,6 +708,9 @@ static void mesh_batch_cache_request_surface_batches(MeshBatchCache *cache)
}
}
+/* Free batches with material-mapped looptris.
+ * NOTE: The updating of the indices buffers (#tris_per_mat) is handled in the extractors.
+ * No need to discard they here. */
static void mesh_batch_cache_discard_surface_batches(MeshBatchCache *cache)
{
GPU_BATCH_DISCARD_SAFE(cache->batch.surface);
@@ -719,41 +722,41 @@ static void mesh_batch_cache_discard_surface_batches(MeshBatchCache *cache)
static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache)
{
- FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.uv);
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.tan);
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.vcol);
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.orco);
+ FOREACH_MESH_BUFFER_CACHE (cache, mbc) {
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.uv);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.tan);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.vcol);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.orco);
}
- DRWBatchFlag batch_map = MDEPS_CREATE_MAP(vbo.uv, vbo.tan, vbo.vcol, vbo.orco);
+ DRWBatchFlag batch_map = BATCH_MAP(vbo.uv, vbo.tan, vbo.vcol, vbo.orco);
mesh_batch_cache_discard_batch(cache, batch_map);
mesh_cd_layers_type_clear(&cache->cd_used);
}
static void mesh_batch_cache_discard_uvedit(MeshBatchCache *cache)
{
- FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.edituv_stretch_angle);
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.edituv_stretch_area);
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.uv);
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.edituv_data);
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_uv);
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_edituv_data);
- GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_tris);
- GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_lines);
- GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_points);
- GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_fdots);
- }
- DRWBatchFlag batch_map = MDEPS_CREATE_MAP(vbo.edituv_stretch_angle,
- vbo.edituv_stretch_area,
- vbo.uv,
- vbo.edituv_data,
- vbo.fdots_uv,
- vbo.fdots_edituv_data,
- ibo.edituv_tris,
- ibo.edituv_lines,
- ibo.edituv_points,
- ibo.edituv_fdots);
+ FOREACH_MESH_BUFFER_CACHE (cache, mbc) {
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.edituv_stretch_angle);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.edituv_stretch_area);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.uv);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.edituv_data);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.fdots_uv);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.fdots_edituv_data);
+ GPU_INDEXBUF_DISCARD_SAFE(mbc->buff.ibo.edituv_tris);
+ GPU_INDEXBUF_DISCARD_SAFE(mbc->buff.ibo.edituv_lines);
+ GPU_INDEXBUF_DISCARD_SAFE(mbc->buff.ibo.edituv_points);
+ GPU_INDEXBUF_DISCARD_SAFE(mbc->buff.ibo.edituv_fdots);
+ }
+ DRWBatchFlag batch_map = BATCH_MAP(vbo.edituv_stretch_angle,
+ vbo.edituv_stretch_area,
+ vbo.uv,
+ vbo.edituv_data,
+ vbo.fdots_uv,
+ vbo.fdots_edituv_data,
+ ibo.edituv_tris,
+ ibo.edituv_lines,
+ ibo.edituv_points,
+ ibo.edituv_fdots);
mesh_batch_cache_discard_batch(cache, batch_map);
cache->tot_area = 0.0f;
@@ -768,20 +771,20 @@ static void mesh_batch_cache_discard_uvedit(MeshBatchCache *cache)
static void mesh_batch_cache_discard_uvedit_select(MeshBatchCache *cache)
{
- FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.edituv_data);
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_edituv_data);
- GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_tris);
- GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_lines);
- GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_points);
- GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_fdots);
- }
- DRWBatchFlag batch_map = MDEPS_CREATE_MAP(vbo.edituv_data,
- vbo.fdots_edituv_data,
- ibo.edituv_tris,
- ibo.edituv_lines,
- ibo.edituv_points,
- ibo.edituv_fdots);
+ FOREACH_MESH_BUFFER_CACHE (cache, mbc) {
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.edituv_data);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.fdots_edituv_data);
+ GPU_INDEXBUF_DISCARD_SAFE(mbc->buff.ibo.edituv_tris);
+ GPU_INDEXBUF_DISCARD_SAFE(mbc->buff.ibo.edituv_lines);
+ GPU_INDEXBUF_DISCARD_SAFE(mbc->buff.ibo.edituv_points);
+ GPU_INDEXBUF_DISCARD_SAFE(mbc->buff.ibo.edituv_fdots);
+ }
+ DRWBatchFlag batch_map = BATCH_MAP(vbo.edituv_data,
+ vbo.fdots_edituv_data,
+ ibo.edituv_tris,
+ ibo.edituv_lines,
+ ibo.edituv_points,
+ ibo.edituv_fdots);
mesh_batch_cache_discard_batch(cache, batch_map);
}
@@ -794,11 +797,11 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, eMeshBatchDirtyMode mode)
DRWBatchFlag batch_map;
switch (mode) {
case BKE_MESH_BATCH_DIRTY_SELECT:
- FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.edit_data);
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_nor);
+ FOREACH_MESH_BUFFER_CACHE (cache, mbc) {
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.edit_data);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.fdots_nor);
}
- batch_map = MDEPS_CREATE_MAP(vbo.edit_data, vbo.fdots_nor);
+ batch_map = BATCH_MAP(vbo.edit_data, vbo.fdots_nor);
mesh_batch_cache_discard_batch(cache, batch_map);
/* Because visible UVs depends on edit mode selection, discard topology. */
@@ -807,12 +810,12 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, eMeshBatchDirtyMode mode)
case BKE_MESH_BATCH_DIRTY_SELECT_PAINT:
/* Paint mode selection flag is packed inside the nor attribute.
* Note that it can be slow if auto smooth is enabled. (see T63946) */
- FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
- GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.lines_paint_mask);
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.pos_nor);
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.lnor);
+ FOREACH_MESH_BUFFER_CACHE (cache, mbc) {
+ GPU_INDEXBUF_DISCARD_SAFE(mbc->buff.ibo.lines_paint_mask);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.pos_nor);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.lnor);
}
- batch_map = MDEPS_CREATE_MAP(ibo.lines_paint_mask, vbo.pos_nor, vbo.lnor);
+ batch_map = BATCH_MAP(ibo.lines_paint_mask, vbo.pos_nor, vbo.lnor);
mesh_batch_cache_discard_batch(cache, batch_map);
break;
case BKE_MESH_BATCH_DIRTY_ALL:
@@ -826,11 +829,11 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, eMeshBatchDirtyMode mode)
mesh_batch_cache_discard_uvedit(cache);
break;
case BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT:
- FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.edituv_data);
- GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_edituv_data);
+ FOREACH_MESH_BUFFER_CACHE (cache, mbc) {
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.edituv_data);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.fdots_edituv_data);
}
- batch_map = MDEPS_CREATE_MAP(vbo.edituv_data, vbo.fdots_edituv_data);
+ batch_map = BATCH_MAP(vbo.edituv_data, vbo.fdots_edituv_data);
mesh_batch_cache_discard_batch(cache, batch_map);
break;
default:
@@ -838,28 +841,30 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, eMeshBatchDirtyMode mode)
}
}
-static void mesh_buffer_cache_clear(MeshBufferCache *mbufcache)
+static void mesh_buffer_list_clear(MeshBufferList *mbuflist)
{
- GPUVertBuf **vbos = (GPUVertBuf **)&mbufcache->vbo;
- GPUIndexBuf **ibos = (GPUIndexBuf **)&mbufcache->ibo;
- for (int i = 0; i < sizeof(mbufcache->vbo) / sizeof(void *); i++) {
+ GPUVertBuf **vbos = (GPUVertBuf **)&mbuflist->vbo;
+ GPUIndexBuf **ibos = (GPUIndexBuf **)&mbuflist->ibo;
+ for (int i = 0; i < sizeof(mbuflist->vbo) / sizeof(void *); i++) {
GPU_VERTBUF_DISCARD_SAFE(vbos[i]);
}
- for (int i = 0; i < sizeof(mbufcache->ibo) / sizeof(void *); i++) {
+ for (int i = 0; i < sizeof(mbuflist->ibo) / sizeof(void *); i++) {
GPU_INDEXBUF_DISCARD_SAFE(ibos[i]);
}
}
-static void mesh_buffer_extraction_cache_clear(MeshBufferExtractionCache *extraction_cache)
+static void mesh_buffer_cache_clear(MeshBufferCache *mbc)
{
- MEM_SAFE_FREE(extraction_cache->loose_geom.verts);
- MEM_SAFE_FREE(extraction_cache->loose_geom.edges);
- extraction_cache->loose_geom.edge_len = 0;
- extraction_cache->loose_geom.vert_len = 0;
+ mesh_buffer_list_clear(&mbc->buff);
- MEM_SAFE_FREE(extraction_cache->poly_sorted.tri_first_index);
- MEM_SAFE_FREE(extraction_cache->poly_sorted.mat_tri_len);
- extraction_cache->poly_sorted.visible_tri_len = 0;
+ MEM_SAFE_FREE(mbc->loose_geom.verts);
+ MEM_SAFE_FREE(mbc->loose_geom.edges);
+ mbc->loose_geom.edge_len = 0;
+ mbc->loose_geom.vert_len = 0;
+
+ MEM_SAFE_FREE(mbc->poly_sorted.tri_first_index);
+ MEM_SAFE_FREE(mbc->poly_sorted.mat_tri_len);
+ mbc->poly_sorted.visible_tri_len = 0;
}
static void mesh_batch_cache_clear(Mesh *me)
@@ -868,18 +873,14 @@ static void mesh_batch_cache_clear(Mesh *me)
if (!cache) {
return;
}
- FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
- mesh_buffer_cache_clear(mbufcache);
+ FOREACH_MESH_BUFFER_CACHE (cache, mbc) {
+ mesh_buffer_cache_clear(mbc);
}
- mesh_buffer_extraction_cache_clear(&cache->final_extraction_cache);
- mesh_buffer_extraction_cache_clear(&cache->cage_extraction_cache);
- mesh_buffer_extraction_cache_clear(&cache->uv_cage_extraction_cache);
-
for (int i = 0; i < cache->mat_len; i++) {
- GPU_INDEXBUF_DISCARD_SAFE(cache->final.tris_per_mat[i]);
+ GPU_INDEXBUF_DISCARD_SAFE(cache->tris_per_mat[i]);
}
- MEM_SAFE_FREE(cache->final.tris_per_mat);
+ MEM_SAFE_FREE(cache->tris_per_mat);
for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) {
GPUBatch **batch = (GPUBatch **)&cache->batch;
@@ -1083,8 +1084,8 @@ GPUVertBuf *DRW_mesh_batch_cache_pos_vertbuf_get(Mesh *me)
/* Request surface to trigger the vbo filling. Otherwise it may do nothing. */
mesh_batch_cache_request_surface_batches(cache);
- DRW_vbo_request(NULL, &cache->final.vbo.pos_nor);
- return cache->final.vbo.pos_nor;
+ DRW_vbo_request(NULL, &cache->final.buff.vbo.pos_nor);
+ return cache->final.buff.vbo.pos_nor;
}
/** \} */
@@ -1316,22 +1317,22 @@ static void drw_mesh_batch_cache_check_available(struct TaskGraph *task_graph, M
BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0));
}
for (int i = 0; i < MBC_VBO_LEN; i++) {
- BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->final.vbo)[i]));
+ BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->final.buff.vbo)[i]));
}
for (int i = 0; i < MBC_IBO_LEN; i++) {
- BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->final.ibo)[i]));
+ BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->final.buff.ibo)[i]));
}
for (int i = 0; i < MBC_VBO_LEN; i++) {
- BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->cage.vbo)[i]));
+ BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->cage.buff.vbo)[i]));
}
for (int i = 0; i < MBC_IBO_LEN; i++) {
- BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->cage.ibo)[i]));
+ BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->cage.buff.ibo)[i]));
}
for (int i = 0; i < MBC_VBO_LEN; i++) {
- BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->uv_cage.vbo)[i]));
+ BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->uv_cage.buff.vbo)[i]));
}
for (int i = 0; i < MBC_IBO_LEN; i++) {
- BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->uv_cage.ibo)[i]));
+ BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->uv_cage.buff.ibo)[i]));
}
}
#endif
@@ -1414,25 +1415,25 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
* material. */
bool cd_overlap = mesh_cd_layers_type_overlap(cache->cd_used, cache->cd_needed);
if (cd_overlap == false) {
- FOREACH_MESH_BUFFER_CACHE (cache, mbuffercache) {
+ FOREACH_MESH_BUFFER_CACHE (cache, mbc) {
if ((cache->cd_used.uv & cache->cd_needed.uv) != cache->cd_needed.uv) {
- GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.uv);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.uv);
cd_uv_update = true;
}
if ((cache->cd_used.tan & cache->cd_needed.tan) != cache->cd_needed.tan ||
cache->cd_used.tan_orco != cache->cd_needed.tan_orco) {
- GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.tan);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.tan);
}
if (cache->cd_used.orco != cache->cd_needed.orco) {
- GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.orco);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.orco);
}
if (cache->cd_used.sculpt_overlays != cache->cd_needed.sculpt_overlays) {
- GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.sculpt_data);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.sculpt_data);
}
if (((cache->cd_used.vcol & cache->cd_needed.vcol) != cache->cd_needed.vcol) ||
((cache->cd_used.sculpt_vcol & cache->cd_needed.sculpt_vcol) !=
cache->cd_needed.sculpt_vcol)) {
- GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.vcol);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.vcol);
}
}
/* We can't discard batches at this point as they have been
@@ -1454,14 +1455,14 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
const bool is_uvsyncsel = ts && (ts->uv_flag & UV_SYNC_SELECTION);
if (cd_uv_update || (cache->is_uvsyncsel != is_uvsyncsel)) {
cache->is_uvsyncsel = is_uvsyncsel;
- FOREACH_MESH_BUFFER_CACHE (cache, mbuffercache) {
- GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.edituv_data);
- GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.fdots_uv);
- GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.fdots_edituv_data);
- GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_tris);
- GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_lines);
- GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_points);
- GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_fdots);
+ FOREACH_MESH_BUFFER_CACHE (cache, mbc) {
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.edituv_data);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.fdots_uv);
+ GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.fdots_edituv_data);
+ GPU_INDEXBUF_DISCARD_SAFE(mbc->buff.ibo.edituv_tris);
+ GPU_INDEXBUF_DISCARD_SAFE(mbc->buff.ibo.edituv_lines);
+ GPU_INDEXBUF_DISCARD_SAFE(mbc->buff.ibo.edituv_points);
+ GPU_INDEXBUF_DISCARD_SAFE(mbc->buff.ibo.edituv_fdots);
}
/* We only clear the batches as they may already have been
* referenced. */
@@ -1502,173 +1503,174 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
const bool do_uvcage = is_editmode && !me->edit_mesh->mesh_eval_final->runtime.is_original;
- MeshBufferCache *mbufcache = &cache->final;
+ MeshBufferList *mbuflist = &cache->final.buff;
/* Initialize batches and request VBO's & IBO's. */
- MDEPS_ASSERT(batch.surface, ibo.tris, vbo.lnor, vbo.pos_nor, vbo.uv, vbo.vcol);
+ MDEPS_ASSERT(surface, ibo.tris, vbo.lnor, vbo.pos_nor, vbo.uv, vbo.vcol);
if (DRW_batch_requested(cache->batch.surface, GPU_PRIM_TRIS)) {
- DRW_ibo_request(cache->batch.surface, &mbufcache->ibo.tris);
+ DRW_ibo_request(cache->batch.surface, &mbuflist->ibo.tris);
/* Order matters. First ones override latest VBO's attributes. */
- DRW_vbo_request(cache->batch.surface, &mbufcache->vbo.lnor);
- DRW_vbo_request(cache->batch.surface, &mbufcache->vbo.pos_nor);
+ DRW_vbo_request(cache->batch.surface, &mbuflist->vbo.lnor);
+ DRW_vbo_request(cache->batch.surface, &mbuflist->vbo.pos_nor);
if (cache->cd_used.uv != 0) {
- DRW_vbo_request(cache->batch.surface, &mbufcache->vbo.uv);
+ DRW_vbo_request(cache->batch.surface, &mbuflist->vbo.uv);
}
if (cache->cd_used.vcol != 0 || cache->cd_used.sculpt_vcol != 0) {
- DRW_vbo_request(cache->batch.surface, &mbufcache->vbo.vcol);
+ DRW_vbo_request(cache->batch.surface, &mbuflist->vbo.vcol);
}
}
- MDEPS_ASSERT(batch.all_verts, vbo.pos_nor);
+ MDEPS_ASSERT(all_verts, vbo.pos_nor);
if (DRW_batch_requested(cache->batch.all_verts, GPU_PRIM_POINTS)) {
- DRW_vbo_request(cache->batch.all_verts, &mbufcache->vbo.pos_nor);
+ DRW_vbo_request(cache->batch.all_verts, &mbuflist->vbo.pos_nor);
}
- MDEPS_ASSERT(batch.sculpt_overlays, ibo.tris, vbo.pos_nor, vbo.sculpt_data);
+ MDEPS_ASSERT(sculpt_overlays, ibo.tris, vbo.pos_nor, vbo.sculpt_data);
if (DRW_batch_requested(cache->batch.sculpt_overlays, GPU_PRIM_TRIS)) {
- DRW_ibo_request(cache->batch.sculpt_overlays, &mbufcache->ibo.tris);
- DRW_vbo_request(cache->batch.sculpt_overlays, &mbufcache->vbo.pos_nor);
- DRW_vbo_request(cache->batch.sculpt_overlays, &mbufcache->vbo.sculpt_data);
+ DRW_ibo_request(cache->batch.sculpt_overlays, &mbuflist->ibo.tris);
+ DRW_vbo_request(cache->batch.sculpt_overlays, &mbuflist->vbo.pos_nor);
+ DRW_vbo_request(cache->batch.sculpt_overlays, &mbuflist->vbo.sculpt_data);
}
- MDEPS_ASSERT(batch.all_edges, ibo.lines, vbo.pos_nor);
+ MDEPS_ASSERT(all_edges, ibo.lines, vbo.pos_nor);
if (DRW_batch_requested(cache->batch.all_edges, GPU_PRIM_LINES)) {
- DRW_ibo_request(cache->batch.all_edges, &mbufcache->ibo.lines);
- DRW_vbo_request(cache->batch.all_edges, &mbufcache->vbo.pos_nor);
+ DRW_ibo_request(cache->batch.all_edges, &mbuflist->ibo.lines);
+ DRW_vbo_request(cache->batch.all_edges, &mbuflist->vbo.pos_nor);
}
- MDEPS_ASSERT(batch.loose_edges, ibo.lines_loose, vbo.pos_nor);
+ MDEPS_ASSERT(loose_edges, ibo.lines_loose, vbo.pos_nor);
if (DRW_batch_requested(cache->batch.loose_edges, GPU_PRIM_LINES)) {
- DRW_ibo_request(NULL, &mbufcache->ibo.lines);
- DRW_ibo_request(cache->batch.loose_edges, &mbufcache->ibo.lines_loose);
- DRW_vbo_request(cache->batch.loose_edges, &mbufcache->vbo.pos_nor);
+ DRW_ibo_request(NULL, &mbuflist->ibo.lines);
+ DRW_ibo_request(cache->batch.loose_edges, &mbuflist->ibo.lines_loose);
+ DRW_vbo_request(cache->batch.loose_edges, &mbuflist->vbo.pos_nor);
}
- MDEPS_ASSERT(batch.edge_detection, ibo.lines_adjacency, vbo.pos_nor);
+ MDEPS_ASSERT(edge_detection, ibo.lines_adjacency, vbo.pos_nor);
if (DRW_batch_requested(cache->batch.edge_detection, GPU_PRIM_LINES_ADJ)) {
- DRW_ibo_request(cache->batch.edge_detection, &mbufcache->ibo.lines_adjacency);
- DRW_vbo_request(cache->batch.edge_detection, &mbufcache->vbo.pos_nor);
+ DRW_ibo_request(cache->batch.edge_detection, &mbuflist->ibo.lines_adjacency);
+ DRW_vbo_request(cache->batch.edge_detection, &mbuflist->vbo.pos_nor);
}
- MDEPS_ASSERT(batch.surface_weights, ibo.tris, vbo.pos_nor, vbo.weights);
+ MDEPS_ASSERT(surface_weights, ibo.tris, vbo.pos_nor, vbo.weights);
if (DRW_batch_requested(cache->batch.surface_weights, GPU_PRIM_TRIS)) {
- DRW_ibo_request(cache->batch.surface_weights, &mbufcache->ibo.tris);
- DRW_vbo_request(cache->batch.surface_weights, &mbufcache->vbo.pos_nor);
- DRW_vbo_request(cache->batch.surface_weights, &mbufcache->vbo.weights);
+ DRW_ibo_request(cache->batch.surface_weights, &mbuflist->ibo.tris);
+ DRW_vbo_request(cache->batch.surface_weights, &mbuflist->vbo.pos_nor);
+ DRW_vbo_request(cache->batch.surface_weights, &mbuflist->vbo.weights);
}
- MDEPS_ASSERT(batch.wire_loops, ibo.lines_paint_mask, vbo.lnor, vbo.pos_nor);
+ MDEPS_ASSERT(wire_loops, ibo.lines_paint_mask, vbo.lnor, vbo.pos_nor);
if (DRW_batch_requested(cache->batch.wire_loops, GPU_PRIM_LINES)) {
- DRW_ibo_request(cache->batch.wire_loops, &mbufcache->ibo.lines_paint_mask);
+ DRW_ibo_request(cache->batch.wire_loops, &mbuflist->ibo.lines_paint_mask);
/* Order matters. First ones override latest VBO's attributes. */
- DRW_vbo_request(cache->batch.wire_loops, &mbufcache->vbo.lnor);
- DRW_vbo_request(cache->batch.wire_loops, &mbufcache->vbo.pos_nor);
+ DRW_vbo_request(cache->batch.wire_loops, &mbuflist->vbo.lnor);
+ DRW_vbo_request(cache->batch.wire_loops, &mbuflist->vbo.pos_nor);
}
- MDEPS_ASSERT(batch.wire_edges, ibo.lines, vbo.pos_nor, vbo.edge_fac);
+ MDEPS_ASSERT(wire_edges, ibo.lines, vbo.pos_nor, vbo.edge_fac);
if (DRW_batch_requested(cache->batch.wire_edges, GPU_PRIM_LINES)) {
- DRW_ibo_request(cache->batch.wire_edges, &mbufcache->ibo.lines);
- DRW_vbo_request(cache->batch.wire_edges, &mbufcache->vbo.pos_nor);
- DRW_vbo_request(cache->batch.wire_edges, &mbufcache->vbo.edge_fac);
+ DRW_ibo_request(cache->batch.wire_edges, &mbuflist->ibo.lines);
+ DRW_vbo_request(cache->batch.wire_edges, &mbuflist->vbo.pos_nor);
+ DRW_vbo_request(cache->batch.wire_edges, &mbuflist->vbo.edge_fac);
}
- MDEPS_ASSERT(batch.wire_loops_uvs, ibo.edituv_lines, vbo.uv);
+ MDEPS_ASSERT(wire_loops_uvs, ibo.edituv_lines, vbo.uv);
if (DRW_batch_requested(cache->batch.wire_loops_uvs, GPU_PRIM_LINES)) {
- DRW_ibo_request(cache->batch.wire_loops_uvs, &mbufcache->ibo.edituv_lines);
+ DRW_ibo_request(cache->batch.wire_loops_uvs, &mbuflist->ibo.edituv_lines);
/* For paint overlay. Active layer should have been queried. */
if (cache->cd_used.uv != 0) {
- DRW_vbo_request(cache->batch.wire_loops_uvs, &mbufcache->vbo.uv);
+ DRW_vbo_request(cache->batch.wire_loops_uvs, &mbuflist->vbo.uv);
}
}
- MDEPS_ASSERT(batch.edit_mesh_analysis, ibo.tris, vbo.pos_nor, vbo.mesh_analysis);
+ MDEPS_ASSERT(edit_mesh_analysis, ibo.tris, vbo.pos_nor, vbo.mesh_analysis);
if (DRW_batch_requested(cache->batch.edit_mesh_analysis, GPU_PRIM_TRIS)) {
- DRW_ibo_request(cache->batch.edit_mesh_analysis, &mbufcache->ibo.tris);
- DRW_vbo_request(cache->batch.edit_mesh_analysis, &mbufcache->vbo.pos_nor);
- DRW_vbo_request(cache->batch.edit_mesh_analysis, &mbufcache->vbo.mesh_analysis);
+ DRW_ibo_request(cache->batch.edit_mesh_analysis, &mbuflist->ibo.tris);
+ DRW_vbo_request(cache->batch.edit_mesh_analysis, &mbuflist->vbo.pos_nor);
+ DRW_vbo_request(cache->batch.edit_mesh_analysis, &mbuflist->vbo.mesh_analysis);
}
/* Per Material */
- MDEPS_ASSERT(
- surface_per_mat, tris_per_mat, vbo.lnor, vbo.pos_nor, vbo.uv, vbo.tan, vbo.vcol, vbo.orco);
+ MDEPS_ASSERT_FLAG(
+ SURFACE_PER_MAT_FLAG, vbo.lnor, vbo.pos_nor, vbo.uv, vbo.tan, vbo.vcol, vbo.orco);
+ MDEPS_ASSERT_INDEX(TRIS_PER_MAT_INDEX, SURFACE_PER_MAT_FLAG);
for (int i = 0; i < cache->mat_len; i++) {
if (DRW_batch_requested(cache->surface_per_mat[i], GPU_PRIM_TRIS)) {
- DRW_ibo_request(cache->surface_per_mat[i], &mbufcache->tris_per_mat[i]);
+ DRW_ibo_request(cache->surface_per_mat[i], &cache->tris_per_mat[i]);
/* Order matters. First ones override latest VBO's attributes. */
- DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.lnor);
- DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.pos_nor);
+ DRW_vbo_request(cache->surface_per_mat[i], &mbuflist->vbo.lnor);
+ DRW_vbo_request(cache->surface_per_mat[i], &mbuflist->vbo.pos_nor);
if (cache->cd_used.uv != 0) {
- DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.uv);
+ DRW_vbo_request(cache->surface_per_mat[i], &mbuflist->vbo.uv);
}
if ((cache->cd_used.tan != 0) || (cache->cd_used.tan_orco != 0)) {
- DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.tan);
+ DRW_vbo_request(cache->surface_per_mat[i], &mbuflist->vbo.tan);
}
if (cache->cd_used.vcol != 0 || cache->cd_used.sculpt_vcol != 0) {
- DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.vcol);
+ DRW_vbo_request(cache->surface_per_mat[i], &mbuflist->vbo.vcol);
}
if (cache->cd_used.orco != 0) {
- DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.orco);
+ DRW_vbo_request(cache->surface_per_mat[i], &mbuflist->vbo.orco);
}
}
}
- mbufcache = (do_cage) ? &cache->cage : &cache->final;
+ mbuflist = (do_cage) ? &cache->cage.buff : &cache->final.buff;
/* Edit Mesh */
- MDEPS_ASSERT(batch.edit_triangles, ibo.tris, vbo.pos_nor, vbo.edit_data);
+ MDEPS_ASSERT(edit_triangles, ibo.tris, vbo.pos_nor, vbo.edit_data);
if (DRW_batch_requested(cache->batch.edit_triangles, GPU_PRIM_TRIS)) {
- DRW_ibo_request(cache->batch.edit_triangles, &mbufcache->ibo.tris);
- DRW_vbo_request(cache->batch.edit_triangles, &mbufcache->vbo.pos_nor);
- DRW_vbo_request(cache->batch.edit_triangles, &mbufcache->vbo.edit_data);
+ DRW_ibo_request(cache->batch.edit_triangles, &mbuflist->ibo.tris);
+ DRW_vbo_request(cache->batch.edit_triangles, &mbuflist->vbo.pos_nor);
+ DRW_vbo_request(cache->batch.edit_triangles, &mbuflist->vbo.edit_data);
}
- MDEPS_ASSERT(batch.edit_vertices, ibo.points, vbo.pos_nor, vbo.edit_data);
+ MDEPS_ASSERT(edit_vertices, ibo.points, vbo.pos_nor, vbo.edit_data);
if (DRW_batch_requested(cache->batch.edit_vertices, GPU_PRIM_POINTS)) {
- DRW_ibo_request(cache->batch.edit_vertices, &mbufcache->ibo.points);
- DRW_vbo_request(cache->batch.edit_vertices, &mbufcache->vbo.pos_nor);
- DRW_vbo_request(cache->batch.edit_vertices, &mbufcache->vbo.edit_data);
+ DRW_ibo_request(cache->batch.edit_vertices, &mbuflist->ibo.points);
+ DRW_vbo_request(cache->batch.edit_vertices, &mbuflist->vbo.pos_nor);
+ DRW_vbo_request(cache->batch.edit_vertices, &mbuflist->vbo.edit_data);
}
- MDEPS_ASSERT(batch.edit_edges, ibo.lines, vbo.pos_nor, vbo.edit_data);
+ MDEPS_ASSERT(edit_edges, ibo.lines, vbo.pos_nor, vbo.edit_data);
if (DRW_batch_requested(cache->batch.edit_edges, GPU_PRIM_LINES)) {
- DRW_ibo_request(cache->batch.edit_edges, &mbufcache->ibo.lines);
- DRW_vbo_request(cache->batch.edit_edges, &mbufcache->vbo.pos_nor);
- DRW_vbo_request(cache->batch.edit_edges, &mbufcache->vbo.edit_data);
+ DRW_ibo_request(cache->batch.edit_edges, &mbuflist->ibo.lines);
+ DRW_vbo_request(cache->batch.edit_edges, &mbuflist->vbo.pos_nor);
+ DRW_vbo_request(cache->batch.edit_edges, &mbuflist->vbo.edit_data);
}
- MDEPS_ASSERT(batch.edit_vnor, ibo.points, vbo.pos_nor);
+ MDEPS_ASSERT(edit_vnor, ibo.points, vbo.pos_nor);
if (DRW_batch_requested(cache->batch.edit_vnor, GPU_PRIM_POINTS)) {
- DRW_ibo_request(cache->batch.edit_vnor, &mbufcache->ibo.points);
- DRW_vbo_request(cache->batch.edit_vnor, &mbufcache->vbo.pos_nor);
+ DRW_ibo_request(cache->batch.edit_vnor, &mbuflist->ibo.points);
+ DRW_vbo_request(cache->batch.edit_vnor, &mbuflist->vbo.pos_nor);
}
- MDEPS_ASSERT(batch.edit_lnor, ibo.tris, vbo.pos_nor, vbo.lnor);
+ MDEPS_ASSERT(edit_lnor, ibo.tris, vbo.pos_nor, vbo.lnor);
if (DRW_batch_requested(cache->batch.edit_lnor, GPU_PRIM_POINTS)) {
- DRW_ibo_request(cache->batch.edit_lnor, &mbufcache->ibo.tris);
- DRW_vbo_request(cache->batch.edit_lnor, &mbufcache->vbo.pos_nor);
- DRW_vbo_request(cache->batch.edit_lnor, &mbufcache->vbo.lnor);
+ DRW_ibo_request(cache->batch.edit_lnor, &mbuflist->ibo.tris);
+ DRW_vbo_request(cache->batch.edit_lnor, &mbuflist->vbo.pos_nor);
+ DRW_vbo_request(cache->batch.edit_lnor, &mbuflist->vbo.lnor);
}
- MDEPS_ASSERT(batch.edit_fdots, ibo.fdots, vbo.fdots_pos, vbo.fdots_nor);
+ MDEPS_ASSERT(edit_fdots, ibo.fdots, vbo.fdots_pos, vbo.fdots_nor);
if (DRW_batch_requested(cache->batch.edit_fdots, GPU_PRIM_POINTS)) {
- DRW_ibo_request(cache->batch.edit_fdots, &mbufcache->ibo.fdots);
- DRW_vbo_request(cache->batch.edit_fdots, &mbufcache->vbo.fdots_pos);
- DRW_vbo_request(cache->batch.edit_fdots, &mbufcache->vbo.fdots_nor);
+ DRW_ibo_request(cache->batch.edit_fdots, &mbuflist->ibo.fdots);
+ DRW_vbo_request(cache->batch.edit_fdots, &mbuflist->vbo.fdots_pos);
+ DRW_vbo_request(cache->batch.edit_fdots, &mbuflist->vbo.fdots_nor);
}
- MDEPS_ASSERT(batch.edit_skin_roots, vbo.skin_roots);
+ MDEPS_ASSERT(edit_skin_roots, vbo.skin_roots);
if (DRW_batch_requested(cache->batch.edit_skin_roots, GPU_PRIM_POINTS)) {
- DRW_vbo_request(cache->batch.edit_skin_roots, &mbufcache->vbo.skin_roots);
+ DRW_vbo_request(cache->batch.edit_skin_roots, &mbuflist->vbo.skin_roots);
}
/* Selection */
- MDEPS_ASSERT(batch.edit_selection_verts, ibo.points, vbo.pos_nor, vbo.vert_idx);
+ MDEPS_ASSERT(edit_selection_verts, ibo.points, vbo.pos_nor, vbo.vert_idx);
if (DRW_batch_requested(cache->batch.edit_selection_verts, GPU_PRIM_POINTS)) {
- DRW_ibo_request(cache->batch.edit_selection_verts, &mbufcache->ibo.points);
- DRW_vbo_request(cache->batch.edit_selection_verts, &mbufcache->vbo.pos_nor);
- DRW_vbo_request(cache->batch.edit_selection_verts, &mbufcache->vbo.vert_idx);
+ DRW_ibo_request(cache->batch.edit_selection_verts, &mbuflist->ibo.points);
+ DRW_vbo_request(cache->batch.edit_selection_verts, &mbuflist->vbo.pos_nor);
+ DRW_vbo_request(cache->batch.edit_selection_verts, &mbuflist->vbo.vert_idx);
}
- MDEPS_ASSERT(batch.edit_selection_edges, ibo.lines, vbo.pos_nor, vbo.edge_idx);
+ MDEPS_ASSERT(edit_selection_edges, ibo.lines, vbo.pos_nor, vbo.edge_idx);
if (DRW_batch_requested(cache->batch.edit_selection_edges, GPU_PRIM_LINES)) {
- DRW_ibo_request(cache->batch.edit_selection_edges, &mbufcache->ibo.lines);
- DRW_vbo_request(cache->batch.edit_selection_edges, &mbufcache->vbo.pos_nor);
- DRW_vbo_request(cache->batch.edit_selection_edges, &mbufcache->vbo.edge_idx);
+ DRW_ibo_request(cache->batch.edit_selection_edges, &mbuflist->ibo.lines);
+ DRW_vbo_request(cache->batch.edit_selection_edges, &mbuflist->vbo.pos_nor);
+ DRW_vbo_request(cache->batch.edit_selection_edges, &mbuflist->vbo.edge_idx);
}
- MDEPS_ASSERT(batch.edit_selection_faces, ibo.tris, vbo.pos_nor, vbo.poly_idx);
+ MDEPS_ASSERT(edit_selection_faces, ibo.tris, vbo.pos_nor, vbo.poly_idx);
if (DRW_batch_requested(cache->batch.edit_selection_faces, GPU_PRIM_TRIS)) {
- DRW_ibo_request(cache->batch.edit_selection_faces, &mbufcache->ibo.tris);
- DRW_vbo_request(cache->batch.edit_selection_faces, &mbufcache->vbo.pos_nor);
- DRW_vbo_request(cache->batch.edit_selection_faces, &mbufcache->vbo.poly_idx);
+ DRW_ibo_request(cache->batch.edit_selection_faces, &mbuflist->ibo.tris);
+ DRW_vbo_request(cache->batch.edit_selection_faces, &mbuflist->vbo.pos_nor);
+ DRW_vbo_request(cache->batch.edit_selection_faces, &mbuflist->vbo.poly_idx);
}
- MDEPS_ASSERT(batch.edit_selection_fdots, ibo.fdots, vbo.fdots_pos, vbo.fdot_idx);
+ MDEPS_ASSERT(edit_selection_fdots, ibo.fdots, vbo.fdots_pos, vbo.fdot_idx);
if (DRW_batch_requested(cache->batch.edit_selection_fdots, GPU_PRIM_POINTS)) {
- DRW_ibo_request(cache->batch.edit_selection_fdots, &mbufcache->ibo.fdots);
- DRW_vbo_request(cache->batch.edit_selection_fdots, &mbufcache->vbo.fdots_pos);
- DRW_vbo_request(cache->batch.edit_selection_fdots, &mbufcache->vbo.fdot_idx);
+ DRW_ibo_request(cache->batch.edit_selection_fdots, &mbuflist->ibo.fdots);
+ DRW_vbo_request(cache->batch.edit_selection_fdots, &mbuflist->vbo.fdots_pos);
+ DRW_vbo_request(cache->batch.edit_selection_fdots, &mbuflist->vbo.fdot_idx);
}
/**
@@ -1676,54 +1678,54 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
* but the selection code for UVs needs to support it first. So for now, only
* display the cage in all cases.
*/
- mbufcache = (do_uvcage) ? &cache->uv_cage : &cache->final;
+ mbuflist = (do_uvcage) ? &cache->uv_cage.buff : &cache->final.buff;
/* Edit UV */
- MDEPS_ASSERT(batch.edituv_faces, ibo.edituv_tris, vbo.uv, vbo.edituv_data);
+ MDEPS_ASSERT(edituv_faces, ibo.edituv_tris, vbo.uv, vbo.edituv_data);
if (DRW_batch_requested(cache->batch.edituv_faces, GPU_PRIM_TRIS)) {
- DRW_ibo_request(cache->batch.edituv_faces, &mbufcache->ibo.edituv_tris);
- DRW_vbo_request(cache->batch.edituv_faces, &mbufcache->vbo.uv);
- DRW_vbo_request(cache->batch.edituv_faces, &mbufcache->vbo.edituv_data);
+ DRW_ibo_request(cache->batch.edituv_faces, &mbuflist->ibo.edituv_tris);
+ DRW_vbo_request(cache->batch.edituv_faces, &mbuflist->vbo.uv);
+ DRW_vbo_request(cache->batch.edituv_faces, &mbuflist->vbo.edituv_data);
}
- MDEPS_ASSERT(batch.edituv_faces_stretch_area,
+ MDEPS_ASSERT(edituv_faces_stretch_area,
ibo.edituv_tris,
vbo.uv,
vbo.edituv_data,
vbo.edituv_stretch_area);
if (DRW_batch_requested(cache->batch.edituv_faces_stretch_area, GPU_PRIM_TRIS)) {
- DRW_ibo_request(cache->batch.edituv_faces_stretch_area, &mbufcache->ibo.edituv_tris);
- DRW_vbo_request(cache->batch.edituv_faces_stretch_area, &mbufcache->vbo.uv);
- DRW_vbo_request(cache->batch.edituv_faces_stretch_area, &mbufcache->vbo.edituv_data);
- DRW_vbo_request(cache->batch.edituv_faces_stretch_area, &mbufcache->vbo.edituv_stretch_area);
+ DRW_ibo_request(cache->batch.edituv_faces_stretch_area, &mbuflist->ibo.edituv_tris);
+ DRW_vbo_request(cache->batch.edituv_faces_stretch_area, &mbuflist->vbo.uv);
+ DRW_vbo_request(cache->batch.edituv_faces_stretch_area, &mbuflist->vbo.edituv_data);
+ DRW_vbo_request(cache->batch.edituv_faces_stretch_area, &mbuflist->vbo.edituv_stretch_area);
}
- MDEPS_ASSERT(batch.edituv_faces_stretch_angle,
+ MDEPS_ASSERT(edituv_faces_stretch_angle,
ibo.edituv_tris,
vbo.uv,
vbo.edituv_data,
vbo.edituv_stretch_angle);
if (DRW_batch_requested(cache->batch.edituv_faces_stretch_angle, GPU_PRIM_TRIS)) {
- DRW_ibo_request(cache->batch.edituv_faces_stretch_angle, &mbufcache->ibo.edituv_tris);
- DRW_vbo_request(cache->batch.edituv_faces_stretch_angle, &mbufcache->vbo.uv);
- DRW_vbo_request(cache->batch.edituv_faces_stretch_angle, &mbufcache->vbo.edituv_data);
- DRW_vbo_request(cache->batch.edituv_faces_stretch_angle, &mbufcache->vbo.edituv_stretch_angle);
+ DRW_ibo_request(cache->batch.edituv_faces_stretch_angle, &mbuflist->ibo.edituv_tris);
+ DRW_vbo_request(cache->batch.edituv_faces_stretch_angle, &mbuflist->vbo.uv);
+ DRW_vbo_request(cache->batch.edituv_faces_stretch_angle, &mbuflist->vbo.edituv_data);
+ DRW_vbo_request(cache->batch.edituv_faces_stretch_angle, &mbuflist->vbo.edituv_stretch_angle);
}
- MDEPS_ASSERT(batch.edituv_edges, ibo.edituv_lines, vbo.uv, vbo.edituv_data);
+ MDEPS_ASSERT(edituv_edges, ibo.edituv_lines, vbo.uv, vbo.edituv_data);
if (DRW_batch_requested(cache->batch.edituv_edges, GPU_PRIM_LINES)) {
- DRW_ibo_request(cache->batch.edituv_edges, &mbufcache->ibo.edituv_lines);
- DRW_vbo_request(cache->batch.edituv_edges, &mbufcache->vbo.uv);
- DRW_vbo_request(cache->batch.edituv_edges, &mbufcache->vbo.edituv_data);
+ DRW_ibo_request(cache->batch.edituv_edges, &mbuflist->ibo.edituv_lines);
+ DRW_vbo_request(cache->batch.edituv_edges, &mbuflist->vbo.uv);
+ DRW_vbo_request(cache->batch.edituv_edges, &mbuflist->vbo.edituv_data);
}
- MDEPS_ASSERT(batch.edituv_verts, ibo.edituv_points, vbo.uv, vbo.edituv_data);
+ MDEPS_ASSERT(edituv_verts, ibo.edituv_points, vbo.uv, vbo.edituv_data);
if (DRW_batch_requested(cache->batch.edituv_verts, GPU_PRIM_POINTS)) {
- DRW_ibo_request(cache->batch.edituv_verts, &mbufcache->ibo.edituv_points);
- DRW_vbo_request(cache->batch.edituv_verts, &mbufcache->vbo.uv);
- DRW_vbo_request(cache->batch.edituv_verts, &mbufcache->vbo.edituv_data);
+ DRW_ibo_request(cache->batch.edituv_verts, &mbuflist->ibo.edituv_points);
+ DRW_vbo_request(cache->batch.edituv_verts, &mbuflist->vbo.uv);
+ DRW_vbo_request(cache->batch.edituv_verts, &mbuflist->vbo.edituv_data);
}
- MDEPS_ASSERT(batch.edituv_fdots, ibo.edituv_fdots, vbo.fdots_uv, vbo.fdots_edituv_data);
+ MDEPS_ASSERT(edituv_fdots, ibo.edituv_fdots, vbo.fdots_uv, vbo.fdots_edituv_data);
if (DRW_batch_requested(cache->batch.edituv_fdots, GPU_PRIM_POINTS)) {
- DRW_ibo_request(cache->batch.edituv_fdots, &mbufcache->ibo.edituv_fdots);
- DRW_vbo_request(cache->batch.edituv_fdots, &mbufcache->vbo.fdots_uv);
- DRW_vbo_request(cache->batch.edituv_fdots, &mbufcache->vbo.fdots_edituv_data);
+ DRW_ibo_request(cache->batch.edituv_fdots, &mbuflist->ibo.edituv_fdots);
+ DRW_vbo_request(cache->batch.edituv_fdots, &mbuflist->vbo.fdots_uv);
+ DRW_vbo_request(cache->batch.edituv_fdots, &mbuflist->vbo.fdots_edituv_data);
}
MDEPS_ASSERT_MAP(vbo.lnor);
@@ -1762,7 +1764,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
MDEPS_ASSERT_MAP(ibo.edituv_points);
MDEPS_ASSERT_MAP(ibo.edituv_fdots);
- MDEPS_ASSERT_MAP(tris_per_mat);
+ MDEPS_ASSERT_MAP_INDEX(TRIS_PER_MAT_INDEX);
/* Meh loose Scene const correctness here. */
const bool use_subsurf_fdots = scene ? BKE_modifiers_uses_subsurf_facedots(scene, ob) : false;
@@ -1771,7 +1773,6 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
mesh_buffer_cache_create_requested(task_graph,
cache,
&cache->uv_cage,
- &cache->uv_cage_extraction_cache,
me,
is_editmode,
is_paint_mode,
@@ -1789,7 +1790,6 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
mesh_buffer_cache_create_requested(task_graph,
cache,
&cache->cage,
- &cache->cage_extraction_cache,
me,
is_editmode,
is_paint_mode,
@@ -1806,7 +1806,6 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
mesh_buffer_cache_create_requested(task_graph,
cache,
&cache->final,
- &cache->final_extraction_cache,
me,
is_editmode,
is_paint_mode,
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.c b/source/blender/draw/intern/mesh_extractors/extract_mesh.c
index 53827dcc7d9..44de07c8594 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh.c
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.c
@@ -33,11 +33,11 @@
#include "draw_cache_impl.h"
-void *mesh_extract_buffer_get(const MeshExtract *extractor, MeshBufferCache *mbc)
+void *mesh_extract_buffer_get(const MeshExtract *extractor, MeshBufferList *mbuflist)
{
/* NOTE: POINTER_OFFSET on windows platforms casts internally to `void *`, but on GCC/CLANG to
- * `MeshBufferCache *`. What shows a different usage versus intent. */
- void **buffer_ptr = (void **)POINTER_OFFSET(mbc, extractor->mesh_buffer_offset);
+ * `MeshBufferList *`. What shows a different usage versus intent. */
+ void **buffer_ptr = (void **)POINTER_OFFSET(mbuflist, extractor->mesh_buffer_offset);
void *buffer = *buffer_ptr;
BLI_assert(buffer);
return buffer;
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.h b/source/blender/draw/intern/mesh_extractors/extract_mesh.h
index f24ccf1a028..d9f397fd8b8 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh.h
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.h
@@ -232,7 +232,7 @@ typedef struct MeshExtract {
/** Used to know if the element callbacks are thread-safe and can be parallelized. */
bool use_threading;
/**
- * Offset in bytes of the buffer inside a MeshBufferCache instance. Points to a vertex or index
+ * Offset in bytes of the buffer inside a MeshBufferList instance. Points to a vertex or index
* buffer.
*/
size_t mesh_buffer_offset;
@@ -252,11 +252,11 @@ MeshRenderData *mesh_render_data_create(Mesh *me,
void mesh_render_data_free(MeshRenderData *mr);
void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_flag);
void mesh_render_data_update_loose_geom(MeshRenderData *mr,
- MeshBufferExtractionCache *cache,
+ MeshBufferCache *cache,
const eMRIterType iter_type,
const eMRDataType data_flag);
void mesh_render_data_update_polys_sorted(MeshRenderData *mr,
- MeshBufferExtractionCache *cache,
+ MeshBufferCache *cache,
const eMRDataType data_flag);
void mesh_render_data_update_looptris(MeshRenderData *mr,
const eMRIterType iter_type,
@@ -270,7 +270,7 @@ typedef struct EditLoopData {
uchar bweight;
} EditLoopData;
-void *mesh_extract_buffer_get(const MeshExtract *extractor, MeshBufferCache *mbc);
+void *mesh_extract_buffer_get(const MeshExtract *extractor, MeshBufferList *mbuflist);
eMRIterType mesh_extract_iter_type(const MeshExtract *ext);
const MeshExtract *mesh_extract_override_get(const MeshExtract *extractor,
const bool do_hq_normals,
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc
index 5bd5f7adaa8..d06fb91411e 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc
@@ -104,7 +104,7 @@ constexpr MeshExtract create_extractor_edituv_tris()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_EditUvElem_Data);
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.edituv_tris);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.edituv_tris);
return extractor;
}
@@ -194,7 +194,7 @@ constexpr MeshExtract create_extractor_edituv_lines()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_EditUvElem_Data);
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.edituv_lines);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.edituv_lines);
return extractor;
}
@@ -278,7 +278,7 @@ constexpr MeshExtract create_extractor_edituv_points()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_EditUvElem_Data);
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.edituv_points);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.edituv_points);
return extractor;
}
@@ -374,7 +374,7 @@ constexpr MeshExtract create_extractor_edituv_fdots()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_EditUvElem_Data);
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.edituv_fdots);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.edituv_fdots);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc
index 0f41702a22c..ea58e1aeed8 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc
@@ -105,7 +105,7 @@ constexpr MeshExtract create_extractor_fdots()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(GPUIndexBufBuilder);
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.fdots);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.fdots);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc
index 0096da9e56f..54f5611106f 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc
@@ -168,7 +168,7 @@ constexpr MeshExtract create_extractor_lines()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(GPUIndexBufBuilder);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.lines);
return extractor;
}
@@ -180,12 +180,12 @@ constexpr MeshExtract create_extractor_lines()
static void extract_lines_loose_subbuffer(const MeshRenderData *mr, struct MeshBatchCache *cache)
{
- BLI_assert(cache->final.ibo.lines);
+ BLI_assert(cache->final.buff.ibo.lines);
/* Multiply by 2 because these are edges indices. */
const int start = mr->edge_len * 2;
const int len = mr->edge_loose_len * 2;
GPU_indexbuf_create_subrange_in_place(
- cache->final.ibo.lines_loose, cache->final.ibo.lines, start, len);
+ cache->final.buff.ibo.lines_loose, cache->final.buff.ibo.lines, start, len);
cache->no_loose_wire = (len == 0);
}
@@ -213,7 +213,7 @@ constexpr MeshExtract create_extractor_lines_with_lines_loose()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(GPUIndexBufBuilder);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.lines);
return extractor;
}
@@ -228,7 +228,7 @@ static void extract_lines_loose_only_init(const MeshRenderData *mr,
void *buf,
void *UNUSED(tls_data))
{
- BLI_assert(buf == cache->final.ibo.lines_loose);
+ BLI_assert(buf == cache->final.buff.ibo.lines_loose);
UNUSED_VARS_NDEBUG(buf);
extract_lines_loose_subbuffer(mr, cache);
}
@@ -240,7 +240,7 @@ constexpr MeshExtract create_extractor_lines_loose_only()
extractor.data_type = MR_DATA_LOOSE_GEOM;
extractor.data_size = 0;
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines_loose);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.lines_loose);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc
index 7a37cf50264..522afcd44a1 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc
@@ -185,7 +185,7 @@ constexpr MeshExtract create_extractor_lines_adjacency()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_LineAdjacency_Data);
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines_adjacency);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.lines_adjacency);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc
index 5def7edb75a..494a43e97d1 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc
@@ -114,7 +114,7 @@ constexpr MeshExtract create_extractor_lines_paint_mask()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_LinePaintMask_Data);
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines_paint_mask);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.lines_paint_mask);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc
index cc1a19b8d26..b801ba04162 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc
@@ -169,7 +169,7 @@ constexpr MeshExtract create_extractor_points()
extractor.use_threading = true;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(GPUIndexBufBuilder);
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.points);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.points);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc
index e346177af52..54e733d3d86 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc
@@ -105,20 +105,19 @@ static void extract_tris_finish(const MeshRenderData *mr,
/* Create ibo sub-ranges. Always do this to avoid error when the standard surface batch
* is created before the surfaces-per-material. */
- if (mr->use_final_mesh && cache->final.tris_per_mat) {
- MeshBufferCache *mbc_final = &cache->final;
+ if (mr->use_final_mesh && cache->tris_per_mat) {
int mat_start = 0;
for (int i = 0; i < mr->mat_len; i++) {
/* These IBOs have not been queried yet but we create them just in case they are needed
* later since they are not tracked by mesh_buffer_cache_create_requested(). */
- if (mbc_final->tris_per_mat[i] == nullptr) {
- mbc_final->tris_per_mat[i] = GPU_indexbuf_calloc();
+ if (cache->tris_per_mat[i] == nullptr) {
+ cache->tris_per_mat[i] = GPU_indexbuf_calloc();
}
const int mat_tri_len = mr->poly_sorted.mat_tri_len[i];
/* Multiply by 3 because these are triangle indices. */
const int start = mat_start * 3;
const int len = mat_tri_len * 3;
- GPU_indexbuf_create_subrange_in_place(mbc_final->tris_per_mat[i], ibo, start, len);
+ GPU_indexbuf_create_subrange_in_place(cache->tris_per_mat[i], ibo, start, len);
mat_start += mat_tri_len;
}
}
@@ -135,7 +134,7 @@ constexpr MeshExtract create_extractor_tris()
extractor.data_type = MR_DATA_LOOPTRI | MR_DATA_POLYS_SORTED;
extractor.data_size = sizeof(GPUIndexBufBuilder);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.tris);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.tris);
return extractor;
}
@@ -197,17 +196,16 @@ static void extract_tris_single_mat_finish(const MeshRenderData *mr,
/* Create ibo sub-ranges. Always do this to avoid error when the standard surface batch
* is created before the surfaces-per-material. */
- if (mr->use_final_mesh && cache->final.tris_per_mat) {
- MeshBufferCache *mbc = &cache->final;
+ if (mr->use_final_mesh && cache->tris_per_mat) {
for (int i = 0; i < mr->mat_len; i++) {
/* These IBOs have not been queried yet but we create them just in case they are needed
* later since they are not tracked by mesh_buffer_cache_create_requested(). */
- if (mbc->tris_per_mat[i] == nullptr) {
- mbc->tris_per_mat[i] = GPU_indexbuf_calloc();
+ if (cache->tris_per_mat[i] == nullptr) {
+ cache->tris_per_mat[i] = GPU_indexbuf_calloc();
}
/* Multiply by 3 because these are triangle indices. */
const int len = mr->tri_len * 3;
- GPU_indexbuf_create_subrange_in_place(mbc->tris_per_mat[i], ibo, 0, len);
+ GPU_indexbuf_create_subrange_in_place(cache->tris_per_mat[i], ibo, 0, len);
}
}
}
@@ -223,7 +221,7 @@ constexpr MeshExtract create_extractor_tris_single_mat()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(GPUIndexBufBuilder);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.tris);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.tris);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc
index 302616d4da9..2e2444a8e3d 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc
@@ -228,7 +228,7 @@ constexpr MeshExtract create_extractor_edge_fac()
extractor.data_type = MR_DATA_POLY_NOR;
extractor.data_size = sizeof(MeshExtract_EdgeFac_Data);
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edge_fac);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.edge_fac);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc
index a7efb9c8a1b..5232346e51e 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc
@@ -253,7 +253,7 @@ constexpr MeshExtract create_extractor_edit_data()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(EditLoopData *);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edit_data);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.edit_data);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc
index 0378aadabd0..b8494428eed 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc
@@ -128,7 +128,7 @@ constexpr MeshExtract create_extractor_edituv_data()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_EditUVData_Data);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_data);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.edituv_data);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc
index a60c0182e89..a947d98f955 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc
@@ -222,7 +222,7 @@ constexpr MeshExtract create_extractor_edituv_edituv_stretch_angle()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_StretchAngle_Data);
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_stretch_angle);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.edituv_stretch_angle);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc
index d79ac493c33..3db8cd79af5 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc
@@ -143,7 +143,7 @@ constexpr MeshExtract create_extractor_edituv_stretch_area()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = 0;
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_stretch_area);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.edituv_stretch_area);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc
index b7182d1b60f..28592417183 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc
@@ -89,7 +89,7 @@ constexpr MeshExtract create_extractor_fdots_edituv_data()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_EditUVFdotData_Data);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_edituv_data);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.fdots_edituv_data);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc
index 5e4ad54f7b6..fed66f0057d 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc
@@ -105,7 +105,7 @@ constexpr MeshExtract create_extractor_fdots_nor()
extractor.data_type = MR_DATA_LOOP_NOR;
extractor.data_size = 0;
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_nor);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.fdots_nor);
return extractor;
}
@@ -186,7 +186,7 @@ constexpr MeshExtract create_extractor_fdots_nor_hq()
extractor.data_type = MR_DATA_LOOP_NOR;
extractor.data_size = 0;
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_nor);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.fdots_nor);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc
index e765fb8a8bf..33f9180e122 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc
@@ -106,7 +106,7 @@ constexpr MeshExtract create_extractor_fdots_pos()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(float(*)[3]);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_pos);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.fdots_pos);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc
index 042a0d2debe..6fe714def30 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc
@@ -114,7 +114,7 @@ constexpr MeshExtract create_extractor_fdots_uv()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_FdotUV_Data);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_uv);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.fdots_uv);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc
index 8344a615cbe..f9f66c27aaa 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc
@@ -116,7 +116,7 @@ constexpr MeshExtract create_extractor_lnor()
extractor.data_type = MR_DATA_LOOP_NOR;
extractor.data_size = sizeof(GPUPackedNormal *);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.lnor);
return extractor;
}
@@ -214,7 +214,7 @@ constexpr MeshExtract create_extractor_lnor_hq()
extractor.data_type = MR_DATA_LOOP_NOR;
extractor.data_size = sizeof(gpuHQNor *);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.lnor);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc
index 075d54e268e..33a33c81bc2 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc
@@ -641,7 +641,7 @@ constexpr MeshExtract create_extractor_mesh_analysis()
extractor.data_type = MR_DATA_POLY_NOR | MR_DATA_LOOPTRI;
extractor.data_size = 0;
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.mesh_analysis);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.mesh_analysis);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc
index 269c0343e32..c5187a47892 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc
@@ -102,7 +102,7 @@ constexpr MeshExtract create_extractor_orco()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_Orco_Data);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.orco);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.orco);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc
index b8e5dcb613f..eb9a138590c 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc
@@ -208,7 +208,7 @@ constexpr MeshExtract create_extractor_pos_nor()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_PosNor_Data);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.pos_nor);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.pos_nor);
return extractor;
}
@@ -401,7 +401,7 @@ constexpr MeshExtract create_extractor_pos_nor_hq()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_PosNorHQ_Data);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.pos_nor);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.pos_nor);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc
index dbb1e1f880b..fd91bc5258f 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc
@@ -128,7 +128,7 @@ constexpr MeshExtract create_extractor_sculpt_data()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = 0;
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.sculpt_data);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.sculpt_data);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc
index cd8d46901c5..5ac30dd3be9 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc
@@ -205,7 +205,7 @@ constexpr MeshExtract create_extractor_poly_idx()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(uint32_t *);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.poly_idx);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.poly_idx);
return extractor;
}
@@ -220,7 +220,7 @@ constexpr MeshExtract create_extractor_edge_idx()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(uint32_t *);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edge_idx);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.edge_idx);
return extractor;
}
@@ -237,7 +237,7 @@ constexpr MeshExtract create_extractor_vert_idx()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(uint32_t *);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.vert_idx);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.vert_idx);
return extractor;
}
@@ -279,7 +279,7 @@ constexpr MeshExtract create_extractor_fdot_idx()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(uint32_t *);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdot_idx);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.fdot_idx);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc
index ffca01d00dd..1847a360837 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc
@@ -80,7 +80,7 @@ constexpr MeshExtract create_extractor_skin_roots()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = 0;
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.skin_roots);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.skin_roots);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc
index 8f36bfdf1ef..1f8776fc98e 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc
@@ -226,7 +226,7 @@ constexpr MeshExtract create_extractor_tan()
extractor.data_type = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI;
extractor.data_size = 0;
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.tan);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.tan);
return extractor;
}
@@ -252,7 +252,7 @@ constexpr MeshExtract create_extractor_tan_hq()
extractor.data_type = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI;
extractor.data_size = 0;
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.tan);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.tan);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc
index 013da7d674a..af279b08a59 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc
@@ -123,7 +123,7 @@ constexpr MeshExtract create_extractor_uv()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = 0;
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.uv);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.uv);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc
index d810acfb617..2c7770c8e72 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc
@@ -178,7 +178,7 @@ constexpr MeshExtract create_extractor_vcol()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = 0;
extractor.use_threading = false;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.vcol);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.vcol);
return extractor;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc
index c547a453aeb..bdb1410a755 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc
@@ -176,7 +176,7 @@ constexpr MeshExtract create_extractor_weights()
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_Weight_Data);
extractor.use_threading = true;
- extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.weights);
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.weights);
return extractor;
}
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 39fb2882e4b..b7deea5069e 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -576,7 +576,7 @@ static int paste_from_file_exec(bContext *C, wmOperator *op)
char *path;
int retval;
- path = RNA_string_get_alloc(op->ptr, "filepath", NULL, 0);
+ path = RNA_string_get_alloc(op->ptr, "filepath", NULL, 0, NULL);
retval = paste_from_file(C, op->reports, path);
MEM_freeN(path);
@@ -1627,7 +1627,7 @@ static int insert_text_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- inserted_utf8 = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
+ inserted_utf8 = RNA_string_get_alloc(op->ptr, "text", NULL, 0, NULL);
len = BLI_strlen_utf8(inserted_utf8);
inserted_text = MEM_callocN(sizeof(char32_t) * (len + 1), "FONT_insert_text");
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index 6e4002fcc0a..1d51a3e77cf 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -53,8 +53,9 @@ typedef enum {
#define NODE_EDGE_PAN_INSIDE_PAD 2
#define NODE_EDGE_PAN_OUTSIDE_PAD 0 /* Disable clamping for node panning, use whole screen. */
#define NODE_EDGE_PAN_SPEED_RAMP 1
-#define NODE_EDGE_PAN_MAX_SPEED 40 /* In UI units per second, slower than default. */
-#define NODE_EDGE_PAN_DELAY 1.0f
+#define NODE_EDGE_PAN_MAX_SPEED 26 /* In UI units per second, slower than default. */
+#define NODE_EDGE_PAN_DELAY 0.5f
+#define NODE_EDGE_PAN_ZOOM_INFLUENCE 0.5f
/* space_node.c */
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index cb6fb0dba60..69ac48d842f 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -137,6 +137,7 @@ int BIF_countTransformOrientation(const struct bContext *C);
#define P_GPENCIL_EDIT (1 << 13)
#define P_CURSOR_EDIT (1 << 14)
#define P_CLNOR_INVALIDATE (1 << 15)
+#define P_VIEW2D_EDGE_PAN (1 << 16)
/* For properties performed when confirming the transformation. */
#define P_POST_TRANSFORM (1 << 19)
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index c99c7f681b3..dde8a637e05 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -185,7 +185,7 @@ typedef enum ThemeColorID {
TH_NODE_LAYOUT,
TH_NODE_SHADER,
TH_NODE_INTERFACE,
- TH_NODE_CONVERTOR,
+ TH_NODE_CONVERTER,
TH_NODE_GROUP,
TH_NODE_FRAME,
TH_NODE_MATTE,
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 4ee7df89487..e3c02b4c249 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -26,6 +26,7 @@
#pragma once
#include "BLI_compiler_attrs.h"
+#include "BLI_rect.h"
#ifdef __cplusplus
extern "C" {
@@ -321,6 +322,14 @@ typedef struct View2DEdgePanData {
float max_speed;
/** Delay in seconds before maximum speed is reached. */
float delay;
+ /** Influence factor for view zoom:
+ * 0 = Constant speed in UI units
+ * 1 = Constant speed in view space, UI speed slows down when zooming out
+ */
+ float zoom_influence;
+
+ /** Initial view rect. */
+ rctf initial_rect;
/** Amount to move view relative to zoom. */
float facx, facy;
@@ -338,7 +347,8 @@ void UI_view2d_edge_pan_init(struct bContext *C,
float outside_pad,
float speed_ramp,
float max_speed,
- float delay);
+ float delay,
+ float zoom_influence);
void UI_view2d_edge_pan_reset(struct View2DEdgePanData *vpd);
@@ -350,6 +360,8 @@ void UI_view2d_edge_pan_apply_event(struct bContext *C,
struct View2DEdgePanData *vpd,
const struct wmEvent *event);
+void UI_view2d_edge_pan_cancel(struct bContext *C, struct View2DEdgePanData *vpd);
+
void UI_view2d_edge_pan_operator_properties(struct wmOperatorType *ot);
void UI_view2d_edge_pan_operator_properties_ex(struct wmOperatorType *ot,
@@ -357,7 +369,8 @@ void UI_view2d_edge_pan_operator_properties_ex(struct wmOperatorType *ot,
float outside_pad,
float speed_ramp,
float max_speed,
- float delay);
+ float delay,
+ float zoom_influence);
/* Initialize panning data with operator settings. */
void UI_view2d_edge_pan_operator_init(struct bContext *C,
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 76f6640c714..a618daec4bc 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -3350,7 +3350,7 @@ static bool ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, const in
if (pbuf) {
if (UI_but_is_utf8(but)) {
- buf_len -= BLI_utf8_invalid_strip(pbuf, (size_t)buf_len);
+ buf_len -= BLI_str_utf8_invalid_strip(pbuf, (size_t)buf_len);
}
ui_textedit_insert_buf(but, data, pbuf, buf_len);
@@ -3527,7 +3527,7 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
if (but) {
if (UI_but_is_utf8(but)) {
- const int strip = BLI_utf8_invalid_strip(but->editstr, strlen(but->editstr));
+ const int strip = BLI_str_utf8_invalid_strip(but->editstr, strlen(but->editstr));
/* not a file?, strip non utf-8 chars */
if (strip) {
/* won't happen often so isn't that annoying to keep it here for a while */
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index c9bfd883332..e13b69a9763 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -631,7 +631,7 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_NODE_SHADER:
cp = ts->nodeclass_shader;
break;
- case TH_NODE_CONVERTOR:
+ case TH_NODE_CONVERTER:
cp = ts->syntaxv;
break;
case TH_NODE_GROUP:
diff --git a/source/blender/editors/interface/view2d_edge_pan.c b/source/blender/editors/interface/view2d_edge_pan.c
index 1d300c7b275..eaf8ef30311 100644
--- a/source/blender/editors/interface/view2d_edge_pan.c
+++ b/source/blender/editors/interface/view2d_edge_pan.c
@@ -71,7 +71,8 @@ void UI_view2d_edge_pan_init(bContext *C,
float outside_pad,
float speed_ramp,
float max_speed,
- float delay)
+ float delay,
+ float zoom_influence)
{
if (!UI_view2d_edge_pan_poll(C)) {
return;
@@ -89,6 +90,7 @@ void UI_view2d_edge_pan_init(bContext *C,
vpd->speed_ramp = speed_ramp;
vpd->max_speed = max_speed;
vpd->delay = delay;
+ vpd->zoom_influence = zoom_influence;
/* Calculate translation factor, based on size of view. */
const float winx = (float)(BLI_rcti_size_x(&vpd->region->winrct) + 1);
@@ -104,6 +106,7 @@ void UI_view2d_edge_pan_reset(View2DEdgePanData *vpd)
vpd->edge_pan_start_time_x = 0.0;
vpd->edge_pan_start_time_y = 0.0;
vpd->edge_pan_last_time = PIL_check_seconds_timer();
+ vpd->initial_rect = vpd->region->v2d.cur;
}
/**
@@ -168,9 +171,15 @@ static float edge_pan_speed(View2DEdgePanData *vpd,
/* Apply a fade in to the speed based on a start time delay. */
const double start_time = x_dir ? vpd->edge_pan_start_time_x : vpd->edge_pan_start_time_y;
- const float delay_factor = smootherstep(vpd->delay, (float)(current_time - start_time));
+ const float delay_factor = vpd->delay > 0.01f ?
+ smootherstep(vpd->delay, (float)(current_time - start_time)) :
+ 1.0f;
- return distance_factor * delay_factor * vpd->max_speed * U.widget_unit * (float)U.dpi_fac;
+ /* Zoom factor increases speed when zooming in and decreases speed when zooming out. */
+ const float zoomx = (float)(BLI_rcti_size_x(&region->winrct) + 1) / BLI_rctf_size_x(&region->v2d.cur);
+ const float zoom_factor = 1.0f + CLAMPIS(vpd->zoom_influence, 0.0f, 1.0f) * (zoomx - 1.0f);
+
+ return distance_factor * delay_factor * zoom_factor * vpd->max_speed * U.widget_unit * (float)U.dpi_fac;
}
static void edge_pan_apply_delta(bContext *C, View2DEdgePanData *vpd, float dx, float dy)
@@ -264,6 +273,27 @@ void UI_view2d_edge_pan_apply_event(bContext *C, View2DEdgePanData *vpd, const w
UI_view2d_edge_pan_apply(C, vpd, event->x, event->y);
}
+void UI_view2d_edge_pan_cancel(bContext *C, View2DEdgePanData *vpd)
+{
+ View2D *v2d = vpd->v2d;
+ if (!v2d) {
+ return;
+ }
+
+ v2d->cur = vpd->initial_rect;
+
+ /* Inform v2d about changes after this operation. */
+ UI_view2d_curRect_changed(C, v2d);
+
+ /* Don't rebuild full tree in outliner, since we're just changing our view. */
+ ED_region_tag_redraw_no_rebuild(vpd->region);
+
+ /* Request updates to be done. */
+ WM_event_add_mousemove(CTX_wm_window(C));
+
+ UI_view2d_sync(vpd->screen, vpd->area, v2d, V2D_LOCK_COPY);
+}
+
void UI_view2d_edge_pan_operator_properties(wmOperatorType *ot)
{
/* Default values for edge panning operators. */
@@ -272,7 +302,8 @@ void UI_view2d_edge_pan_operator_properties(wmOperatorType *ot)
/*outside_pad*/ 0.0f,
/*speed_ramp*/ 1.0f,
/*max_speed*/ 500.0f,
- /*delay*/ 1.0f);
+ /*delay*/ 1.0f,
+ /*zoom_influence*/ 0.0f);
}
void UI_view2d_edge_pan_operator_properties_ex(struct wmOperatorType *ot,
@@ -280,7 +311,8 @@ void UI_view2d_edge_pan_operator_properties_ex(struct wmOperatorType *ot,
float outside_pad,
float speed_ramp,
float max_speed,
- float delay)
+ float delay,
+ float zoom_influence)
{
RNA_def_float(
ot->srna,
@@ -329,6 +361,15 @@ void UI_view2d_edge_pan_operator_properties_ex(struct wmOperatorType *ot,
"Delay in seconds before maximum speed is reached",
0.0f,
10.0f);
+ RNA_def_float(ot->srna,
+ "zoom_influence",
+ zoom_influence,
+ 0.0f,
+ 1.0f,
+ "Zoom Influence",
+ "Influence of the zoom factor on scroll speed",
+ 0.0f,
+ 1.0f);
}
void UI_view2d_edge_pan_operator_init(bContext *C, View2DEdgePanData *vpd, wmOperator *op)
@@ -339,7 +380,8 @@ void UI_view2d_edge_pan_operator_init(bContext *C, View2DEdgePanData *vpd, wmOpe
RNA_float_get(op->ptr, "outside_padding"),
RNA_float_get(op->ptr, "speed_ramp"),
RNA_float_get(op->ptr, "max_speed"),
- RNA_float_get(op->ptr, "delay"));
+ RNA_float_get(op->ptr, "delay"),
+ RNA_float_get(op->ptr, "zoom_influence"));
}
/** \} */
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 12b52907057..34400462d38 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -3359,8 +3359,13 @@ Base *ED_object_add_duplicate(
Base *basen;
Object *ob;
- basen = object_add_duplicate_internal(
- bmain, scene, view_layer, base->object, dupflag, LIB_ID_DUPLICATE_IS_SUBPROCESS);
+ basen = object_add_duplicate_internal(bmain,
+ scene,
+ view_layer,
+ base->object,
+ dupflag,
+ LIB_ID_DUPLICATE_IS_SUBPROCESS |
+ LIB_ID_DUPLICATE_IS_ROOT_ID);
if (basen == NULL) {
return NULL;
}
@@ -3395,8 +3400,13 @@ static int duplicate_exec(bContext *C, wmOperator *op)
BKE_main_id_newptr_and_tag_clear(bmain);
CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
- Base *basen = object_add_duplicate_internal(
- bmain, scene, view_layer, base->object, dupflag, LIB_ID_DUPLICATE_IS_SUBPROCESS);
+ Base *basen = object_add_duplicate_internal(bmain,
+ scene,
+ view_layer,
+ base->object,
+ dupflag,
+ LIB_ID_DUPLICATE_IS_SUBPROCESS |
+ LIB_ID_DUPLICATE_IS_ROOT_ID);
/* note that this is safe to do with this context iterator,
* the list is made in advance */
@@ -3516,7 +3526,7 @@ static int object_add_named_exec(bContext *C, wmOperator *op)
* the case here. So we have to do the new-ID relinking ourselves
* (#copy_object_set_idnew()).
*/
- LIB_ID_DUPLICATE_IS_SUBPROCESS);
+ LIB_ID_DUPLICATE_IS_SUBPROCESS | LIB_ID_DUPLICATE_IS_ROOT_ID);
}
else {
/* basen is actually not a new base in this case. */
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index e9142742d15..e1e0a0600be 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -352,7 +352,7 @@ static bool object_modifier_remove(
/* special cases */
if (md->type == eModifierType_ParticleSystem) {
- object_remove_particle_system(bmain, scene, ob);
+ object_remove_particle_system(bmain, scene, ob, ((ParticleSystemModifierData *)md)->psys);
return true;
}
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 2668846284d..3ac6dca3044 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -124,7 +124,8 @@ static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op))
}
mode_orig = ob->mode;
- object_remove_particle_system(bmain, scene, ob);
+ ParticleSystem *psys = psys_get_current(ob);
+ object_remove_particle_system(bmain, scene, ob, psys);
/* possible this isn't the active object
* object_remove_particle_system() clears the mode on the last psys
diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c
index c141789f171..798f4898aaa 100644
--- a/source/blender/editors/space_buttons/buttons_ops.c
+++ b/source/blender/editors/space_buttons/buttons_ops.c
@@ -198,7 +198,8 @@ static int file_browse_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
FileBrowseOp *fbo = op->customdata;
ID *id;
- char *str, path[FILE_MAX];
+ char *str;
+ int str_len;
const char *path_prop = RNA_struct_find_property(op->ptr, "directory") ? "directory" :
"filepath";
@@ -206,10 +207,11 @@ static int file_browse_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- str = RNA_string_get_alloc(op->ptr, path_prop, NULL, 0);
+ str = RNA_string_get_alloc(op->ptr, path_prop, NULL, 0, &str_len);
/* Add slash for directories, important for some properties. */
if (RNA_property_subtype(fbo->prop) == PROP_DIRPATH) {
+ char path[FILE_MAX];
const bool is_relative = RNA_boolean_get(op->ptr, "relative_path");
id = fbo->ptr.owner_id;
@@ -220,13 +222,13 @@ static int file_browse_exec(bContext *C, wmOperator *op)
/* Do this first so '//' isn't converted to '//\' on windows. */
BLI_path_slash_ensure(path);
if (is_relative) {
- BLI_strncpy(path, str, FILE_MAX);
+ const int path_len = BLI_strncpy_rlen(path, str, FILE_MAX);
BLI_path_rel(path, BKE_main_blendfile_path(bmain));
- str = MEM_reallocN(str, strlen(path) + 2);
+ str = MEM_reallocN(str, path_len + 2);
BLI_strncpy(str, path, FILE_MAX);
}
else {
- str = MEM_reallocN(str, strlen(str) + 2);
+ str = MEM_reallocN(str, str_len + 2);
}
}
else {
diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c
index bdb7c622cd2..763beb8671b 100644
--- a/source/blender/editors/space_console/console_ops.c
+++ b/source/blender/editors/space_console/console_ops.c
@@ -384,7 +384,7 @@ static int console_insert_exec(bContext *C, wmOperator *op)
SpaceConsole *sc = CTX_wm_space_console(C);
ARegion *region = CTX_wm_region(C);
ConsoleLine *ci = console_history_verify(C);
- char *str = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
+ char *str = RNA_string_get_alloc(op->ptr, "text", NULL, 0, NULL);
int len;
if (str[0] == '\t' && str[1] == '\0') {
@@ -860,7 +860,7 @@ static int console_history_append_exec(bContext *C, wmOperator *op)
ScrArea *area = CTX_wm_area(C);
ConsoleLine *ci = console_history_verify(C);
/* own this text in the new line, don't free */
- char *str = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
+ char *str = RNA_string_get_alloc(op->ptr, "text", NULL, 0, NULL);
int cursor = RNA_int_get(op->ptr, "current_character");
const bool rem_dupes = RNA_boolean_get(op->ptr, "remove_duplicates");
int prev_len = ci->len;
@@ -923,7 +923,7 @@ static int console_scrollback_append_exec(bContext *C, wmOperator *op)
ConsoleLine *ci;
/* own this text in the new line, don't free */
- char *str = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
+ char *str = RNA_string_get_alloc(op->ptr, "text", NULL, 0, NULL);
int type = RNA_enum_get(op->ptr, "type");
console_history_verify(C);
diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c
index 169dafcb8d0..a95189a303f 100644
--- a/source/blender/editors/space_image/image_edit.c
+++ b/source/blender/editors/space_image/image_edit.c
@@ -139,8 +139,10 @@ ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **r_lock, int tile)
ImBuf *ibuf;
if (sima && sima->image) {
+ const Image *image = sima->image;
+
#if 0
- if (sima->image->type == IMA_TYPE_R_RESULT && BIF_show_render_spare()) {
+ if (image->type == IMA_TYPE_R_RESULT && BIF_show_render_spare()) {
return BIF_render_spare_imbuf();
}
else
@@ -152,6 +154,12 @@ ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **r_lock, int tile)
}
if (ibuf) {
+ if (image->type == IMA_TYPE_R_RESULT && ibuf->x != 0 && ibuf->y != 0) {
+ /* Render result might be lazily allocated. Return ibuf without buffers to indicate that
+ * there is image buffer but it has no data yet. */
+ return ibuf;
+ }
+
if (ibuf->rect || ibuf->rect_float) {
return ibuf;
}
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 29c1452b988..4f8feda3911 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -3935,7 +3935,7 @@ static int tile_add_exec(bContext *C, wmOperator *op)
}
bool fill_tile = RNA_boolean_get(op->ptr, "fill");
- char *label = RNA_string_get_alloc(op->ptr, "label", NULL, 0);
+ char *label = RNA_string_get_alloc(op->ptr, "label", NULL, 0, NULL);
/* BKE_image_add_tile assumes a pre-sorted list of tiles. */
BKE_image_sort_tiles(ima);
diff --git a/source/blender/editors/space_image/image_sequence.c b/source/blender/editors/space_image/image_sequence.c
index 288b3d94b1d..c4f111264a3 100644
--- a/source/blender/editors/space_image/image_sequence.c
+++ b/source/blender/editors/space_image/image_sequence.c
@@ -68,7 +68,7 @@ static void image_sequence_get_frame_ranges(wmOperator *op, ListBase *ranges)
RNA_BEGIN (op->ptr, itemptr, "files") {
char head[FILE_MAX], tail[FILE_MAX];
ushort digits;
- char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+ char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0, NULL);
ImageFrame *frame = MEM_callocN(sizeof(ImageFrame), "image_frame");
/* use the first file in the list as base filename */
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
index 94e53958524..a99396ecdf0 100644
--- a/source/blender/editors/space_info/info_ops.c
+++ b/source/blender/editors/space_info/info_ops.c
@@ -512,7 +512,7 @@ void FILE_OT_report_missing_files(wmOperatorType *ot)
static int find_missing_files_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- const char *searchpath = RNA_string_get_alloc(op->ptr, "directory", NULL, 0);
+ const char *searchpath = RNA_string_get_alloc(op->ptr, "directory", NULL, 0, NULL);
const bool find_all = RNA_boolean_get(op->ptr, "find_all");
BKE_bpath_missing_files_find(bmain, searchpath, op->reports, find_all);
diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc
index 6ec6315a238..3b1a55f55ab 100644
--- a/source/blender/editors/space_node/node_draw.cc
+++ b/source/blender/editors/space_node/node_draw.cc
@@ -670,8 +670,8 @@ int node_get_colorid(bNode *node)
return TH_NODE_INPUT;
case NODE_CLASS_OUTPUT:
return (node->flag & NODE_DO_OUTPUT) ? TH_NODE_OUTPUT : TH_NODE;
- case NODE_CLASS_CONVERTOR:
- return TH_NODE_CONVERTOR;
+ case NODE_CLASS_CONVERTER:
+ return TH_NODE_CONVERTER;
case NODE_CLASS_OP_COLOR:
return TH_NODE_COLOR;
case NODE_CLASS_OP_VECTOR:
diff --git a/source/blender/editors/space_node/node_geometry_attribute_search.cc b/source/blender/editors/space_node/node_geometry_attribute_search.cc
index a6901c21862..411719cf6c0 100644
--- a/source/blender/editors/space_node/node_geometry_attribute_search.cc
+++ b/source/blender/editors/space_node/node_geometry_attribute_search.cc
@@ -17,6 +17,7 @@
#include "BLI_index_range.hh"
#include "BLI_listbase.h"
#include "BLI_map.hh"
+#include "BLI_rect.h"
#include "BLI_set.hh"
#include "BLI_string_ref.hh"
#include "BLI_string_search.h"
diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc
index c6c3ca27d6e..e908a61eed9 100644
--- a/source/blender/editors/space_node/node_relationships.cc
+++ b/source/blender/editors/space_node/node_relationships.cc
@@ -880,6 +880,8 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links)
bNodeTree *ntree = snode->edittree;
bNodeLinkDrag *nldrag = (bNodeLinkDrag *)op->customdata;
bool do_tag_update = false;
+ /* View will be reset if no links connect. */
+ bool reset_view = true;
/* avoid updates while applying links */
ntree->is_updating = true;
@@ -917,6 +919,8 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links)
if (link->tonode) {
do_tag_update |= (do_tag_update || node_connected_to_output(bmain, ntree, link->tonode));
}
+
+ reset_view = false;
}
else {
nodeRemLink(ntree, link);
@@ -930,6 +934,10 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links)
snode_dag_update(C, snode);
}
+ if (reset_view) {
+ UI_view2d_edge_pan_cancel(C, &nldrag->pan_data);
+ }
+
BLI_remlink(&snode->runtime->linkdrag, nldrag);
/* links->data pointers are either held by the tree or freed already */
BLI_freelistN(&nldrag->links);
@@ -1207,6 +1215,8 @@ static void node_link_cancel(bContext *C, wmOperator *op)
BLI_remlink(&snode->runtime->linkdrag, nldrag);
+ UI_view2d_edge_pan_cancel(C, &nldrag->pan_data);
+
BLI_freelistN(&nldrag->links);
MEM_freeN(nldrag);
clear_picking_highlight(&snode->edittree->links);
@@ -1258,7 +1268,8 @@ void NODE_OT_link(wmOperatorType *ot)
NODE_EDGE_PAN_OUTSIDE_PAD,
NODE_EDGE_PAN_SPEED_RAMP,
NODE_EDGE_PAN_MAX_SPEED,
- NODE_EDGE_PAN_DELAY);
+ NODE_EDGE_PAN_DELAY,
+ NODE_EDGE_PAN_ZOOM_INFLUENCE);
}
/** \} */
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 1ec1afe86fc..ff0bd533671 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -625,7 +625,7 @@ static int collection_duplicate_exec(bContext *C, wmOperator *op)
}
const eDupli_ID_Flags dupli_flags = USER_DUP_OBJECT | (linked ? 0 : U.dupflag);
- BKE_collection_duplicate(bmain, parent, collection, dupli_flags, 0);
+ BKE_collection_duplicate(bmain, parent, collection, dupli_flags, LIB_ID_DUPLICATE_IS_ROOT_ID);
DEG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_LAYER, CTX_data_scene(C));
diff --git a/source/blender/editors/space_script/script_edit.c b/source/blender/editors/space_script/script_edit.c
index 50cfa2e71c7..13adf6bfc2d 100644
--- a/source/blender/editors/space_script/script_edit.c
+++ b/source/blender/editors/space_script/script_edit.c
@@ -47,12 +47,14 @@
static int run_pyfile_exec(bContext *C, wmOperator *op)
{
- char path[512];
+ char path[FILE_MAX];
RNA_string_get(op->ptr, "filepath", path);
#ifdef WITH_PYTHON
if (BPY_run_filepath(C, path, op->reports)) {
ARegion *region = CTX_wm_region(C);
- ED_region_tag_redraw(region);
+ if (region != NULL) {
+ ED_region_tag_redraw(region);
+ }
return OPERATOR_FINISHED;
}
#else
@@ -70,7 +72,6 @@ void SCRIPT_OT_python_file_run(wmOperatorType *ot)
/* api callbacks */
ot->exec = run_pyfile_exec;
- ot->poll = ED_operator_areaactive;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index ff8cbdb1a59..16b690dd6e4 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -254,11 +254,11 @@ static void load_data_init_from_operator(SeqLoadData *load_data, bContext *C, wm
BLI_strncpy(load_data->name, BLI_path_basename(load_data->path), sizeof(load_data->name));
}
else if ((prop = RNA_struct_find_property(op->ptr, "directory"))) {
- char *directory = RNA_string_get_alloc(op->ptr, "directory", NULL, 0);
+ char *directory = RNA_string_get_alloc(op->ptr, "directory", NULL, 0, NULL);
if ((prop = RNA_struct_find_property(op->ptr, "files"))) {
RNA_PROP_BEGIN (op->ptr, itemptr, prop) {
- char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+ 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);
MEM_freeN(filename);
@@ -944,7 +944,7 @@ int sequencer_image_seq_get_minmax_frame(wmOperator *op,
RNA_BEGIN (op->ptr, itemptr, "files") {
char *filename;
int frame;
- filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+ filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0, NULL);
if (filename) {
if (BLI_path_frame_get(filename, &frame, &numdigits)) {
@@ -973,7 +973,7 @@ void sequencer_image_seq_reserve_frames(
{
char *filename = NULL;
RNA_BEGIN (op->ptr, itemptr, "files") {
- filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+ filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0, NULL);
break;
}
RNA_END;
@@ -1023,7 +1023,7 @@ static void sequencer_add_image_strip_load_files(
else {
size_t strip_frame = 0;
RNA_BEGIN (op->ptr, itemptr, "files") {
- char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+ char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0, NULL);
SEQ_add_image_load_file(seq, strip_frame, filename);
MEM_freeN(filename);
strip_frame++;
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index afad8999e88..694e5fbb41d 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -1446,9 +1446,14 @@ static int sequencer_split_exec(bContext *C, wmOperator *op)
}
if (ignore_selection || seq->flag & SELECT) {
- if (SEQ_edit_strip_split(bmain, scene, ed->seqbasep, seq, split_frame, method) != NULL) {
+ const char *error_msg = NULL;
+ if (SEQ_edit_strip_split(bmain, scene, ed->seqbasep, seq, split_frame, method, &error_msg) !=
+ NULL) {
changed = true;
}
+ if (error_msg != NULL) {
+ BKE_report(op->reports, RPT_ERROR, error_msg);
+ }
}
}
@@ -2826,7 +2831,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
}
else {
RNA_BEGIN (op->ptr, itemptr, "files") {
- char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+ char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0, NULL);
BLI_strncpy(se->name, filename, sizeof(se->name));
MEM_freeN(filename);
se++;
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
index a38ed12e53b..32e455f3ac9 100644
--- a/source/blender/editors/space_text/text_autocomplete.c
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -177,13 +177,12 @@ static GHash *text_autocomplete_build(Text *text)
i_pos = i_start;
while ((i_start < linep->len) &&
(!text_check_identifier_nodigit_unicode(
- BLI_str_utf8_as_unicode_and_size_safe(&linep->line[i_start], &i_pos)))) {
+ BLI_str_utf8_as_unicode_step(linep->line, linep->len, &i_pos)))) {
i_start = i_pos;
}
i_pos = i_end = i_start;
- while ((i_end < linep->len) &&
- (text_check_identifier_unicode(
- BLI_str_utf8_as_unicode_and_size_safe(&linep->line[i_end], &i_pos)))) {
+ while ((i_end < linep->len) && (text_check_identifier_unicode(BLI_str_utf8_as_unicode_step(
+ linep->line, linep->len, &i_pos)))) {
i_end = i_pos;
}
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 2b78ecb245d..f480f60a2b9 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -3424,25 +3424,26 @@ static int text_insert_exec(bContext *C, wmOperator *op)
SpaceText *st = CTX_wm_space_text(C);
Text *text = CTX_data_edit_text(C);
char *str;
+ int str_len;
bool done = false;
size_t i = 0;
uint code;
text_drawcache_tag_update(st, 0);
- str = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
+ str = RNA_string_get_alloc(op->ptr, "text", NULL, 0, &str_len);
ED_text_undo_push_init(C);
if (st && st->overwrite) {
while (str[i]) {
- code = BLI_str_utf8_as_unicode_step(str, &i);
+ code = BLI_str_utf8_as_unicode_step(str, str_len, &i);
done |= txt_replace_char(text, code);
}
}
else {
while (str[i]) {
- code = BLI_str_utf8_as_unicode_step(str, &i);
+ code = BLI_str_utf8_as_unicode_step(str, str_len, &i);
done |= txt_add_char(text, code);
}
}
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 4069a72a8fc..7a83fb71c28 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1671,6 +1671,13 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
}
+ if ((prop = RNA_struct_find_property(op->ptr, "view2d_edge_pan")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ options |= CTX_VIEW2D_EDGE_PAN;
+ }
+ }
+
t->options = options;
t->mode = mode;
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 549ad770ac6..013c5faa54a 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -94,6 +94,8 @@ typedef enum {
CTX_OBMODE_XFORM_OBDATA = (1 << 12),
/** Transform object parents without moving their children. */
CTX_OBMODE_XFORM_SKIP_CHILDREN = (1 << 13),
+ /** Enable edge scrolling in 2D views */
+ CTX_VIEW2D_EDGE_PAN = (1 << 14),
} eTContext;
/** #TransInfo.flag */
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index 094ae080de0..d756e2c90a6 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -1662,20 +1662,23 @@ void animrecord_check_state(TransInfo *t, struct Object *ob)
}
}
-void transform_convert_flush_handle2D(TransData *td, TransData2D *td2d, const float inv_unit_scale)
+void transform_convert_flush_handle2D(TransData *td, TransData2D *td2d, const float y_fac)
{
+ float delta_x = td->loc[0] - td->iloc[0];
+ float delta_y = (td->loc[1] - td->iloc[1]) * y_fac;
+
/* If the handles are to be moved too
* (as side-effect of keyframes moving, to keep the general effect)
* offset them by the same amount so that the general angles are maintained
* (i.e. won't change while handles are free-to-roam and keyframes are snap-locked).
*/
if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) {
- td2d->h1[0] = td2d->ih1[0] + td->loc[0] - td->iloc[0];
- td2d->h1[1] = td2d->ih1[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale;
+ td2d->h1[0] = td2d->ih1[0] + delta_x;
+ td2d->h1[1] = td2d->ih1[1] + delta_y;
}
if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) {
- td2d->h2[0] = td2d->ih2[0] + td->loc[0] - td->iloc[0];
- td2d->h2[1] = td2d->ih2[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale;
+ td2d->h2[0] = td2d->ih2[0] + delta_x;
+ td2d->h2[1] = td2d->ih2[1] + delta_y;
}
}
diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h
index fa34e2555d6..9cb0400cad9 100644
--- a/source/blender/editors/transform/transform_convert.h
+++ b/source/blender/editors/transform/transform_convert.h
@@ -43,9 +43,7 @@ void sort_trans_data_dist(TransInfo *t);
void createTransData(struct bContext *C, TransInfo *t);
bool clipUVTransform(TransInfo *t, float vec[2], const bool resize);
void clipUVData(TransInfo *t);
-void transform_convert_flush_handle2D(TransData *td,
- TransData2D *td2d,
- const float inv_unit_scale);
+void transform_convert_flush_handle2D(TransData *td, TransData2D *td2d, const float y_fac);
void recalcData(TransInfo *t);
/* transform_convert_mesh.c */
diff --git a/source/blender/editors/transform/transform_convert_action.c b/source/blender/editors/transform/transform_convert_action.c
index a5565b5fb88..075db30fa61 100644
--- a/source/blender/editors/transform/transform_convert_action.c
+++ b/source/blender/editors/transform/transform_convert_action.c
@@ -158,8 +158,9 @@ static void TimeToTransData(
/* Setup #TransData. */
td->loc = time; /* Usually #td2d->loc is used here. But this is for when the original location is
not float[3]. */
+ copy_v3_v3(td->iloc, td->loc);
td->val = time;
- td->ival = td->iloc[0] = *(time);
+ td->ival = *(time);
td->center[0] = td->ival;
td->center[1] = ypos;
@@ -615,7 +616,11 @@ void recalcData_actedit(TransInfo *t)
if ((autosnap != SACTSNAP_OFF) && (t->state != TRANS_CANCEL) && !(td->flag & TD_NOTIMESNAP)) {
transform_snap_anim_flush_data(t, td, autosnap, td->loc);
}
- transform_convert_flush_handle2D(td, td2d, 1.0f);
+
+ /* Constrain Y. */
+ td->loc[1] = td->iloc[1];
+
+ transform_convert_flush_handle2D(td, td2d, 0.0f);
}
if (ac.datatype != ANIMCONT_MASK) {
diff --git a/source/blender/editors/transform/transform_convert_node.c b/source/blender/editors/transform/transform_convert_node.c
index 9d2d3713bf0..ecc7f01be33 100644
--- a/source/blender/editors/transform/transform_convert_node.c
+++ b/source/blender/editors/transform/transform_convert_node.c
@@ -46,12 +46,6 @@
/** \name Node Transform Creation
* \{ */
-typedef struct NodeTransCustomData {
- /* Initial rect of the view2d, used for computing offset during edge panning */
- rctf initial_v2d_cur;
- View2DEdgePanData edge_pan;
-} NodeTransCustomData;
-
/* transcribe given node into TransData2D for Transforming */
static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node, const float dpi_fac)
{
@@ -115,21 +109,16 @@ void createTransNodeData(TransInfo *t)
const float dpi_fac = UI_DPI_FAC;
SpaceNode *snode = t->area->spacedata.first;
- if (t->mode == TFM_TRANSLATION) {
- /* Disable cursor wrapping in the node editor for edge pan */
- t->flag |= T_NO_CURSOR_WRAP;
- }
-
/* Custom data to enable edge panning during the node transform */
- NodeTransCustomData *customdata = MEM_callocN(sizeof(*customdata), __func__);
+ View2DEdgePanData *customdata = MEM_callocN(sizeof(*customdata), __func__);
UI_view2d_edge_pan_init(t->context,
- &customdata->edge_pan,
+ customdata,
NODE_EDGE_PAN_INSIDE_PAD,
NODE_EDGE_PAN_OUTSIDE_PAD,
NODE_EDGE_PAN_SPEED_RAMP,
NODE_EDGE_PAN_MAX_SPEED,
- NODE_EDGE_PAN_DELAY);
- customdata->initial_v2d_cur = t->region->v2d.cur;
+ NODE_EDGE_PAN_DELAY,
+ NODE_EDGE_PAN_ZOOM_INFLUENCE);
t->custom.type.data = customdata;
t->custom.type.use_free = true;
@@ -176,17 +165,22 @@ void flushTransNodes(TransInfo *t)
{
const float dpi_fac = UI_DPI_FAC;
- NodeTransCustomData *customdata = (NodeTransCustomData *)t->custom.type.data;
+ View2DEdgePanData *customdata = (View2DEdgePanData *)t->custom.type.data;
- if (t->mode == TFM_TRANSLATION) {
- /* Edge panning functions expect window coordinates, mval is relative to region */
- const float x = t->region->winrct.xmin + t->mval[0];
- const float y = t->region->winrct.ymin + t->mval[1];
- UI_view2d_edge_pan_apply(t->context, &customdata->edge_pan, x, y);
+ if (t->options & CTX_VIEW2D_EDGE_PAN) {
+ if (t->state == TRANS_CANCEL) {
+ UI_view2d_edge_pan_cancel(t->context, customdata);
+ }
+ else {
+ /* Edge panning functions expect window coordinates, mval is relative to region */
+ const float x = t->region->winrct.xmin + t->mval[0];
+ const float y = t->region->winrct.ymin + t->mval[1];
+ UI_view2d_edge_pan_apply(t->context, customdata, x, y);
+ }
}
/* Initial and current view2D rects for additional transform due to view panning and zooming */
- const rctf *rect_src = &customdata->initial_v2d_cur;
+ const rctf *rect_src = &customdata->initial_rect;
const rctf *rect_dst = &t->region->v2d.cur;
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c
index 17512c79d03..45ed0f3b664 100644
--- a/source/blender/editors/transform/transform_convert_sequencer.c
+++ b/source/blender/editors/transform/transform_convert_sequencer.c
@@ -400,15 +400,14 @@ static void seq_transform_handle_overlap(TransInfo *t, SeqCollection *transforme
if (seq_transform_check_strip_effects(transformed_strips)) {
/* Update effect strips based on strips just moved in time. */
seq_transform_update_effects(t, transformed_strips);
+ }
- /* If any effects still overlap, we need to move them up. */
- Sequence *seq;
- SEQ_ITERATOR_FOREACH (seq, transformed_strips) {
- if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) {
- if (SEQ_transform_test_overlap(seqbasep, seq)) {
- SEQ_transform_seqbase_shuffle(seqbasep, seq, t->scene);
- }
- }
+ /* If any effects still overlap, we need to move them up.
+ * In some cases other strips can be overlapping still, see T90646. */
+ Sequence *seq;
+ SEQ_ITERATOR_FOREACH (seq, transformed_strips) {
+ if (SEQ_transform_test_overlap(seqbasep, seq)) {
+ SEQ_transform_seqbase_shuffle(seqbasep, seq, t->scene);
}
}
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 81fc1496b1a..9f5e74db501 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -625,6 +625,11 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
#endif
+ /* Disable cursor wrap when edge panning is enabled. */
+ if (t->options & CTX_VIEW2D_EDGE_PAN) {
+ t->flag |= T_NO_CURSOR_WRAP;
+ }
+
setTransformViewAspect(t, t->aspect);
if (op && (prop = RNA_struct_find_property(op->ptr, "center_override")) &&
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 45c077b8a07..cbc2adf641f 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -709,6 +709,11 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
RNA_def_property_ui_text(prop, "Center Override", "Force using this center value (when set)");
}
+ if (flags & P_VIEW2D_EDGE_PAN) {
+ prop = RNA_def_boolean(ot->srna, "view2d_edge_pan", false, "Edge Pan", "Enable edge panning in 2D view");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ }
+
if ((flags & P_NO_DEFAULTS) == 0) {
prop = RNA_def_boolean(ot->srna,
"release_confirm",
@@ -754,7 +759,8 @@ static void TRANSFORM_OT_translate(struct wmOperatorType *ot)
Transform_Properties(ot,
P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP |
- P_OPTIONS | P_GPENCIL_EDIT | P_CURSOR_EDIT | P_POST_TRANSFORM);
+ P_OPTIONS | P_GPENCIL_EDIT | P_CURSOR_EDIT | P_VIEW2D_EDGE_PAN |
+ P_POST_TRANSFORM);
}
static void TRANSFORM_OT_resize(struct wmOperatorType *ot)
diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c
index 823837e2a42..d0eed6a6eb1 100644
--- a/source/blender/editors/util/numinput.c
+++ b/source/blender/editors/util/numinput.c
@@ -178,7 +178,7 @@ void outputNumInput(NumInput *n, char *str, UnitSettings *unit_settings)
}
/* We might have cut some multi-bytes utf8 chars
* (e.g. trailing '°' of degrees values can become only 'A')... */
- BLI_utf8_invalid_strip(&str[j * ln], strlen(&str[j * ln]));
+ BLI_str_utf8_invalid_strip(&str[j * ln], strlen(&str[j * ln]));
}
}
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
index 99e3d59a57f..c71cde8ec43 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
@@ -1692,7 +1692,7 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu
}
if (obi->free_use_mesh) {
- BKE_id_free(NULL, &obi->original_me);
+ BKE_id_free(NULL, obi->original_me);
}
if (rb->remove_doubles) {
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index fd794ed1b21..361fefa59d2 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1836,9 +1836,9 @@ typedef enum NodeShaderOutputTarget {
/* Geometry Nodes */
typedef enum GeometryNodeAttributeProximityTargetType {
- GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_POINTS = 0,
- GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_EDGES = 1,
- GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_FACES = 2,
+ GEO_NODE_PROXIMITY_TARGET_POINTS = 0,
+ GEO_NODE_PROXIMITY_TARGET_EDGES = 1,
+ GEO_NODE_PROXIMITY_TARGET_FACES = 2,
} GeometryNodeAttributeProximityTargetType;
typedef enum GeometryNodeBooleanOperation {
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index df18501d2ea..03c38eb71a0 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -339,11 +339,8 @@ typedef struct SpeedControlVars {
float *frameMap;
/* DEPRECATED, only used for versioning. */
float globalSpeed;
- /* DEPRECATED, only used for versioning. */
int flags;
- int length;
- int lastValidFrame;
int speed_control_type;
float speed_fader;
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index f206bde4705..b943a8fad5a 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -1029,10 +1029,8 @@ void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *val
void RNA_property_string_set_bytes(PointerRNA *ptr, PropertyRNA *prop, const char *value, int len);
int RNA_property_string_length(PointerRNA *ptr, PropertyRNA *prop);
void RNA_property_string_get_default(PointerRNA *ptr, PropertyRNA *prop, char *value);
-char *RNA_property_string_get_default_alloc(PointerRNA *ptr,
- PropertyRNA *prop,
- char *fixedbuf,
- int fixedlen);
+char *RNA_property_string_get_default_alloc(
+ PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen, int *r_len);
int RNA_property_string_default_length(PointerRNA *ptr, PropertyRNA *prop);
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop);
@@ -1238,7 +1236,8 @@ bool RNA_enum_icon_from_value(const EnumPropertyItem *item, int value, int *r_ic
bool RNA_enum_name_from_value(const EnumPropertyItem *item, int value, const char **r_name);
void RNA_string_get(PointerRNA *ptr, const char *name, char *value);
-char *RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen);
+char *RNA_string_get_alloc(
+ PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen, int *r_len);
int RNA_string_length(PointerRNA *ptr, const char *name);
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value);
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 41c31dfebcb..c838032f1bb 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -3397,7 +3397,7 @@ char *RNA_property_string_get_alloc(
buf = fixedbuf;
}
else {
- buf = MEM_mallocN(sizeof(char) * (length + 1), "RNA_string_get_alloc");
+ buf = MEM_mallocN(sizeof(char) * (length + 1), __func__);
}
#ifndef NDEBUG
@@ -3537,10 +3537,8 @@ void RNA_property_string_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop,
strcpy(value, sprop->defaultvalue);
}
-char *RNA_property_string_get_default_alloc(PointerRNA *ptr,
- PropertyRNA *prop,
- char *fixedbuf,
- int fixedlen)
+char *RNA_property_string_get_default_alloc(
+ PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen, int *r_len)
{
char *buf;
int length;
@@ -3553,11 +3551,15 @@ char *RNA_property_string_get_default_alloc(PointerRNA *ptr,
buf = fixedbuf;
}
else {
- buf = MEM_callocN(sizeof(char) * (length + 1), "RNA_string_get_alloc");
+ buf = MEM_callocN(sizeof(char) * (length + 1), __func__);
}
RNA_property_string_get_default(ptr, prop, buf);
+ if (r_len) {
+ *r_len = length;
+ }
+
return buf;
}
@@ -6587,15 +6589,18 @@ void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
}
}
-char *RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen)
+char *RNA_string_get_alloc(
+ PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen, int *r_len)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, name);
if (prop) {
- /* TODO: pass length. */
- return RNA_property_string_get_alloc(ptr, prop, fixedbuf, fixedlen, NULL);
+ return RNA_property_string_get_alloc(ptr, prop, fixedbuf, fixedlen, r_len);
}
printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
+ if (r_len != NULL) {
+ *r_len = 0;
+ }
return NULL;
}
@@ -8166,7 +8171,7 @@ bool RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index)
}
case PROP_STRING: {
- char *value = RNA_property_string_get_default_alloc(ptr, prop, NULL, 0);
+ char *value = RNA_property_string_get_default_alloc(ptr, prop, NULL, 0, NULL);
RNA_property_string_set(ptr, prop, value);
MEM_freeN(value);
return true;
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index 9faf2ae7cb7..5f198a8ed4c 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -701,11 +701,7 @@ static float rna_CurveMapping_evaluateF(struct CurveMapping *cumap,
}
if (!cuma->table) {
- BKE_report(
- reports,
- RPT_ERROR,
- "CurveMap table not initialized, call initialize() on CurveMapping owner of the CurveMap");
- return 0.0f;
+ BKE_curvemapping_init(cumap);
}
return BKE_curvemap_evaluateF(cumap, cuma, value);
}
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index 8e6ff961721..9a33849b645 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -122,7 +122,7 @@
static void rna_idname_validate(const char *name, char *r_name)
{
BLI_strncpy(r_name, name, MAX_ID_NAME - 2);
- BLI_utf8_invalid_strip(r_name, strlen(r_name));
+ BLI_str_utf8_invalid_strip(r_name, strlen(r_name));
}
static void rna_Main_ID_remove(Main *bmain,
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index d8ab7c7a61b..8d672e9b570 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -9853,17 +9853,17 @@ static void def_geo_collection_info(StructRNA *srna)
static void def_geo_attribute_proximity(StructRNA *srna)
{
static const EnumPropertyItem target_geometry_element[] = {
- {GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_POINTS,
+ {GEO_NODE_PROXIMITY_TARGET_POINTS,
"POINTS",
ICON_NONE,
"Points",
"Calculate proximity to the target's points (usually faster than the other two modes)"},
- {GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_EDGES,
+ {GEO_NODE_PROXIMITY_TARGET_EDGES,
"EDGES",
ICON_NONE,
"Edges",
"Calculate proximity to the target's edges"},
- {GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_FACES,
+ {GEO_NODE_PROXIMITY_TARGET_FACES,
"FACES",
ICON_NONE,
"Faces",
@@ -9877,7 +9877,7 @@ static void def_geo_attribute_proximity(StructRNA *srna)
prop = RNA_def_property(srna, "target_geometry_element", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, target_geometry_element);
- RNA_def_property_enum_default(prop, GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_FACES);
+ RNA_def_property_enum_default(prop, GEO_NODE_PROXIMITY_TARGET_FACES);
RNA_def_property_ui_text(
prop, "Target Geometry", "Element of the target geometry to calculate the distance from");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c
index 264ccccd350..7ddbf450e6a 100644
--- a/source/blender/makesrna/intern/rna_sequencer_api.c
+++ b/source/blender/makesrna/intern/rna_sequencer_api.c
@@ -102,13 +102,18 @@ static void rna_Sequences_move_strip_to_meta(
}
static Sequence *rna_Sequence_split(
- ID *id, Sequence *seq, Main *bmain, int frame, int split_method)
+ ID *id, Sequence *seq, Main *bmain, ReportList *reports, int frame, int split_method)
{
Scene *scene = (Scene *)id;
Editing *ed = SEQ_editing_get(scene, false);
ListBase *seqbase = SEQ_get_seqbase_by_seq(&ed->seqbase, seq);
- Sequence *r_seq = SEQ_edit_strip_split(bmain, scene, seqbase, seq, frame, split_method);
+ const char *error_msg = NULL;
+ Sequence *r_seq = SEQ_edit_strip_split(
+ bmain, scene, seqbase, seq, frame, split_method, &error_msg);
+ if (error_msg != NULL) {
+ BKE_report(reports, RPT_ERROR, error_msg);
+ }
/* Update depsgraph. */
DEG_relations_tag_update(bmain);
@@ -119,6 +124,14 @@ static Sequence *rna_Sequence_split(
return r_seq;
}
+static Sequence *rna_Sequence_parent_meta(ID *id, Sequence *seq_self)
+{
+ Scene *scene = (Scene *)id;
+ Editing *ed = SEQ_editing_get(scene, false);
+
+ return SEQ_find_metastrip_by_sequence(&ed->seqbase, NULL, seq_self);
+}
+
static Sequence *rna_Sequences_new_clip(ID *id,
ListBase *seqbase,
Main *bmain,
@@ -697,6 +710,13 @@ void RNA_api_sequence_strip(StructRNA *srna)
"Meta to move the strip into");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ func = RNA_def_function(srna, "parent_meta", "rna_Sequence_parent_meta");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Parent meta");
+ /* return type */
+ parm = RNA_def_pointer(func, "sequence", "Sequence", "", "Parent Meta");
+ RNA_def_function_return(func, parm);
+
func = RNA_def_function(srna, "invalidate_cache", "rna_Sequence_invalidate_cache_rnafunc");
RNA_def_function_flag(func, FUNC_USE_SELF_ID);
RNA_def_function_ui_description(func,
@@ -705,7 +725,7 @@ void RNA_api_sequence_strip(StructRNA *srna)
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
func = RNA_def_function(srna, "split", "rna_Sequence_split");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
+ RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID | FUNC_USE_MAIN);
RNA_def_function_ui_description(func, "Split Sequence");
parm = RNA_def_int(
func, "frame", 0, INT_MIN, INT_MAX, "", "Frame where to split the strip", INT_MIN, INT_MAX);
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index b910648495b..21a3c087197 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -649,10 +649,9 @@ static void rna_Event_unicode_get(PointerRNA *ptr, char *value)
size_t len = 0;
if (event->utf8_buf[0]) {
- BLI_str_utf8_as_unicode_and_size(event->utf8_buf, &len);
- if (len > 0) {
+ if (BLI_str_utf8_as_unicode_step_or_error(event->utf8_buf, sizeof(event->utf8_buf), &len) !=
+ BLI_UTF8_ERR)
memcpy(value, event->utf8_buf, len);
- }
}
value[len] = '\0';
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index 9f86727ce0a..2c28e9710ef 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -72,7 +72,7 @@ static void requiredDataMask(Object *UNUSED(ob),
CustomData_MeshMasks *r_cddata_masks)
{
/* ask for UV coordinates */
- r_cddata_masks->lmask |= CD_MLOOPUV;
+ r_cddata_masks->lmask |= CD_MASK_MLOOPUV;
}
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c
index d21e0938356..cc657d6f91d 100644
--- a/source/blender/nodes/composite/node_composite_tree.c
+++ b/source/blender/nodes/composite/node_composite_tree.c
@@ -67,7 +67,7 @@ static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCa
func(calldata, NODE_CLASS_OP_COLOR, N_("Color"));
func(calldata, NODE_CLASS_OP_VECTOR, N_("Vector"));
func(calldata, NODE_CLASS_OP_FILTER, N_("Filter"));
- func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor"));
+ func(calldata, NODE_CLASS_CONVERTER, N_("Converter"));
func(calldata, NODE_CLASS_MATTE, N_("Matte"));
func(calldata, NODE_CLASS_DISTORT, N_("Distort"));
func(calldata, NODE_CLASS_GROUP, N_("Group"));
diff --git a/source/blender/nodes/composite/nodes/node_composite_idMask.c b/source/blender/nodes/composite/nodes/node_composite_idMask.c
index a81dce10284..84563e7560b 100644
--- a/source/blender/nodes/composite/nodes/node_composite_idMask.c
+++ b/source/blender/nodes/composite/nodes/node_composite_idMask.c
@@ -38,7 +38,7 @@ void register_node_type_cmp_idmask(void)
{
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_ID_MASK, "ID Mask", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_ID_MASK, "ID Mask", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, cmp_node_idmask_in, cmp_node_idmask_out);
nodeRegisterType(&ntype);
diff --git a/source/blender/nodes/composite/nodes/node_composite_math.c b/source/blender/nodes/composite/nodes/node_composite_math.c
index c2982964a9f..2191c6bcdc3 100644
--- a/source/blender/nodes/composite/nodes/node_composite_math.c
+++ b/source/blender/nodes/composite/nodes/node_composite_math.c
@@ -36,7 +36,7 @@ void register_node_type_cmp_math(void)
{
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_MATH, "Math", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, cmp_node_math_in, cmp_node_math_out);
node_type_label(&ntype, node_math_label);
node_type_update(&ntype, node_math_update);
diff --git a/source/blender/nodes/composite/nodes/node_composite_premulkey.c b/source/blender/nodes/composite/nodes/node_composite_premulkey.c
index b5dc15a2789..be76bbf01cf 100644
--- a/source/blender/nodes/composite/nodes/node_composite_premulkey.c
+++ b/source/blender/nodes/composite/nodes/node_composite_premulkey.c
@@ -38,7 +38,7 @@ void register_node_type_cmp_premulkey(void)
{
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_PREMULKEY, "Alpha Convert", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_PREMULKEY, "Alpha Convert", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, cmp_node_premulkey_in, cmp_node_premulkey_out);
nodeRegisterType(&ntype);
diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c
index 03d27caa701..001b197e23a 100644
--- a/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c
+++ b/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c
@@ -40,7 +40,7 @@ void register_node_type_cmp_sephsva(void)
{
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_SEPHSVA, "Separate HSVA", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_SEPHSVA, "Separate HSVA", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, cmp_node_sephsva_in, cmp_node_sephsva_out);
nodeRegisterType(&ntype);
@@ -63,7 +63,7 @@ void register_node_type_cmp_combhsva(void)
{
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_COMBHSVA, "Combine HSVA", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_COMBHSVA, "Combine HSVA", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, cmp_node_combhsva_in, cmp_node_combhsva_out);
nodeRegisterType(&ntype);
diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c
index ee8d6b0c186..e08f27db254 100644
--- a/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c
+++ b/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c
@@ -40,7 +40,7 @@ void register_node_type_cmp_seprgba(void)
{
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_SEPRGBA, "Separate RGBA", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_SEPRGBA, "Separate RGBA", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, cmp_node_seprgba_in, cmp_node_seprgba_out);
nodeRegisterType(&ntype);
@@ -63,7 +63,7 @@ void register_node_type_cmp_combrgba(void)
{
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_COMBRGBA, "Combine RGBA", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_COMBRGBA, "Combine RGBA", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, cmp_node_combrgba_in, cmp_node_combrgba_out);
nodeRegisterType(&ntype);
diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c
index a4aa6e4bf77..b3884296600 100644
--- a/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c
+++ b/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c
@@ -43,7 +43,7 @@ void register_node_type_cmp_sepycca(void)
{
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_SEPYCCA, "Separate YCbCrA", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_SEPYCCA, "Separate YCbCrA", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, cmp_node_sepycca_in, cmp_node_sepycca_out);
node_type_init(&ntype, node_composit_init_mode_sepycca);
@@ -72,7 +72,7 @@ void register_node_type_cmp_combycca(void)
{
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_COMBYCCA, "Combine YCbCrA", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_COMBYCCA, "Combine YCbCrA", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, cmp_node_combycca_in, cmp_node_combycca_out);
node_type_init(&ntype, node_composit_init_mode_combycca);
diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c
index 6c416b4f485..4da79ec7981 100644
--- a/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c
+++ b/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c
@@ -38,7 +38,7 @@ void register_node_type_cmp_sepyuva(void)
{
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_SEPYUVA, "Separate YUVA", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_SEPYUVA, "Separate YUVA", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, cmp_node_sepyuva_in, cmp_node_sepyuva_out);
nodeRegisterType(&ntype);
@@ -61,7 +61,7 @@ void register_node_type_cmp_combyuva(void)
{
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_COMBYUVA, "Combine YUVA", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_COMBYUVA, "Combine YUVA", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, cmp_node_combyuva_in, cmp_node_combyuva_out);
nodeRegisterType(&ntype);
diff --git a/source/blender/nodes/composite/nodes/node_composite_setalpha.c b/source/blender/nodes/composite/nodes/node_composite_setalpha.c
index 1488ff1a25f..1b44cc011e9 100644
--- a/source/blender/nodes/composite/nodes/node_composite_setalpha.c
+++ b/source/blender/nodes/composite/nodes/node_composite_setalpha.c
@@ -45,7 +45,7 @@ void register_node_type_cmp_setalpha(void)
{
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_SETALPHA, "Set Alpha", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_SETALPHA, "Set Alpha", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, cmp_node_setalpha_in, cmp_node_setalpha_out);
node_type_init(&ntype, node_composit_init_setalpha);
node_type_storage(
diff --git a/source/blender/nodes/composite/nodes/node_composite_switchview.c b/source/blender/nodes/composite/nodes/node_composite_switchview.c
index ec5c79cc087..b09d5119bc4 100644
--- a/source/blender/nodes/composite/nodes/node_composite_switchview.c
+++ b/source/blender/nodes/composite/nodes/node_composite_switchview.c
@@ -146,7 +146,7 @@ void register_node_type_cmp_switch_view(void)
{
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_SWITCH_VIEW, "Switch View", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_SWITCH_VIEW, "Switch View", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, NULL, cmp_node_switch_view_out);
ntype.initfunc_api = init_switch_view;
diff --git a/source/blender/nodes/composite/nodes/node_composite_valToRgb.c b/source/blender/nodes/composite/nodes/node_composite_valToRgb.c
index 0d46341b610..ed6dbfa2bf3 100644
--- a/source/blender/nodes/composite/nodes/node_composite_valToRgb.c
+++ b/source/blender/nodes/composite/nodes/node_composite_valToRgb.c
@@ -43,7 +43,7 @@ void register_node_type_cmp_valtorgb(void)
{
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, cmp_node_valtorgb_in, cmp_node_valtorgb_out);
node_type_size(&ntype, 240, 200, 320);
node_type_init(&ntype, node_composit_init_valtorgb);
@@ -66,7 +66,7 @@ void register_node_type_cmp_rgbtobw(void)
{
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, cmp_node_rgbtobw_in, cmp_node_rgbtobw_out);
node_type_size_preset(&ntype, NODE_SIZE_SMALL);
diff --git a/source/blender/nodes/function/nodes/node_fn_boolean_math.cc b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc
index 0ba9080918c..58e7d82beea 100644
--- a/source/blender/nodes/function/nodes/node_fn_boolean_math.cc
+++ b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc
@@ -90,7 +90,7 @@ void register_node_type_fn_boolean_math()
{
static bNodeType ntype;
- fn_node_type_base(&ntype, FN_NODE_BOOLEAN_MATH, "Boolean Math", NODE_CLASS_CONVERTOR, 0);
+ fn_node_type_base(&ntype, FN_NODE_BOOLEAN_MATH, "Boolean Math", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, fn_node_boolean_math_in, fn_node_boolean_math_out);
node_type_label(&ntype, node_boolean_math_label);
node_type_update(&ntype, node_boolean_math_update);
diff --git a/source/blender/nodes/function/nodes/node_fn_float_compare.cc b/source/blender/nodes/function/nodes/node_fn_float_compare.cc
index 16ffb761a15..918dd24e520 100644
--- a/source/blender/nodes/function/nodes/node_fn_float_compare.cc
+++ b/source/blender/nodes/function/nodes/node_fn_float_compare.cc
@@ -109,7 +109,7 @@ void register_node_type_fn_float_compare()
{
static bNodeType ntype;
- fn_node_type_base(&ntype, FN_NODE_FLOAT_COMPARE, "Float Compare", NODE_CLASS_CONVERTOR, 0);
+ fn_node_type_base(&ntype, FN_NODE_FLOAT_COMPARE, "Float Compare", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, fn_node_float_compare_in, fn_node_float_compare_out);
node_type_label(&ntype, node_float_compare_label);
node_type_update(&ntype, node_float_compare_update);
diff --git a/source/blender/nodes/function/nodes/node_fn_float_to_int.cc b/source/blender/nodes/function/nodes/node_fn_float_to_int.cc
index 52acfefe615..40b8f27f895 100644
--- a/source/blender/nodes/function/nodes/node_fn_float_to_int.cc
+++ b/source/blender/nodes/function/nodes/node_fn_float_to_int.cc
@@ -87,7 +87,7 @@ void register_node_type_fn_float_to_int()
{
static bNodeType ntype;
- fn_node_type_base(&ntype, FN_NODE_FLOAT_TO_INT, "Float to Integer", NODE_CLASS_CONVERTOR, 0);
+ fn_node_type_base(&ntype, FN_NODE_FLOAT_TO_INT, "Float to Integer", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, fn_node_float_to_int_in, fn_node_float_to_int_out);
node_type_label(&ntype, node_float_to_int_label);
ntype.build_multi_function = fn_node_float_to_int_build_multi_function;
diff --git a/source/blender/nodes/geometry/node_geometry_tree.cc b/source/blender/nodes/geometry/node_geometry_tree.cc
index 07a89a1fa8c..d6b23c38ee4 100644
--- a/source/blender/nodes/geometry/node_geometry_tree.cc
+++ b/source/blender/nodes/geometry/node_geometry_tree.cc
@@ -80,7 +80,7 @@ static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCa
func(calldata, NODE_CLASS_ATTRIBUTE, N_("Attribute"));
func(calldata, NODE_CLASS_OP_COLOR, N_("Color"));
func(calldata, NODE_CLASS_OP_VECTOR, N_("Vector"));
- func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor"));
+ func(calldata, NODE_CLASS_CONVERTER, N_("Converter"));
func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc
index d71cb09f1bd..e94267cc936 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc
@@ -53,8 +53,7 @@ static void geo_attribute_proximity_init(bNodeTree *UNUSED(ntree), bNode *node)
NodeGeometryAttributeProximity *node_storage = (NodeGeometryAttributeProximity *)MEM_callocN(
sizeof(NodeGeometryAttributeProximity), __func__);
- node_storage->target_geometry_element =
- GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_FACES;
+ node_storage->target_geometry_element = GEO_NODE_PROXIMITY_TARGET_FACES;
node->storage = node_storage;
}
@@ -63,15 +62,10 @@ namespace blender::nodes {
static void proximity_calc(MutableSpan<float> distance_span,
MutableSpan<float3> location_span,
const VArray<float3> &positions,
- BVHTreeFromMesh &tree_data_mesh,
- BVHTreeFromPointCloud &tree_data_pointcloud,
- const bool bvh_mesh_success,
- const bool bvh_pointcloud_success,
- const bool store_distances,
- const bool store_locations)
+ BVHTreeFromMesh *tree_data_mesh,
+ BVHTreeFromPointCloud *tree_data_pointcloud)
{
- IndexRange range = positions.index_range();
- threading::parallel_for(range, 512, [&](IndexRange range) {
+ threading::parallel_for(positions.index_range(), 512, [&](IndexRange range) {
BVHTreeNearest nearest_from_mesh;
BVHTreeNearest nearest_from_pointcloud;
@@ -85,12 +79,12 @@ static void proximity_calc(MutableSpan<float> distance_span,
/* Use the distance to the last found point as upper bound to speedup the bvh lookup. */
nearest_from_mesh.dist_sq = len_squared_v3v3(nearest_from_mesh.co, positions[i]);
- if (bvh_mesh_success) {
- BLI_bvhtree_find_nearest(tree_data_mesh.tree,
+ if (tree_data_mesh != nullptr) {
+ BLI_bvhtree_find_nearest(tree_data_mesh->tree,
positions[i],
&nearest_from_mesh,
- tree_data_mesh.nearest_callback,
- &tree_data_mesh);
+ tree_data_mesh->nearest_callback,
+ tree_data_mesh);
}
/* Use the distance to the closest point in the mesh to speedup the pointcloud bvh lookup.
@@ -98,27 +92,27 @@ static void proximity_calc(MutableSpan<float> distance_span,
* than the mesh. */
nearest_from_pointcloud.dist_sq = nearest_from_mesh.dist_sq;
- if (bvh_pointcloud_success) {
- BLI_bvhtree_find_nearest(tree_data_pointcloud.tree,
+ if (tree_data_pointcloud != nullptr) {
+ BLI_bvhtree_find_nearest(tree_data_pointcloud->tree,
positions[i],
&nearest_from_pointcloud,
- tree_data_pointcloud.nearest_callback,
- &tree_data_pointcloud);
+ tree_data_pointcloud->nearest_callback,
+ tree_data_pointcloud);
}
if (nearest_from_pointcloud.dist_sq < nearest_from_mesh.dist_sq) {
- if (store_distances) {
+ if (!distance_span.is_empty()) {
distance_span[i] = sqrtf(nearest_from_pointcloud.dist_sq);
}
- if (store_locations) {
+ if (!location_span.is_empty()) {
location_span[i] = nearest_from_pointcloud.co;
}
}
else {
- if (store_distances) {
+ if (!distance_span.is_empty()) {
distance_span[i] = sqrtf(nearest_from_mesh.dist_sq);
}
- if (store_locations) {
+ if (!location_span.is_empty()) {
location_span[i] = nearest_from_mesh.co;
}
}
@@ -132,13 +126,13 @@ static bool bvh_from_mesh(const Mesh *target_mesh,
{
BVHCacheType bvh_type = BVHTREE_FROM_LOOPTRI;
switch (target_geometry_element) {
- case GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_POINTS:
+ case GEO_NODE_PROXIMITY_TARGET_POINTS:
bvh_type = BVHTREE_FROM_VERTS;
break;
- case GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_EDGES:
+ case GEO_NODE_PROXIMITY_TARGET_EDGES:
bvh_type = BVHTREE_FROM_EDGES;
break;
- case GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_FACES:
+ case GEO_NODE_PROXIMITY_TARGET_FACES:
bvh_type = BVHTREE_FROM_LOOPTRI;
break;
}
@@ -181,23 +175,20 @@ static void attribute_calc_proximity(GeometryComponent &component,
}
BLI_assert(position_attribute.varray->type().is<float3>());
- const bNode &node = params.node();
- const NodeGeometryAttributeProximity &storage = *(const NodeGeometryAttributeProximity *)
- node.storage;
+ const NodeGeometryAttributeProximity &storage =
+ *(const NodeGeometryAttributeProximity *)params.node().storage;
- BVHTreeFromMesh tree_data_mesh;
- BVHTreeFromPointCloud tree_data_pointcloud;
bool bvh_mesh_success = false;
- bool bvh_pointcloud_success = false;
-
+ BVHTreeFromMesh tree_data_mesh;
if (geometry_set_target.has_mesh()) {
bvh_mesh_success = bvh_from_mesh(
geometry_set_target.get_mesh_for_read(), storage.target_geometry_element, tree_data_mesh);
}
+ bool bvh_pointcloud_success = false;
+ BVHTreeFromPointCloud tree_data_pointcloud;
if (geometry_set_target.has_pointcloud() &&
- storage.target_geometry_element ==
- GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_POINTS) {
+ storage.target_geometry_element == GEO_NODE_PROXIMITY_TARGET_POINTS) {
bvh_pointcloud_success = bvh_from_pointcloud(geometry_set_target.get_pointcloud_for_read(),
tree_data_pointcloud);
}
@@ -211,12 +202,8 @@ static void attribute_calc_proximity(GeometryComponent &component,
proximity_calc(distance_span,
location_span,
positions,
- tree_data_mesh,
- tree_data_pointcloud,
- bvh_mesh_success,
- bvh_pointcloud_success,
- distance_attribute, /* Boolean. */
- location_attribute); /* Boolean. */
+ bvh_mesh_success ? &tree_data_mesh : nullptr,
+ bvh_pointcloud_success ? &tree_data_pointcloud : nullptr);
if (bvh_mesh_success) {
free_bvhtree_from_mesh(&tree_data_mesh);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_switch.cc b/source/blender/nodes/geometry/nodes/node_geo_switch.cc
index 0aa5c68aaf5..c9ce2de1ea1 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_switch.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_switch.cc
@@ -179,7 +179,7 @@ void register_node_type_geo_switch()
{
static bNodeType ntype;
- geo_node_type_base(&ntype, GEO_NODE_SWITCH, "Switch", NODE_CLASS_CONVERTOR, 0);
+ geo_node_type_base(&ntype, GEO_NODE_SWITCH, "Switch", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, geo_node_switch_in, geo_node_switch_out);
node_type_init(&ntype, geo_node_switch_init);
node_type_update(&ntype, blender::nodes::geo_node_switch_update);
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 98edc133a1d..c3a675fcd20 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -130,7 +130,7 @@ static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCa
func(calldata, NODE_CLASS_TEXTURE, N_("Texture"));
func(calldata, NODE_CLASS_OP_COLOR, N_("Color"));
func(calldata, NODE_CLASS_OP_VECTOR, N_("Vector"));
- func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor"));
+ func(calldata, NODE_CLASS_CONVERTER, N_("Converter"));
func(calldata, NODE_CLASS_SCRIPT, N_("Script"));
func(calldata, NODE_CLASS_GROUP, N_("Group"));
func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
diff --git a/source/blender/nodes/shader/nodes/node_shader_blackbody.c b/source/blender/nodes/shader/nodes/node_shader_blackbody.c
index c946a76ab51..95c35affc27 100644
--- a/source/blender/nodes/shader/nodes/node_shader_blackbody.c
+++ b/source/blender/nodes/shader/nodes/node_shader_blackbody.c
@@ -52,7 +52,7 @@ void register_node_type_sh_blackbody(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_BLACKBODY, "Blackbody", NODE_CLASS_CONVERTOR, 0);
+ sh_node_type_base(&ntype, SH_NODE_BLACKBODY, "Blackbody", NODE_CLASS_CONVERTER, 0);
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
node_type_socket_templates(&ntype, sh_node_blackbody_in, sh_node_blackbody_out);
node_type_init(&ntype, NULL);
diff --git a/source/blender/nodes/shader/nodes/node_shader_clamp.cc b/source/blender/nodes/shader/nodes/node_shader_clamp.cc
index f105f8bcaf9..b90397e4892 100644
--- a/source/blender/nodes/shader/nodes/node_shader_clamp.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_clamp.cc
@@ -78,7 +78,7 @@ void register_node_type_sh_clamp(void)
{
static bNodeType ntype;
- sh_fn_node_type_base(&ntype, SH_NODE_CLAMP, "Clamp", NODE_CLASS_CONVERTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_CLAMP, "Clamp", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, sh_node_clamp_in, sh_node_clamp_out);
node_type_init(&ntype, node_shader_init_clamp);
node_type_gpu(&ntype, gpu_shader_clamp);
diff --git a/source/blender/nodes/shader/nodes/node_shader_map_range.cc b/source/blender/nodes/shader/nodes/node_shader_map_range.cc
index e4739e2864d..f48e824ccb5 100644
--- a/source/blender/nodes/shader/nodes/node_shader_map_range.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_map_range.cc
@@ -310,7 +310,7 @@ void register_node_type_sh_map_range(void)
{
static bNodeType ntype;
- sh_fn_node_type_base(&ntype, SH_NODE_MAP_RANGE, "Map Range", NODE_CLASS_CONVERTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_MAP_RANGE, "Map Range", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, sh_node_map_range_in, sh_node_map_range_out);
node_type_init(&ntype, node_shader_init_map_range);
node_type_update(&ntype, node_shader_update_map_range);
diff --git a/source/blender/nodes/shader/nodes/node_shader_math.cc b/source/blender/nodes/shader/nodes/node_shader_math.cc
index c30f2948ab1..66c50b6de46 100644
--- a/source/blender/nodes/shader/nodes/node_shader_math.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_math.cc
@@ -152,7 +152,7 @@ void register_node_type_sh_math(void)
{
static bNodeType ntype;
- sh_fn_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, sh_node_math_in, sh_node_math_out);
node_type_label(&ntype, node_math_label);
node_type_gpu(&ntype, gpu_shader_math);
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c b/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c
index 951755be4f3..dfecb830b35 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c
@@ -61,7 +61,7 @@ void register_node_type_sh_sephsv(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_SEPHSV, "Separate HSV", NODE_CLASS_CONVERTOR, 0);
+ sh_node_type_base(&ntype, SH_NODE_SEPHSV, "Separate HSV", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, sh_node_sephsv_in, sh_node_sephsv_out);
node_type_exec(&ntype, NULL, NULL, node_shader_exec_sephsv);
node_type_gpu(&ntype, gpu_shader_sephsv);
@@ -109,7 +109,7 @@ void register_node_type_sh_combhsv(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_COMBHSV, "Combine HSV", NODE_CLASS_CONVERTOR, 0);
+ sh_node_type_base(&ntype, SH_NODE_COMBHSV, "Combine HSV", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, sh_node_combhsv_in, sh_node_combhsv_out);
node_type_exec(&ntype, NULL, NULL, node_shader_exec_combhsv);
node_type_gpu(&ntype, gpu_shader_combhsv);
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc
index 2779fc6bf68..d9cbee33c0f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc
@@ -106,7 +106,7 @@ void register_node_type_sh_seprgb(void)
{
static bNodeType ntype;
- sh_fn_node_type_base(&ntype, SH_NODE_SEPRGB, "Separate RGB", NODE_CLASS_CONVERTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_SEPRGB, "Separate RGB", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, sh_node_seprgb_in, sh_node_seprgb_out);
node_type_exec(&ntype, nullptr, nullptr, node_shader_exec_seprgb);
node_type_gpu(&ntype, gpu_shader_seprgb);
@@ -165,7 +165,7 @@ void register_node_type_sh_combrgb(void)
{
static bNodeType ntype;
- sh_fn_node_type_base(&ntype, SH_NODE_COMBRGB, "Combine RGB", NODE_CLASS_CONVERTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_COMBRGB, "Combine RGB", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, sh_node_combrgb_in, sh_node_combrgb_out);
node_type_exec(&ntype, nullptr, nullptr, node_shader_exec_combrgb);
node_type_gpu(&ntype, gpu_shader_combrgb);
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc
index 1fd794cdd0a..3048ed1e9fc 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc
@@ -91,7 +91,7 @@ void register_node_type_sh_sepxyz(void)
{
static bNodeType ntype;
- sh_fn_node_type_base(&ntype, SH_NODE_SEPXYZ, "Separate XYZ", NODE_CLASS_CONVERTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_SEPXYZ, "Separate XYZ", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, sh_node_sepxyz_in, sh_node_sepxyz_out);
node_type_gpu(&ntype, gpu_shader_sepxyz);
ntype.build_multi_function = sh_node_sepxyz_build_multi_function;
@@ -131,7 +131,7 @@ void register_node_type_sh_combxyz(void)
{
static bNodeType ntype;
- sh_fn_node_type_base(&ntype, SH_NODE_COMBXYZ, "Combine XYZ", NODE_CLASS_CONVERTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_COMBXYZ, "Combine XYZ", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, sh_node_combxyz_in, sh_node_combxyz_out);
node_type_gpu(&ntype, gpu_shader_combxyz);
ntype.build_multi_function = sh_node_combxyz_build_multi_function;
diff --git a/source/blender/nodes/shader/nodes/node_shader_shaderToRgb.c b/source/blender/nodes/shader/nodes/node_shader_shaderToRgb.c
index 4216207d643..25c30aa4081 100644
--- a/source/blender/nodes/shader/nodes/node_shader_shaderToRgb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_shaderToRgb.c
@@ -50,7 +50,7 @@ void register_node_type_sh_shadertorgb(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_SHADERTORGB, "Shader to RGB", NODE_CLASS_CONVERTOR, 0);
+ sh_node_type_base(&ntype, SH_NODE_SHADERTORGB, "Shader to RGB", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, sh_node_shadertorgb_in, sh_node_shadertorgb_out);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
diff --git a/source/blender/nodes/shader/nodes/node_shader_squeeze.c b/source/blender/nodes/shader/nodes/node_shader_squeeze.c
index c7b6af3980a..ca7bdf41df9 100644
--- a/source/blender/nodes/shader/nodes/node_shader_squeeze.c
+++ b/source/blender/nodes/shader/nodes/node_shader_squeeze.c
@@ -61,7 +61,7 @@ void register_node_type_sh_squeeze(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_SQUEEZE, "Squeeze Value", NODE_CLASS_CONVERTOR, 0);
+ sh_node_type_base(&ntype, SH_NODE_SQUEEZE, "Squeeze Value", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, sh_node_squeeze_in, sh_node_squeeze_out);
node_type_storage(&ntype, "", NULL, NULL);
node_type_exec(&ntype, NULL, NULL, node_shader_exec_squeeze);
diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.cc b/source/blender/nodes/shader/nodes/node_shader_valToRgb.cc
index 1bc42ab0cc6..62f6b38c79f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_valToRgb.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_valToRgb.cc
@@ -175,7 +175,7 @@ void register_node_type_sh_valtorgb(void)
{
static bNodeType ntype;
- sh_fn_node_type_base(&ntype, SH_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, sh_node_valtorgb_in, sh_node_valtorgb_out);
node_type_init(&ntype, node_shader_init_valtorgb);
node_type_size_preset(&ntype, NODE_SIZE_LARGE);
@@ -221,7 +221,7 @@ void register_node_type_sh_rgbtobw(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0);
+ sh_node_type_base(&ntype, SH_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, sh_node_rgbtobw_in, sh_node_rgbtobw_out);
node_type_exec(&ntype, nullptr, nullptr, node_shader_exec_rgbtobw);
node_type_gpu(&ntype, gpu_shader_rgbtobw);
diff --git a/source/blender/nodes/shader/nodes/node_shader_wavelength.c b/source/blender/nodes/shader/nodes/node_shader_wavelength.c
index 30f69557020..f978537ee85 100644
--- a/source/blender/nodes/shader/nodes/node_shader_wavelength.c
+++ b/source/blender/nodes/shader/nodes/node_shader_wavelength.c
@@ -62,7 +62,7 @@ void register_node_type_sh_wavelength(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_WAVELENGTH, "Wavelength", NODE_CLASS_CONVERTOR, 0);
+ sh_node_type_base(&ntype, SH_NODE_WAVELENGTH, "Wavelength", NODE_CLASS_CONVERTER, 0);
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
node_type_socket_templates(&ntype, sh_node_wavelength_in, sh_node_wavelength_out);
node_type_init(&ntype, NULL);
diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c
index f771b4934b2..7452007639c 100644
--- a/source/blender/nodes/texture/node_texture_tree.c
+++ b/source/blender/nodes/texture/node_texture_tree.c
@@ -101,7 +101,7 @@ static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCa
func(calldata, NODE_CLASS_OP_COLOR, N_("Color"));
func(calldata, NODE_CLASS_PATTERN, N_("Patterns"));
func(calldata, NODE_CLASS_TEXTURE, N_("Textures"));
- func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor"));
+ func(calldata, NODE_CLASS_CONVERTER, N_("Converter"));
func(calldata, NODE_CLASS_DISTORT, N_("Distort"));
func(calldata, NODE_CLASS_GROUP, N_("Group"));
func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
diff --git a/source/blender/nodes/texture/nodes/node_texture_distance.c b/source/blender/nodes/texture/nodes/node_texture_distance.c
index 489318514e5..f7deac9ff4a 100644
--- a/source/blender/nodes/texture/nodes/node_texture_distance.c
+++ b/source/blender/nodes/texture/nodes/node_texture_distance.c
@@ -61,7 +61,7 @@ void register_node_type_tex_distance(void)
{
static bNodeType ntype;
- tex_node_type_base(&ntype, TEX_NODE_DISTANCE, "Distance", NODE_CLASS_CONVERTOR, 0);
+ tex_node_type_base(&ntype, TEX_NODE_DISTANCE, "Distance", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_storage(&ntype, "", NULL, NULL);
node_type_exec(&ntype, NULL, NULL, exec);
diff --git a/source/blender/nodes/texture/nodes/node_texture_math.c b/source/blender/nodes/texture/nodes/node_texture_math.c
index 53022c9e120..ab226a4dd38 100644
--- a/source/blender/nodes/texture/nodes/node_texture_math.c
+++ b/source/blender/nodes/texture/nodes/node_texture_math.c
@@ -335,7 +335,7 @@ void register_node_type_tex_math(void)
{
static bNodeType ntype;
- tex_node_type_base(&ntype, TEX_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, 0);
+ tex_node_type_base(&ntype, TEX_NODE_MATH, "Math", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_label(&ntype, node_math_label);
node_type_storage(&ntype, "", NULL, NULL);
diff --git a/source/blender/nodes/texture/nodes/node_texture_valToNor.c b/source/blender/nodes/texture/nodes/node_texture_valToNor.c
index 2fb04777848..5ccd44b8bf0 100644
--- a/source/blender/nodes/texture/nodes/node_texture_valToNor.c
+++ b/source/blender/nodes/texture/nodes/node_texture_valToNor.c
@@ -80,7 +80,7 @@ void register_node_type_tex_valtonor(void)
{
static bNodeType ntype;
- tex_node_type_base(&ntype, TEX_NODE_VALTONOR, "Value to Normal", NODE_CLASS_CONVERTOR, 0);
+ tex_node_type_base(&ntype, TEX_NODE_VALTONOR, "Value to Normal", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_exec(&ntype, NULL, NULL, exec);
diff --git a/source/blender/nodes/texture/nodes/node_texture_valToRgb.c b/source/blender/nodes/texture/nodes/node_texture_valToRgb.c
index 8d365e13fc4..2446ef05e0c 100644
--- a/source/blender/nodes/texture/nodes/node_texture_valToRgb.c
+++ b/source/blender/nodes/texture/nodes/node_texture_valToRgb.c
@@ -63,7 +63,7 @@ void register_node_type_tex_valtorgb(void)
{
static bNodeType ntype;
- tex_node_type_base(&ntype, TEX_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, 0);
+ tex_node_type_base(&ntype, TEX_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, valtorgb_in, valtorgb_out);
node_type_size_preset(&ntype, NODE_SIZE_LARGE);
node_type_init(&ntype, valtorgb_init);
@@ -105,7 +105,7 @@ void register_node_type_tex_rgbtobw(void)
{
static bNodeType ntype;
- tex_node_type_base(&ntype, TEX_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0);
+ tex_node_type_base(&ntype, TEX_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTER, 0);
node_type_socket_templates(&ntype, rgbtobw_in, rgbtobw_out);
node_type_exec(&ntype, NULL, NULL, rgbtobw_exec);
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index ac1a7f68885..e9d5ae278bb 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -7774,7 +7774,7 @@ void BPY_rna_exit(void)
* will crash giving a useful error with address sanitizer. The likely cause
* for this list not being empty is a missing call to: #BKE_libblock_free_data_py. */
const int id_weakref_pool_len = BLI_ghash_len(id_weakref_pool);
- if (id_weakref_pool_len != id_weakref_pool_len) {
+ if (id_weakref_pool_len != 0) {
printf("Found %d unreleased ID's\n", id_weakref_pool_len);
GHashIterator gh_iter;
GHASH_ITER (gh_iter, id_weakref_pool) {
diff --git a/source/blender/render/RE_pipeline.h b/source/blender/render/RE_pipeline.h
index 4534c86f7f7..cd839385bfb 100644
--- a/source/blender/render/RE_pipeline.h
+++ b/source/blender/render/RE_pipeline.h
@@ -155,6 +155,8 @@ typedef struct RenderResult {
char *error;
struct StampData *stamp_data;
+
+ bool passes_allocated;
} RenderResult;
typedef struct RenderStats {
diff --git a/source/blender/render/intern/engine.c b/source/blender/render/intern/engine.c
index 75b3f2db249..1510587502b 100644
--- a/source/blender/render/intern/engine.c
+++ b/source/blender/render/intern/engine.c
@@ -212,6 +212,8 @@ static RenderResult *render_result_from_bake(RenderEngine *engine, int x, int y,
RenderPass *primitive_pass = render_layer_add_pass(rr, rl, 4, "BakePrimitive", "", "RGBA");
RenderPass *differential_pass = render_layer_add_pass(rr, rl, 4, "BakeDifferential", "", "RGBA");
+ render_result_passes_allocated_ensure(rr);
+
/* Fill render passes from bake pixel array, to be read by the render engine. */
for (int ty = 0; ty < h; ty++) {
size_t offset = ty * w * 4;
@@ -328,6 +330,7 @@ RenderResult *RE_engine_begin_result(
/* can be NULL if we CLAMP the width or height to 0 */
if (result) {
render_result_clone_passes(re, result, viewname);
+ render_result_passes_allocated_ensure(result);
RenderPart *pa;
@@ -400,6 +403,14 @@ void RE_engine_end_result(
return;
}
+ if (!re->result->passes_allocated) {
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ if (!re->result->passes_allocated) {
+ render_result_passes_allocated_ensure(re->result);
+ }
+ BLI_rw_mutex_unlock(&re->resultmutex);
+ }
+
/* merge. on break, don't merge in result for preview renders, looks nicer */
if (!highlight) {
/* for exr tile render, detect tiles that are done */
diff --git a/source/blender/render/intern/pipeline.c b/source/blender/render/intern/pipeline.c
index 479ad9209f0..9ef52b4bf41 100644
--- a/source/blender/render/intern/pipeline.c
+++ b/source/blender/render/intern/pipeline.c
@@ -354,6 +354,7 @@ RenderResult *RE_AcquireResultWrite(Render *re)
{
if (re) {
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ render_result_passes_allocated_ensure(re->result);
return re->result;
}
diff --git a/source/blender/render/intern/render_result.c b/source/blender/render/intern/render_result.c
index 091f5964291..c29ab342ed7 100644
--- a/source/blender/render/intern/render_result.c
+++ b/source/blender/render/intern/render_result.c
@@ -222,7 +222,6 @@ RenderPass *render_layer_add_pass(RenderResult *rr,
{
const int view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name));
RenderPass *rpass = MEM_callocN(sizeof(RenderPass), name);
- size_t rectsize = ((size_t)rr->rectx) * rr->recty * channels;
rpass->channels = channels;
rpass->rectx = rl->rectx;
@@ -249,33 +248,6 @@ RenderPass *render_layer_add_pass(RenderResult *rr,
}
}
- /* Always allocate combined for display, in case of save buffers
- * other passes are not allocated and only saved to the EXR file. */
- if (rl->exrhandle == NULL || STREQ(rpass->name, RE_PASSNAME_COMBINED)) {
- float *rect;
- int x;
-
- rpass->rect = MEM_callocN(sizeof(float) * rectsize, name);
- if (rpass->rect == NULL) {
- MEM_freeN(rpass);
- return NULL;
- }
-
- if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) {
- /* initialize to max speed */
- rect = rpass->rect;
- for (x = rectsize - 1; x >= 0; x--) {
- rect[x] = PASS_VECTOR_MAX;
- }
- }
- else if (STREQ(rpass->name, RE_PASSNAME_Z)) {
- rect = rpass->rect;
- for (x = rectsize - 1; x >= 0; x--) {
- rect[x] = 10e10;
- }
- }
- }
-
BLI_addtail(&rl->passes, rpass);
return rpass;
@@ -316,6 +288,8 @@ RenderResult *render_result_new(
rr->do_exr_tile = true;
}
+ rr->passes_allocated = false;
+
render_result_views_new(rr, &re->r);
/* check renderdata for amount of layers */
@@ -484,6 +458,40 @@ RenderResult *render_result_new(
return rr;
}
+void render_result_passes_allocated_ensure(RenderResult *rr)
+{
+ LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) {
+ LISTBASE_FOREACH (RenderPass *, rp, &rl->passes) {
+ if (rl->exrhandle != NULL && !STREQ(rp->name, RE_PASSNAME_COMBINED)) {
+ continue;
+ }
+
+ if (rp->rect != NULL) {
+ continue;
+ }
+
+ const size_t rectsize = ((size_t)rr->rectx) * rr->recty * rp->channels;
+ rp->rect = MEM_callocN(sizeof(float) * rectsize, rp->name);
+
+ if (STREQ(rp->name, RE_PASSNAME_VECTOR)) {
+ /* initialize to max speed */
+ float *rect = rp->rect;
+ for (int x = rectsize - 1; x >= 0; x--) {
+ rect[x] = PASS_VECTOR_MAX;
+ }
+ }
+ else if (STREQ(rp->name, RE_PASSNAME_Z)) {
+ float *rect = rp->rect;
+ for (int x = rectsize - 1; x >= 0; x--) {
+ rect[x] = 10e10;
+ }
+ }
+ }
+ }
+
+ rr->passes_allocated = true;
+}
+
void render_result_clone_passes(Render *re, RenderResult *rr, const char *viewname)
{
RenderLayer *rl;
@@ -1243,6 +1251,7 @@ void render_result_exr_file_end(Render *re, RenderEngine *engine)
render_result_free_list(&re->fullresult, re->result);
re->result = render_result_new(re, &re->disprect, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
re->result->stamp_data = stamp_data;
+ render_result_passes_allocated_ensure(re->result);
BLI_rw_mutex_unlock(&re->resultmutex);
LISTBASE_FOREACH (RenderLayer *, rl, &re->result->layers) {
diff --git a/source/blender/render/intern/render_result.h b/source/blender/render/intern/render_result.h
index 7732c113700..1fc64a4ea97 100644
--- a/source/blender/render/intern/render_result.h
+++ b/source/blender/render/intern/render_result.h
@@ -55,6 +55,8 @@ struct RenderResult *render_result_new(struct Render *re,
const char *layername,
const char *viewname);
+void render_result_passes_allocated_ensure(struct RenderResult *rr);
+
struct RenderResult *render_result_new_from_exr(
void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty);
diff --git a/source/blender/sequencer/CMakeLists.txt b/source/blender/sequencer/CMakeLists.txt
index e324bc8b407..f060e6ad69b 100644
--- a/source/blender/sequencer/CMakeLists.txt
+++ b/source/blender/sequencer/CMakeLists.txt
@@ -33,6 +33,7 @@ set(INC
../render
../windowmanager
../../../intern/atomic
+ ../../../intern/clog
../../../intern/guardedalloc
# dna_type_offsets.h
diff --git a/source/blender/sequencer/SEQ_edit.h b/source/blender/sequencer/SEQ_edit.h
index 6d043dffe72..fbbf4bc53ea 100644
--- a/source/blender/sequencer/SEQ_edit.h
+++ b/source/blender/sequencer/SEQ_edit.h
@@ -53,7 +53,8 @@ struct Sequence *SEQ_edit_strip_split(struct Main *bmain,
struct ListBase *seqbase,
struct Sequence *seq,
const int timeline_frame,
- const eSeqSplitMethod method);
+ const eSeqSplitMethod method,
+ const char **r_error);
bool SEQ_edit_remove_gaps(struct Scene *scene,
struct ListBase *seqbase,
const int initial_frame,
diff --git a/source/blender/sequencer/SEQ_iterator.h b/source/blender/sequencer/SEQ_iterator.h
index cb2091511a9..3ade7309f89 100644
--- a/source/blender/sequencer/SEQ_iterator.h
+++ b/source/blender/sequencer/SEQ_iterator.h
@@ -73,6 +73,7 @@ struct Sequence *SEQ_iterator_yield(SeqIterator *iterator);
SeqCollection *SEQ_collection_create(const char *name);
SeqCollection *SEQ_collection_duplicate(SeqCollection *collection);
uint SEQ_collection_len(const SeqCollection *collection);
+bool SEQ_collection_has_strip(const struct Sequence *seq, const SeqCollection *collection);
bool SEQ_collection_append_strip(struct Sequence *seq, SeqCollection *data);
bool SEQ_collection_remove_strip(struct Sequence *seq, SeqCollection *data);
void SEQ_collection_free(SeqCollection *collection);
diff --git a/source/blender/sequencer/SEQ_relations.h b/source/blender/sequencer/SEQ_relations.h
index 366c1002e22..54e53193b48 100644
--- a/source/blender/sequencer/SEQ_relations.h
+++ b/source/blender/sequencer/SEQ_relations.h
@@ -65,6 +65,9 @@ void SEQ_cache_iterate(
void *userdata,
bool callback_init(void *userdata, size_t item_count),
bool callback_iter(void *userdata, struct Sequence *seq, int timeline_frame, int cache_type));
+struct Sequence *SEQ_find_metastrip_by_sequence(ListBase *seqbase /* = ed->seqbase */,
+ struct Sequence *meta /* = NULL */,
+ struct Sequence *seq);
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/sequencer/intern/effects.c b/source/blender/sequencer/intern/effects.c
index 3ca0555d9a5..d4adad9a34d 100644
--- a/source/blender/sequencer/intern/effects.c
+++ b/source/blender/sequencer/intern/effects.c
@@ -61,6 +61,7 @@
#include "SEQ_effects.h"
#include "SEQ_proxy.h"
+#include "SEQ_relations.h"
#include "SEQ_render.h"
#include "SEQ_utils.h"
@@ -3023,7 +3024,7 @@ static ImBuf *do_adjustment_impl(const SeqRenderData *context, Sequence *seq, fl
if (!i) {
Sequence *meta;
- meta = seq_find_metastrip_by_sequence(&ed->seqbase, NULL, seq);
+ meta = SEQ_find_metastrip_by_sequence(&ed->seqbase, NULL, seq);
if (meta) {
i = do_adjustment_impl(context, meta, timeline_frame);
@@ -3069,8 +3070,6 @@ static void init_speed_effect(Sequence *seq)
seq->effectdata = MEM_callocN(sizeof(SpeedControlVars), "speedcontrolvars");
v = (SpeedControlVars *)seq->effectdata;
- v->frameMap = NULL;
- v->length = 0;
v->speed_control_type = SEQ_SPEED_STRETCH;
v->speed_fader = 1.0f;
v->speed_fader_length = 0.0f;
@@ -3080,9 +3079,7 @@ static void init_speed_effect(Sequence *seq)
static void load_speed_effect(Sequence *seq)
{
SpeedControlVars *v = (SpeedControlVars *)seq->effectdata;
-
v->frameMap = NULL;
- v->length = 0;
}
static int num_inputs_speed(void)
@@ -3105,7 +3102,6 @@ static void copy_speed_effect(Sequence *dst, Sequence *src, const int UNUSED(fla
dst->effectdata = MEM_dupallocN(src->effectdata);
v = (SpeedControlVars *)dst->effectdata;
v->frameMap = NULL;
- v->length = 0;
}
static int early_out_speed(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
@@ -3127,164 +3123,114 @@ static int seq_effect_speed_get_strip_content_length(const Sequence *seq)
return seq->len;
}
-void seq_effect_speed_rebuild_map(Scene *scene, Sequence *seq, bool force)
+static FCurve *seq_effect_speed_speed_factor_curve_get(Scene *scene, Sequence *seq)
{
- int timeline_frame;
- float fallback_fac = 1.0f;
- SpeedControlVars *v = (SpeedControlVars *)seq->effectdata;
- FCurve *fcu = NULL;
-
- /* if not already done, load / initialize data */
- SEQ_effect_handle_get(seq);
+ return id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_factor", 0, NULL);
+}
- if ((force == false) && (seq->len == v->length) && (v->frameMap != NULL)) {
- return;
- }
+/* Build frame map when speed in mode #SEQ_SPEED_MULTIPLY is animated.
+ * This is, because `target_frame` value is integrated over time. */
+void seq_effect_speed_rebuild_map(Scene *scene, Sequence *seq)
+{
if ((seq->seq1 == NULL) || (seq->len < 1)) {
- /* make coverity happy and check for (CID 598) input strip ... */
- return;
+ return; /* Make coverity happy and check for (CID 598) input strip... */
}
- /* XXX(campbell): new in 2.5x. should we use the animation system this way?
- * The fcurve is needed because many frames need evaluating at once. */
- switch (v->speed_control_type) {
- case SEQ_SPEED_MULTIPLY: {
- fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_factor", 0, NULL);
- break;
- }
- case SEQ_SPEED_FRAME_NUMBER: {
- fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_frame_number", 0, NULL);
- break;
- }
- case SEQ_SPEED_LENGTH: {
- fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_length", 0, NULL);
- break;
- }
+ FCurve *fcu = seq_effect_speed_speed_factor_curve_get(scene, seq);
+ if (fcu == NULL) {
+ return;
}
- if (!v->frameMap || v->length != seq->len) {
- if (v->frameMap) {
- MEM_freeN(v->frameMap);
- }
-
- v->length = seq->len;
- v->frameMap = MEM_callocN(sizeof(float) * v->length, "speedcontrol frameMap");
+ SpeedControlVars *v = (SpeedControlVars *)seq->effectdata;
+ if (v->frameMap) {
+ MEM_freeN(v->frameMap);
}
- fallback_fac = 1.0;
+ const int effect_strip_length = seq->enddisp - seq->startdisp;
+ v->frameMap = MEM_mallocN(sizeof(float) * effect_strip_length, __func__);
+ v->frameMap[0] = 0.0f;
- const int target_strip_length = seq_effect_speed_get_strip_content_length(seq->seq1);
-
- if (v->speed_control_type == SEQ_SPEED_STRETCH) {
- if ((seq->seq1->enddisp != seq->seq1->start) && (target_strip_length != 0)) {
- fallback_fac = (float)target_strip_length / (float)(seq->seq1->enddisp - seq->seq1->start);
- fcu = NULL;
- }
- }
- else {
- /* if there is no fcurve, use value as simple multiplier */
- if (!fcu) {
- switch (v->speed_control_type) {
- case SEQ_SPEED_MULTIPLY: {
- fallback_fac = v->speed_fader;
- break;
- }
- case SEQ_SPEED_FRAME_NUMBER: {
- fallback_fac = v->speed_fader_frame_number;
- break;
- }
- case SEQ_SPEED_LENGTH: {
- fallback_fac = v->speed_fader_length;
- break;
- }
- }
- }
+ float target_frame = 0;
+ for (int frame_index = 1; frame_index < effect_strip_length; frame_index++) {
+ target_frame += evaluate_fcurve(fcu, seq->startdisp + frame_index);
+ v->frameMap[frame_index] = target_frame;
}
+}
- if (ELEM(v->speed_control_type, SEQ_SPEED_MULTIPLY, SEQ_SPEED_STRETCH)) {
- float cursor = 0;
- float facf;
-
- v->frameMap[0] = 0;
- v->lastValidFrame = 0;
-
- for (timeline_frame = 1; timeline_frame < v->length; timeline_frame++) {
- if (fcu) {
- facf = evaluate_fcurve(fcu, seq->startdisp + timeline_frame);
- }
- else {
- facf = fallback_fac;
- }
-
- cursor += facf;
-
- if (cursor >= target_strip_length) {
- v->frameMap[timeline_frame] = target_strip_length - 1;
- }
- else {
- v->frameMap[timeline_frame] = cursor;
- v->lastValidFrame = timeline_frame;
- }
- }
+static void seq_effect_speed_frame_map_ensure(Scene *scene, Sequence *seq)
+{
+ SpeedControlVars *v = (SpeedControlVars *)seq->effectdata;
+ if (v->frameMap != NULL) {
+ return;
}
- else {
- float facf;
- v->lastValidFrame = 0;
- for (timeline_frame = 0; timeline_frame < v->length; timeline_frame++) {
+ seq_effect_speed_rebuild_map(scene, seq);
+}
- if (fcu) {
- facf = evaluate_fcurve(fcu, seq->startdisp + timeline_frame);
- }
- else {
- facf = fallback_fac;
- }
+/* Override timeline_frame when rendering speed effect input. */
+float seq_speed_effect_target_frame_get(Scene *scene,
+ Sequence *seq_speed,
+ float timeline_frame,
+ int input)
+{
+ if (seq_speed->seq1 == NULL) {
+ return 0.0f;
+ }
- if (v->speed_control_type == SEQ_SPEED_LENGTH) {
- facf *= target_strip_length;
- facf /= 100.0f;
- }
+ SEQ_effect_handle_get(seq_speed); /* Ensure, that data are initialized. */
+ int frame_index = seq_give_frame_index(seq_speed, timeline_frame);
+ SpeedControlVars *s = (SpeedControlVars *)seq_speed->effectdata;
+ const Sequence *source = seq_speed->seq1;
- if (facf >= target_strip_length) {
- facf = target_strip_length - 1;
+ float target_frame = 0.0f;
+ switch (s->speed_control_type) {
+ case SEQ_SPEED_STRETCH: {
+ const float target_content_length = seq_effect_speed_get_strip_content_length(source);
+ const float target_strip_length = source->enddisp - source->startdisp;
+ const float ratio = target_content_length / target_strip_length;
+ target_frame = frame_index * ratio;
+ break;
+ }
+ case SEQ_SPEED_MULTIPLY: {
+ FCurve *fcu = seq_effect_speed_speed_factor_curve_get(scene, seq_speed);
+ if (fcu != NULL) {
+ seq_effect_speed_frame_map_ensure(scene, seq_speed);
+ target_frame = s->frameMap[frame_index];
}
else {
- v->lastValidFrame = timeline_frame;
+ target_frame = frame_index * s->speed_fader;
}
- v->frameMap[timeline_frame] = facf;
+ break;
}
+ case SEQ_SPEED_LENGTH:
+ target_frame = seq_effect_speed_get_strip_content_length(source) *
+ (s->speed_fader_length / 100.0f);
+ break;
+ case SEQ_SPEED_FRAME_NUMBER:
+ target_frame = s->speed_fader_frame_number;
+ break;
}
-}
-/* Override timeline_frame when rendering speed effect input. */
-float seq_speed_effect_target_frame_get(const SeqRenderData *context,
- Sequence *seq,
- float timeline_frame,
- int input)
-{
- int frame_index = seq_give_frame_index(seq, timeline_frame);
- SpeedControlVars *s = (SpeedControlVars *)seq->effectdata;
- seq_effect_speed_rebuild_map(context->scene, seq, false);
+ CLAMP(target_frame, 0, seq_effect_speed_get_strip_content_length(source));
+ target_frame += seq_speed->start;
/* No interpolation. */
if ((s->flags & SEQ_SPEED_USE_INTERPOLATION) == 0) {
- return seq->start + s->frameMap[frame_index];
+ return target_frame;
}
- /* We need to provide current and next image for interpolation. */
- if (input == 0) { /* Current frame. */
- return floor(seq->start + s->frameMap[frame_index]);
- }
- /* Next frame. */
- return ceil(seq->start + s->frameMap[frame_index]);
+ /* Interpolation is used, switch between current and next frame based on which input is
+ * requested. */
+ return input == 0 ? target_frame : ceil(target_frame);
}
-static float speed_effect_interpolation_ratio_get(SpeedControlVars *s,
- Sequence *seq,
+static float speed_effect_interpolation_ratio_get(Scene *scene,
+ Sequence *seq_speed,
float timeline_frame)
{
- int frame_index = seq_give_frame_index(seq, timeline_frame);
- return s->frameMap[frame_index] - floor(s->frameMap[frame_index]);
+ const float target_frame = seq_speed_effect_target_frame_get(
+ scene, seq_speed, timeline_frame, 0);
+ return target_frame - floor(target_frame);
}
static ImBuf *do_speed_effect(const SeqRenderData *context,
@@ -3302,7 +3248,7 @@ static ImBuf *do_speed_effect(const SeqRenderData *context,
if (s->flags & SEQ_SPEED_USE_INTERPOLATION) {
out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
- facf0 = facf1 = speed_effect_interpolation_ratio_get(s, seq, timeline_frame);
+ facf0 = facf1 = speed_effect_interpolation_ratio_get(context->scene, seq, timeline_frame);
/* Current frame is ibuf1, next frame is ibuf2. */
out = seq_render_effect_execute_threaded(
&cross_effect, context, NULL, timeline_frame, facf0, facf1, ibuf1, ibuf2, ibuf3);
diff --git a/source/blender/sequencer/intern/effects.h b/source/blender/sequencer/intern/effects.h
index 1bce4f324c3..25ba4d8956e 100644
--- a/source/blender/sequencer/intern/effects.h
+++ b/source/blender/sequencer/intern/effects.h
@@ -39,8 +39,8 @@ struct Sequence;
*/
struct SeqEffectHandle seq_effect_get_sequence_blend(struct Sequence *seq);
-void seq_effect_speed_rebuild_map(struct Scene *scene, struct Sequence *seq, bool force);
-float seq_speed_effect_target_frame_get(const struct SeqRenderData *context,
+void seq_effect_speed_rebuild_map(struct Scene *scene, struct Sequence *seq);
+float seq_speed_effect_target_frame_get(struct Scene *scene,
struct Sequence *seq,
float timeline_frame,
int input);
diff --git a/source/blender/sequencer/intern/iterator.c b/source/blender/sequencer/intern/iterator.c
index 09f033e70fb..333a8e46c44 100644
--- a/source/blender/sequencer/intern/iterator.c
+++ b/source/blender/sequencer/intern/iterator.c
@@ -123,6 +123,14 @@ uint SEQ_collection_len(const SeqCollection *collection)
}
/**
+ * Check if seq is in collection.
+ */
+bool SEQ_collection_has_strip(const Sequence *seq, const SeqCollection *collection)
+{
+ return BLI_gset_haskey(collection->set, seq);
+}
+
+/**
* Query strips from seqbase. seq_reference is used by query function as filter condition.
*
* \param seq_reference: reference strip for query function
diff --git a/source/blender/sequencer/intern/prefetch.c b/source/blender/sequencer/intern/prefetch.c
index 15609a76f5c..dd2d828415c 100644
--- a/source/blender/sequencer/intern/prefetch.c
+++ b/source/blender/sequencer/intern/prefetch.c
@@ -53,7 +53,9 @@
#include "DEG_depsgraph_debug.h"
#include "DEG_depsgraph_query.h"
+#include "SEQ_iterator.h"
#include "SEQ_prefetch.h"
+#include "SEQ_relations.h"
#include "SEQ_render.h"
#include "SEQ_sequencer.h"
@@ -359,67 +361,93 @@ void seq_prefetch_free(Scene *scene)
scene->ed->prefetch_job = NULL;
}
-/* Skip frame if we need to render 3D scene strip. Rendering 3D scene requires main lock or setting
- * up render job that doesn't have API to do openGL renders which can be used for sequencer. */
-static bool seq_prefetch_do_skip_frame(PrefetchJob *pfjob, ListBase *seqbase)
+static bool seq_prefetch_seq_has_disk_cache(PrefetchJob *pfjob,
+ Sequence *seq,
+ bool can_have_final_image)
{
- float cfra = seq_prefetch_cfra(pfjob);
- Sequence *seq_arr[MAXSEQ + 1];
- int count = seq_get_shown_sequences(seqbase, cfra, 0, seq_arr);
SeqRenderData *ctx = &pfjob->context_cpy;
- ImBuf *ibuf = NULL;
+ float cfra = seq_prefetch_cfra(pfjob);
- /* Disable prefetching 3D scene strips, but check for disk cache. */
- for (int i = 0; i < count; i++) {
- if (seq_arr[i]->type == SEQ_TYPE_META &&
- seq_prefetch_do_skip_frame(pfjob, &seq_arr[i]->seqbase)) {
- return true;
- }
+ ImBuf *ibuf = seq_cache_get(ctx, seq, cfra, SEQ_CACHE_STORE_PREPROCESSED);
+ if (ibuf != NULL) {
+ IMB_freeImBuf(ibuf);
+ return true;
+ }
- if (seq_arr[i]->type == SEQ_TYPE_SCENE && (seq_arr[i]->flag & SEQ_SCENE_STRIPS) == 0) {
- int cached_types = 0;
+ ibuf = seq_cache_get(ctx, seq, cfra, SEQ_CACHE_STORE_RAW);
+ if (ibuf != NULL) {
+ IMB_freeImBuf(ibuf);
+ return true;
+ }
- ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_FINAL_OUT);
- if (ibuf != NULL) {
- cached_types |= SEQ_CACHE_STORE_FINAL_OUT;
- IMB_freeImBuf(ibuf);
- ibuf = NULL;
- }
+ if (!can_have_final_image) {
+ return false;
+ }
- ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_COMPOSITE);
- if (ibuf != NULL) {
- cached_types |= SEQ_CACHE_STORE_COMPOSITE;
- IMB_freeImBuf(ibuf);
- ibuf = NULL;
- }
+ ibuf = seq_cache_get(ctx, seq, cfra, SEQ_CACHE_STORE_FINAL_OUT);
+ if (ibuf != NULL) {
+ IMB_freeImBuf(ibuf);
+ return true;
+ }
- ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_PREPROCESSED);
- if (ibuf != NULL) {
- cached_types |= SEQ_CACHE_STORE_PREPROCESSED;
- IMB_freeImBuf(ibuf);
- ibuf = NULL;
- }
+ return false;
+}
- ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_RAW);
- if (ibuf != NULL) {
- cached_types |= SEQ_CACHE_STORE_RAW;
- IMB_freeImBuf(ibuf);
- ibuf = NULL;
- }
+static bool seq_prefetch_scene_strip_is_rendered(PrefetchJob *pfjob,
+ ListBase *seqbase,
+ SeqCollection *scene_strips,
+ bool is_recursive_check)
+{
+ float cfra = seq_prefetch_cfra(pfjob);
+ Sequence *seq_arr[MAXSEQ + 1];
+ int count = seq_get_shown_sequences(seqbase, cfra, 0, seq_arr);
- if ((cached_types & (SEQ_CACHE_STORE_RAW | SEQ_CACHE_STORE_PREPROCESSED)) != 0) {
- continue;
- }
+ /* Iterate over rendered strips. */
+ for (int i = 0; i < count; i++) {
+ Sequence *seq = seq_arr[i];
+ if (seq->type == SEQ_TYPE_META &&
+ seq_prefetch_scene_strip_is_rendered(pfjob, &seq->seqbase, scene_strips, true)) {
+ return true;
+ }
+
+ /* Disable prefetching 3D scene strips, but check for disk cache. */
+ if (seq->type == SEQ_TYPE_SCENE && (seq->flag & SEQ_SCENE_STRIPS) == 0 &&
+ !seq_prefetch_seq_has_disk_cache(pfjob, seq, !is_recursive_check)) {
+ return true;
+ }
- /* It is only safe to use these cache types if strip is last in stack. */
- if (i == count - 1 && (cached_types & SEQ_CACHE_STORE_FINAL_OUT) != 0) {
- continue;
+ /* Check if strip is effect of scene strip or uses it as modifier. This is recursive check. */
+ Sequence *seq_scene;
+ SEQ_ITERATOR_FOREACH (seq_scene, scene_strips) {
+ if (SEQ_relations_render_loop_check(seq, seq_scene)) {
+ return true;
}
+ }
+ }
+ return false;
+}
- return true;
+static SeqCollection *query_scene_strips(ListBase *seqbase)
+{
+ SeqCollection *collection = SEQ_query_all_strips_recursive(seqbase);
+ LISTBASE_FOREACH (Sequence *, seq, seqbase) {
+ if (seq->type != SEQ_TYPE_SCENE || (seq->flag & SEQ_SCENE_STRIPS) != 0) {
+ SEQ_collection_remove_strip(seq, collection);
}
}
+ return collection;
+}
+/* Prefetch must avoid rendering scene strips, because rendering in background locks UI and can
+ * make it unresponsive for long time periods. */
+static bool seq_prefetch_must_skip_frame(PrefetchJob *pfjob, ListBase *seqbase)
+{
+ SeqCollection *scene_strips = query_scene_strips(seqbase);
+ if (seq_prefetch_scene_strip_is_rendered(pfjob, seqbase, scene_strips, false)) {
+ SEQ_collection_free(scene_strips);
+ return true;
+ }
+ SEQ_collection_free(scene_strips);
return false;
}
@@ -464,7 +492,7 @@ static void *seq_prefetch_frames(void *job)
pfjob->scene_eval->ed->prefetch_job = pfjob;
ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(pfjob->scene, false));
- if (seq_prefetch_do_skip_frame(pfjob, seqbase)) {
+ if (seq_prefetch_must_skip_frame(pfjob, seqbase)) {
pfjob->num_frames_prefetched++;
continue;
}
diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c
index aba84743621..0c07a25e2e2 100644
--- a/source/blender/sequencer/intern/render.c
+++ b/source/blender/sequencer/intern/render.c
@@ -840,7 +840,7 @@ static ImBuf *seq_render_effect_strip_impl(const SeqRenderData *context,
for (i = 0; i < 3; i++) {
/* Speed effect requires time remapping of `timeline_frame` for input(s). */
if (input[0] && seq->type == SEQ_TYPE_SPEED) {
- float target_frame = seq_speed_effect_target_frame_get(context, seq, timeline_frame, i);
+ float target_frame = seq_speed_effect_target_frame_get(scene, seq, timeline_frame, i);
ibuf[i] = seq_render_strip(context, state, input[0], target_frame);
}
else { /* Other effects. */
diff --git a/source/blender/sequencer/intern/strip_edit.c b/source/blender/sequencer/intern/strip_edit.c
index e92afee08cd..17ff1c90be8 100644
--- a/source/blender/sequencer/intern/strip_edit.c
+++ b/source/blender/sequencer/intern/strip_edit.c
@@ -351,6 +351,11 @@ static void seq_split_set_left_offset(Sequence *seq, int timeline_frame)
SEQ_transform_set_left_handle_frame(seq, timeline_frame);
}
+static bool seq_edit_split_effect_intersect_check(const Sequence *seq, const int timeline_frame)
+{
+ return timeline_frame > seq->startdisp && timeline_frame < seq->enddisp;
+}
+
static void seq_edit_split_handle_strip_offsets(Main *bmain,
Scene *scene,
Sequence *left_seq,
@@ -358,20 +363,82 @@ static void seq_edit_split_handle_strip_offsets(Main *bmain,
const int timeline_frame,
const eSeqSplitMethod method)
{
- switch (method) {
- case SEQ_SPLIT_SOFT:
- seq_split_set_left_offset(right_seq, timeline_frame);
- seq_split_set_right_offset(left_seq, timeline_frame);
- break;
- case SEQ_SPLIT_HARD:
- seq_split_set_right_hold_offset(left_seq, timeline_frame);
- seq_split_set_left_hold_offset(right_seq, timeline_frame);
- SEQ_add_reload_new_file(bmain, scene, left_seq, false);
- SEQ_add_reload_new_file(bmain, scene, right_seq, false);
- break;
- }
- SEQ_time_update_sequence(scene, left_seq);
- SEQ_time_update_sequence(scene, right_seq);
+ if (seq_edit_split_effect_intersect_check(right_seq, timeline_frame)) {
+ switch (method) {
+ case SEQ_SPLIT_SOFT:
+ seq_split_set_left_offset(right_seq, timeline_frame);
+ break;
+ case SEQ_SPLIT_HARD:
+ seq_split_set_left_hold_offset(right_seq, timeline_frame);
+ SEQ_add_reload_new_file(bmain, scene, right_seq, false);
+ break;
+ }
+ SEQ_time_update_sequence(scene, right_seq);
+ }
+
+ if (seq_edit_split_effect_intersect_check(left_seq, timeline_frame)) {
+ switch (method) {
+ case SEQ_SPLIT_SOFT:
+ seq_split_set_right_offset(left_seq, timeline_frame);
+ break;
+ case SEQ_SPLIT_HARD:
+ seq_split_set_right_hold_offset(left_seq, timeline_frame);
+ SEQ_add_reload_new_file(bmain, scene, left_seq, false);
+ break;
+ }
+ SEQ_time_update_sequence(scene, left_seq);
+ }
+}
+
+static bool seq_edit_split_effect_inputs_intersect(const Sequence *seq, const int timeline_frame)
+{
+ bool input_does_intersect = false;
+ if (seq->seq1) {
+ input_does_intersect |= seq_edit_split_effect_intersect_check(seq->seq1, timeline_frame);
+ if ((seq->seq1->type & SEQ_TYPE_EFFECT) != 0) {
+ input_does_intersect |= seq_edit_split_effect_inputs_intersect(seq->seq1, timeline_frame);
+ }
+ }
+ if (seq->seq2) {
+ input_does_intersect |= seq_edit_split_effect_intersect_check(seq->seq2, timeline_frame);
+ if ((seq->seq1->type & SEQ_TYPE_EFFECT) != 0) {
+ input_does_intersect |= seq_edit_split_effect_inputs_intersect(seq->seq2, timeline_frame);
+ }
+ }
+ if (seq->seq3) {
+ input_does_intersect |= seq_edit_split_effect_intersect_check(seq->seq3, timeline_frame);
+ if ((seq->seq1->type & SEQ_TYPE_EFFECT) != 0) {
+ input_does_intersect |= seq_edit_split_effect_inputs_intersect(seq->seq3, timeline_frame);
+ }
+ }
+ return input_does_intersect;
+}
+
+static bool seq_edit_split_operation_permitted_check(SeqCollection *strips,
+ const int timeline_frame,
+ const char **r_error)
+{
+ Sequence *seq;
+ SEQ_ITERATOR_FOREACH (seq, strips) {
+ if ((seq->type & SEQ_TYPE_EFFECT) == 0) {
+ continue;
+ }
+ if (!seq_edit_split_effect_intersect_check(seq, timeline_frame)) {
+ continue;
+ }
+ if (SEQ_effect_get_num_inputs(seq->type) <= 1) {
+ continue;
+ }
+ if (ELEM(seq->type, SEQ_TYPE_CROSS, SEQ_TYPE_GAMCROSS, SEQ_TYPE_WIPE)) {
+ *r_error = "Splitting transition effect is not permitted.";
+ return false;
+ }
+ if (!seq_edit_split_effect_inputs_intersect(seq, timeline_frame)) {
+ *r_error = "Effect inputs don't overlap. Can not split such effect.";
+ return false;
+ }
+ }
+ return true;
}
/**
@@ -390,16 +457,23 @@ Sequence *SEQ_edit_strip_split(Main *bmain,
ListBase *seqbase,
Sequence *seq,
const int timeline_frame,
- const eSeqSplitMethod method)
+ const eSeqSplitMethod method,
+ const char **r_error)
{
- if (timeline_frame <= seq->startdisp || timeline_frame >= seq->enddisp) {
+ if (!seq_edit_split_effect_intersect_check(seq, timeline_frame)) {
return NULL;
}
+ /* Whole strip chain must be duplicated in order to preserve relationships. */
SeqCollection *collection = SEQ_collection_create(__func__);
SEQ_collection_append_strip(seq, collection);
SEQ_collection_expand(seqbase, collection, SEQ_query_strip_effect_chain);
+ if (!seq_edit_split_operation_permitted_check(collection, timeline_frame, r_error)) {
+ SEQ_collection_free(collection);
+ return NULL;
+ }
+
/* Move strips in collection from seqbase to new ListBase. */
ListBase left_strips = {NULL, NULL};
SEQ_ITERATOR_FOREACH (seq, collection) {
@@ -421,7 +495,19 @@ Sequence *SEQ_edit_strip_split(Main *bmain,
Sequence *left_seq = left_strips.first;
Sequence *right_seq = right_strips.first;
Sequence *return_seq = right_strips.first;
+
+ /* Strips can't be tagged while in detached `seqbase`. Collect all strips which needs to be
+ * deleted and delay tagging until they are moved back to `seqbase` in `Editing`. */
+ SeqCollection *strips_to_delete = SEQ_collection_create(__func__);
+
while (left_seq && right_seq) {
+ if (left_seq->startdisp >= timeline_frame) {
+ SEQ_collection_append_strip(left_seq, strips_to_delete);
+ }
+ if (right_seq->enddisp <= timeline_frame) {
+ SEQ_collection_append_strip(right_seq, strips_to_delete);
+ }
+
seq_edit_split_handle_strip_offsets(bmain, scene, left_seq, right_seq, timeline_frame, method);
left_seq = left_seq->next;
right_seq = right_seq->next;
@@ -435,6 +521,12 @@ Sequence *SEQ_edit_strip_split(Main *bmain,
SEQ_ensure_unique_name(seq, scene);
}
+ Sequence *seq_delete;
+ SEQ_ITERATOR_FOREACH (seq_delete, strips_to_delete) {
+ SEQ_edit_flag_for_removal(scene, seqbase, seq_delete);
+ }
+ SEQ_edit_remove_flagged_sequences(scene, seqbase);
+ SEQ_collection_free(strips_to_delete);
return return_seq;
}
@@ -476,6 +568,6 @@ bool SEQ_edit_remove_gaps(Scene *scene,
void SEQ_edit_sequence_name_set(Scene *scene, Sequence *seq, const char *new_name)
{
BLI_strncpy_utf8(seq->name + 2, new_name, MAX_NAME - 2);
- BLI_utf8_invalid_strip(seq->name + 2, strlen(seq->name + 2));
+ BLI_str_utf8_invalid_strip(seq->name + 2, strlen(seq->name + 2));
SEQ_sequence_lookup_tag(scene, SEQ_LOOKUP_TAG_INVALID);
}
diff --git a/source/blender/sequencer/intern/strip_relations.c b/source/blender/sequencer/intern/strip_relations.c
index 7c5a3f031db..ec70a683da5 100644
--- a/source/blender/sequencer/intern/strip_relations.c
+++ b/source/blender/sequencer/intern/strip_relations.c
@@ -118,7 +118,7 @@ static void sequence_invalidate_cache(Scene *scene,
}
if (seq->effectdata && seq->type == SEQ_TYPE_SPEED) {
- seq_effect_speed_rebuild_map(scene, seq, true);
+ seq_effect_speed_rebuild_map(scene, seq);
}
sequence_do_invalidate_dependent(scene, seq, &ed->seqbase);
@@ -268,7 +268,7 @@ void SEQ_relations_free_imbuf(Scene *scene, ListBase *seqbase, bool for_render)
SEQ_relations_sequence_free_anim(seq);
}
if (seq->type == SEQ_TYPE_SPEED) {
- seq_effect_speed_rebuild_map(scene, seq, true);
+ seq_effect_speed_rebuild_map(scene, seq);
}
}
if (seq->type == SEQ_TYPE_META) {
@@ -325,7 +325,7 @@ static bool update_changed_seq_recurs(
SEQ_relations_sequence_free_anim(seq);
}
else if (seq->type == SEQ_TYPE_SPEED) {
- seq_effect_speed_rebuild_map(scene, seq, true);
+ seq_effect_speed_rebuild_map(scene, seq);
}
}
@@ -504,3 +504,23 @@ void SEQ_relations_check_uuids_unique_and_report(const Scene *scene)
BLI_gset_free(used_uuids, NULL);
}
+
+/* Return immediate parent meta of sequence */
+struct Sequence *SEQ_find_metastrip_by_sequence(ListBase *seqbase, Sequence *meta, Sequence *seq)
+{
+ Sequence *iseq;
+
+ for (iseq = seqbase->first; iseq; iseq = iseq->next) {
+ Sequence *rval;
+
+ if (seq == iseq) {
+ return meta;
+ }
+ if (iseq->seqbase.first &&
+ (rval = SEQ_find_metastrip_by_sequence(&iseq->seqbase, iseq, seq))) {
+ return rval;
+ }
+ }
+
+ return NULL;
+} \ No newline at end of file
diff --git a/source/blender/sequencer/intern/strip_transform.c b/source/blender/sequencer/intern/strip_transform.c
index c9af2fced65..9f69f434ca0 100644
--- a/source/blender/sequencer/intern/strip_transform.c
+++ b/source/blender/sequencer/intern/strip_transform.c
@@ -40,6 +40,10 @@
#include "SEQ_time.h"
#include "SEQ_transform.h"
+#include "CLG_log.h"
+
+static CLG_LogRef LOG = {"seq.strip_transform"};
+
static int seq_tx_get_start(Sequence *seq)
{
return seq->start;
@@ -315,6 +319,12 @@ static int shuffle_seq_time_offset_test(SeqCollection *strips_to_shuffle,
if (!seq_overlap(seq, seq_other)) {
continue;
}
+ if (UNLIKELY(SEQ_collection_has_strip(seq_other, strips_to_shuffle))) {
+ CLOG_WARN(&LOG,
+ "Strip overlaps with itself or another strip, that is to be shuffled."
+ "This should never happen.");
+ continue;
+ }
if (dir == 'L') {
offset = min_ii(offset, seq_other->startdisp - seq->enddisp);
}
diff --git a/source/blender/sequencer/intern/utils.c b/source/blender/sequencer/intern/utils.c
index 98640ea8a5c..f946affe1d8 100644
--- a/source/blender/sequencer/intern/utils.c
+++ b/source/blender/sequencer/intern/utils.c
@@ -431,7 +431,7 @@ const Sequence *SEQ_get_topmost_sequence(const Scene *scene, int frame)
return best_seq;
}
-/* in cases where we done know the sequence's listbase */
+/* in cases where we don't know the sequence's listbase */
ListBase *SEQ_get_seqbase_by_seq(ListBase *seqbase, Sequence *seq)
{
Sequence *iseq;
@@ -449,25 +449,6 @@ ListBase *SEQ_get_seqbase_by_seq(ListBase *seqbase, Sequence *seq)
return NULL;
}
-Sequence *seq_find_metastrip_by_sequence(ListBase *seqbase, Sequence *meta, Sequence *seq)
-{
- Sequence *iseq;
-
- for (iseq = seqbase->first; iseq; iseq = iseq->next) {
- Sequence *rval;
-
- if (seq == iseq) {
- return meta;
- }
- if (iseq->seqbase.first &&
- (rval = seq_find_metastrip_by_sequence(&iseq->seqbase, iseq, seq))) {
- return rval;
- }
- }
-
- return NULL;
-}
-
/**
* Only use as last resort when the StripElem is available but no the Sequence.
* (needed for RNA)
diff --git a/source/blender/sequencer/intern/utils.h b/source/blender/sequencer/intern/utils.h
index 97f33bb3ae0..7aee7d229c9 100644
--- a/source/blender/sequencer/intern/utils.h
+++ b/source/blender/sequencer/intern/utils.h
@@ -31,10 +31,6 @@ struct Scene;
bool sequencer_seq_generates_image(struct Sequence *seq);
void seq_open_anim_file(struct Scene *scene, struct Sequence *seq, bool openfile);
-struct Sequence *seq_find_metastrip_by_sequence(ListBase *seqbase /* = ed->seqbase */,
- struct Sequence *meta /* = NULL */,
- struct Sequence *seq);
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index b5a038757c2..f1a8f4ffd71 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -2497,7 +2497,7 @@ static int radial_control_get_path(PointerRNA *ctx_ptr,
/* get an rna string path from the operator's properties */
char *str;
- if (!(str = RNA_string_get_alloc(op->ptr, name, NULL, 0))) {
+ if (!(str = RNA_string_get_alloc(op->ptr, name, NULL, 0, NULL))) {
return 1;
}
diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt
index 0f9665f0a95..79632e49c1f 100644
--- a/tests/python/CMakeLists.txt
+++ b/tests/python/CMakeLists.txt
@@ -741,10 +741,17 @@ if(WITH_COMPOSITOR)
endif()
set(geo_node_tests
+ attributes
+ curve_primitives
curves
geometry
+ mesh_primitives
mesh
points
+ utilities
+ vector
+ volume
+
)
foreach(geo_node_test ${geo_node_tests})