Compare commits

..

80 Commits

Author SHA1 Message Date
eed93aaa07 make dot output more compact 2021-08-22 22:34:25 +02:00
fc0bb6cdee avoid allocating index array in some cases 2021-08-22 20:29:52 +02:00
10f2ad1556 add return instruction and initial procedure validation 2021-08-22 20:16:27 +02:00
6d77b87b13 support span buffer reuse 2021-08-22 15:07:23 +02:00
2101b46802 fix comment 2021-08-22 12:49:22 +02:00
34f6765630 Merge branch 'master' into temp-multi-function-procedure 2021-08-22 12:21:52 +02:00
c58d1acba8 improve naming 2021-08-20 14:29:01 +02:00
0ee79f304e cleanup 2021-08-20 13:38:38 +02:00
e642de3d6f Merge branch 'master' into temp-multi-function-procedure 2021-08-20 13:37:32 +02:00
eca5a8b695 Merge branch 'master' into temp-multi-function-procedure 2021-08-20 12:48:18 +02:00
79c79f3c70 cleanup 2021-08-20 11:37:23 +02:00
a9970d3cb9 bring back clamping in math node 2021-08-20 10:44:29 +02:00
b812f289f5 Merge branch 'master' into mf-procedure 2021-08-20 10:36:04 +02:00
215ce0fb57 fix 2021-08-19 18:19:15 +02:00
5154598845 Merge branch 'master' into mf-procedure 2021-08-19 18:11:51 +02:00
1ee80d792c cleanup 2021-08-19 18:09:52 +02:00
95284d2f1e bring back function nodes 2021-08-19 18:07:36 +02:00
7281f3eb56 start bringing back function nodes 2021-08-19 17:28:15 +02:00
607ef8f6c5 pull out multi function network 2021-08-19 16:49:00 +02:00
1ce640cc0b test vector processing 2021-08-19 16:24:32 +02:00
7bed18fdb1 support creating loops with builder 2021-08-19 15:33:35 +02:00
c827b50d40 add dummy instruction type 2021-08-19 14:06:43 +02:00
3c7e3c8e44 improve naming 2021-08-19 13:46:19 +02:00
98e38ce4f3 cleanup 2021-08-19 13:44:15 +02:00
132cf268c0 add comments 2021-08-19 13:36:52 +02:00
fd7edc9b05 cleanup 2021-08-19 13:28:15 +02:00
ecf7c90840 remove redundant utilties 2021-08-19 13:15:11 +02:00
d78a530af1 initial procedure builder 2021-08-19 13:09:41 +02:00
3ebe61db9f support evaluation on one 2021-08-19 11:22:57 +02:00
86c2f139c6 cleanup 2021-08-19 10:09:02 +02:00
3596c348eb cleanup 2021-08-19 10:07:51 +02:00
41a81474e4 refactor procedure executor 2021-08-18 20:19:12 +02:00
aa2822d137 cleanup 2021-08-18 20:18:19 +02:00
55b333d3e3 Merge branch 'master' into mf-procedure 2021-08-18 16:14:32 +02:00
00cfad8578 add utility method 2021-08-18 10:00:51 +02:00
1891c956e5 refactor variable store 2021-08-17 17:24:01 +02:00
249c050757 add single test 2021-08-17 15:27:46 +02:00
a0081046b6 cleanup instruction scheduling 2021-08-17 15:01:27 +02:00
635f73b7f1 fixes after merge 2021-08-17 14:00:06 +02:00
74fcd50e2f Merge branch 'master' into mf-procedure 2021-08-17 13:44:25 +02:00
b04a2a7be7 add utility 2021-06-13 14:42:22 +02:00
083671e8ac progress 2021-06-13 14:25:23 +02:00
78ea401e19 Merge branch 'master' into mf-procedure 2021-06-13 14:13:22 +02:00
f3ca987bce start constructing procedure from node tree 2021-06-11 13:39:38 +02:00
2245add9f8 Merge branch 'master' into mf-procedure 2021-06-11 12:59:12 +02:00
31004d7fac start with creating procedure for node tree 2021-05-31 10:51:34 +02:00
3d3f66ed41 fix merge conflicts 2021-05-29 12:14:48 +02:00
c9c0195da5 Merge branch 'master' into mf-procedure 2021-05-29 12:07:13 +02:00
70c0403858 fixes 2021-03-27 22:58:44 +01:00
8d4de82c7f initial network to procedure 2021-03-27 22:30:53 +01:00
22c51c2d51 cleanup 2021-03-27 21:22:28 +01:00
158bd7c6a0 cleanup 2021-03-27 21:18:48 +01:00
4a28d0b583 another check 2021-03-27 15:52:13 +01:00
0501e6e693 fix memory leak in test 2021-03-27 15:45:59 +01:00
8450ac09c1 comment containing things to check 2021-03-27 15:36:08 +01:00
1af00015e8 initial destruct support 2021-03-27 15:29:02 +01:00
b44c3a3125 count initializations 2021-03-27 15:12:36 +01:00
d729f1ca37 cleanup 2021-03-27 15:08:21 +01:00
0fc9f00c14 start extracting container 2021-03-27 14:53:39 +01:00
6c9b339af7 refactor variable store 2021-03-27 14:46:53 +01:00
b7a976af01 branch test 2021-03-27 14:07:23 +01:00
a689037917 initial branch instruction 2021-03-27 13:48:18 +01:00
313403c1f1 support mutable params 2021-03-27 13:33:42 +01:00
60409b8823 simplify 2021-03-27 13:19:46 +01:00
773dc2ec94 improve dot graph 2021-03-27 13:14:19 +01:00
2a98c5d06b initial execution 2021-03-27 13:06:50 +01:00
6d1b4ce3c6 simplify 2021-03-27 12:06:40 +01:00
0b2d961b70 move executor to separate file 2021-03-27 11:55:51 +01:00
d553b70470 Merge branch 'master' into mf-procedure 2021-03-27 11:52:12 +01:00
6954f2cdd7 dot export 2021-03-24 18:46:17 +01:00
8cc832110a more 2021-03-24 18:23:36 +01:00
7b8c54b5a1 more 2021-03-24 17:51:37 +01:00
e850d175b5 more 2021-03-24 17:42:18 +01:00
326f79d59b more 2021-03-24 17:39:22 +01:00
ec4954ece2 destructor 2021-03-24 17:34:14 +01:00
b30e782c82 more stuff 2021-03-24 17:30:53 +01:00
e34fe5d28e add destruct instruction 2021-03-24 16:49:52 +01:00
8581a062f1 Merge branch 'master' into mf-procedure 2021-03-24 16:47:48 +01:00
b43971e5e9 add executor class 2021-03-23 16:20:40 +01:00
855382170e initial mf procedure data structure 2021-03-23 16:18:23 +01:00
305 changed files with 5414 additions and 11002 deletions

View File

@@ -1598,7 +1598,8 @@ 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)
# Using C++20 features while having C++17 as the project language isn't allowed by MSVC.
# Designated initializer is a C++20 feature & breaks MSVC build. Dropping MSVC 2019 or
# updating to C++20 allows removing this.
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)

View File

@@ -51,9 +51,9 @@ buildbot:
gcc:
version: '9.0.0'
cuda10:
version: '10.1.243'
version: '10.1.0'
cuda11:
version: '11.4.1'
version: '11.4.0'
optix:
version: '7.1.0'
cmake:

View File

@@ -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), NULL);
char *cstr = RNA_string_get_alloc(&ptr, name, cstrbuf, sizeof(cstrbuf));
string str(cstr);
if (cstr != cstrbuf)
MEM_freeN(cstr);

View File

@@ -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 = dot(N, L);
float NdotV = dot(N, V);
float NdotL = max(dot(N, L), 0.0f);
float NdotV = max(dot(N, V), 0.0f);
if (NdotL <= 0 || NdotV <= 0) {
if (NdotL < 0 || NdotV < 0) {
*pdf = 0.0f;
return make_float3(0.0f, 0.0f, 0.0f);
}

View File

@@ -997,6 +997,7 @@ 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)

View File

@@ -475,15 +475,24 @@ texture_node_categories = [
geometry_node_categories = [
# Geometry Nodes
GeometryNodeCategory("GEO_ATTRIBUTE", "Attribute", items=[
NodeItem("GeometryNodeAttributeRandomize"),
NodeItem("GeometryNodeAttributeMath"),
NodeItem("GeometryNodeAttributeClamp"),
NodeItem("GeometryNodeAttributeCompare"),
NodeItem("GeometryNodeAttributeConvert"),
NodeItem("GeometryNodeAttributeCurveMap"),
NodeItem("GeometryNodeAttributeFill"),
NodeItem("GeometryNodeAttributeMix"),
NodeItem("GeometryNodeAttributeProximity"),
NodeItem("GeometryNodeAttributeColorRamp"),
NodeItem("GeometryNodeAttributeVectorMath"),
NodeItem("GeometryNodeAttributeVectorRotate"),
NodeItem("GeometryNodeAttributeSampleTexture"),
NodeItem("GeometryNodeAttributeCombineXYZ"),
NodeItem("GeometryNodeAttributeSeparateXYZ"),
NodeItem("GeometryNodeAttributeRemove"),
NodeItem("GeometryNodeAttributeMapRange"),
NodeItem("GeometryNodeAttributeTransfer"),
NodeItem("GeometryNodeAttributeExtract"),
NodeItem("GeometryNodeAttributeFreeze"),
]),
GeometryNodeCategory("GEO_COLOR", "Color", items=[
NodeItem("ShaderNodeMixRGB"),
@@ -505,7 +514,6 @@ geometry_node_categories = [
NodeItem("GeometryNodeCurveSplineType"),
NodeItem("GeometryNodeCurveSetHandles"),
NodeItem("GeometryNodeCurveSelectHandles"),
NodeItem("GeometryNodeEvaluateCurve"),
]),
GeometryNodeCategory("GEO_PRIMITIVES_CURVE", "Curve Primitives", items=[
NodeItem("GeometryNodeCurvePrimitiveLine"),
@@ -524,8 +532,6 @@ geometry_node_categories = [
NodeItem("GeometryNodeJoinGeometry"),
NodeItem("GeometryNodeSeparateComponents"),
NodeItem("GeometryNodeRaycast"),
NodeItem("GeometryNodeAttributeProximity"),
NodeItem("GeometryNodeSetPosition"),
]),
GeometryNodeCategory("GEO_INPUT", "Input", items=[
NodeItem("GeometryNodeObjectInfo"),
@@ -536,11 +542,6 @@ geometry_node_categories = [
NodeItem("FunctionNodeInputVector"),
NodeItem("GeometryNodeInputMaterial"),
NodeItem("GeometryNodeIsViewport"),
NodeItem("GeometryNodeAttribute"),
NodeItem("GeometryNodeIndex"),
NodeItem("GeometryNodeNormal"),
NodeItem("GeometryNodePosition"),
NodeItem("GeometryNodeCurveParameter"),
]),
GeometryNodeCategory("GEO_MATERIAL", "Material", items=[
NodeItem("GeometryNodeMaterialAssign"),
@@ -553,9 +554,6 @@ geometry_node_categories = [
NodeItem("GeometryNodeEdgeSplit"),
NodeItem("GeometryNodeSubdivisionSurface"),
NodeItem("GeometryNodeMeshSubdivide"),
NodeItem("GeometryNodeExtrude"),
NodeItem("GeometryNodeExtrudeAndMove"),
NodeItem("GeometryNodeSampleMeshSurface"),
]),
GeometryNodeCategory("GEO_PRIMITIVES_MESH", "Mesh Primitives", items=[
NodeItem("GeometryNodeMeshCircle"),
@@ -567,6 +565,7 @@ geometry_node_categories = [
NodeItem("GeometryNodeMeshLine"),
NodeItem("GeometryNodeMeshUVSphere"),
]),
GeometryNodeCategory("GEO_POINT", "Point", items=[
NodeItem("GeometryNodePointDistribute"),
NodeItem("GeometryNodePointInstance"),
@@ -574,6 +573,7 @@ geometry_node_categories = [
NodeItem("GeometryNodePointScale"),
NodeItem("GeometryNodePointTranslate"),
NodeItem("GeometryNodeRotatePoints"),
NodeItem("GeometryNodeAlignRotationToVector"),
]),
GeometryNodeCategory("GEO_UTILITIES", "Utilities", items=[
NodeItem("ShaderNodeMapRange"),
@@ -583,7 +583,6 @@ geometry_node_categories = [
NodeItem("FunctionNodeFloatCompare"),
NodeItem("FunctionNodeFloatToInt"),
NodeItem("GeometryNodeSwitch"),
NodeItem("ShaderNodeTexNoise"),
]),
GeometryNodeCategory("GEO_VECTOR", "Vector", items=[
NodeItem("ShaderNodeVectorCurve"),
@@ -591,7 +590,6 @@ geometry_node_categories = [
NodeItem("ShaderNodeCombineXYZ"),
NodeItem("ShaderNodeVectorMath"),
NodeItem("ShaderNodeVectorRotate"),
NodeItem("FunctionNodeAlignRotationToVector"),
]),
GeometryNodeCategory("GEO_OUTPUT", "Output", items=[
NodeItem("GeometryNodeViewer"),

View File

@@ -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 str_len, struct ResultBLF *r_info)
void BLF_draw_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
ATTR_NONNULL(2);
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)
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)
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);
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);
typedef bool (*BLF_GlyphBoundsFn)(const char *str,
const size_t str_step_ofs,
@@ -116,45 +116,43 @@ typedef bool (*BLF_GlyphBoundsFn)(const char *str,
void BLF_boundbox_foreach_glyph_ex(int fontid,
const char *str,
size_t str_len,
size_t 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 str_len,
size_t 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 str_len, float width, float *r_width) ATTR_NONNULL(2);
size_t BLF_width_to_strlen(int fontid, const char *str, size_t 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 str_len, float width, float *r_width) ATTR_NONNULL(2);
size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t 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 str_len,
size_t len,
struct rctf *box,
struct ResultBLF *r_info) ATTR_NONNULL(2);
void BLF_boundbox(int fontid, const char *str, size_t str_len, struct rctf *box) ATTR_NONNULL();
void BLF_boundbox(int fontid, const char *str, size_t 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 str_len, struct ResultBLF *r_info)
float BLF_width_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2);
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)
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)
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2);
float BLF_height(int fontid, const char *str, size_t str_len) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
float BLF_height(int fontid, const char *str, size_t 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;
@@ -165,8 +163,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 str_len, float *r_width, float *r_height) ATTR_NONNULL();
void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_width, float *r_height)
ATTR_NONNULL();
/* For fixed width fonts only, returns the width of a
* character.
@@ -223,9 +221,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 str_len, struct ResultBLF *r_info)
void BLF_draw_buffer_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
ATTR_NONNULL(2);
void BLF_draw_buffer(int fontid, const char *str, size_t str_len) ATTR_NONNULL(2);
void BLF_draw_buffer(int fontid, const char *str, size_t len) ATTR_NONNULL(2);
/* Add a path to the font dir paths. */
void BLF_dir_add(const char *path) ATTR_NONNULL();
@@ -256,9 +254,8 @@ 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 str_len) ATTR_NONNULL();
void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t str_len)
ATTR_NONNULL();
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();
/* Set size and DPI, and return default font ID. */
int BLF_set_default(void);

View File

@@ -521,7 +521,7 @@ static void blf_draw_gl__end(FontBLF *font)
}
}
void BLF_draw_ex(int fontid, const char *str, const size_t str_len, struct ResultBLF *r_info)
void BLF_draw_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
@@ -530,27 +530,27 @@ void BLF_draw_ex(int fontid, const char *str, const size_t str_len, struct Resul
if (font) {
blf_draw_gl__start(font);
if (font->flags & BLF_WORD_WRAP) {
blf_font_draw__wrap(font, str, str_len, r_info);
blf_font_draw__wrap(font, str, len, r_info);
}
else {
blf_font_draw(font, str, str_len, r_info);
blf_font_draw(font, str, len, r_info);
}
blf_draw_gl__end(font);
}
}
void BLF_draw(int fontid, const char *str, const size_t str_len)
void BLF_draw(int fontid, const char *str, size_t len)
{
if (str_len == 0 || str[0] == '\0') {
if (len == 0 || str[0] == '\0') {
return;
}
/* Avoid bgl usage to corrupt BLF drawing. */
GPU_bgl_end();
BLF_draw_ex(fontid, str, str_len, NULL);
BLF_draw_ex(fontid, str, len, NULL);
}
void BLF_draw_ascii_ex(int fontid, const char *str, const size_t str_len, struct ResultBLF *r_info)
void BLF_draw_ascii_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
@@ -560,27 +560,27 @@ void BLF_draw_ascii_ex(int fontid, const char *str, const size_t str_len, struct
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, str_len, r_info);
blf_font_draw__wrap(font, str, len, r_info);
}
else {
blf_font_draw_ascii(font, str, str_len, r_info);
blf_font_draw_ascii(font, str, len, r_info);
}
blf_draw_gl__end(font);
}
}
void BLF_draw_ascii(int fontid, const char *str, const size_t str_len)
void BLF_draw_ascii(int fontid, const char *str, size_t len)
{
if (str_len == 0 || str[0] == '\0') {
if (len == 0 || str[0] == '\0') {
return;
}
BLF_draw_ascii_ex(fontid, str, str_len, NULL);
BLF_draw_ascii_ex(fontid, str, len, NULL);
}
int BLF_draw_mono(int fontid, const char *str, const size_t str_len, int cwidth)
int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
{
if (str_len == 0 || str[0] == '\0') {
if (len == 0 || str[0] == '\0') {
return 0;
}
@@ -589,7 +589,7 @@ int BLF_draw_mono(int fontid, const char *str, const size_t str_len, int cwidth)
if (font) {
blf_draw_gl__start(font);
columns = blf_font_draw_mono(font, str, str_len, cwidth);
columns = blf_font_draw_mono(font, str, len, cwidth);
blf_draw_gl__end(font);
}
@@ -606,7 +606,7 @@ int BLF_draw_mono(int fontid, const char *str, const size_t str_len, int cwidth)
*/
void BLF_boundbox_foreach_glyph_ex(int fontid,
const char *str,
size_t str_len,
size_t len,
BLF_GlyphBoundsFn user_fn,
void *user_data,
struct ResultBLF *r_info)
@@ -621,26 +621,25 @@ void BLF_boundbox_foreach_glyph_ex(int fontid,
BLI_assert(0);
}
else {
blf_font_boundbox_foreach_glyph(font, str, str_len, user_fn, user_data, r_info);
blf_font_boundbox_foreach_glyph(font, str, len, user_fn, user_data, r_info);
}
}
}
void BLF_boundbox_foreach_glyph(
int fontid, const char *str, const size_t str_len, BLF_GlyphBoundsFn user_fn, void *user_data)
int fontid, const char *str, size_t len, BLF_GlyphBoundsFn user_fn, void *user_data)
{
BLF_boundbox_foreach_glyph_ex(fontid, str, str_len, user_fn, user_data, NULL);
BLF_boundbox_foreach_glyph_ex(fontid, str, len, user_fn, user_data, NULL);
}
size_t BLF_width_to_strlen(
int fontid, const char *str, const size_t str_len, float width, float *r_width)
size_t BLF_width_to_strlen(int fontid, const char *str, size_t 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, str_len, width / xa, r_width);
ret = blf_font_width_to_strlen(font, str, len, width / xa, r_width);
if (r_width) {
*r_width *= xa;
}
@@ -653,15 +652,14 @@ size_t BLF_width_to_strlen(
return 0;
}
size_t BLF_width_to_rstrlen(
int fontid, const char *str, const size_t str_len, float width, float *r_width)
size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t 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, str_len, width / xa, r_width);
ret = blf_font_width_to_rstrlen(font, str, len, width / xa, r_width);
if (r_width) {
*r_width *= xa;
}
@@ -675,7 +673,7 @@ size_t BLF_width_to_rstrlen(
}
void BLF_boundbox_ex(
int fontid, const char *str, const size_t str_len, rctf *r_box, struct ResultBLF *r_info)
int fontid, const char *str, size_t len, rctf *r_box, struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
@@ -683,48 +681,47 @@ void BLF_boundbox_ex(
if (font) {
if (font->flags & BLF_WORD_WRAP) {
blf_font_boundbox__wrap(font, str, str_len, r_box, r_info);
blf_font_boundbox__wrap(font, str, len, r_box, r_info);
}
else {
blf_font_boundbox(font, str, str_len, r_box, r_info);
blf_font_boundbox(font, str, len, r_box, r_info);
}
}
}
void BLF_boundbox(int fontid, const char *str, const size_t str_len, rctf *r_box)
void BLF_boundbox(int fontid, const char *str, size_t len, rctf *r_box)
{
BLF_boundbox_ex(fontid, str, str_len, r_box, NULL);
BLF_boundbox_ex(fontid, str, len, r_box, NULL);
}
void BLF_width_and_height(
int fontid, const char *str, const size_t str_len, float *r_width, float *r_height)
void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_width, float *r_height)
{
FontBLF *font = blf_get(fontid);
if (font) {
blf_font_width_and_height(font, str, str_len, r_width, r_height, NULL);
blf_font_width_and_height(font, str, len, r_width, r_height, NULL);
}
else {
*r_width = *r_height = 0.0f;
}
}
float BLF_width_ex(int fontid, const char *str, const size_t str_len, struct ResultBLF *r_info)
float BLF_width_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
BLF_RESULT_CHECK_INIT(r_info);
if (font) {
return blf_font_width(font, str, str_len, r_info);
return blf_font_width(font, str, len, r_info);
}
return 0.0f;
}
float BLF_width(int fontid, const char *str, const size_t str_len)
float BLF_width(int fontid, const char *str, size_t len)
{
return BLF_width_ex(fontid, str, str_len, NULL);
return BLF_width_ex(fontid, str, len, NULL);
}
float BLF_fixed_width(int fontid)
@@ -738,22 +735,22 @@ float BLF_fixed_width(int fontid)
return 0.0f;
}
float BLF_height_ex(int fontid, const char *str, const size_t str_len, struct ResultBLF *r_info)
float BLF_height_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
BLF_RESULT_CHECK_INIT(r_info);
if (font) {
return blf_font_height(font, str, str_len, r_info);
return blf_font_height(font, str, len, r_info);
}
return 0.0f;
}
float BLF_height(int fontid, const char *str, const size_t str_len)
float BLF_height(int fontid, const char *str, size_t len)
{
return BLF_height_ex(fontid, str, str_len, NULL);
return BLF_height_ex(fontid, str, len, NULL);
}
int BLF_height_max(int fontid)
@@ -897,27 +894,24 @@ void blf_draw_buffer__end(void)
{
}
void BLF_draw_buffer_ex(int fontid,
const char *str,
const size_t str_len,
struct ResultBLF *r_info)
void BLF_draw_buffer_ex(int fontid, const char *str, size_t 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, str_len, r_info);
blf_font_draw_buffer__wrap(font, str, len, r_info);
}
else {
blf_font_draw_buffer(font, str, str_len, r_info);
blf_font_draw_buffer(font, str, len, r_info);
}
blf_draw_buffer__end();
}
}
void BLF_draw_buffer(int fontid, const char *str, const size_t str_len)
void BLF_draw_buffer(int fontid, const char *str, size_t len)
{
BLF_draw_buffer_ex(fontid, str, str_len, NULL);
BLF_draw_buffer_ex(fontid, str, len, NULL);
}
char *BLF_display_name_from_file(const char *filename)

