Changeset View
Changeset View
Standalone View
Standalone View
source/blender/makesrna/intern/rna_define.c
| Context not available. | |||||
| * \ingroup RNA | * \ingroup RNA | ||||
| */ | */ | ||||
| #include <assert.h> | |||||
| #include <ctype.h> | #include <ctype.h> | ||||
| #include <float.h> | #include <float.h> | ||||
| #include <limits.h> | #include <limits.h> | ||||
| #include <stdalign.h> | |||||
| #include <stddef.h> | #include <stddef.h> | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| Context not available. | |||||
| #include "rna_internal.h" | #include "rna_internal.h" | ||||
| #include "CLG_log.h" | #include "CLG_log.h" | ||||
| #include "RNA_types.h" | |||||
| static CLG_LogRef LOG = {"rna.define"}; | static CLG_LogRef LOG = {"rna.define"}; | ||||
| Context not available. | |||||
| func->description = description; | func->description = description; | ||||
| } | } | ||||
| int rna_parameter_size(PropertyRNA *parm) | struct ParameterInfo rna_parameter_info(PropertyRNA *parm) | ||||
| { | { | ||||
| struct ParameterInfo result; | |||||
| /* Define these as macros so all return values honor postcondition. */ | |||||
| #define LOCAL__POPULATE_PARAM_INFO( \ | |||||
| _struct_name, _size, _count, _alignment, _c_type_name, _orig_type_name) \ | |||||
| _struct_name.size = _size; \ | |||||
| _struct_name.count = _count; \ | |||||
| _struct_name.alignment = _alignment; \ | |||||
| _struct_name.c_type_name = _c_type_name; \ | |||||
| _struct_name.orig_type_name = _orig_type_name /* Expect ';' on usage */ | |||||
| #define LOCAL__RETURN_PARAM_INFO_GENERIC( \ | |||||
| _type, _after_size, _count, _c_type_name, _orig_type_name) \ | |||||
| STATIC_ASSERT(alignof(_type) <= RNA_PARAMETER_INFO__ALIGNMENT__MAXIMUM, \ | |||||
| "None of the types in RNA Parameters should require extended alignment.", \ | |||||
| 17); \ | |||||
| STATIC_ASSERT( \ | |||||
| (_c_type_name || _orig_type_name), "At least one type name needs to be populated.", 19); \ | |||||
| STATIC_ASSERT((alignof(_type) <= sizeof(_type)), "Alignment should not exceed size.", 27); \ | |||||
| STATIC_ASSERT(((alignof(_type) & (alignof(_type) - 1)) == 0), \ | |||||
linux_dr: I think `rna_parameter_size()` and `rna_parameter_alignment()` should be one function that… | |||||
Not Done Inline ActionsI don't think we need a rna_parameter_alignment function, we can use power_of_2_max_i(rna_parameter_size(parm)). These parameters are small enough that it doesn't matter if there is some wasted space. brecht: I don't think we need a `rna_parameter_alignment` function, we can use `power_of_2_max_i… | |||||
Not Done Inline ActionsThere are places where the alignment isn't the same as the type size, for instance: sizeof(ParameterDynAlloc) linux_dr: There are places where the alignment isn't the same as the type size, for instance: `sizeof… | |||||
| "Alignment should always be a power of two.", \ | |||||
| 31); \ | |||||
| LOCAL__POPULATE_PARAM_INFO( \ | |||||
| result, sizeof(_type) _after_size, _count, alignof(_type), _c_type_name, _orig_type_name); \ | |||||
| return result /* Expect ';' on usage */ | |||||
| #define LOCAL__RETURN_PARAM_INFO_ANONYMOUS_TYPE(_type) \ | |||||
| LOCAL__RETURN_PARAM_INFO_GENERIC( \ | |||||
| _type, , RNA_PARAMETER_INFO__COUNT__NOT_AN_ARRAY, NULLPTR, #_type) | |||||
| #define LOCAL__RETURN_PARAM_INFO_ALIASED_TYPE(_type, _type_alias) \ | |||||
| STATIC_ASSERT((sizeof(_type) == sizeof(_type_alias)) && \ | |||||
| (alignof(_type) == alignof(_type_alias)), \ | |||||
| #_type " must have the same size and alignment as " #_type_alias, \ | |||||
| 23); \ | |||||
| LOCAL__RETURN_PARAM_INFO_GENERIC( \ | |||||
| _type, , RNA_PARAMETER_INFO__COUNT__NOT_AN_ARRAY, #_type_alias, #_type) | |||||
| #define LOCAL__RETURN_PARAM_INFO_ARRAY_TYPE(_type, _count) \ | |||||
| LOCAL__RETURN_PARAM_INFO_GENERIC(_type, *_count, _count, #_type, NULLPTR) | |||||
| #define LOCAL__RETURN_PARAM_INFO_TYPE(_type) \ | |||||
| LOCAL__RETURN_PARAM_INFO_GENERIC( \ | |||||
| _type, , RNA_PARAMETER_INFO__COUNT__NOT_AN_ARRAY, #_type, NULLPTR) | |||||
| if (!parm) { | |||||
| /* default to no alignment */ | |||||
| LOCAL__POPULATE_PARAM_INFO(result, 0, RNA_PARAMETER_INFO__COUNT__NOT_AN_ARRAY, 1, NULL, NULL); | |||||
| return result; | |||||
| } | |||||
| PropertyType ptype = parm->type; | PropertyType ptype = parm->type; | ||||
| int len = parm->totarraylength; | int len = parm->totarraylength; | ||||
| /* XXX in other parts is mentioned that strings can be dynamic as well */ | /* XXX in other parts is mentioned that strings can be dynamic as well */ | ||||
| if (parm->flag & PROP_DYNAMIC) { | if (parm->flag & PROP_DYNAMIC) { | ||||
| return sizeof(ParameterDynAlloc); | LOCAL__RETURN_PARAM_INFO_ANONYMOUS_TYPE(ParameterDynAlloc); | ||||
| } | } | ||||
| if (len > 0) { | if (len > 0) { | ||||
| switch (ptype) { | switch (ptype) { | ||||
| case PROP_BOOLEAN: | case PROP_BOOLEAN: | ||||
| return sizeof(bool) * len; | LOCAL__RETURN_PARAM_INFO_ARRAY_TYPE(bool, len); | ||||
| case PROP_INT: | case PROP_INT: | ||||
| return sizeof(int) * len; | LOCAL__RETURN_PARAM_INFO_ARRAY_TYPE(int, len); | ||||
| case PROP_FLOAT: | case PROP_FLOAT: | ||||
| return sizeof(float) * len; | LOCAL__RETURN_PARAM_INFO_ARRAY_TYPE(float, len); | ||||
| default: | default: | ||||
| break; | break; | ||||
| } | } | ||||
| Context not available. | |||||
| else { | else { | ||||
| switch (ptype) { | switch (ptype) { | ||||
| case PROP_BOOLEAN: | case PROP_BOOLEAN: | ||||
| return sizeof(bool); | LOCAL__RETURN_PARAM_INFO_TYPE(bool); | ||||
| case PROP_INT: | case PROP_INT: | ||||
| case PROP_ENUM: | case PROP_ENUM: | ||||
| return sizeof(int); | LOCAL__RETURN_PARAM_INFO_TYPE(int); | ||||
| case PROP_FLOAT: | case PROP_FLOAT: | ||||
| return sizeof(float); | LOCAL__RETURN_PARAM_INFO_TYPE(float); | ||||
| case PROP_STRING: | case PROP_STRING: | ||||
| /* return values don't store a pointer to the original */ | /* return values don't store a pointer to the original */ | ||||
| if (parm->flag & PROP_THICK_WRAP) { | if (parm->flag & PROP_THICK_WRAP) { | ||||
Done Inline ActionsThis seems like it overlaps some with ParameterIterator which probably needs some changes to handle size and padding as distinct. linux_dr: This seems like it overlaps some with `ParameterIterator` which probably needs some changes to… | |||||
Done Inline ActionsI think this concept of "aligned parameter size" is confusing. We should be thinking in terms of aligning the offset, not the size. I think a function like this would be better: int rna_parameter_align_offset(const int offset, PropertyRNA *parm)
{
const int alignment = power_of_2_max_i(rna_parameter_size(parm));
return (offset + alignment - 1) & ~(alignment - 1);
}brecht: I think this concept of "aligned parameter size" is confusing. We should be thinking in terms… | |||||
Done Inline ActionsI think I adopted the intent of this approach, even if I haven't done it the same way. linux_dr: I think I adopted the intent of this approach, even if I haven't done it the same way. | |||||
| StringPropertyRNA *sparm = (StringPropertyRNA *)parm; | StringPropertyRNA *sparm = (StringPropertyRNA *)parm; | ||||
| return sizeof(char) * sparm->maxlength; | LOCAL__RETURN_PARAM_INFO_ARRAY_TYPE(char, sparm->maxlength); | ||||
| } | } | ||||
| else { | else { | ||||
| return sizeof(char *); | LOCAL__RETURN_PARAM_INFO_TYPE(char *); | ||||
| } | } | ||||
| case PROP_POINTER: { | case PROP_POINTER: { | ||||
| #ifdef RNA_RUNTIME | |||||
| if (parm->flag_parameter & PARM_RNAPTR) { | |||||
| if (parm->flag & PROP_THICK_WRAP) { | |||||
| return sizeof(PointerRNA); | |||||
| } | |||||
| else { | |||||
| return sizeof(PointerRNA *); | |||||
| } | |||||
| } | |||||
| else { | |||||
| return sizeof(void *); | |||||
| } | |||||
| #else | |||||
| if (parm->flag_parameter & PARM_RNAPTR) { | if (parm->flag_parameter & PARM_RNAPTR) { | ||||
| if (parm->flag & PROP_THICK_WRAP) { | if (parm->flag & PROP_THICK_WRAP) { | ||||
| return sizeof(PointerRNA); | LOCAL__RETURN_PARAM_INFO_ANONYMOUS_TYPE(PointerRNA); | ||||
| } | } | ||||
| return sizeof(PointerRNA *); | LOCAL__RETURN_PARAM_INFO_ALIASED_TYPE(PointerRNA *, void *); | ||||
| } | } | ||||
| return sizeof(void *); | LOCAL__RETURN_PARAM_INFO_TYPE(void *); | ||||
| #endif | |||||
| } | } | ||||
| case PROP_COLLECTION: | case PROP_COLLECTION: | ||||
| return sizeof(ListBase); | LOCAL__RETURN_PARAM_INFO_ANONYMOUS_TYPE(ListBase); | ||||
| } | } | ||||
| } | } | ||||
| LOCAL__RETURN_PARAM_INFO_TYPE(void *); | |||||
| #undef LOCAL__POPULATE_PARAM_INFO | |||||
| #undef LOCAL__RETURN_PARAM_INFO_GENERIC | |||||
| #undef LOCAL__RETURN_PARAM_INFO_ANONYMOUS_TYPE | |||||
| #undef LOCAL__RETURN_PARAM_INFO_ALIASED_TYPE | |||||
| #undef LOCAL__RETURN_PARAM_INFO_ARRAY_TYPE | |||||
| #undef LOCAL__RETURN_PARAM_INFO_TYPE | |||||
| } | |||||
| return sizeof(void *); | size_t rna_compute_parameter_padding(size_t size_so_far, | ||||
| size_t this_parm_size, | |||||
| size_t next_parm_alignment) | |||||
| { | |||||
| /* Alignment should always be a power of two. */ | |||||
| assert((next_parm_alignment & (next_parm_alignment - 1)) == 0); | |||||
| size_t mis_alignment = (size_so_far + this_parm_size) % next_parm_alignment; | |||||
| size_t padding = (mis_alignment == 0) ? 0 : (next_parm_alignment - mis_alignment); | |||||
| /* Padding should not exceed alignment. */ | |||||
| assert(padding < next_parm_alignment); | |||||
| /* New, padded offset should be properly aligned. */ | |||||
| assert(((size_so_far + this_parm_size + padding) & (next_parm_alignment - 1)) == 0); | |||||
| return padding; | |||||
| } | } | ||||
| /* Dynamic Enums */ | /* Dynamic Enums */ | ||||
| Context not available. | |||||
I think rna_parameter_size() and rna_parameter_alignment() should be one function that populates a struct instead.