View File

@@ -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, const size_t str_len)
void BLF_draw_default(float x, float y, float z, const char *str, size_t 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, str_len);
BLF_draw(global_font_default, str, len);
}
/* same as above but call 'BLF_draw_ascii' */
void BLF_draw_default_ascii(float x, float y, float z, const char *str, const size_t str_len)
void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t 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, str_len); /* XXX, use real length */
BLF_draw_ascii(global_font_default, str, len); /* XXX, use real length */
}

View File

@@ -365,7 +365,7 @@ BLI_INLINE void blf_kerning_step_fast(FontBLF *font,
static void blf_font_draw_ex(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
const size_t str_len,
size_t len,
struct ResultBLF *r_info,
int pen_y)
{
@@ -374,14 +374,14 @@ static void blf_font_draw_ex(FontBLF *font,
int pen_x = 0;
size_t i = 0;
if (str_len == 0) {
if (len == 0) {
/* early output, don't do any IMM OpenGL. */
return;
}
blf_batch_draw_begin(font);
while ((i < str_len) && str[i]) {
while ((i < len) && str[i]) {
g = blf_utf8_next_fast(font, gc, str, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
@@ -407,16 +407,16 @@ static void blf_font_draw_ex(FontBLF *font,
r_info->width = pen_x;
}
}
void blf_font_draw(FontBLF *font, const char *str, const size_t str_len, struct ResultBLF *r_info)
void blf_font_draw(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
{
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
blf_font_draw_ex(font, gc, str, str_len, r_info, 0);
blf_font_draw_ex(font, gc, 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 str_len, struct ResultBLF *r_info, int pen_y)
FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info, int pen_y)
{
unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev = NULL;
@@ -426,7 +426,7 @@ static void blf_font_draw_ascii_ex(
blf_batch_draw_begin(font);
while ((c = *(str++)) && str_len--) {
while ((c = *(str++)) && len--) {
BLI_assert(c < GLYPH_ASCII_TABLE_SIZE);
g = gc->glyph_ascii_table[c];
if (UNLIKELY(g == NULL)) {
@@ -456,16 +456,13 @@ static void blf_font_draw_ascii_ex(
blf_glyph_cache_release(font);
}
void blf_font_draw_ascii(FontBLF *font,
const char *str,
const size_t str_len,
struct ResultBLF *r_info)
void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
{
blf_font_draw_ascii_ex(font, str, str_len, r_info, 0);
blf_font_draw_ascii_ex(font, 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, const size_t str_len, int cwidth)
int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
{
unsigned int c;
GlyphBLF *g;
@@ -477,7 +474,7 @@ int blf_font_draw_mono(FontBLF *font, const char *str, const size_t str_len, int
blf_batch_draw_begin(font);
while ((i < str_len) && str[i]) {
while ((i < len) && str[i]) {
g = blf_utf8_next_fast(font, gc, str, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
@@ -515,7 +512,7 @@ int blf_font_draw_mono(FontBLF *font, const char *str, const size_t str_len, int
static void blf_font_draw_buffer_ex(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
const size_t str_len,
size_t len,
struct ResultBLF *r_info,
int pen_y)
{
@@ -534,7 +531,7 @@ static void blf_font_draw_buffer_ex(FontBLF *font,
/* another buffer specific call for color conversion */
while ((i < str_len) && str[i]) {
while ((i < len) && str[i]) {
g = blf_utf8_next_fast(font, gc, str, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
@@ -649,13 +646,10 @@ static void blf_font_draw_buffer_ex(FontBLF *font,
}
}
void blf_font_draw_buffer(FontBLF *font,
const char *str,
const size_t str_len,
struct ResultBLF *r_info)
void blf_font_draw_buffer(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
{
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
blf_font_draw_buffer_ex(font, gc, str, str_len, r_info, 0);
blf_font_draw_buffer_ex(font, gc, str, len, r_info, 0);
blf_glyph_cache_release(font);
}
@@ -691,7 +685,7 @@ static bool blf_font_width_to_strlen_glyph_process(FontBLF *font,
}
size_t blf_font_width_to_strlen(
FontBLF *font, const char *str, const size_t str_len, float width, float *r_width)
FontBLF *font, const char *str, size_t len, float width, float *r_width)
{
unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev;
@@ -701,7 +695,7 @@ 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 < str_len) && str[i];
for (i_prev = i = 0, width_new = pen_x = 0, g_prev = NULL, c_prev = 0; (i < 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);
@@ -719,7 +713,7 @@ size_t blf_font_width_to_strlen(
}
size_t blf_font_width_to_rstrlen(
FontBLF *font, const char *str, const size_t str_len, float width, float *r_width)
FontBLF *font, const char *str, size_t len, float width, float *r_width)
{
unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev;
@@ -730,7 +724,7 @@ size_t blf_font_width_to_rstrlen(
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
const int width_i = (int)width;
i = BLI_strnlen(str, str_len);
i = BLI_strnlen(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);
@@ -771,7 +765,7 @@ size_t blf_font_width_to_rstrlen(
static void blf_font_boundbox_ex(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
const size_t str_len,
size_t len,
rctf *box,
struct ResultBLF *r_info,
int pen_y)
@@ -787,7 +781,7 @@ static void blf_font_boundbox_ex(FontBLF *font,
box->ymin = 32000.0f;
box->ymax = -32000.0f;
while ((i < str_len) && str[i]) {
while ((i < len) && str[i]) {
g = blf_utf8_next_fast(font, gc, str, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
@@ -835,16 +829,16 @@ static void blf_font_boundbox_ex(FontBLF *font,
}
}
void blf_font_boundbox(
FontBLF *font, const char *str, const size_t str_len, rctf *r_box, struct ResultBLF *r_info)
FontBLF *font, const char *str, size_t len, rctf *r_box, struct ResultBLF *r_info)
{
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
blf_font_boundbox_ex(font, gc, str, str_len, r_box, r_info, 0);
blf_font_boundbox_ex(font, gc, str, len, r_box, r_info, 0);
blf_glyph_cache_release(font);
}
void blf_font_width_and_height(FontBLF *font,
const char *str,
const size_t str_len,
size_t len,
float *r_width,
float *r_height,
struct ResultBLF *r_info)
@@ -862,19 +856,16 @@ void blf_font_width_and_height(FontBLF *font,
}
if (font->flags & BLF_WORD_WRAP) {
blf_font_boundbox__wrap(font, str, str_len, &box, r_info);
blf_font_boundbox__wrap(font, str, len, &box, r_info);
}
else {
blf_font_boundbox(font, str, str_len, &box, r_info);
blf_font_boundbox(font, 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,
const size_t str_len,
struct ResultBLF *r_info)
float blf_font_width(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
{
float xa;
rctf box;
@@ -887,18 +878,15 @@ float blf_font_width(FontBLF *font,
}
if (font->flags & BLF_WORD_WRAP) {
blf_font_boundbox__wrap(font, str, str_len, &box, r_info);
blf_font_boundbox__wrap(font, str, len, &box, r_info);
}
else {
blf_font_boundbox(font, str, str_len, &box, r_info);
blf_font_boundbox(font, str, len, &box, r_info);
}
return BLI_rctf_size_x(&box) * xa;
}
float blf_font_height(FontBLF *font,
const char *str,
const size_t str_len,
struct ResultBLF *r_info)
float blf_font_height(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
{
float ya;
rctf box;
@@ -911,10 +899,10 @@ float blf_font_height(FontBLF *font,
}
if (font->flags & BLF_WORD_WRAP) {
blf_font_boundbox__wrap(font, str, str_len, &box, r_info);
blf_font_boundbox__wrap(font, str, len, &box, r_info);
}
else {
blf_font_boundbox(font, str, str_len, &box, r_info);
blf_font_boundbox(font, str, len, &box, r_info);
}
return BLI_rctf_size_y(&box) * ya;
}
@@ -942,7 +930,7 @@ float blf_font_fixed_width(FontBLF *font)
static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
const size_t str_len,
size_t len,
BLF_GlyphBoundsFn user_fn,
void *user_data,
struct ResultBLF *r_info,
@@ -954,12 +942,12 @@ static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
size_t i = 0, i_curr;
rcti gbox;
if (str_len == 0) {
if (len == 0) {
/* early output. */
return;
}
while ((i < str_len) && str[i]) {
while ((i < len) && str[i]) {
i_curr = i;
g = blf_utf8_next_fast(font, gc, str, &i, &c);
@@ -993,13 +981,13 @@ static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
}
void blf_font_boundbox_foreach_glyph(FontBLF *font,
const char *str,
const size_t str_len,
size_t 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, str_len, user_fn, user_data, r_info, 0);
blf_font_boundbox_foreach_glyph_ex(font, gc, str, len, user_fn, user_data, r_info, 0);
blf_glyph_cache_release(font);
}
@@ -1020,12 +1008,12 @@ void blf_font_boundbox_foreach_glyph(FontBLF *font,
*/
static void blf_font_wrap_apply(FontBLF *font,
const char *str,
const size_t str_len,
size_t len,
struct ResultBLF *r_info,
void (*callback)(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
const size_t str_len,
size_t len,
int pen_y,
void *userdata),
void *userdata)
@@ -1044,8 +1032,8 @@ 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__, str_len, strlen(str), str);
while ((i < str_len) && str[i]) {
// printf("%s wrapping (%d, %d) `%s`:\n", __func__, len, strlen(str), str);
while ((i < len) && str[i]) {
/* wrap vars */
size_t i_curr = i;
@@ -1073,7 +1061,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 < str_len) && str[i]) == 0)) {
else if (UNLIKELY(((i < 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;
@@ -1124,61 +1112,54 @@ static void blf_font_wrap_apply(FontBLF *font,
static void blf_font_draw__wrap_cb(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
const size_t str_len,
size_t len,
int pen_y,
void *UNUSED(userdata))
{
blf_font_draw_ex(font, gc, str, str_len, NULL, pen_y);
blf_font_draw_ex(font, gc, str, len, NULL, pen_y);
}
void blf_font_draw__wrap(FontBLF *font,
const char *str,
const size_t str_len,
struct ResultBLF *r_info)
void blf_font_draw__wrap(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
{
blf_font_wrap_apply(font, str, str_len, r_info, blf_font_draw__wrap_cb, NULL);
blf_font_wrap_apply(font, 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,
const size_t str_len,
int pen_y,
void *userdata)
static void blf_font_boundbox_wrap_cb(
FontBLF *font, GlyphCacheBLF *gc, const char *str, size_t len, int pen_y, void *userdata)
{
rctf *box = userdata;
rctf box_single;
blf_font_boundbox_ex(font, gc, str, str_len, &box_single, NULL, pen_y);
blf_font_boundbox_ex(font, gc, str, len, &box_single, NULL, pen_y);
BLI_rctf_union(box, &box_single);
}
void blf_font_boundbox__wrap(
FontBLF *font, const char *str, const size_t str_len, rctf *box, struct ResultBLF *r_info)
FontBLF *font, const char *str, size_t 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, str_len, r_info, blf_font_boundbox_wrap_cb, box);
blf_font_wrap_apply(font, 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,
const size_t str_len,
size_t len,
int pen_y,
void *UNUSED(userdata))
{
blf_font_draw_buffer_ex(font, gc, str, str_len, NULL, pen_y);
blf_font_draw_buffer_ex(font, gc, str, len, NULL, pen_y);
}
void blf_font_draw_buffer__wrap(FontBLF *font,
const char *str,
const size_t str_len,
size_t len,
struct ResultBLF *r_info)
{
blf_font_wrap_apply(font, str, str_len, r_info, blf_font_draw_buffer__wrap_cb, NULL);
blf_font_wrap_apply(font, str, len, r_info, blf_font_draw_buffer__wrap_cb, NULL);
}
/** \} */
@@ -1189,14 +1170,14 @@ void blf_font_draw_buffer__wrap(FontBLF *font,
int blf_font_count_missing_chars(FontBLF *font,
const char *str,
const size_t str_len,
const size_t len,
int *r_tot_chars)
{
int missing = 0;
size_t i = 0;
*r_tot_chars = 0;
while (i < str_len) {
while (i < len) {
unsigned int c;
if ((c = str[i]) < GLYPH_ASCII_TABLE_SIZE) {

View File

@@ -53,55 +53,46 @@ 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 str_len,
struct ResultBLF *r_info);
void blf_font_draw(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
void blf_font_draw__wrap(struct FontBLF *font,
const char *str,
size_t str_len,
size_t len,
struct ResultBLF *r_info);
void blf_font_draw_ascii(struct FontBLF *font,
const char *str,
size_t str_len,
size_t len,
struct ResultBLF *r_info);
int blf_font_draw_mono(struct FontBLF *font, const char *str, size_t str_len, int cwidth);
int blf_font_draw_mono(struct FontBLF *font, const char *str, size_t len, int cwidth);
void blf_font_draw_buffer(struct FontBLF *font,
const char *str,
size_t str_len,
size_t len,
struct ResultBLF *r_info);
void blf_font_draw_buffer__wrap(struct FontBLF *font,
const char *str,
size_t str_len,
size_t len,
struct ResultBLF *r_info);
size_t blf_font_width_to_strlen(
struct FontBLF *font, const char *str, size_t str_len, float width, float *r_width);
struct FontBLF *font, const char *str, size_t len, float width, float *r_width);
size_t blf_font_width_to_rstrlen(
struct FontBLF *font, const char *str, size_t str_len, float width, float *r_width);
struct FontBLF *font, const char *str, size_t len, float width, float *r_width);
void blf_font_boundbox(struct FontBLF *font,
const char *str,
size_t str_len,
size_t len,
struct rctf *r_box,
struct ResultBLF *r_info);
void blf_font_boundbox__wrap(struct FontBLF *font,
const char *str,
size_t str_len,
size_t len,
struct rctf *r_box,
struct ResultBLF *r_info);
void blf_font_width_and_height(struct FontBLF *font,
const char *str,
size_t str_len,
size_t len,
float *r_width,
float *r_height,
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_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_fixed_width(struct FontBLF *font);
int blf_font_height_max(struct FontBLF *font);
int blf_font_width_max(struct FontBLF *font);
@@ -112,7 +103,7 @@ char *blf_display_name(struct FontBLF *font);
void blf_font_boundbox_foreach_glyph(struct FontBLF *font,
const char *str,
size_t str_len,
size_t len,
bool (*user_fn)(const char *str,
const size_t str_step_ofs,
const struct rcti *glyph_step_bounds,
@@ -125,7 +116,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 str_len,
const size_t len,
int *r_tot_chars);
void blf_font_free(struct FontBLF *font);

View File

@@ -37,12 +37,10 @@
struct AttributeMetaData {
AttributeDomain domain;
CustomDataType data_type;
const AnonymousCustomDataLayerID *anonymous_layer_id = nullptr;
constexpr friend bool operator==(AttributeMetaData a, AttributeMetaData b)
{
return (a.domain == b.domain) && (a.data_type == b.data_type) &&
(a.anonymous_layer_id == b.anonymous_layer_id);
return (a.domain == b.domain) && (a.data_type == b.data_type);
}
};
@@ -356,12 +354,6 @@ class CustomDataAttributes {
bool create_by_move(const blender::StringRef name, const CustomDataType data_type, void *buffer);
bool remove(const blender::StringRef name);
bool create_anonymous(const AnonymousCustomDataLayerID &id, const CustomDataType data_type);
std::optional<blender::fn::GSpan> get_anonymous_for_read(
const AnonymousCustomDataLayerID &id) const;
std::optional<blender::fn::GMutableSpan> get_anonymous_for_write(
const AnonymousCustomDataLayerID &id);
bool foreach_attribute(const AttributeForeachCallback callback,
const AttributeDomain domain) const;
};

View File

@@ -482,14 +482,6 @@ void CustomData_external_reload(struct CustomData *data,
CustomDataMask mask,
int totelem);
/* Anonymous layers. */
struct AnonymousCustomDataLayerID *CustomData_anonymous_id_new(const char *debug_name);
void CustomData_anonymous_id_strong_decrement(const struct AnonymousCustomDataLayerID *layer_id);
void CustomData_anonymous_id_strong_increment(const struct AnonymousCustomDataLayerID *layer_id);
void CustomData_anonymous_id_weak_decrement(const struct AnonymousCustomDataLayerID *layer_id);
void CustomData_anonymous_id_weak_increment(const struct AnonymousCustomDataLayerID *layer_id);
bool CustomData_layer_is_unused_anonymous(const struct CustomDataLayer *layer);
/* Mesh-to-mesh transfer data. */
struct CustomDataTransferLayerMap;

View File

@@ -1,553 +0,0 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#pragma once
/** \file
* \ingroup bke
*/
#include <atomic>
#include "BLI_function_ref.hh"
#include "BLI_map.hh"
#include "BLI_optional_ptr.hh"
#include "BLI_user_counter.hh"
#include "BLI_vector.hh"
#include "BLI_virtual_array.hh"
#include "FN_cpp_type.hh"
#include "FN_cpp_type_make.hh"
#include "FN_multi_function.hh"
#include "BKE_customdata.h"
namespace blender::bke {
using fn::CPPType;
using fn::GMutableSpan;
using fn::GVArray;
using fn::GVArrayPtr;
using fn::MultiFunction;
class FieldInputKey {
public:
virtual ~FieldInputKey() = default;
virtual uint64_t hash() const = 0;
virtual const CPPType &type() const = 0;
friend bool operator==(const FieldInputKey &a, const FieldInputKey &b)
{
return a.is_same_as(b);
}
private:
virtual bool is_same_as(const FieldInputKey &other) const
{
UNUSED_VARS(other);
return false;
}
};
class FieldInputValue {
public:
virtual ~FieldInputValue() = default;
};
class IndexFieldInputKey : public FieldInputKey {
public:
uint64_t hash() const override
{
/* Arbitrary number. */
return 78582029;
}
const CPPType &type() const override
{
return CPPType::get<int>();
}
private:
bool is_same_as(const FieldInputKey &other) const override
{
return dynamic_cast<const IndexFieldInputKey *>(&other) != nullptr;
}
};
class CurveParameterFieldInputKey : public FieldInputKey {
public:
uint64_t hash() const override
{
/* Arbitrary number. */
return 928347504059;
}
const CPPType &type() const override
{
return CPPType::get<float>();
}
private:
bool is_same_as(const FieldInputKey &other) const override
{
return dynamic_cast<const CurveParameterFieldInputKey *>(&other) != nullptr;
}
};
class AnonymousAttributeFieldInputKey : public FieldInputKey {
private:
AnonymousCustomDataLayerID *layer_id_;
const CPPType &type_;
public:
AnonymousAttributeFieldInputKey(AnonymousCustomDataLayerID &layer_id, const CPPType &type)
: layer_id_(&layer_id), type_(type)
{
CustomData_anonymous_id_strong_increment(layer_id_);
}
~AnonymousAttributeFieldInputKey()
{
CustomData_anonymous_id_strong_decrement(layer_id_);
}
const CPPType &type() const override
{
return type_;
}
uint64_t hash() const override
{
return get_default_hash(layer_id_);
}
const AnonymousCustomDataLayerID &layer_id() const
{
return *layer_id_;
}
private:
bool is_same_as(const FieldInputKey &other) const override
{
if (const AnonymousAttributeFieldInputKey *other_typed =
dynamic_cast<const AnonymousAttributeFieldInputKey *>(&other)) {
return layer_id_ == other_typed->layer_id_ && type_ == other_typed->type_;
}
return false;
}
};
class PersistentAttributeFieldInputKey : public FieldInputKey {
private:
std::string name_;
const CPPType *type_;
public:
PersistentAttributeFieldInputKey(std::string name, const CPPType &type)
: name_(std::move(name)), type_(&type)
{
}
uint64_t hash() const override
{
return get_default_hash_2(name_, type_);
}
const CPPType &type() const override
{
return *type_;
}
StringRefNull name() const
{
return name_;
}
private:
bool is_same_as(const FieldInputKey &other) const override
{
if (const PersistentAttributeFieldInputKey *other_typed =
dynamic_cast<const PersistentAttributeFieldInputKey *>(&other)) {
return other_typed->type_ == type_ && other_typed->name_ == name_;
}
return false;
}
};
class GVArrayFieldInputValue : public FieldInputValue {
private:
optional_ptr<GVArray> varray_;
public:
GVArrayFieldInputValue(optional_ptr<GVArray> varray) : varray_(std::move(varray))
{
}
const GVArray &varray() const
{
return *varray_;
}
};
class FieldInputs {
private:
using InputMap = Map<std::reference_wrapper<const FieldInputKey>, const FieldInputValue *>;
InputMap inputs_;
friend class Field;
public:
InputMap::KeyIterator begin() const
{
return inputs_.keys().begin();
}
InputMap::KeyIterator end() const
{
return inputs_.keys().end();
}
int tot_inputs() const
{
return inputs_.size();
}
void set_input(const FieldInputKey &key, const FieldInputValue &value)
{
*inputs_.lookup_ptr(key) = &value;
}
const FieldInputValue *get(const FieldInputKey &key) const
{
return inputs_.lookup_default(key, nullptr);
}
template<typename ValueT> const ValueT *get(const FieldInputKey &key) const
{
return dynamic_cast<const ValueT *>(this->get(key));
}
};
class FieldOutput {
private:
optional_ptr<const GVArray> varray_;
public:
FieldOutput(optional_ptr<const GVArray> varray) : varray_(std::move(varray))
{
}
const GVArray &varray_ref() const
{
return *varray_;
}
};
class Field {
private:
mutable std::atomic<int> users_ = 1;
public:
virtual ~Field() = default;
FieldInputs prepare_inputs() const
{
FieldInputs inputs;
this->foreach_input_key([&](const FieldInputKey &key) { inputs.inputs_.add(key, nullptr); });
return inputs;
}
virtual void foreach_input_key(FunctionRef<void(const FieldInputKey &key)> callback) const
{
UNUSED_VARS(callback);
}
virtual const CPPType &output_type() const = 0;
virtual FieldOutput evaluate(IndexMask mask, const FieldInputs &inputs) const = 0;
void user_add() const
{
users_.fetch_add(1);
}
void user_remove() const
{
const int new_users = users_.fetch_sub(1) - 1;
if (new_users == 0) {
delete this;
}
}
};
using FieldPtr = UserCounter<Field>;
template<typename T> class ConstantField : public Field {
private:
T value_;
public:
ConstantField(T value) : value_(std::move(value))
{
}
const CPPType &output_type() const override
{
return CPPType::get<T>();
}
FieldOutput evaluate(IndexMask mask, const FieldInputs &UNUSED(inputs)) const
{
return optional_ptr<const GVArray>{std::make_unique<fn::GVArray_For_SingleValue>(
CPPType::get<T>(), mask.min_array_size(), &value_)};
}
};
template<typename KeyT> class GVArrayInputField : public Field {
private:
KeyT key_;
public:
template<typename... Args> GVArrayInputField(Args &&...args) : key_(std::forward<Args>(args)...)
{
}
void foreach_input_key(FunctionRef<void(const FieldInputKey &key)> callback) const override
{
callback(key_);
}
const CPPType &output_type() const override
{
return key_.type();
}
FieldOutput evaluate(IndexMask mask, const FieldInputs &inputs) const override
{
const GVArrayFieldInputValue *input = inputs.get<GVArrayFieldInputValue>(key_);
if (input == nullptr) {
return FieldOutput{
optional_ptr<const GVArray>{std::make_unique<fn::GVArray_For_SingleValueRef>(
key_.type(), mask.min_array_size(), key_.type().default_value())}};
}
return FieldOutput{optional_ptr<const GVArray>{input->varray()}};
}
};
class MultiFunctionField : public Field {
private:
Vector<FieldPtr> input_fields_;
optional_ptr<const MultiFunction> fn_;
const int output_param_index_;
public:
MultiFunctionField(Vector<FieldPtr> input_fields,
optional_ptr<const MultiFunction> fn,
const int output_param_index)
: input_fields_(std::move(input_fields)),
fn_(std::move(fn)),
output_param_index_(output_param_index)
{
}
const CPPType &output_type() const override
{
return fn_->param_type(output_param_index_).data_type().single_type();
}
void foreach_input_key(FunctionRef<void(const FieldInputKey &key)> callback) const override
{
for (const FieldPtr &field : input_fields_) {
field->foreach_input_key(callback);
}
}
FieldOutput evaluate(IndexMask mask, const FieldInputs &inputs) const final
{
fn::MFParamsBuilder params{*fn_, mask.min_array_size()};
fn::MFContextBuilder context;
ResourceScope &scope = params.resource_scope();
Vector<GMutableSpan> outputs;
int output_span_index = -1;
int input_index = 0;
for (const int param_index : fn_->param_indices()) {
fn::MFParamType param_type = fn_->param_type(param_index);
switch (param_type.category()) {
case fn::MFParamType::SingleInput: {
const Field &field = *input_fields_[input_index];
FieldOutput &output = scope.add_value(field.evaluate(mask, inputs), __func__);
params.add_readonly_single_input(output.varray_ref());
input_index++;
break;
}
case fn::MFParamType::SingleOutput: {
const CPPType &type = param_type.data_type().single_type();
void *buffer = MEM_mallocN_aligned(
mask.min_array_size() * type.size(), type.alignment(), __func__);
GMutableSpan span{type, buffer, mask.min_array_size()};
outputs.append(span);
params.add_uninitialized_single_output(span);
if (param_index == output_param_index_) {
output_span_index = outputs.size() - 1;
}
break;
}
case fn::MFParamType::SingleMutable:
case fn::MFParamType::VectorInput:
case fn::MFParamType::VectorMutable:
case fn::MFParamType::VectorOutput:
BLI_assert_unreachable();
break;
}
}
fn_->call(mask, params, context);
GMutableSpan output_span = outputs[output_span_index];
outputs.remove(output_span_index);
for (GMutableSpan span : outputs) {
span.type().destruct_indices(span.data(), mask);
MEM_freeN(span.data());
}
std::unique_ptr<GVArray> out_array = std::make_unique<fn::GVArray_For_OwnedGSpan>(output_span,
mask);
return FieldOutput{optional_ptr<const GVArray>{std::move(out_array)}};
}
};
class PersistentAttributeField : public GVArrayInputField<PersistentAttributeFieldInputKey> {
public:
PersistentAttributeField(std::string name, const CPPType &type)
: GVArrayInputField<PersistentAttributeFieldInputKey>(std::move(name), type)
{
}
};
class AnonymousAttributeField : public GVArrayInputField<AnonymousAttributeFieldInputKey> {
public:
AnonymousAttributeField(AnonymousCustomDataLayerID &layer_id, const CPPType &type)
: GVArrayInputField<AnonymousAttributeFieldInputKey>(layer_id, type)
{
}
};
class IndexField : public GVArrayInputField<IndexFieldInputKey> {
};
class CurveParameterField : public GVArrayInputField<CurveParameterFieldInputKey> {
};
class FieldRefBase {
protected:
FieldPtr field_;
public:
const FieldPtr &field() const
{
return field_;
}
};
template<typename T> class FieldRef : public FieldRefBase {
public:
FieldRef()
{
field_ = new ConstantField<T>(T());
}
FieldRef(FieldPtr field)
{
field_ = std::move(field);
}
const Field *operator->() const
{
return &*field_;
}
uint64_t hash() const
{
return get_default_hash(&*field_);
}
friend bool operator==(const FieldRef &a, const FieldRef &b)
{
return &*a.field_ == &*b.field_;
}
friend std::ostream &operator<<(std::ostream &stream, const FieldRef &a)
{
stream << &*a.field_;
return stream;
}
};
template<typename T> struct FieldRefCPPTypeParam {
};
class FieldRefCPPType : public CPPType {
private:
const CPPType &field_type_;
FieldPtr (*get_field_)(const void *field_ref);
void (*construct_)(void *dst, FieldPtr field);
public:
template<typename T>
FieldRefCPPType(FieldRefCPPTypeParam<FieldRef<T>> /* unused */, StringRef debug_name)
: CPPType(fn::CPPTypeParam<FieldRef<T>, CPPTypeFlags::BasicType>(), debug_name),
field_type_(CPPType::get<T>())
{
get_field_ = [](const void *field_ref) {
return ((const blender::bke::FieldRef<T> *)field_ref)->field();
};
construct_ = [](void *dst, blender::bke::FieldPtr field) {
new (dst) blender::bke::FieldRef<T>(std::move(field));
};
}
const CPPType &field_type() const
{
return field_type_;
};
FieldPtr get_field(const void *field_ref) const
{
return get_field_(field_ref);
}
void construct(void *dst, FieldPtr field) const
{
construct_(dst, std::move(field));
}
};
} // namespace blender::bke
#define MAKE_FIELD_REF_CPP_TYPE(DEBUG_NAME, FIELD_TYPE) \
template<> \
const blender::fn::CPPType & \
blender::fn::CPPType::get_impl<blender::bke::FieldRef<FIELD_TYPE>>() \
{ \
static blender::bke::FieldRefCPPType cpp_type{ \
blender::bke::FieldRefCPPTypeParam<blender::bke::FieldRef<FIELD_TYPE>>(), \
STRINGIFY(DEBUG_NAME)}; \
return cpp_type; \
}

View File

@@ -128,28 +128,6 @@ class GeometryComponent {
const CustomDataType data_type,
const AttributeInit &initializer);
bool attribute_try_create_anonymous(const AnonymousCustomDataLayerID &layer_id,
const AttributeDomain domain,
const CustomDataType data_type,
const AttributeInit &initializer);
blender::bke::ReadAttributeLookup attribute_try_get_anonymous_for_read(
const AnonymousCustomDataLayerID &layer_id) const;
blender::fn::GVArrayPtr attribute_try_get_anonymous_for_read(
const AnonymousCustomDataLayerID &id,
const AttributeDomain domain,
const CustomDataType data_type) const;
blender::fn::GVArrayPtr attribute_try_get_anonymous_for_read(
const AnonymousCustomDataLayerID &id,
const AttributeDomain domain,
const CustomDataType data_type,
const void *default_value) const;
blender::bke::WriteAttributeLookup attribute_try_get_anonymous_for_write(
const AnonymousCustomDataLayerID &layer_id);
/* Try to create the builtin attribute with the given name. No data type or domain has to be
* provided, because those are fixed for builtin attributes. */
bool attribute_try_create_builtin(const blender::StringRef attribute_name,
@@ -161,8 +139,8 @@ class GeometryComponent {
virtual bool is_empty() const;
/* Get a virtual array to read the data of an attribute on the given domain and data type.
* Returns null when the attribute does not exist or cannot be converted to the requested
* domain and data type. */
* Returns null when the attribute does not exist or cannot be converted to the requested domain
* and data type. */
std::unique_ptr<blender::fn::GVArray> attribute_try_get_for_read(
const blender::StringRef attribute_name,
const AttributeDomain domain,
@@ -203,14 +181,14 @@ class GeometryComponent {
}
/**
* Returns an "output attribute", which is essentially a mutable virtual array with some
* commonly used convince features. The returned output attribute might be empty if requested
* attribute cannot exist on the geometry.
* Returns an "output attribute", which is essentially a mutable virtual array with some commonly
* used convince features. The returned output attribute might be empty if requested attribute
* cannot exist on the geometry.
*
* The included convenience features are:
* - Implicit type conversion when writing to builtin attributes.
* - If the attribute name exists already, but has a different type/domain, a temporary
* attribute is created that will overwrite the existing attribute in the end.
* - If the attribute name exists already, but has a different type/domain, a temporary attribute
* is created that will overwrite the existing attribute in the end.
*/
blender::bke::OutputAttribute attribute_try_get_for_output(
const blender::StringRef attribute_name,
@@ -219,8 +197,8 @@ class GeometryComponent {
const void *default_value = nullptr);
/* Same as attribute_try_get_for_output, but should be used when the original values in the
* attributes are not read, i.e. the attribute is used only for output. Since values are not
* read from this attribute, no default value is necessary. */
* attributes are not read, i.e. the attribute is used only for output. Since values are not read
* from this attribute, no default value is necessary. */
blender::bke::OutputAttribute attribute_try_get_for_output_only(
const blender::StringRef attribute_name,
const AttributeDomain domain,
@@ -246,35 +224,6 @@ class GeometryComponent {
return this->attribute_try_get_for_output_only(attribute_name, domain, data_type);
}
blender::bke::OutputAttribute attribute_try_get_anonymous_for_output(
const AnonymousCustomDataLayerID &id,
const AttributeDomain domain,
const CustomDataType data_type,
const void *default_value = nullptr);
blender::bke::OutputAttribute attribute_try_get_anonymous_for_output_only(
const AnonymousCustomDataLayerID &id,
const AttributeDomain domain,
const CustomDataType data_type);
template<typename T>
blender::bke::OutputAttribute_Typed<T> attribute_try_get_anonymous_for_output(
const AnonymousCustomDataLayerID &id, const AttributeDomain domain, const T default_value)
{
const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
const CustomDataType data_type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
return this->attribute_try_get_anonymous_for_output(id, domain, data_type, &default_value);
}
template<typename T>
blender::bke::OutputAttribute_Typed<T> attribute_try_get_anonymous_for_output_only(
const AnonymousCustomDataLayerID &id, const AttributeDomain domain)
{
const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
const CustomDataType data_type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
return this->attribute_try_get_anonymous_for_output_only(id, domain, data_type);
}
private:
virtual const blender::bke::ComponentAttributeProviders *get_attribute_providers() const;
};
@@ -283,12 +232,12 @@ template<typename T>
inline constexpr bool is_geometry_component_v = std::is_base_of_v<GeometryComponent, T>;
/**
* A geometry set contains zero or more geometry components. There is at most one component of
* each type. Individual components might be shared between multiple geometries. Shared
* components are copied automatically when write access is requested.
* A geometry set contains zero or more geometry components. There is at most one component of each
* type. Individual components might be shared between multiple geometries. Shared components are
* copied automatically when write access is requested.
*
* Copying a geometry set is a relatively cheap operation, because it does not copy the
* referenced geometry components.
* Copying a geometry set is a relatively cheap operation, because it does not copy the referenced
* geometry components.
*/
struct GeometrySet {
private:
@@ -396,10 +345,6 @@ class MeshComponent : public GeometryComponent {
const AttributeDomain from_domain,
const AttributeDomain to_domain) const final;
blender::VArrayPtr<bool> adapt_selection(blender::VArrayPtr<bool> selection,
AttributeDomain from_domain,
AttributeDomain to_domain) const;
bool is_empty() const final;
bool owns_direct_data() const override;
@@ -496,8 +441,8 @@ class InstanceReference {
enum class Type {
/**
* An empty instance. This allows an `InstanceReference` to be default constructed without
* being in an invalid state. There might also be other use cases that we haven't explored
* much yet (such as changing the instance later on, and "disabling" some instances).
* being in an invalid state. There might also be other use cases that we haven't explored much
* yet (such as changing the instance later on, and "disabling" some instances).
*/
None,
Object,
@@ -568,8 +513,8 @@ class InstancesComponent : public GeometryComponent {
blender::Vector<int> instance_ids_;
/* These almost unique ids are generated based on `ids_`, which might not contain unique ids at
* all. They are *almost* unique, because under certain very unlikely circumstances, they are
* not unique. Code using these ids should not crash when they are not unique but can generally
* all. They are *almost* unique, because under certain very unlikely circumstances, they are not
* unique. Code using these ids should not crash when they are not unique but can generally
* expect them to be unique. */
mutable std::mutex almost_unique_ids_mutex_;
mutable blender::Array<int> almost_unique_ids_;

View File

@@ -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_CONVERTER 8
#define NODE_CLASS_CONVERTOR 8
#define NODE_CLASS_MATTE 9
#define NODE_CLASS_DISTORT 10
// #define NODE_CLASS_OP_DYNAMIC 11 /* deprecated */
@@ -1415,7 +1415,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_ATTRIBUTE_COMPARE 1015
#define GEO_NODE_POINT_ROTATE 1016
#define GEO_NODE_ATTRIBUTE_VECTOR_MATH 1017
// #define GEO_NODE_ALIGN_ROTATION_TO_VECTOR 1018
#define GEO_NODE_ALIGN_ROTATION_TO_VECTOR 1018
#define GEO_NODE_POINT_TRANSLATE 1019
#define GEO_NODE_POINT_SCALE 1020
#define GEO_NODE_ATTRIBUTE_SAMPLE_TEXTURE 1021
@@ -1472,18 +1472,6 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_CURVE_SET_HANDLES 1072
#define GEO_NODE_CURVE_SPLINE_TYPE 1073
#define GEO_NODE_CURVE_SELECT_HANDLES 1074
#define GEO_NODE_ATTRIBUTE 1075
#define GEO_NODE_INDEX 1076
#define GEO_NODE_EXTRUDE 1077
#define GEO_NODE_ATTRIBUTE_FREEZE 1078
#define GEO_NODE_ATTRIBUTE_EXTRACT 1079
#define GEO_NODE_NORMAL 1080
#define GEO_NODE_CURVE_PARAMETER 1081
#define GEO_NODE_EXTRUDE_AND_MOVE 1082
#define GEO_NODE_POSITION 1083
#define GEO_NODE_SET_POSITION 1084
#define GEO_NODE_SAMPLE_MESH_SURFACE 1085
#define GEO_NODE_EVALUATE_CURVE 1086
/** \} */
@@ -1497,7 +1485,6 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define FN_NODE_INPUT_VECTOR 1207
#define FN_NODE_INPUT_STRING 1208
#define FN_NODE_FLOAT_TO_INT 1209
#define FN_NODE_ALIGN_ROTATION_TO_VECTOR 1210
/** \} */

View File

@@ -346,33 +346,27 @@ ReadAttributeLookup CustomDataAttributeProvider::try_get_for_read(
if (layer.name != attribute_name) {
continue;
}
return this->layer_to_read_attribute(layer, domain_size);
const CustomDataType data_type = (CustomDataType)layer.type;
switch (data_type) {
case CD_PROP_FLOAT:
return this->layer_to_read_attribute<float>(layer, domain_size);
case CD_PROP_FLOAT2:
return this->layer_to_read_attribute<float2>(layer, domain_size);
case CD_PROP_FLOAT3:
return this->layer_to_read_attribute<float3>(layer, domain_size);
case CD_PROP_INT32:
return this->layer_to_read_attribute<int>(layer, domain_size);
case CD_PROP_COLOR:
return this->layer_to_read_attribute<ColorGeometry4f>(layer, domain_size);
case CD_PROP_BOOL:
return this->layer_to_read_attribute<bool>(layer, domain_size);
default:
break;
}
}
return {};
}
ReadAttributeLookup CustomDataAttributeProvider::layer_to_read_attribute(
const CustomDataLayer &layer, const int domain_size) const
{
const CustomDataType data_type = (CustomDataType)layer.type;
switch (data_type) {
case CD_PROP_FLOAT:
return this->layer_to_read_attribute<float>(layer, domain_size);
case CD_PROP_FLOAT2:
return this->layer_to_read_attribute<float2>(layer, domain_size);
case CD_PROP_FLOAT3:
return this->layer_to_read_attribute<float3>(layer, domain_size);
case CD_PROP_INT32:
return this->layer_to_read_attribute<int>(layer, domain_size);
case CD_PROP_COLOR:
return this->layer_to_read_attribute<ColorGeometry4f>(layer, domain_size);
case CD_PROP_BOOL:
return this->layer_to_read_attribute<bool>(layer, domain_size);
default:
return {};
}
}
WriteAttributeLookup CustomDataAttributeProvider::try_get_for_write(
GeometryComponent &component, const StringRef attribute_name) const
{
@@ -386,33 +380,27 @@ WriteAttributeLookup CustomDataAttributeProvider::try_get_for_write(
continue;
}
CustomData_duplicate_referenced_layer_named(custom_data, layer.type, layer.name, domain_size);
return this->layer_to_write_attribute(layer, domain_size);
const CustomDataType data_type = (CustomDataType)layer.type;
switch (data_type) {
case CD_PROP_FLOAT:
return this->layer_to_write_attribute<float>(layer, domain_size);
case CD_PROP_FLOAT2:
return this->layer_to_write_attribute<float2>(layer, domain_size);
case CD_PROP_FLOAT3:
return this->layer_to_write_attribute<float3>(layer, domain_size);
case CD_PROP_INT32:
return this->layer_to_write_attribute<int>(layer, domain_size);
case CD_PROP_COLOR:
return this->layer_to_write_attribute<ColorGeometry4f>(layer, domain_size);
case CD_PROP_BOOL:
return this->layer_to_write_attribute<bool>(layer, domain_size);
default:
break;
}
}
return {};
}
WriteAttributeLookup CustomDataAttributeProvider::layer_to_write_attribute(
CustomDataLayer &layer, const int domain_size) const
{
const CustomDataType data_type = (CustomDataType)layer.type;
switch (data_type) {
case CD_PROP_FLOAT:
return this->layer_to_write_attribute<float>(layer, domain_size);
case CD_PROP_FLOAT2:
return this->layer_to_write_attribute<float2>(layer, domain_size);
case CD_PROP_FLOAT3:
return this->layer_to_write_attribute<float3>(layer, domain_size);
case CD_PROP_INT32:
return this->layer_to_write_attribute<int>(layer, domain_size);
case CD_PROP_COLOR:
return this->layer_to_write_attribute<ColorGeometry4f>(layer, domain_size);
case CD_PROP_BOOL:
return this->layer_to_write_attribute<bool>(layer, domain_size);
default:
return {};
}
}
bool CustomDataAttributeProvider::try_delete(GeometryComponent &component,
const StringRef attribute_name) const
{
@@ -499,84 +487,6 @@ bool CustomDataAttributeProvider::try_create(GeometryComponent &component,
return true;
}
static std::string get_anonymous_attribute_name()
{
static std::atomic<int> index = 0;
const int next_index = index.fetch_add(1);
return "anonymous_attribute_" + std::to_string(next_index);
}
bool CustomDataAttributeProvider::try_create_anonymous(GeometryComponent &component,
const AnonymousCustomDataLayerID &layer_id,
const AttributeDomain domain,
const CustomDataType data_type,
const AttributeInit &initializer) const
{
if (domain_ != domain) {
return false;
}
if (!this->type_is_supported(data_type)) {
return false;
}
CustomData *custom_data = custom_data_access_.get_custom_data(component);
if (custom_data == nullptr) {
return false;
}
for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) {
if (layer.anonymous_id == &layer_id) {
/* Don't create two layers with the same id. */
return false;
}
}
const int domain_size = component.attribute_domain_size(domain_);
const std::string attribute_name = get_anonymous_attribute_name();
add_named_custom_data_layer_from_attribute_init(
attribute_name, *custom_data, data_type, domain_size, initializer);
const int layer_index = CustomData_get_named_layer_index(
custom_data, data_type, attribute_name.c_str());
CustomDataLayer *layer = &custom_data->layers[layer_index];
layer->flag |= CD_FLAG_ANONYMOUS;
layer->anonymous_id = &layer_id;
CustomData_anonymous_id_weak_increment(&layer_id);
return true;
}
ReadAttributeLookup CustomDataAttributeProvider::try_get_anonymous_for_read(
const GeometryComponent &component, const AnonymousCustomDataLayerID &layer_id) const
{
const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
if (custom_data == nullptr) {
return {};
}
const int domain_size = component.attribute_domain_size(domain_);
for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) {
if (layer.anonymous_id != &layer_id) {
continue;
}
return this->layer_to_read_attribute(layer, domain_size);
}
return {};
}
WriteAttributeLookup CustomDataAttributeProvider::try_get_anonymous_for_write(
GeometryComponent &component, const AnonymousCustomDataLayerID &layer_id) const
{
CustomData *custom_data = custom_data_access_.get_custom_data(component);
if (custom_data == nullptr) {
return {};
}
const int domain_size = component.attribute_domain_size(domain_);
for (CustomDataLayer &layer : MutableSpan(custom_data->layers, custom_data->totlayer)) {
if (layer.anonymous_id != &layer_id) {
continue;
}
CustomData_duplicate_referenced_layer_named(custom_data, layer.type, layer.name, domain_size);
return this->layer_to_write_attribute(layer, domain_size);
}
return {};
}
bool CustomDataAttributeProvider::foreach_attribute(const GeometryComponent &component,
const AttributeForeachCallback callback) const
{
@@ -587,7 +497,7 @@ bool CustomDataAttributeProvider::foreach_attribute(const GeometryComponent &com
for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) {
const CustomDataType data_type = (CustomDataType)layer.type;
if (this->type_is_supported(data_type)) {
AttributeMetaData meta_data{domain_, data_type, layer.anonymous_id};
AttributeMetaData meta_data{domain_, data_type};
if (!callback(layer.name, meta_data)) {
return false;
}
@@ -788,56 +698,6 @@ bool CustomDataAttributes::create_by_move(const blender::StringRef name,
return result != nullptr;
}
bool CustomDataAttributes::create_anonymous(const AnonymousCustomDataLayerID &id,
const CustomDataType data_type)
{
for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
if (layer.anonymous_id == &id) {
/* Don't create two layers with the same id. */
return false;
}
}
const std::string name = get_anonymous_attribute_name();
if (!this->create(name, data_type)) {
return false;
}
const int layer_index = CustomData_get_named_layer_index(&data, data_type, name.c_str());
CustomDataLayer &layer = data.layers[layer_index];
layer.flag |= CD_FLAG_ANONYMOUS;
layer.anonymous_id = &id;
CustomData_anonymous_id_weak_increment(&id);
return true;
}
std::optional<GSpan> CustomDataAttributes::get_anonymous_for_read(
const AnonymousCustomDataLayerID &id) const
{
for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
if (layer.anonymous_id == &id) {
const CPPType *cpp_type = custom_data_type_to_cpp_type((CustomDataType)layer.type);
BLI_assert(cpp_type != nullptr);
return GSpan(*cpp_type, layer.data, size_);
}
}
return {};
}
std::optional<GMutableSpan> CustomDataAttributes::get_anonymous_for_write(
const AnonymousCustomDataLayerID &id)
{
for (CustomDataLayer &layer : MutableSpan(data.layers, data.totlayer)) {
if (layer.anonymous_id == &id) {
const CPPType *cpp_type = custom_data_type_to_cpp_type((CustomDataType)layer.type);
BLI_assert(cpp_type != nullptr);
return GMutableSpan(*cpp_type, layer.data, size_);
}
}
return {};
}
bool CustomDataAttributes::remove(const blender::StringRef name)
{
bool result = false;
@@ -861,7 +721,7 @@ bool CustomDataAttributes::foreach_attribute(const AttributeForeachCallback call
const AttributeDomain domain) const
{
for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
AttributeMetaData meta_data{domain, (CustomDataType)layer.type, layer.anonymous_id};
AttributeMetaData meta_data{domain, (CustomDataType)layer.type};
if (!callback(layer.name, meta_data)) {
return false;
}
@@ -875,14 +735,6 @@ bool CustomDataAttributes::foreach_attribute(const AttributeForeachCallback call
/** \name Geometry Component
* \{ */
static std::unique_ptr<blender::fn::GVArray> try_adapt_data_type(
std::unique_ptr<blender::fn::GVArray> varray, const blender::fn::CPPType &to_type)
{
const blender::nodes::DataTypeConversions &conversions =
blender::nodes::get_implicit_type_conversions();
return conversions.try_convert(std::move(varray), to_type);
}
const blender::bke::ComponentAttributeProviders *GeometryComponent::get_attribute_providers() const
{
return nullptr;
@@ -1023,102 +875,6 @@ bool GeometryComponent::attribute_try_create(const StringRef attribute_name,
return false;
}
bool GeometryComponent::attribute_try_create_anonymous(const AnonymousCustomDataLayerID &layer_id,
const AttributeDomain domain,
const CustomDataType data_type,
const AttributeInit &initializer)
{
using namespace blender::bke;
const ComponentAttributeProviders *providers = this->get_attribute_providers();
for (const DynamicAttributesProvider *dynamic_provider :
providers->dynamic_attribute_providers()) {
if (dynamic_provider->try_create_anonymous(*this, layer_id, domain, data_type, initializer)) {
return true;
}
}
return false;
}
blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_anonymous_for_read(
const AnonymousCustomDataLayerID &layer_id) const
{
using namespace blender::bke;
const ComponentAttributeProviders *providers = this->get_attribute_providers();
for (const DynamicAttributesProvider *dynamic_provider :
providers->dynamic_attribute_providers()) {
ReadAttributeLookup attribute = dynamic_provider->try_get_anonymous_for_read(*this, layer_id);
if (attribute) {
return attribute;
}
}
return {};
}
blender::fn::GVArrayPtr GeometryComponent::attribute_try_get_anonymous_for_read(
const AnonymousCustomDataLayerID &id,
const AttributeDomain domain,
const CustomDataType data_type) const
{
blender::bke::ReadAttributeLookup attribute = this->attribute_try_get_anonymous_for_read(id);
if (!attribute) {
return {};
}
std::unique_ptr<blender::fn::GVArray> varray = std::move(attribute.varray);
if (domain != ATTR_DOMAIN_AUTO && attribute.domain != domain) {
varray = this->attribute_try_adapt_domain(std::move(varray), attribute.domain, domain);
if (!varray) {
return {};
}
}
const blender::fn::CPPType *cpp_type = blender::bke::custom_data_type_to_cpp_type(data_type);
BLI_assert(cpp_type != nullptr);
if (varray->type() != *cpp_type) {
varray = try_adapt_data_type(std::move(varray), *cpp_type);
if (!varray) {
return {};
}
}
return varray;
}
blender::fn::GVArrayPtr GeometryComponent::attribute_try_get_anonymous_for_read(
const AnonymousCustomDataLayerID &id,
const AttributeDomain domain,
const CustomDataType data_type,
const void *default_value) const
{
blender::fn::GVArrayPtr varray = this->attribute_try_get_anonymous_for_read(
id, domain, data_type);
if (varray) {
return varray;
}
const blender::fn::CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type);
if (default_value == nullptr) {
default_value = type->default_value();
}
const int domain_size = this->attribute_domain_size(domain);
return std::make_unique<blender::fn::GVArray_For_SingleValue>(*type, domain_size, default_value);
}
blender::bke::WriteAttributeLookup GeometryComponent::attribute_try_get_anonymous_for_write(
const AnonymousCustomDataLayerID &layer_id)
{
using namespace blender::bke;
const ComponentAttributeProviders *providers = this->get_attribute_providers();
for (const DynamicAttributesProvider *dynamic_providers :
providers->dynamic_attribute_providers()) {
WriteAttributeLookup attribute = dynamic_providers->try_get_anonymous_for_write(*this,
layer_id);
if (attribute) {
return attribute;
}
}
return {};
}
bool GeometryComponent::attribute_try_create_builtin(const blender::StringRef attribute_name,
const AttributeInit &initializer)
{
@@ -1212,6 +968,14 @@ std::optional<AttributeMetaData> GeometryComponent::attribute_get_meta_data(
return result;
}
static std::unique_ptr<blender::fn::GVArray> try_adapt_data_type(
std::unique_ptr<blender::fn::GVArray> varray, const blender::fn::CPPType &to_type)
{
const blender::nodes::DataTypeConversions &conversions =
blender::nodes::get_implicit_type_conversions();
return conversions.try_convert(std::move(varray), to_type);
}
std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_read(
const StringRef attribute_name,
const AttributeDomain domain,
@@ -1463,122 +1227,3 @@ blender::bke::OutputAttribute GeometryComponent::attribute_try_get_for_output_on
{
return create_output_attribute(*this, attribute_name, domain, data_type, true, nullptr);
}
class GVMutableAttribute_For_AnonymousOutputAttribute
: public blender::fn::GVMutableArray_For_GMutableSpan {
public:
GeometryComponent *component;
const AnonymousCustomDataLayerID &final_id;
GVMutableAttribute_For_AnonymousOutputAttribute(GMutableSpan data,
GeometryComponent &component,
const AnonymousCustomDataLayerID &final_id)
: blender::fn::GVMutableArray_For_GMutableSpan(data),
component(&component),
final_id(final_id)
{
}
~GVMutableAttribute_For_AnonymousOutputAttribute() override
{
type_->destruct_n(data_, size_);
MEM_freeN(data_);
}
};
static void save_output_anonymous_attribute(blender::bke::OutputAttribute &output_attribute)
{
using namespace blender;
using namespace blender::fn;
using namespace blender::bke;
GVMutableAttribute_For_AnonymousOutputAttribute &varray =
dynamic_cast<GVMutableAttribute_For_AnonymousOutputAttribute &>(output_attribute.varray());
GeometryComponent &component = *varray.component;
WriteAttributeLookup write_attribute = component.attribute_try_get_anonymous_for_write(
varray.final_id);
BUFFER_FOR_CPP_TYPE_VALUE(varray.type(), buffer);
for (const int i : IndexRange(varray.size())) {
varray.get(i, buffer);
write_attribute.varray->set_by_relocate(i, buffer);
}
}
static blender::bke::OutputAttribute create_output_attribute_anonymous(
GeometryComponent &component,
const AnonymousCustomDataLayerID &id,
const AttributeDomain domain,
const CustomDataType data_type,
const bool ignore_old_values,
const void *default_value)
{
using namespace blender;
using namespace blender::fn;
using namespace blender::bke;
const CPPType *cpp_type = custom_data_type_to_cpp_type(data_type);
BLI_assert(cpp_type != nullptr);
const int domain_size = component.attribute_domain_size(domain);
WriteAttributeLookup attribute = component.attribute_try_get_anonymous_for_write(id);
if (!attribute) {
if (default_value) {
const GVArray_For_SingleValueRef default_varray{*cpp_type, domain_size, default_value};
component.attribute_try_create_anonymous(
id, domain, data_type, AttributeInitVArray(&default_varray));
}
else {
component.attribute_try_create_anonymous(id, domain, data_type, AttributeInitDefault());
}
attribute = component.attribute_try_get_anonymous_for_write(id);
if (!attribute) {
/* Can't create the attribute. */
return {};
}
}
if (attribute.domain == domain && attribute.varray->type() == *cpp_type) {
/* Existing generic attribute matches exactly. */
return OutputAttribute(std::move(attribute.varray), domain, {}, ignore_old_values);
}
/* Allocate a new array that lives next to the existing attribute. It will overwrite the existing
* attribute after processing is done. */
void *data = MEM_mallocN_aligned(
cpp_type->size() * domain_size, cpp_type->alignment(), __func__);
if (ignore_old_values) {
/* This does nothing for trivially constructible types, but is necessary for correctness. */
cpp_type->default_construct_n(data, domain);
}
else {
BLI_assert_unreachable();
/* Fill the temporary array with values from the existing attribute. */
GVArrayPtr old_varray = component.attribute_try_get_anonymous_for_read(
id, domain, data_type, default_value);
old_varray->materialize_to_uninitialized(IndexRange(domain_size), data);
}
GVMutableArrayPtr varray = std::make_unique<GVMutableAttribute_For_AnonymousOutputAttribute>(
GMutableSpan{*cpp_type, data, domain_size}, component, id);
return OutputAttribute(std::move(varray), domain, save_output_anonymous_attribute, true);
}
blender::bke::OutputAttribute GeometryComponent::attribute_try_get_anonymous_for_output(
const AnonymousCustomDataLayerID &id,
const AttributeDomain domain,
const CustomDataType data_type,
const void *default_value)
{
return create_output_attribute_anonymous(*this, id, domain, data_type, false, default_value);
}
blender::bke::OutputAttribute GeometryComponent::attribute_try_get_anonymous_for_output_only(
const AnonymousCustomDataLayerID &id,
const AttributeDomain domain,
const CustomDataType data_type)
{
return create_output_attribute_anonymous(*this, id, domain, data_type, true, nullptr);
}

View File

@@ -130,30 +130,6 @@ class DynamicAttributesProvider {
return false;
};
/** Returns the id of the new anonymous or null if no new attribute was created. */
virtual bool try_create_anonymous(GeometryComponent &UNUSED(component),
const AnonymousCustomDataLayerID &UNUSED(layer_id),
const AttributeDomain UNUSED(domain),
const CustomDataType UNUSED(data_type),
const AttributeInit &UNUSED(initializer)) const
{
return false;
}
virtual ReadAttributeLookup try_get_anonymous_for_read(
const GeometryComponent &UNUSED(component),
const AnonymousCustomDataLayerID &UNUSED(layer_id)) const
{
return {};
}
virtual WriteAttributeLookup try_get_anonymous_for_write(
GeometryComponent &UNUSED(component),
const AnonymousCustomDataLayerID &UNUSED(layer_id)) const
{
return {};
}
virtual bool foreach_attribute(const GeometryComponent &component,
const AttributeForeachCallback callback) const = 0;
virtual void foreach_domain(const FunctionRef<void(AttributeDomain)> callback) const = 0;
@@ -191,18 +167,6 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider {
const CustomDataType data_type,
const AttributeInit &initializer) const final;
bool try_create_anonymous(GeometryComponent &component,
const AnonymousCustomDataLayerID &layer_id,
const AttributeDomain domain,
const CustomDataType data_type,
const AttributeInit &initializer) const final;
ReadAttributeLookup try_get_anonymous_for_read(
const GeometryComponent &component, const AnonymousCustomDataLayerID &layer_id) const final;
WriteAttributeLookup try_get_anonymous_for_write(
GeometryComponent &component, const AnonymousCustomDataLayerID &layer_id) const final;
bool foreach_attribute(const GeometryComponent &component,
const AttributeForeachCallback callback) const final;
@@ -212,9 +176,6 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider {
}
private:
ReadAttributeLookup layer_to_read_attribute(const CustomDataLayer &layer,
const int domain_size) const;
template<typename T>
ReadAttributeLookup layer_to_read_attribute(const CustomDataLayer &layer,
const int domain_size) const
@@ -224,9 +185,6 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider {
domain_};
}
WriteAttributeLookup layer_to_write_attribute(CustomDataLayer &layer,
const int domain_size) const;
template<typename T>
WriteAttributeLookup layer_to_write_attribute(CustomDataLayer &layer,
const int domain_size) const

View File

@@ -1254,10 +1254,11 @@ 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");

View File

@@ -339,11 +339,7 @@ void CurveEval::assert_valid_point_attributes() const
name,
[&](AttributeMetaData *map_data) {
/* All unique attribute names should be added on the first spline. */
/* TODO(Hans/Jacques): This check seems very bad, anonymous attributes with have
* different names on different splines. */
if (meta_data.anonymous_layer_id == nullptr) {
BLI_assert(spline == splines_.first());
}
BLI_assert(spline == splines_.first());
*map_data = meta_data;
},
[&](AttributeMetaData *map_data) {

View File

@@ -57,8 +57,6 @@
#include "BLO_read_write.h"
#include "atomic_ops.h"
#include "bmesh.h"
#include "CLG_log.h"
@@ -2129,9 +2127,6 @@ bool CustomData_merge(const struct CustomData *source,
if (flag & CD_FLAG_NOCOPY) {
continue;
}
if (CustomData_layer_is_unused_anonymous(layer)) {
continue;
}
if (!(mask & CD_TYPE_AS_MASK(type))) {
continue;
}
@@ -2169,13 +2164,8 @@ bool CustomData_merge(const struct CustomData *source,
newlayer->active_rnd = lastrender;
newlayer->active_clone = lastclone;
newlayer->active_mask = lastmask;
newlayer->flag |= flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY | CD_FLAG_ANONYMOUS);
newlayer->flag |= flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY);
changed = true;
if (layer->flag & CD_FLAG_ANONYMOUS) {
CustomData_anonymous_id_weak_increment(layer->anonymous_id);
newlayer->anonymous_id = layer->anonymous_id;
}
}
}
@@ -2216,10 +2206,6 @@ static void customData_free_layer__internal(CustomDataLayer *layer, int totelem)
{
const LayerTypeInfo *typeInfo;
if (layer->flag & CD_FLAG_ANONYMOUS) {
CustomData_anonymous_id_weak_decrement(layer->anonymous_id);
layer->anonymous_id = NULL;
}
if (!(layer->flag & CD_FLAG_NOFREE) && layer->data) {
typeInfo = layerType_getInfo(layer->type);
@@ -4258,8 +4244,7 @@ void CustomData_blend_write_prepare(CustomData *data,
for (i = 0, j = 0; i < totlayer; i++) {
CustomDataLayer *layer = &data->layers[i];
/* Layers with this flag set are not written to file. */
if (layer->flag & (CD_FLAG_NOCOPY | CD_FLAG_ANONYMOUS)) {
if (layer->flag & CD_FLAG_NOCOPY) { /* Layers with this flag set are not written to file. */
data->totlayer--;
// CLOG_WARN(&LOG, "skipping layer %p (%s)", layer, layer->name);
}
@@ -5046,68 +5031,6 @@ void CustomData_data_transfer(const MeshPairRemap *me_remap,
MEM_SAFE_FREE(tmp_data_src);
}
AnonymousCustomDataLayerID *CustomData_anonymous_id_new(const char *debug_name)
{
AnonymousCustomDataLayerID *layer_id = MEM_callocN(sizeof(AnonymousCustomDataLayerID), __func__);
layer_id->debug_name = BLI_strdup(debug_name);
return layer_id;
}
static void CustomData_anonymous_id_free(AnonymousCustomDataLayerID *layer_id)
{
BLI_assert(layer_id->strong_references == 0);
BLI_assert(layer_id->tot_references == 0);
MEM_freeN(layer_id->debug_name);
MEM_freeN(layer_id);
}
void CustomData_anonymous_id_strong_decrement(const AnonymousCustomDataLayerID *layer_id)
{
AnonymousCustomDataLayerID *mutable_layer_id = (AnonymousCustomDataLayerID *)layer_id;
int strong_references = atomic_sub_and_fetch_int32(&mutable_layer_id->strong_references, 1);
BLI_assert(strong_references >= 0);
UNUSED_VARS_NDEBUG(strong_references);
int tot_references = atomic_sub_and_fetch_int32(&mutable_layer_id->tot_references, 1);
BLI_assert(tot_references >= 0);
if (tot_references == 0) {
CustomData_anonymous_id_free(mutable_layer_id);
}
}
void CustomData_anonymous_id_strong_increment(const AnonymousCustomDataLayerID *layer_id)
{
AnonymousCustomDataLayerID *mutable_layer_id = (AnonymousCustomDataLayerID *)layer_id;
atomic_add_and_fetch_int32(&mutable_layer_id->tot_references, 1);
atomic_add_and_fetch_int32(&mutable_layer_id->strong_references, 1);
}
void CustomData_anonymous_id_weak_decrement(const AnonymousCustomDataLayerID *layer_id)
{
AnonymousCustomDataLayerID *mutable_layer_id = (AnonymousCustomDataLayerID *)layer_id;
int tot_references = atomic_sub_and_fetch_int32(&mutable_layer_id->tot_references, 1);
BLI_assert(tot_references >= 0);
if (tot_references == 0) {
CustomData_anonymous_id_free(mutable_layer_id);
}
}
void CustomData_anonymous_id_weak_increment(const AnonymousCustomDataLayerID *layer_id)
{
AnonymousCustomDataLayerID *mutable_layer_id = (AnonymousCustomDataLayerID *)layer_id;
atomic_add_and_fetch_int32(&mutable_layer_id->tot_references, 1);
}
bool CustomData_layer_is_unused_anonymous(const CustomDataLayer *layer)
{
if (layer->flag & CD_FLAG_ANONYMOUS) {
if (layer->anonymous_id->strong_references == 0) {
return true;
}
}
return false;
}
static void write_mdisps(BlendWriter *writer, int count, MDisps *mdlist, int external)
{
if (mdlist) {

View File

@@ -1094,165 +1094,6 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
return true;
}
bool try_create_anonymous(GeometryComponent &component,
const AnonymousCustomDataLayerID &layer_id,
const AttributeDomain domain,
const CustomDataType data_type,
const AttributeInit &initializer) const
{
BLI_assert(this->type_is_supported(data_type));
if (domain != ATTR_DOMAIN_POINT) {
return false;
}
CurveEval *curve = get_curve_from_component_for_write(component);
if (curve == nullptr || curve->splines().size() == 0) {
return false;
}
MutableSpan<SplinePtr> splines = curve->splines();
/* Otherwise just create a custom data layer on each of the splines. */
for (const int i : splines.index_range()) {
if (!splines[i]->attributes.create_anonymous(layer_id, data_type)) {
/* If attribute creation fails on one of the splines, we cannot leave the custom data
* layers in the previous splines around, so delete them before returning. However,
* this is not an expected case. */
BLI_assert_unreachable();
return false;
}
}
/* With a default initializer type, we can keep the values at their initial values. */
if (initializer.type == AttributeInit::Type::Default) {
return true;
}
WriteAttributeLookup write_attribute = this->try_get_anonymous_for_write(component, layer_id);
/* We just created the attribute, it should exist. */
BLI_assert(write_attribute);
const int total_size = curve->control_point_offsets().last();
GVArrayPtr source_varray = varray_from_initializer(initializer, data_type, total_size);
/* TODO: When we can call a variant of #set_all with a virtual array argument,
* this theoretically unnecessary materialize step could be removed. */
GVArray_GSpan source_varray_span{*source_varray};
write_attribute.varray->set_all(source_varray_span.data());
if (initializer.type == AttributeInit::Type::MoveArray) {
MEM_freeN(static_cast<const AttributeInitMove &>(initializer).data);
}
curve->assert_valid_point_attributes();
return true;
}
ReadAttributeLookup try_get_anonymous_for_read(const GeometryComponent &component,
const AnonymousCustomDataLayerID &layer_id) const
{
const CurveEval *curve = get_curve_from_component_for_read(component);
if (curve == nullptr || curve->splines().size() == 0) {
return {};
}
Span<SplinePtr> splines = curve->splines();
Vector<GSpan> spans; /* GSpan has no default constructor. */
spans.reserve(splines.size());
std::optional<GSpan> first_span = splines[0]->attributes.get_anonymous_for_read(layer_id);
if (!first_span) {
return {};
}
spans.append(*first_span);
for (const int i : IndexRange(1, splines.size() - 1)) {
std::optional<GSpan> span = splines[i]->attributes.get_anonymous_for_read(layer_id);
if (!span) {
/* All splines should have the same set of data layers. It would be possible to recover
* here and return partial data instead, but that would add a lot of complexity for a
* situation we don't even expect to encounter. */
BLI_assert_unreachable();
return {};
}
if (span->type() != spans.last().type()) {
/* Data layer types on separate splines do not match. */
BLI_assert_unreachable();
return {};
}
spans.append(*span);
}
/* First check for the simpler situation when we can return a simpler span virtual array. */
if (spans.size() == 1) {
return {std::make_unique<GVArray_For_GSpan>(spans.first()), ATTR_DOMAIN_POINT};
}
ReadAttributeLookup attribute = {};
Array<int> offsets = curve->control_point_offsets();
attribute_math::convert_to_static_type(spans[0].type(), [&](auto dummy) {
using T = decltype(dummy);
Array<Span<T>> data(splines.size());
for (const int i : splines.index_range()) {
data[i] = spans[i].typed<T>();
BLI_assert(data[i].data() != nullptr);
}
attribute = {point_data_gvarray(data, offsets), ATTR_DOMAIN_POINT};
});
return attribute;
}
WriteAttributeLookup try_get_anonymous_for_write(
GeometryComponent &component, const AnonymousCustomDataLayerID &layer_id) const
{
CurveEval *curve = get_curve_from_component_for_write(component);
if (curve == nullptr || curve->splines().size() == 0) {
return {};
}
MutableSpan<SplinePtr> splines = curve->splines();
Vector<GMutableSpan> spans; /* GMutableSpan has no default constructor. */
spans.reserve(splines.size());
std::optional<GMutableSpan> first_span = splines[0]->attributes.get_anonymous_for_write(
layer_id);
if (!first_span) {
return {};
}
spans.append(*first_span);
for (const int i : IndexRange(1, splines.size() - 1)) {
std::optional<GMutableSpan> span = splines[i]->attributes.get_anonymous_for_write(layer_id);
if (!span) {
/* All splines should have the same set of data layers. It would be possible to recover
* here and return partial data instead, but that would add a lot of complexity for a
* situation we don't even expect to encounter. */
BLI_assert_unreachable();
return {};
}
if (span->type() != spans.last().type()) {
/* Data layer types on separate splines do not match. */
BLI_assert_unreachable();
return {};
}
spans.append(*span);
}
/* First check for the simpler situation when we can return a simpler span virtual array. */
if (spans.size() == 1) {
return {std::make_unique<GVMutableArray_For_GMutableSpan>(spans.first()), ATTR_DOMAIN_POINT};
}
WriteAttributeLookup attribute = {};
Array<int> offsets = curve->control_point_offsets();
attribute_math::convert_to_static_type(spans[0].type(), [&](auto dummy) {
using T = decltype(dummy);
Array<MutableSpan<T>> data(splines.size());
for (const int i : splines.index_range()) {
data[i] = spans[i].typed<T>();
BLI_assert(data[i].data() != nullptr);
}
attribute = {point_data_gvarray(data, offsets), ATTR_DOMAIN_POINT};
});
return attribute;
}
bool foreach_attribute(const GeometryComponent &component,
const AttributeForeachCallback callback) const final
{

View File

@@ -651,207 +651,6 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
return {};
}
namespace blender::bke::adapt_selection_domain {
static VArrayPtr<bool> varray_from_array(Array<bool> array)
{
return std::make_unique<VArray_For_ArrayContainer<Array<bool>>>(std::move(array));
}
static VArrayPtr<bool> adapt_selection_point_to_face(const Mesh &mesh, VArrayPtr<bool> selection)
{
Array<bool> new_selection(mesh.totpoly);
for (const int poly_index : IndexRange(mesh.totpoly)) {
const MPoly &poly = mesh.mpoly[poly_index];
bool poly_is_selected = true;
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const MLoop &loop = mesh.mloop[loop_index];
if (!selection->get(loop.v)) {
poly_is_selected = false;
break;
}
}
new_selection[poly_index] = poly_is_selected;
}
return varray_from_array(std::move(new_selection));
}
static VArrayPtr<bool> adapt_selection_point_to_corner(const Mesh &mesh, VArrayPtr<bool> selection)
{
Array<bool> new_selection(mesh.totloop);
for (const int loop_index : IndexRange(mesh.totloop)) {
const MLoop &loop = mesh.mloop[loop_index];
new_selection[loop_index] = selection->get(loop.v);
}
return varray_from_array(std::move(new_selection));
}
static VArrayPtr<bool> adapt_selection_point_to_edge(const Mesh &mesh, VArrayPtr<bool> selection)
{
Array<bool> new_selection(mesh.totedge);
for (const int edge_index : IndexRange(mesh.totedge)) {
const MEdge &edge = mesh.medge[edge_index];
const bool edge_is_selected = selection->get(edge.v1) && selection->get(edge.v2);
new_selection[edge_index] = edge_is_selected;
}
return varray_from_array(std::move(new_selection));
}
static VArrayPtr<bool> adapt_selection_edge_to_point(const Mesh &mesh, VArrayPtr<bool> selection)
{
Array<bool> new_selection(mesh.totvert, false);
for (const int edge_index : IndexRange(mesh.totedge)) {
if (selection->get(edge_index)) {
const MEdge &edge = mesh.medge[edge_index];
new_selection[edge.v1] = true;
new_selection[edge.v2] = true;
}
}
return varray_from_array(std::move(new_selection));
}
static VArrayPtr<bool> adapt_selection_edge_to_face(const Mesh &mesh, VArrayPtr<bool> selection)
{
Array<bool> new_selection(mesh.totpoly);
for (const int poly_index : IndexRange(mesh.totpoly)) {
const MPoly &poly = mesh.mpoly[poly_index];
bool poly_is_selected = true;
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const MLoop &loop = mesh.mloop[loop_index];
if (!selection->get(loop.e)) {
poly_is_selected = false;
break;
}
}
new_selection[poly_index] = poly_is_selected;
}
return varray_from_array(std::move(new_selection));
}
static VArrayPtr<bool> adapt_selection_face_to_point(const Mesh &mesh, VArrayPtr<bool> selection)
{
Array<bool> new_selection(mesh.totvert, false);
for (const int poly_index : IndexRange(mesh.totpoly)) {
const MPoly &poly = mesh.mpoly[poly_index];
if (selection->get(poly_index)) {
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const MLoop &loop = mesh.mloop[loop_index];
BLI_assert(loop.v < mesh.totvert);
new_selection[loop.v] = true;
}
}
}
return varray_from_array(std::move(new_selection));
}
static VArrayPtr<bool> adapt_selection_face_to_edge(const Mesh &mesh, VArrayPtr<bool> selection)
{
Array<bool> new_selection(mesh.totedge, false);
for (const int poly_index : IndexRange(mesh.totpoly)) {
const MPoly &poly = mesh.mpoly[poly_index];
if (selection->get(poly_index)) {
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const MLoop &loop = mesh.mloop[loop_index];
new_selection[loop.e] = true;
}
}
}
return varray_from_array(std::move(new_selection));
}
static VArrayPtr<bool> adapt_selection_face_to_corner(const Mesh &mesh, VArrayPtr<bool> selection)
{
Array<bool> new_selection(mesh.totloop);
for (const int poly_index : IndexRange(mesh.totpoly)) {
const MPoly &poly = mesh.mpoly[poly_index];
const bool is_selected = selection->get(poly_index);
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
new_selection[loop_index] = is_selected;
}
}
return varray_from_array(std::move(new_selection));
}
} // namespace blender::bke::adapt_selection_domain
blender::VArrayPtr<bool> MeshComponent::adapt_selection(blender::VArrayPtr<bool> selection,
const AttributeDomain from_domain,
const AttributeDomain to_domain) const
{
using namespace blender::bke::adapt_selection_domain;
const int from_domain_size = this->attribute_domain_size(from_domain);
BLI_assert(selection->size() == from_domain_size);
if (from_domain == to_domain) {
return selection;
}
if (from_domain_size == 0) {
return selection;
}
if (selection->is_single()) {
return selection;
}
switch (from_domain) {
case ATTR_DOMAIN_CORNER: {
switch (to_domain) {
case ATTR_DOMAIN_POINT:
break;
case ATTR_DOMAIN_FACE:
break;
case ATTR_DOMAIN_EDGE:
break;
default:
break;
}
break;
}
case ATTR_DOMAIN_POINT: {
switch (to_domain) {
case ATTR_DOMAIN_CORNER:
return adapt_selection_point_to_corner(*mesh_, std::move(selection));
case ATTR_DOMAIN_FACE:
return adapt_selection_point_to_face(*mesh_, std::move(selection));
case ATTR_DOMAIN_EDGE:
return adapt_selection_point_to_edge(*mesh_, std::move(selection));
default:
break;
}
break;
}
case ATTR_DOMAIN_FACE: {
switch (to_domain) {
case ATTR_DOMAIN_POINT:
return adapt_selection_face_to_point(*mesh_, std::move(selection));
case ATTR_DOMAIN_CORNER:
return adapt_selection_face_to_corner(*mesh_, std::move(selection));
case ATTR_DOMAIN_EDGE:
return adapt_selection_face_to_edge(*mesh_, std::move(selection));
default:
break;
}
break;
}
case ATTR_DOMAIN_EDGE: {
switch (to_domain) {
case ATTR_DOMAIN_CORNER:
break;
case ATTR_DOMAIN_POINT:
return adapt_selection_edge_to_point(*mesh_, std::move(selection));
case ATTR_DOMAIN_FACE:
return adapt_selection_edge_to_face(*mesh_, std::move(selection));
default:
break;
}
break;
}
default:
break;
}
return {};
}
static Mesh *get_mesh_from_component_for_write(GeometryComponent &component)
{
BLI_assert(component.type() == GEO_COMPONENT_TYPE_MESH);

View File

@@ -18,7 +18,6 @@
#include "BKE_attribute.h"
#include "BKE_attribute_access.hh"
#include "BKE_field.hh"
#include "BKE_geometry_set.hh"
#include "BKE_lib_id.h"
#include "BKE_mesh.h"

View File

@@ -620,10 +620,7 @@ bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const
}
if (new_count == 1) {
if (gps->dvert) {
BKE_gpencil_free_stroke_weights(gps);
MEM_freeN(gps->dvert);
}
BKE_gpencil_free_stroke_weights(gps);
MEM_freeN(gps->points);
gps->points = nullptr;
gps->dvert = nullptr;
@@ -631,24 +628,27 @@ bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const
return false;
}
new_pt = (bGPDspoint *)MEM_mallocN(sizeof(bGPDspoint) * new_count, "gp_stroke_points_trimmed");
memcpy(new_pt, &pt[index_from], sizeof(bGPDspoint) * new_count);
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));
}
if (gps->dvert) {
new_dv = (MDeformVert *)MEM_mallocN(sizeof(MDeformVert) * new_count,
new_dv = (MDeformVert *)MEM_callocN(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_mallocN(sizeof(MDeformWeight) * dv->totweight,
new_dv[i].dw = (MDeformWeight *)MEM_callocN(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,21 +692,25 @@ bool BKE_gpencil_stroke_split(bGPdata *gpd,
gpf, gps, gps->mat_nr, new_count, gps->thickness);
new_pt = new_gps->points; /* Allocated from above. */
memcpy(new_pt, &pt[before_index], sizeof(bGPDspoint) * new_count);
for (int i = 0; i < new_count; i++) {
memcpy(&new_pt[i], &pt[i + before_index], sizeof(bGPDspoint));
}
if (gps->dvert) {
new_dv = (MDeformVert *)MEM_mallocN(sizeof(MDeformVert) * new_count,
new_dv = (MDeformVert *)MEM_callocN(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_mallocN(sizeof(MDeformWeight) * dv->totweight,
new_dv[i].dw = (MDeformWeight *)MEM_callocN(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;
}

View File

@@ -1481,7 +1481,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_str_utf8_invalid_strip(base_name, base_name_len);
base_name_len -= (size_t)BLI_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 +1731,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_str_utf8_invalid_strip(name, strlen(name));
BLI_utf8_invalid_strip(name, strlen(name));
}
ID *id_sorting_hint = NULL;

View File

@@ -5115,16 +5115,13 @@ static void registerGeometryNodes()
{
register_node_type_geo_group();
register_node_type_geo_extrude();
register_node_type_geo_attribute();
register_node_type_geo_align_rotation_to_vector();
register_node_type_geo_attribute_clamp();
register_node_type_geo_attribute_color_ramp();
register_node_type_geo_attribute_combine_xyz();
register_node_type_geo_attribute_compare();
register_node_type_geo_attribute_convert();
register_node_type_geo_attribute_curve_map();
register_node_type_geo_attribute_extract();
register_node_type_geo_attribute_fill();
register_node_type_geo_attribute_map_range();
register_node_type_geo_attribute_math();
@@ -5142,7 +5139,6 @@ static void registerGeometryNodes()
register_node_type_geo_convex_hull();
register_node_type_geo_curve_endpoints();
register_node_type_geo_curve_length();
register_node_type_geo_curve_parameter();
register_node_type_geo_curve_primitive_bezier_segment();
register_node_type_geo_curve_primitive_circle();
register_node_type_geo_curve_primitive_line();
@@ -5160,9 +5156,6 @@ static void registerGeometryNodes()
register_node_type_geo_curve_trim();
register_node_type_geo_delete_geometry();
register_node_type_geo_edge_split();
register_node_type_geo_evaluate_curve();
register_node_type_geo_extrude_and_move();
register_node_type_geo_index();
register_node_type_geo_input_material();
register_node_type_geo_is_viewport();
register_node_type_geo_join_geometry();
@@ -5178,7 +5171,6 @@ static void registerGeometryNodes()
register_node_type_geo_mesh_primitive_uv_sphere();
register_node_type_geo_mesh_subdivide();
register_node_type_geo_mesh_to_curve();
register_node_type_geo_normal();
register_node_type_geo_object_info();
register_node_type_geo_point_distribute();
register_node_type_geo_point_instance();
@@ -5187,21 +5179,17 @@ static void registerGeometryNodes()
register_node_type_geo_point_separate();
register_node_type_geo_point_translate();
register_node_type_geo_points_to_volume();
register_node_type_geo_position();
register_node_type_geo_raycast();
register_node_type_geo_sample_mesh_surface();
register_node_type_geo_sample_texture();
register_node_type_geo_select_by_handle_type();
register_node_type_geo_select_by_material();
register_node_type_geo_separate_components();
register_node_type_geo_set_position();
register_node_type_geo_subdivision_surface();
register_node_type_geo_switch();
register_node_type_geo_transform();
register_node_type_geo_triangulate();
register_node_type_geo_viewer();
register_node_type_geo_volume_to_mesh();
register_node_type_geo_attribute_freeze();
}
static void registerFunctionNodes()
@@ -5211,7 +5199,6 @@ static void registerFunctionNodes()
register_node_type_fn_float_to_int();
register_node_type_fn_input_string();
register_node_type_fn_input_vector();
register_node_type_fn_align_rotation_to_vector();
register_node_type_fn_random_float();
}

View File

@@ -123,7 +123,7 @@ int Spline::evaluated_edges_size() const
float Spline::length() const
{
Span<float> lengths = this->evaluated_lengths();
return lengths.is_empty() ? 0.0f : this->evaluated_lengths().last();
return (lengths.size() == 0) ? 0 : this->evaluated_lengths().last();
}
int Spline::segments_size() const

View File

@@ -308,7 +308,7 @@ int txt_extended_ascii_as_utf8(char **str)
int added = 0;
while ((*str)[i]) {
if ((bad_char = BLI_str_utf8_invalid_byte(*str + i, length - i)) == -1) {
if ((bad_char = BLI_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_str_utf8_invalid_byte((*str) + i, length - i)) == -1) {
if ((bad_char = BLI_utf8_invalid_byte((*str) + i, length - i)) == -1) {
memcpy(newstr + mi, (*str) + i, length - i + 1);
break;
}

View File

@@ -250,20 +250,6 @@ template<typename T> struct DefaultHash<std::unique_ptr<T>> {
}
};
template<typename T> struct DefaultHash<std::shared_ptr<T>> {
uint64_t operator()(const std::shared_ptr<T> &value) const
{
return get_default_hash(value.get());
}
};
template<typename T> struct DefaultHash<std::reference_wrapper<T>> {
uint64_t operator()(const std::reference_wrapper<T> &value) const
{
return get_default_hash(value.get());
}
};
template<typename T1, typename T2> struct DefaultHash<std::pair<T1, T2>> {
uint64_t operator()(const std::pair<T1, T2> &value) const
{

View File

@@ -196,8 +196,6 @@ 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);

View File

@@ -1,88 +0,0 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#pragma once
/** \file
* \ingroup bli
*/
#include <memory>
#include "BLI_utildefines.h"
namespace blender {
template<typename T, typename OwnedTPtr = std::unique_ptr<T>> class optional_ptr {
private:
OwnedTPtr owned_ptr_;
T *ptr_ = nullptr;
public:
optional_ptr() = default;
optional_ptr(T &ptr) : ptr_(&ptr)
{
}
optional_ptr(OwnedTPtr owned_ptr) : owned_ptr_(std::move(owned_ptr)), ptr_(&*owned_ptr_)
{
}
bool is_owned() const
{
return static_cast<bool>(owned_ptr_);
}
OwnedTPtr extract_owned()
{
OwnedTPtr ptr = std::move(owned_ptr_);
owned_ptr_ = OwnedTPtr{nullptr};
ptr_ = nullptr;
return ptr;
}
T *operator->()
{
BLI_assert(ptr_ != nullptr);
return ptr_;
}
const T *operator->() const
{
BLI_assert(ptr_ != nullptr);
return ptr_;
}
T &operator*()
{
BLI_assert(ptr_ != nullptr);
return *ptr_;
}
const T &operator*() const
{
BLI_assert(ptr_ != nullptr);
return *ptr_;
}
operator bool() const
{
return ptr_ != nullptr;
}
};
} // namespace blender

View File

@@ -478,8 +478,8 @@ template<typename T> class MutableSpan {
using size_type = int64_t;
protected:
T *data_ = nullptr;
int64_t size_ = 0;
T *data_;
int64_t size_;
public:
constexpr MutableSpan() = default;

View File

@@ -31,8 +31,8 @@ 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_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();
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();
/* warning, can return -1 on bad chars */
int BLI_str_utf8_size(const char *p) ATTR_NONNULL();

View File

@@ -84,24 +84,12 @@ template<typename T> class UserCounter {
return data_;
}
const T *operator->() const
{
BLI_assert(data_ != nullptr);
return data_;
}
T &operator*()
{
BLI_assert(data_ != nullptr);
return *data_;
}
const T &operator*() const
{
BLI_assert(data_ != nullptr);
return *data_;
}
operator bool() const
{
return data_ != nullptr;

View File

@@ -255,7 +255,7 @@ template<typename T> class VMutableArray : public VArray<T> {
}
};
template<typename T> using VArrayPtr = std::unique_ptr<const VArray<T>>;
template<typename T> using VArrayPtr = std::unique_ptr<VArray<T>>;
template<typename T> using VMutableArrayPtr = std::unique_ptr<VMutableArray<T>>;
/**

View File

@@ -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_str_utf8_invalid_strip(vfd->name, strlen(vfd->name));
BLI_utf8_invalid_strip(vfd->name, strlen(vfd->name));
}
/* Select a character map. */

View File

@@ -363,14 +363,6 @@ 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)

View File

@@ -70,7 +70,7 @@ static const size_t utf8_skip_data[256] = {
*
* \return the offset of the first invalid byte.
*/
ptrdiff_t BLI_str_utf8_invalid_byte(const char *str, size_t length)
ptrdiff_t BLI_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_str_utf8_invalid_strip(char *str, size_t length)
int BLI_utf8_invalid_strip(char *str, size_t length)
{
ptrdiff_t bad_char;
int tot = 0;
BLI_assert(str[length] == '\0');
while ((bad_char = BLI_str_utf8_invalid_byte(str, length)) != -1) {
while ((bad_char = BLI_utf8_invalid_byte(str, length)) != -1) {
str += bad_char;
length -= (size_t)(bad_char + 1);

View File

@@ -653,18 +653,6 @@ TEST(map, LookupKey)
EXPECT_EQ(map.lookup_key_ptr("a"), map.lookup_key_ptr_as("a"));
}
TEST(map, ReferenceWrapperKey)
{
Map<std::reference_wrapper<int>, int> map;
int a = 2;
int b = 5;
map.add(a, 10);
map.add(a, 20);
map.add(b, 20);
EXPECT_EQ(map.lookup(a), 10);
EXPECT_EQ(map.lookup(b), 20);
}
/**
* Set this to 1 to activate the benchmark. It is disabled by default, because it prints a lot.
*/

View File

@@ -266,7 +266,7 @@ static const char *utf8_invalid_tests[][3] = {
};
/* clang-format on */
/* BLI_str_utf8_invalid_strip (and indirectly, BLI_str_utf8_invalid_byte). */
/* BLI_utf8_invalid_strip (and indirectly, BLI_utf8_invalid_byte). */
TEST(string, Utf8InvalidBytes)
{
for (int i = 0; utf8_invalid_tests[i][0] != nullptr; i++) {
@@ -277,7 +277,7 @@ TEST(string, Utf8InvalidBytes)
char buff[80];
memcpy(buff, tst, sizeof(buff));
const int num_errors_found = BLI_str_utf8_invalid_strip(buff, sizeof(buff) - 1);
const int num_errors_found = BLI_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);

View File

@@ -1446,141 +1446,4 @@ void BM_mesh_vert_coords_apply_with_mat4(BMesh *bm,
}
}
/**
* Use to select bmesh vertex data based on an array of bool.
*/
void BM_select_vertices(BMesh *bm, const bool *mask)
{
BMIter iter;
BMVert *v;
int i = 0;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (mask[i]) {
BM_elem_flag_set(v, BM_ELEM_SELECT, true);
}
else {
BM_elem_flag_set(v, BM_ELEM_SELECT, false);
}
i++;
}
}
/**
* Use to select bmesh edge data based on an array of bool.
*/
void BM_select_edges(BMesh *bm, const bool *mask)
{
BMIter iter;
BMEdge *e;
int i = 0;
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (mask[i]) {
BM_elem_flag_set(e, BM_ELEM_SELECT, true);
}
else {
BM_elem_flag_set(e, BM_ELEM_SELECT, false);
}
i++;
}
}
/**
* Use to select bmesh face data based on an array of bool.
*/
void BM_select_faces(BMesh *bm, const bool *mask)
{
BMIter iter;
BMFace *f;
int i = 0;
BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
BM_elem_flag_set(f, BM_ELEM_SELECT, mask[i]);
}
}
void BM_tag_vertices(BMesh *bm, const bool *mask)
{
BMIter iter;
BMVert *v;
int i = 0;
BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
BM_elem_flag_set(v, BM_ELEM_TAG, mask[i]);
}
}
/**
* Use to temporary tag bmesh edge data based on an array of bool.
*/
void BM_tag_edges(BMesh *bm, const bool *mask)
{
BMIter iter;
BMEdge *e;
int i = 0;
BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
BM_elem_flag_set(e, BM_ELEM_TAG, mask[i]);
}
}
/**
* Use to temporary tag bmesh face data based on an array of bool.
*/
void BM_tag_faces(BMesh *bm, const bool *mask)
{
BMIter iter;
BMFace *f;
int i = 0;
BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
BM_elem_flag_set(f, BM_ELEM_TAG, mask[i]);
}
}
void BM_get_tagged_faces(BMesh *bm, bool *selection)
{
BMIter iter;
BMFace *f;
int i = 0;
BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
selection[i] = BM_elem_flag_test(f, BM_ELEM_TAG);
}
}
void BM_tag_new_faces(BMesh *bm, BMOperator *b_mesh_operator)
{
BMOIter iter;
BMFace *f;
BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
BMO_ITER (f, &iter, b_mesh_operator->slots_out, "faces.out", BM_FACE) {
BM_elem_flag_enable(f, BM_ELEM_TAG);
}
}
void BM_get_selected_faces(BMesh *bm, bool *selection)
{
BMIter iter;
BMFace *f;
int i = 0;
BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
selection[i] = BM_elem_flag_test(f, BM_ELEM_SELECT);
}
}
void BM_get_selected_edges(BMesh *bm, bool *selection)
{
BMIter iter;
BMEdge *e;
int i = 0;
BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
selection[i] = BM_elem_flag_test(e, BM_ELEM_SELECT);
}
}
void BM_get_selected_vertices(BMesh *bm, bool *selection)
{
BMIter iter;
BMVert *v;
int i = 0;
BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
selection[i] = BM_elem_flag_test(v, BM_ELEM_SELECT);
}
}
/** \} */

View File

@@ -134,16 +134,3 @@ void BM_mesh_vert_coords_apply(BMesh *bm, const float (*vert_coords)[3]);
void BM_mesh_vert_coords_apply_with_mat4(BMesh *bm,
const float (*vert_coords)[3],
const float mat[4][4]);
void BM_select_vertices(BMesh *bm, const bool *mask);
void BM_select_edges(BMesh *bm, const bool *mask);
void BM_select_faces(BMesh *bm, const bool *mask);
void BM_tag_vertices(BMesh *bm, const bool *mask);
void BM_tag_edges(BMesh *bm, const bool *mask);
void BM_tag_faces(BMesh *bm, const bool *mask);
void BM_get_tagged_faces(BMesh *bm, bool *selection);
void BM_get_selected_faces(BMesh *bm, bool *selection);
void BM_get_selected_edges(BMesh *bm, bool *selection);
void BM_get_selected_vertices(BMesh *bm, bool *selection);
void BM_tag_new_faces(BMesh *bm, BMOperator *b_mesh_operator);

View File

@@ -1898,9 +1898,6 @@ static BMOpDefine bmo_inset_individual_def = {
{{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
{"thickness", BMO_OP_SLOT_FLT}, /* thickness */
{"depth", BMO_OP_SLOT_FLT}, /* depth */
{"thickness_array", BMO_OP_SLOT_PTR}, /* thickness */
{"depth_array", BMO_OP_SLOT_PTR}, /* depth */
{"use_attributes", BMO_OP_SLOT_BOOL}, /* Use spans for thickness and depth */
{"use_even_offset", BMO_OP_SLOT_BOOL}, /* scale the offset to give more even thickness */
{"use_interpolate", BMO_OP_SLOT_BOOL}, /* blend face data across the inset */
{"use_relative_offset", BMO_OP_SLOT_BOOL}, /* scale the offset by surrounding geometry */
@@ -1932,9 +1929,6 @@ static BMOpDefine bmo_inset_region_def = {
{"use_edge_rail", BMO_OP_SLOT_BOOL}, /* inset the region along existing edges */
{"thickness", BMO_OP_SLOT_FLT}, /* thickness */
{"depth", BMO_OP_SLOT_FLT}, /* depth */
{"thickness_array", BMO_OP_SLOT_PTR}, /* thickness */
{"depth_array", BMO_OP_SLOT_PTR}, /* depth */
{"use_attributes", BMO_OP_SLOT_BOOL}, /* Use spans for thickness and depth */
{"use_outset", BMO_OP_SLOT_BOOL}, /* outset rather than inset */
{{'\0'}},
},
@@ -1946,6 +1940,7 @@ static BMOpDefine bmo_inset_region_def = {
(BMO_OPTYPE_FLAG_NORMALS_CALC |
BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
* Edge-loop Offset.
*

View File

@@ -471,7 +471,6 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundary_map.out", 0); e;
e = BMO_iter_step(&siter)) {
BMVert *f_verts[4];
#ifdef USE_EDGE_REGION_FLAGS
BMEdge *f_edges[4];
#endif

View File

@@ -419,9 +419,6 @@ void bmo_inset_individual_exec(BMesh *bm, BMOperator *op)
BMOIter oiter;
MemArena *interp_arena = NULL;
const bool use_attributes = BMO_slot_bool_get(op->slots_in, "use_attributes");
const float *thickness_array = BMO_slot_ptr_get(op->slots_in, "thickness_array");
const float *depth_array = BMO_slot_ptr_get(op->slots_in, "depth_array");
const float thickness = BMO_slot_float_get(op->slots_in, "thickness");
const float depth = BMO_slot_float_get(op->slots_in, "depth");
const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
@@ -436,37 +433,19 @@ void bmo_inset_individual_exec(BMesh *bm, BMOperator *op)
if (use_interpolate) {
interp_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
}
int i = 0;
if (use_attributes) {
BMO_ITER_INDEX (f, &oiter, op->slots_in, "faces", BM_FACE, i) {
bmo_face_inset_individual(bm,
f,
interp_arena,
thickness_array[i],
depth_array[i],
use_even_offset,
use_relative_offset,
use_interpolate);
if (use_interpolate) {
BLI_memarena_clear(interp_arena);
}
}
}
else {
BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
bmo_face_inset_individual(bm,
f,
interp_arena,
thickness,
depth,
use_even_offset,
use_relative_offset,
use_interpolate);
BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
bmo_face_inset_individual(bm,
f,
interp_arena,
thickness,
depth,
use_even_offset,
use_relative_offset,
use_interpolate);
if (use_interpolate) {
BLI_memarena_clear(interp_arena);
}
if (use_interpolate) {
BLI_memarena_clear(interp_arena);
}
}
@@ -698,16 +677,12 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
const bool use_outset = BMO_slot_bool_get(op->slots_in, "use_outset");
const bool use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary") &&
(use_outset == false);
const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
const bool use_even_boundary = use_even_offset; /* could make own option */
const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
const bool use_edge_rail = BMO_slot_bool_get(op->slots_in, "use_edge_rail");
const bool use_interpolate = BMO_slot_bool_get(op->slots_in, "use_interpolate");
const float thickness = BMO_slot_float_get(op->slots_in, "thickness");
const bool use_attributes = BMO_slot_bool_get(op->slots_in, "use_attributes");
const float *thickness_array = BMO_slot_ptr_get(op->slots_in, "thickness_array");
// const float *depth_array = BMO_slot_ptr_get(op->slots_in, "depth_array");
const float depth = BMO_slot_float_get(op->slots_in, "depth");
#ifdef USE_LOOP_CUSTOMDATA_MERGE
const bool has_math_ldata = (use_interpolate && CustomData_has_math(&bm->ldata));
@@ -1121,12 +1096,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
}
/* apply the offset */
if (use_attributes) {
madd_v3_v3fl(v_split->co, tvec, thickness_array[v_split->head.index]);
}
else {
madd_v3_v3fl(v_split->co, tvec, thickness);
}
madd_v3_v3fl(v_split->co, tvec, thickness);
}
/* this saves expensive/slow glue check for common cases */

View File

@@ -328,14 +328,10 @@ 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
@@ -519,8 +515,6 @@ 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

View File

@@ -33,8 +33,6 @@ enum class eExecutionModel {
FullFrame
};
enum class eDimension { X, Y };
/**
* \brief possible data types for sockets
* \ingroup Model
@@ -121,8 +119,6 @@ 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);

View File

@@ -239,12 +239,6 @@ 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
*/

View File

@@ -245,9 +245,7 @@ void MemoryBuffer::copy_from(const MemoryBuffer *src,
void MemoryBuffer::copy_from(const uchar *src, const rcti &area)
{
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);
copy_from(src, area, 0, this->get_num_channels(), this->get_num_channels(), 0);
}
void MemoryBuffer::copy_from(const uchar *src,
@@ -255,18 +253,10 @@ 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,
row_stride,
area.xmin,
area.ymin,
to_channel_offset);
copy_from(
src, area, channel_offset, elem_size, elem_stride, area.xmin, area.ymin, to_channel_offset);
}
void MemoryBuffer::copy_from(const uchar *src,
@@ -274,7 +264,6 @@ 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)
@@ -284,9 +273,10 @@ void MemoryBuffer::copy_from(const uchar *src,
const int width = BLI_rcti_size_x(&area);
const int height = BLI_rcti_size_y(&area);
const uchar *const src_start = src + area.ymin * row_stride + channel_offset;
const int src_row_stride = width * elem_stride;
const uchar *const src_start = src + area.ymin * src_row_stride + channel_offset;
for (int y = 0; y < height; y++) {
const uchar *from_elem = src_start + y * row_stride + area.xmin * elem_stride;
const uchar *from_elem = src_start + y * src_row_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) {
@@ -356,16 +346,7 @@ void MemoryBuffer::copy_from(const ImBuf *src,
else if (src->rect) {
const uchar *uc_buf = (uchar *)src->rect;
const int elem_stride = src->channels;
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);
copy_from(uc_buf, area, channel_offset, elem_size, elem_stride, to_x, to_y, to_channel_offset);
if (ensure_linear_space) {
colorspace_to_scene_linear(this, area, src->rect_colorspace);
}
@@ -424,48 +405,12 @@ 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) {

View File

@@ -191,96 +191,23 @@ class MemoryBuffer {
void read_elem(int x, int y, float *out) const
{
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));
memcpy(out, get_elem(x, y), m_num_channels * sizeof(float));
}
void read_elem_sampled(float x, float y, PixelSampler sampler, float *out) const
{
switch (sampler) {
case PixelSampler::Nearest:
read_elem_checked(x, y, out);
this->read_elem(x, y, out);
break;
case PixelSampler::Bilinear:
case PixelSampler::Bicubic:
/* No bicubic. Current implementation produces fuzzy results. */
read_elem_bilinear(x, y, out);
this->readBilinear(out, x, y);
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.
*/
@@ -476,8 +403,6 @@ 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,
@@ -500,7 +425,6 @@ class MemoryBuffer {
}
}
/* TODO(manzanilla): to be removed with tiled implementation. */
inline void readNoCheck(float *result,
int x,
int y,
@@ -583,14 +507,12 @@ 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);
@@ -660,21 +582,6 @@ 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,

View File

@@ -248,9 +248,7 @@ void NodeGraph::add_proxies_group_inputs(bNode *b_node, bNode *b_node_io)
}
}
void NodeGraph::add_proxies_group_outputs(const CompositorContext &context,
bNode *b_node,
bNode *b_node_io)
void NodeGraph::add_proxies_group_outputs(bNode *b_node, bNode *b_node_io, bool use_buffer)
{
bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
BLI_assert(b_group_tree); /* should have been checked in advance */
@@ -263,8 +261,7 @@ void NodeGraph::add_proxies_group_outputs(const CompositorContext &context,
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 (context.isGroupnodeBufferEnabled() &&
context.get_execution_model() == eExecutionModel::Tiled) {
if (use_buffer) {
SocketBufferNode *buffer = new SocketBufferNode(b_node_io, b_sock_io, b_sock_group);
add_node(buffer, b_group_tree, key, is_active_group);
}
@@ -300,7 +297,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(context, b_node, b_node_io);
add_proxies_group_outputs(b_node, b_node_io, context.isGroupnodeBufferEnabled());
}
}

View File

@@ -107,9 +107,7 @@ class NodeGraph {
bool is_active_group);
void add_proxies_group_inputs(bNode *b_node, bNode *b_node_io);
void add_proxies_group_outputs(const CompositorContext &context,
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(const CompositorContext &context, bNode *b_node, bNodeInstanceKey key);
void add_proxies_reroute(bNodeTree *b_ntree,

View File

@@ -82,12 +82,8 @@ void NodeOperation::determineResolution(unsigned int resolution[2],
input.determineResolution(resolution, preferredResolution);
used_resolution_index = m_resolutionInputSocketIndex;
}
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) {

View File

@@ -287,8 +287,6 @@ 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.
@@ -519,15 +517,6 @@ 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

View File

@@ -124,10 +124,6 @@ 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(

View File

@@ -30,31 +30,20 @@ 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);
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.addLink(sampler->getOutputSocket(), operation->getInputSocket(0));
converter.mapInputSocket(inputSocket, sampler->getInputSocket(0));
converter.mapInputSocket(inputDegreeSocket, operation->getInputSocket(1));
converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
}

View File

@@ -22,7 +22,6 @@
#include "COM_RotateOperation.h"
#include "COM_ScaleOperation.h"
#include "COM_SetSamplerOperation.h"
#include "COM_TransformOperation.h"
#include "COM_TranslateOperation.h"
#include "BKE_tracking.h"
@@ -43,12 +42,18 @@ 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());
@@ -74,67 +79,38 @@ 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);
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.addLink(scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(1));
converter.addLink(scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(2));
converter.addOperation(scaleOperation);
converter.addOperation(translateOperation);
converter.addOperation(rotateOperation);
converter.addOperation(psoperation);
converter.addLink(angleAttribute->getOutputSocket(), rotateOperation->getInputSocket(1));
converter.addLink(scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(1));
converter.addLink(scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(2));
converter.addLink(xAttribute->getOutputSocket(), translateOperation->getInputSocket(1));
converter.addLink(yAttribute->getOutputSocket(), translateOperation->getInputSocket(2));
converter.addLink(angleAttribute->getOutputSocket(), rotateOperation->getInputSocket(1));
converter.mapOutputSocket(getOutputSocket(), psoperation->getOutputSocket());
converter.addLink(xAttribute->getOutputSocket(), translateOperation->getInputSocket(1));
converter.addLink(yAttribute->getOutputSocket(), translateOperation->getInputSocket(2));
if (invert) {
// Translate -> Rotate -> Scale.
converter.mapInputSocket(imageInput, translateOperation->getInputSocket(0));
converter.mapOutputSocket(getOutputSocket(), psoperation->getOutputSocket());
converter.addLink(translateOperation->getOutputSocket(), rotateOperation->getInputSocket(0));
converter.addLink(rotateOperation->getOutputSocket(), scaleOperation->getInputSocket(0));
if (invert) {
// Translate -> Rotate -> Scale.
converter.mapInputSocket(imageInput, translateOperation->getInputSocket(0));
converter.addLink(scaleOperation->getOutputSocket(), psoperation->getInputSocket(0));
}
else {
// Scale -> Rotate -> Translate.
converter.mapInputSocket(imageInput, scaleOperation->getInputSocket(0));
converter.addLink(translateOperation->getOutputSocket(),
rotateOperation->getInputSocket(0));
converter.addLink(rotateOperation->getOutputSocket(), scaleOperation->getInputSocket(0));
converter.addLink(scaleOperation->getOutputSocket(), rotateOperation->getInputSocket(0));
converter.addLink(rotateOperation->getOutputSocket(), translateOperation->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());
}
converter.addLink(translateOperation->getOutputSocket(), psoperation->getInputSocket(0));
}
}

View File

@@ -22,7 +22,6 @@
#include "COM_ScaleOperation.h"
#include "COM_SetSamplerOperation.h"
#include "COM_SetValueOperation.h"
#include "COM_TransformOperation.h"
#include "COM_TranslateOperation.h"
namespace blender::compositor {
@@ -33,7 +32,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);
@@ -41,51 +40,33 @@ void TransformNode::convertToOperations(NodeConverter &converter,
NodeInput *angleInput = this->getInputSocket(3);
NodeInput *scaleInput = this->getInputSocket(4);
switch (context.get_execution_model()) {
case eExecutionModel::Tiled: {
ScaleRelativeOperation *scaleOperation = new ScaleRelativeOperation();
converter.addOperation(scaleOperation);
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());
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;
}
}
converter.mapOutputSocket(getOutputSocket(), translateOperation->getOutputSocket());
}
} // namespace blender::compositor

View File

@@ -17,8 +17,6 @@
*/
#include "COM_BlurBaseOperation.h"
#include "COM_ConstantOperation.h"
#include "BLI_math.h"
#include "MEM_guardedalloc.h"
@@ -38,15 +36,11 @@ 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::init_data()
void BlurBaseOperation::initExecution()
{
if (execution_model_ == eExecutionModel::FullFrame) {
updateSize();
}
this->m_inputProgram = this->getInputSocketReader(0);
this->m_inputSize = this->getInputSocketReader(1);
this->m_data.image_in_width = this->getWidth();
this->m_data.image_in_height = this->getHeight();
if (this->m_data.relative) {
@@ -67,12 +61,6 @@ void BlurBaseOperation::init_data()
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);
}
@@ -177,82 +165,23 @@ 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 || use_variable_size_) {
return;
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;
}
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])
{
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 convertions 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;
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;
}
}

View File

@@ -18,7 +18,7 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
#include "COM_QualityStepHelper.h"
#define MAX_GAUSSTAB_RADIUS 30000
@@ -27,16 +27,10 @@
namespace blender::compositor {
class BlurBaseOperation : public MultiThreadedOperation, public QualityStepHelper {
class BlurBaseOperation : public NodeOperation, 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_type8);
BlurBaseOperation(DataType data_type);
float *make_gausstab(float rad, int size);
#ifdef BLI_HAVE_SSE2
__m128 *convert_gausstab_sse(const float *gausstab, int size);
@@ -55,11 +49,9 @@ class BlurBaseOperation : public MultiThreadedOperation, public QualityStepHelpe
float m_size;
bool m_sizeavailable;
/* Flags for inheriting classes. */
bool use_variable_size_;
bool m_extend_bounds;
public:
virtual void init_data() override;
/**
* Initialize the execution
*/
@@ -83,14 +75,8 @@ class BlurBaseOperation : public MultiThreadedOperation, public QualityStepHelpe
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

View File

@@ -17,8 +17,6 @@
*/
#include "COM_BokehBlurOperation.h"
#include "COM_ConstantOperation.h"
#include "BLI_math.h"
#include "COM_OpenCLDevice.h"
@@ -26,11 +24,6 @@
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);
@@ -51,23 +44,6 @@ 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();
@@ -82,11 +58,18 @@ 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);
}
@@ -242,146 +225,23 @@ void BokehBlurOperation::executeOpenCL(OpenCLDevice *device,
void BokehBlurOperation::updateSize()
{
if (this->m_sizeavailable) {
return;
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;
}
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])
{
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]);
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;
}
}

View File

@@ -18,12 +18,12 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
#include "COM_QualityStepHelper.h"
namespace blender::compositor {
class BokehBlurOperation : public MultiThreadedOperation, public QualityStepHelper {
class BokehBlurOperation : public NodeOperation, public QualityStepHelper {
private:
SocketReader *m_inputProgram;
SocketReader *m_inputBokehProgram;
@@ -31,7 +31,6 @@ class BokehBlurOperation : public MultiThreadedOperation, public QualityStepHelp
void updateSize();
float m_size;
bool m_sizeavailable;
float m_bokehMidX;
float m_bokehMidY;
float m_bokehDimension;
@@ -40,8 +39,6 @@ class BokehBlurOperation : public MultiThreadedOperation, public QualityStepHelp
public:
BokehBlurOperation();
void init_data() override;
void *initializeTileData(rcti *rect) override;
/**
* The inner loop of this operation.
@@ -82,11 +79,6 @@ class BokehBlurOperation : public MultiThreadedOperation, public QualityStepHelp
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

View File

@@ -27,7 +27,6 @@ ChannelMatteOperation::ChannelMatteOperation()
addOutputSocket(DataType::Value);
this->m_inputImageProgram = nullptr;
flags.can_be_constant = true;
}
void ChannelMatteOperation::initExecution()
@@ -122,37 +121,4 @@ 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

View File

@@ -18,7 +18,7 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_MixOperation.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 MultiThreadedOperation {
class ChannelMatteOperation : public NodeOperation {
private:
SocketReader *m_inputImageProgram;
@@ -71,10 +71,6 @@ class ChannelMatteOperation : public MultiThreadedOperation {
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

View File

@@ -29,7 +29,6 @@ ChromaMatteOperation::ChromaMatteOperation()
this->m_inputImageProgram = nullptr;
this->m_inputKeyProgram = nullptr;
flags.can_be_constant = true;
}
void ChromaMatteOperation::initExecution()
@@ -111,58 +110,4 @@ 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

View File

@@ -18,7 +18,7 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_MixOperation.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 MultiThreadedOperation {
class ChromaMatteOperation : public NodeOperation {
private:
NodeChroma *m_settings;
SocketReader *m_inputImageProgram;
@@ -50,10 +50,6 @@ class ChromaMatteOperation : public MultiThreadedOperation {
{
this->m_settings = nodeChroma;
}
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -29,7 +29,6 @@ ColorMatteOperation::ColorMatteOperation()
this->m_inputImageProgram = nullptr;
this->m_inputKeyProgram = nullptr;
flags.can_be_constant = true;
}
void ColorMatteOperation::initExecution()
@@ -83,40 +82,4 @@ 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

View File

@@ -18,7 +18,7 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_MixOperation.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 MultiThreadedOperation {
class ColorMatteOperation : public NodeOperation {
private:
NodeChroma *m_settings;
SocketReader *m_inputImageProgram;
@@ -50,10 +50,6 @@ class ColorMatteOperation : public MultiThreadedOperation {
{
this->m_settings = nodeChroma;
}
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -29,7 +29,6 @@ ColorRampOperation::ColorRampOperation()
this->m_inputProgram = nullptr;
this->m_colorBand = nullptr;
this->flags.can_be_constant = true;
}
void ColorRampOperation::initExecution()
{
@@ -52,13 +51,4 @@ 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

View File

@@ -18,12 +18,12 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
#include "DNA_texture_types.h"
namespace blender::compositor {
class ColorRampOperation : public MultiThreadedOperation {
class ColorRampOperation : public NodeOperation {
private:
/**
* Cached reference to the inputProgram
@@ -53,10 +53,6 @@ class ColorRampOperation : public MultiThreadedOperation {
{
this->m_colorBand = colorBand;
}
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -32,7 +32,6 @@ ColorSpillOperation::ColorSpillOperation()
this->m_inputFacReader = nullptr;
this->m_spillChannel = 1; // GREEN
this->m_spillMethod = 0;
flags.can_be_constant = true;
}
void ColorSpillOperation::initExecution()
@@ -119,36 +118,4 @@ 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

View File

@@ -18,7 +18,7 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.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 MultiThreadedOperation {
class ColorSpillOperation : public NodeOperation {
protected:
NodeColorspill *m_settings;
SocketReader *m_inputImageReader;
@@ -65,10 +65,6 @@ class ColorSpillOperation : public MultiThreadedOperation {
}
float calculateMapValue(float fac, float *input);
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -27,7 +27,6 @@ namespace blender::compositor {
ConvertBaseOperation::ConvertBaseOperation()
{
this->m_inputOperation = nullptr;
this->flags.can_be_constant = true;
}
void ConvertBaseOperation::initExecution()
@@ -40,14 +39,6 @@ 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()
@@ -67,14 +58,6 @@ 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()
@@ -93,14 +76,6 @@ 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()
@@ -119,13 +94,6 @@ 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()
@@ -144,13 +112,6 @@ 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()
@@ -169,13 +130,6 @@ 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()
@@ -193,14 +147,6 @@ 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()
@@ -219,14 +165,6 @@ 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()
@@ -269,18 +207,6 @@ 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()
@@ -327,22 +253,6 @@ 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()
@@ -368,15 +278,6 @@ 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()
@@ -402,15 +303,6 @@ 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()
@@ -430,15 +322,6 @@ 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()
@@ -461,18 +344,6 @@ 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()
@@ -492,13 +363,6 @@ 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()
@@ -518,13 +382,6 @@ 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()
@@ -553,15 +410,6 @@ 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()
@@ -618,16 +466,4 @@ 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

View File

@@ -18,11 +18,11 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
namespace blender::compositor {
class ConvertBaseOperation : public MultiThreadedOperation {
class ConvertBaseOperation : public NodeOperation {
protected:
SocketReader *m_inputOperation;
@@ -31,13 +31,6 @@ class ConvertBaseOperation : public MultiThreadedOperation {
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 {
@@ -45,9 +38,6 @@ 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 {
@@ -55,9 +45,6 @@ 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 {
@@ -65,9 +52,6 @@ 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 {
@@ -75,9 +59,6 @@ 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 {
@@ -85,9 +66,6 @@ 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 {
@@ -95,9 +73,6 @@ 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 {
@@ -105,9 +80,6 @@ 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 {
@@ -122,9 +94,6 @@ 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 {
@@ -139,9 +108,6 @@ 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 {
@@ -149,9 +115,6 @@ 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 {
@@ -159,9 +122,6 @@ 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 {
@@ -169,9 +129,6 @@ 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 {
@@ -179,9 +136,6 @@ 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 {
@@ -189,9 +143,6 @@ 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 {
@@ -199,12 +150,9 @@ 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 MultiThreadedOperation {
class SeparateChannelOperation : public NodeOperation {
private:
SocketReader *m_inputOperation;
int m_channel;
@@ -220,13 +168,9 @@ class SeparateChannelOperation : public MultiThreadedOperation {
{
this->m_channel = channel;
}
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
class CombineChannelsOperation : public MultiThreadedOperation {
class CombineChannelsOperation : public NodeOperation {
private:
SocketReader *m_inputChannel1Operation;
SocketReader *m_inputChannel2Operation;
@@ -239,10 +183,6 @@ class CombineChannelsOperation : public MultiThreadedOperation {
void initExecution() override;
void deinitExecution() override;
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -95,22 +95,6 @@ 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 */
@@ -130,18 +114,6 @@ 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])
{
@@ -164,21 +136,4 @@ 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

View File

@@ -18,11 +18,11 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
namespace blender::compositor {
class CropBaseOperation : public MultiThreadedOperation {
class CropBaseOperation : public NodeOperation {
protected:
SocketReader *m_inputOperation;
NodeTwoXYs *m_settings;
@@ -53,10 +53,6 @@ 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 {
@@ -69,11 +65,6 @@ 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

View File

@@ -71,34 +71,4 @@ 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

View File

@@ -18,11 +18,11 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
namespace blender::compositor {
class CryptomatteOperation : public MultiThreadedOperation {
class CryptomatteOperation : public NodeOperation {
private:
Vector<float> m_objectIndex;
@@ -35,10 +35,6 @@ class CryptomatteOperation : public MultiThreadedOperation {
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

View File

@@ -29,7 +29,6 @@ DifferenceMatteOperation::DifferenceMatteOperation()
this->m_inputImage1Program = nullptr;
this->m_inputImage2Program = nullptr;
flags.can_be_constant = true;
}
void DifferenceMatteOperation::initExecution()
@@ -87,44 +86,4 @@ 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

View File

@@ -18,7 +18,7 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_MixOperation.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 MultiThreadedOperation {
class DifferenceMatteOperation : public NodeOperation {
private:
NodeChroma *m_settings;
SocketReader *m_inputImage1Program;
@@ -50,10 +50,6 @@ class DifferenceMatteOperation : public MultiThreadedOperation {
{
this->m_settings = nodeChroma;
}
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -32,30 +32,20 @@ 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);
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_inputVectorProgram = this->getInputSocketReader(1);
this->m_inputScaleXProgram = this->getInputSocketReader(2);
this->m_inputScaleYProgram = this->getInputSocketReader(3);
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],
@@ -79,8 +69,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 = input_vector_width_;
float height = input_vector_height_;
float width = m_inputVectorProgram->getWidth();
float height = m_inputVectorProgram->getHeight();
if (x < 0.0f || x >= width || y < 0.0f || y >= height) {
r_u = 0.0f;
r_v = 0.0f;
@@ -88,7 +78,7 @@ bool DisplaceOperation::read_displacement(
}
float col[4];
vector_read_fn_(x, y, col);
m_inputVectorProgram->readSampled(col, x, y, PixelSampler::Bilinear);
r_u = origin[0] - col[0] * xscale;
r_v = origin[1] - col[1] * yscale;
return true;
@@ -100,9 +90,9 @@ void DisplaceOperation::pixelTransform(const float xy[2], float r_uv[2], float r
float uv[2]; /* temporary variables for derivative estimation */
int num;
scale_x_read_fn_(xy[0], xy[1], col);
m_inputScaleXProgram->readSampled(col, xy[0], xy[1], PixelSampler::Nearest);
float xs = col[0];
scale_y_read_fn_(xy[0], xy[1], col);
m_inputScaleYProgram->readSampled(col, xy[0], xy[1], PixelSampler::Nearest);
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 */
@@ -156,9 +146,9 @@ void DisplaceOperation::pixelTransform(const float xy[2], float r_uv[2], float r
void DisplaceOperation::deinitExecution()
{
this->m_inputColorProgram = nullptr;
vector_read_fn_ = nullptr;
scale_x_read_fn_ = nullptr;
scale_y_read_fn_ = nullptr;
this->m_inputVectorProgram = nullptr;
this->m_inputScaleXProgram = nullptr;
this->m_inputScaleYProgram = nullptr;
}
bool DisplaceOperation::determineDependingAreaOfInterest(rcti *input,
@@ -205,61 +195,4 @@ 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

View File

@@ -18,27 +18,23 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
namespace blender::compositor {
class DisplaceOperation : public MultiThreadedOperation {
class DisplaceOperation : public NodeOperation {
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();
@@ -66,14 +62,6 @@ class DisplaceOperation : public MultiThreadedOperation {
*/
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);

View File

@@ -132,56 +132,4 @@ 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

View File

@@ -18,11 +18,11 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
namespace blender::compositor {
class DisplaceSimpleOperation : public MultiThreadedOperation {
class DisplaceSimpleOperation : public NodeOperation {
private:
/**
* Cached reference to the inputProgram
@@ -59,11 +59,6 @@ class DisplaceSimpleOperation : public MultiThreadedOperation {
* 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

View File

@@ -29,7 +29,6 @@ DistanceRGBMatteOperation::DistanceRGBMatteOperation()
this->m_inputImageProgram = nullptr;
this->m_inputKeyProgram = nullptr;
flags.can_be_constant = true;
}
void DistanceRGBMatteOperation::initExecution()
@@ -44,7 +43,7 @@ void DistanceRGBMatteOperation::deinitExecution()
this->m_inputKeyProgram = nullptr;
}
float DistanceRGBMatteOperation::calculateDistance(const float key[4], const float image[4])
float DistanceRGBMatteOperation::calculateDistance(float key[4], float image[4])
{
return len_v3v3(key, image);
}
@@ -94,43 +93,4 @@ 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

View File

@@ -18,7 +18,7 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_MixOperation.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 MultiThreadedOperation {
class DistanceRGBMatteOperation : public NodeOperation {
protected:
NodeChroma *m_settings;
SocketReader *m_inputImageProgram;
SocketReader *m_inputKeyProgram;
virtual float calculateDistance(const float key[4], const float image[4]);
virtual float calculateDistance(float key[4], float image[4]);
public:
/**
@@ -52,10 +52,6 @@ class DistanceRGBMatteOperation : public MultiThreadedOperation {
{
this->m_settings = nodeChroma;
}
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -21,7 +21,7 @@
namespace blender::compositor {
float DistanceYCCMatteOperation::calculateDistance(const float key[4], const float image[4])
float DistanceYCCMatteOperation::calculateDistance(float key[4], float image[4])
{
/* only measure the second 2 values */
return len_v2v2(key + 1, image + 1);

View File

@@ -29,7 +29,7 @@ namespace blender::compositor {
*/
class DistanceYCCMatteOperation : public DistanceRGBMatteOperation {
protected:
float calculateDistance(const float key[4], const float image[4]) override;
float calculateDistance(float key[4], float image[4]) override;
};
} // namespace blender::compositor

View File

@@ -62,13 +62,6 @@ 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();
@@ -124,7 +117,6 @@ 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();
@@ -265,64 +257,6 @@ 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);
@@ -407,44 +341,4 @@ 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

View File

@@ -38,19 +38,8 @@ 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 {
@@ -59,7 +48,7 @@ enum {
FAST_GAUSS_OVERLAY_MAX = 1,
};
class FastGaussianBlurValueOperation : public MultiThreadedOperation {
class FastGaussianBlurValueOperation : public NodeOperation {
private:
float m_sigma;
MemoryBuffer *m_iirgaus;
@@ -91,14 +80,6 @@ class FastGaussianBlurValueOperation : public MultiThreadedOperation {
{
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

View File

@@ -75,42 +75,4 @@ 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

View File

@@ -18,11 +18,11 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
namespace blender::compositor {
class FlipOperation : public MultiThreadedOperation {
class FlipOperation : public NodeOperation {
private:
SocketReader *m_inputOperation;
bool m_flipX;
@@ -45,11 +45,6 @@ class FlipOperation : public MultiThreadedOperation {
{
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

View File

@@ -26,7 +26,6 @@ GammaCorrectOperation::GammaCorrectOperation()
this->addInputSocket(DataType::Color);
this->addOutputSocket(DataType::Color);
this->m_inputProgram = nullptr;
flags.can_be_constant = true;
}
void GammaCorrectOperation::initExecution()
{
@@ -59,34 +58,6 @@ 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;
@@ -97,7 +68,6 @@ GammaUncorrectOperation::GammaUncorrectOperation()
this->addInputSocket(DataType::Color);
this->addOutputSocket(DataType::Color);
this->m_inputProgram = nullptr;
flags.can_be_constant = true;
}
void GammaUncorrectOperation::initExecution()
{
@@ -130,33 +100,6 @@ 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;

View File

@@ -18,11 +18,11 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
namespace blender::compositor {
class GammaCorrectOperation : public MultiThreadedOperation {
class GammaCorrectOperation : public NodeOperation {
private:
/**
* Cached reference to the inputProgram
@@ -46,13 +46,9 @@ class GammaCorrectOperation : public MultiThreadedOperation {
* Deinitialize the execution
*/
void deinitExecution() override;
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
class GammaUncorrectOperation : public MultiThreadedOperation {
class GammaUncorrectOperation : public NodeOperation {
private:
/**
* Cached reference to the inputProgram
@@ -76,10 +72,6 @@ class GammaUncorrectOperation : public MultiThreadedOperation {
* Deinitialize the execution
*/
void deinitExecution() override;
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -1,168 +0,0 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* 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

View File

@@ -1,62 +0,0 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* 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

View File

@@ -24,9 +24,11 @@
namespace blender::compositor {
GaussianAlphaXBlurOperation::GaussianAlphaXBlurOperation()
: GaussianAlphaBlurBaseOperation(eDimension::X)
GaussianAlphaXBlurOperation::GaussianAlphaXBlurOperation() : BlurBaseOperation(DataType::Value)
{
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*/)
@@ -42,11 +44,12 @@ void *GaussianAlphaXBlurOperation::initializeTileData(rcti * /*rect*/)
void GaussianAlphaXBlurOperation::initExecution()
{
GaussianAlphaBlurBaseOperation::initExecution();
/* Until we support size input - comment this. */
// BlurBaseOperation::initExecution();
initMutex();
if (this->m_sizeavailable && execution_model_ == eExecutionModel::Tiled) {
if (this->m_sizeavailable) {
float rad = max_ff(m_size * m_data.sizex, 0.0f);
m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS);
@@ -141,7 +144,7 @@ void GaussianAlphaXBlurOperation::executePixel(float output[4], int x, int y, vo
void GaussianAlphaXBlurOperation::deinitExecution()
{
GaussianAlphaBlurBaseOperation::deinitExecution();
BlurBaseOperation::deinitExecution();
if (this->m_gausstab) {
MEM_freeN(this->m_gausstab);

View File

@@ -18,13 +18,18 @@
#pragma once
#include "COM_GaussianAlphaBlurBaseOperation.h"
#include "COM_BlurBaseOperation.h"
#include "COM_NodeOperation.h"
namespace blender::compositor {
/* TODO(manzanilla): everything to be removed with tiled implementation except the constructor. */
class GaussianAlphaXBlurOperation : public GaussianAlphaBlurBaseOperation {
class GaussianAlphaXBlurOperation : public BlurBaseOperation {
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:
@@ -49,6 +54,18 @@ class GaussianAlphaXBlurOperation : public GaussianAlphaBlurBaseOperation {
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

View File

@@ -24,9 +24,11 @@
namespace blender::compositor {
GaussianAlphaYBlurOperation::GaussianAlphaYBlurOperation()
: GaussianAlphaBlurBaseOperation(eDimension::Y)
GaussianAlphaYBlurOperation::GaussianAlphaYBlurOperation() : BlurBaseOperation(DataType::Value)
{
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*/)
@@ -40,14 +42,14 @@ void *GaussianAlphaYBlurOperation::initializeTileData(rcti * /*rect*/)
return buffer;
}
/* TODO(manzanilla): to be removed with tiled implementation. */
void GaussianAlphaYBlurOperation::initExecution()
{
GaussianAlphaBlurBaseOperation::initExecution();
/* Until we support size input - comment this. */
// BlurBaseOperation::initExecution();
initMutex();
if (this->m_sizeavailable && execution_model_ == eExecutionModel::Tiled) {
if (this->m_sizeavailable) {
float rad = max_ff(m_size * m_data.sizey, 0.0f);
m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS);
@@ -56,7 +58,6 @@ void GaussianAlphaYBlurOperation::initExecution()
}
}
/* TODO(manzanilla): to be removed with tiled implementation. */
void GaussianAlphaYBlurOperation::updateGauss()
{
if (this->m_gausstab == nullptr) {
@@ -142,7 +143,7 @@ void GaussianAlphaYBlurOperation::executePixel(float output[4], int x, int y, vo
void GaussianAlphaYBlurOperation::deinitExecution()
{
GaussianAlphaBlurBaseOperation::deinitExecution();
BlurBaseOperation::deinitExecution();
if (this->m_gausstab) {
MEM_freeN(this->m_gausstab);

Some files were not shown because too many files have changed in this diff Show More