Object Model & Memory Layout.
Blend2D object model is a foundation of all Blend2D objects. It was designed only for Blend2D and it's not supposed to be used as a foundation of other libraries. The object model provides runtime reflection, small size optimization (SSO), and good performance. In general, it focuses on optimizing memory footprint by taking advantage of SSO storage, however, this makes the implementation more complex compared to a traditional non-SSO model.
Blend2D object model used by BLObjectCore consists of 16 bytes that have the following layout:
char char_data[16];
uint8_t u8_data[16];
uint16_t u16_data[8];
uint32_t u32_data[4];
uint64_t u64_data[2];
float f32_data[4];
double f64_data[2];
struct {
uint32_t u32_data_overlap[2];
uint32_t impl_payload;
};
};
Which allows to have either static or dynamic instances:
- Static instance stores payload in object detail,
impl
is not a valid pointer and cannot be accessed.
- Dynamic instance has a valid
impl
pointer having a content, which type depends on BLObjectType.
The layout was designed to provide the following properties:
- Reflection - any Blend2D object can be casted to a generic BLObjectCore or BLVarCore and inspected at runtime.
- Small string, container, and value optimization saves memory allocations (BLString, BLArray, BLBitSet).
- No atomic reference counting operations for small containers and default constructed objects without data.
- It's possible to store a floating point RGBA color (BLRgba) as f32_data, which uses all 16 bytes. The last value of the color, which describes alpha channel, cannot have a sign bit set (cannot be negative and cannot be NaN with sign).
32-bit Floating Point is represented the following way (32 bits):
[--------+--------+--------+--------]
[31....24|23....16|15.....8|7......0] (32-bit integer layout)
[--------+--------+--------+--------]
[Seeeeeee|eQ......|........|........] (32-bit floating point)
[--------+--------+--------+--------]
Where:
- 'S' - Sign bit
- 'e' - Exponent bits (all bits must be '1' to form NaN).
- 'Q' - Mantissa bit that can be used to describe quiet and signaling NaNs, the value is not standardized (X86 and ARM use '1' for quiet NaN and '0' for signaling NaN).
- '.' - Mantissa bits.
Blend2D uses a sign bit to determine whether the data is BLRgba or object compatible. This design has been chosen, because we don't allow alpha values to be negative. When the sign bit is set it means that it's a type inherited from BLObjectCore. When the sign bit is not set the whole payload represents 128-bit BLRgba color, where alpha is not a negative number. It's designed in a way that 31 bits out of 32 can be used as payload that represents object type, object info flags, and additional type-dependent payload.
Object info value looks like this (also compared with floating point):
[--------+--------+--------+--------]
[31....24|23....16|15.....8|7......0] Info Layout:
[--------+--------+--------+--------]
[Seeeeeee|eQ......|........|........] - 32-bit floating-point data view (\ref
BLRgba case,
'S' bit (sign bit) set to zero).
[MDRttttt|ttaaaaaa|bbbbcccc|pppppppp] -
object info fields view 1 (\ref
BLObjectCore case,
'M' bit set to one).
[MDRttttt|ttaaaaaa|qqqqqqqq|pppppppp] -
object info fields view 2 (\ref
BLObjectCore case,
'M' bit set to one).
[--------+--------+--------+--------]
[--------+--------+--------+--------]
[31....24|23....16|15.....8|7......0] SSO Layout:
[--------+--------+--------+--------]
[1DRttttt|ttaaaaaa|bbbbcccc|pppppppp] -
BLArray -
'aaaaaa' is size,
'bbbb' is capacity).
[1DRttttt|00aaaaaa|bbbbcccc|pppppppp] -
BLString -
'aaaaaa' is size ^ kSSOCapacity, the rest can be used as characters).
[1DRttttt|ttaaaaaa|bbbbcccc|pppppppp] -
BLBitSet -
'R' is used to distinguish between SSO Range and SSO Dense representation.
[1DRttttt|ttaaaaaa|bbbbcccc|pppppppp] -
BLFontFeatureSettings -
'aaaaaa' is size,
'bbbbcccc|pppppppp' is used to store feature data.
[1DRttttt|ttaaaaaa|bbbbcccc|pppppppp] -
BLFontVariationSettings -
'aaaaaa' is size,
'bbbbcccc|pppppppp' is used to store variation ids.
[--------+--------+--------+--------]
Where:
- 'M' - Object marker, forms a valid BLObject signature when set to '1'.
- 'D' - Dynamic flag - when set the Impl pointer is valid. When 'D' == '0' it means the object is in SSO mode, when 'D' == '1' it means it's in Dynamic mode.
- 'R' - Ref counted flag - when set together with 'M' and 'D' it makes it guaranteed that teh Impl pointer is ref-counted. Otherwise if 'D' is not set, 'R' flag can be used by the SSO representation to store another bit.
- 't' - Object type bits - 'ttttttt' forms a 7-bit type having possible values from 0 to 127, see BLObjectType.
- 'a' - Object 'a' payload (6 bits).
- 'b' - Object 'b' payload (4 bits).
- 'c' - Object 'c' payload (4 bits).
- 'p' - Object 'p' payload (8 bits).
- 'q' - Object 'q' payload (8 bits aliased with 'bbbbcccc' fields).
Common meaning of payload fields:
- 'a' - If the object is a container (BLArray, BLString) 'a' field always represents its size in SSO mode. If the object is a BLBitSet, 'a' field is combined with other fields to store a start word index or to mark a BitSet, which contains an SSO range instead of dense words.
- 'b' - If the object is a container (BLArray) 'b' field always represents its capacity in SSO mode except BLString, which doesn't store capacity in 'b' field and uses it as an additional SSO content byte on little endian targets (SSO capacity is then either 14 on little endian targets or 11 on big endian targets). This is possible as BL_OBJECT_TYPE_STRING must be identifier that has 2 low bits zero, which then makes it possible to use 'ttIRaaaa' as null terminator when the string length is 14 characters.
- 'c' - Used freely.
- 'p' - Used freely.
- 'q' - Used freely.
If the 'D' flag is '1' the following payload fields are used by the allocator (and thus cannot be used by the object):
- 'a' - Allocation adjustment (4 bits) - At the moment the field describes how many bytes (shifted) to subtract from Impl to get the real pointer returned by Impl allocator. Object deallocation relies on this offset.
Not all object support all defined flags, here is a little overview:
+--------------------------+---+---+---+---+---+---+---+
| Type | M |SSO|Dyn|Ext|Imm|Vrt|Ref|
+--------------------------+---+---+---+---+---+---+---|
|
BLVar {Null} | 1 | 1 | 0 | 0 | 0 | 0 | 0 |
'M' - Object marker (always used except wrapping
BLRgba).
|
BLVar {Bool} | 1 | 1 | 0 | 0 | 0 | 0 | 0 |
'SSO' - Small size optimization support (no Impl).
|
BLVar {Int64} | 1 | 1 | 0 | 0 | 0 | 0 | 0 |
'Dyn' - Dynamic Impl support.
|
BLVar {UInt64} | 1 | 1 | 0 | 0 | 0 | 0 | 0 |
'Ext' - External data support.
|
BLVar {Double} | 1 | 1 | 0 | 0 | 0 | 0 | 0 |
'Imm' - Immutable data support.
|
BLVar {
BLRgba} | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
'Vrt' - Object provides
virtual function table.
|
BLVar {
BLRgba32} | 1 | 1 | 0 | 0 | 0 | 0 | 0 |
'Ref' - Reference counting support.
|
BLArray<T> | 1 | x | x | x | x | 0 | x |
'0' - Never used
|
BLBitArray | 1 | x | x | 0 | 0 | 0 | x |
'1' - Always used
|
BLBitSet | 1 | x | x | 0 | 0 | 0 | x |
'x' - Variable (either used or not)
|
BLString | 1 | x | x | 0 | 0 | 0 | x |
|
BLPath | 1 | 0 | 1 | 0 | x | 0 | x |
|
BLImage | 1 | 0 | 1 | x | x | 0 | x |
|
BLFont | 1 | 0 | 1 | 0 | 0 | 0 | x |
+--------------------------+---+---+---+---+---+---+---+
#define
BL_CLASS_INHERITS(BASE) : public BASE
#define
BL_DEFINE_OBJECT_DETAIL#define
BL_DEFINE_VIRT_BASE
BLResult blObjectAllocImplAligned(
BLObjectCore* self,
uint32_t objectInfo,
size_t implSize,
size_t implAlignment)
BLResult blObjectGetPropertyBool(
const BLUnknown* self,
const char* name,
size_t nameSize,
bool* valueOut)
BLResult blObjectGetPropertyInt32(
const BLUnknown* self,
const char* name,
size_t nameSize,
int32_t* valueOut)
BLResult blObjectGetPropertyInt64(
const BLUnknown* self,
const char* name,
size_t nameSize,
int64_t* valueOut)
BLResult blObjectGetPropertyUInt32(
const BLUnknown* self,
const char* name,
size_t nameSize,
uint32_t* valueOut)
BLResult blObjectGetPropertyUInt64(
const BLUnknown* self,
const char* name,
size_t nameSize,
uint64_t* valueOut)
BLResult blObjectGetPropertyDouble(
const BLUnknown* self,
const char* name,
size_t nameSize,
double* valueOut)
BLResult blObjectSetPropertyBool(
BLUnknown* self,
const char* name,
size_t nameSize,
bool value)
BLResult blObjectSetPropertyInt32(
BLUnknown* self,
const char* name,
size_t nameSize,
int32_t value)
BLResult blObjectSetPropertyInt64(
BLUnknown* self,
const char* name,
size_t nameSize,
int64_t value)
BLResult blObjectSetPropertyUInt32(
BLUnknown* self,
const char* name,
size_t nameSize,
uint32_t value)
BLResult blObjectSetPropertyUInt64(
BLUnknown* self,
const char* name,
size_t nameSize,
uint64_t value)
BLResult blObjectSetPropertyDouble(
BLUnknown* self,
const char* name,
size_t nameSize,
double value)
#define BL_DEFINE_OBJECT_DCAST(DERIVED_TYPE)◆
Value: \
template<typename T = DERIVED_TYPE> \
BL_NODISCARD \
BL_INLINE_NODEBUG T& dcast() noexcept { return static_cast<T&>(*this); } \
\
template<typename T = DERIVED_TYPE> \
BL_NODISCARD \
BL_INLINE_NODEBUG const T& dcast() const noexcept { return static_cast<const T&>(*this); } \
#define BL_DEFINE_OBJECT_PROPERTY_API◆
Value: \
return blObjectGetProperty(this, name, SIZE_MAX, &valueOut); \
} \
\ \
return blObjectGetProperty(this, name.data, name.size, &valueOut); \
} \
\ \
return blObjectSetProperty(this, name, SIZE_MAX, &value); \
} \
\ \
return blObjectSetProperty(this, name.data, name.size, &value); \
}
typedef void(* BLDestroyExternalDataFunc)(void* impl, void* externalData, void* userData)◆
A function callback that is called when an Impl that holds external data is going to be destroyed. It's often used as a notification that a data passed to a certain Impl is no longer in use by Blend2D.
Defines a mask of each field of the object info.
- Note
- This is part of the official documentation, however, users should not use these enumerations in any context.
Constant | Description |
---|
BL_OBJECT_INFO_P_MASK | Mask describing 'P' payload (8 bits).
|
BL_OBJECT_INFO_Q_MASK | Mask describing 'Q' payload (8 bits aliased with 'bbbbcccc' bits).
|
BL_OBJECT_INFO_C_MASK | Mask describing 'C' payload (4 bits).
|
BL_OBJECT_INFO_B_MASK | Mask describing 'B' payload (4 bits).
|
BL_OBJECT_INFO_A_MASK | Mask describing 'A' payload (6 bits).
|
BL_OBJECT_INFO_FIELDS_MASK | Mask of all payload fields combined, except 'M', 'T', type identification, and 'R' (RefCounted marker).
|
BL_OBJECT_INFO_TYPE_MASK | Mask describing object type (8 bits), see BLObjectType.
|
BL_OBJECT_INFO_R_FLAG | Flag describing a ref-counted object (if set together with 'D' flag)
- Note
- This flag is free for use by SSO, it has no meaning when 'D' flag is not set).
|
BL_OBJECT_INFO_D_FLAG | Flag describing a dynamic object - if this flag is not set, it means the object is in SSO mode.
|
BL_OBJECT_INFO_M_FLAG | Flag describing a valid object compatible with BLObjectCore interface (otherwise it's most likely BLRgba).
|
BL_OBJECT_INFO_MD_FLAGS | A combination of BL_OBJECT_INFO_M_FLAG and BL_OBJECT_INFO_D_FLAG flags.
|
BL_OBJECT_INFO_MDR_FLAGS | A combination of BL_OBJECT_INFO_M_FLAG , BL_OBJECT_INFO_D_FLAG , BL_OBJECT_INFO_R_FLAG flags.
|
Object type identifier.
Constant | Description |
---|
BL_OBJECT_TYPE_RGBA | Object represents a RGBA value stored as four 32-bit floating point components (can be used as Style).
|
BL_OBJECT_TYPE_RGBA32 | Object represents a RGBA32 value stored as 32-bit integer in 0xAARRGGBB form.
|
BL_OBJECT_TYPE_RGBA64 | Object represents a RGBA64 value stored as 64-bit integer in 0xAAAARRRRGGGGBBBB form.
|
BL_OBJECT_TYPE_NULL | Object is Null (can be used as style).
|
BL_OBJECT_TYPE_PATTERN | Object is BLPattern (can be used as style).
|
BL_OBJECT_TYPE_GRADIENT | Object is BLGradient (can be used as style).
|
BL_OBJECT_TYPE_IMAGE | Object is BLImage .
|
BL_OBJECT_TYPE_PATH | Object is BLPath .
|
BL_OBJECT_TYPE_FONT | Object is BLFont .
|
BL_OBJECT_TYPE_FONT_FEATURE_SETTINGS | Object is BLFontFeatureSettings .
|
BL_OBJECT_TYPE_FONT_VARIATION_SETTINGS | Object is BLFontVariationSettings .
|
BL_OBJECT_TYPE_BIT_ARRAY | Object is BLBitArray .
|
BL_OBJECT_TYPE_BIT_SET | Object is BLBitSet .
|
BL_OBJECT_TYPE_BOOL | Object represents a boolean value.
|
BL_OBJECT_TYPE_INT64 | Object represents a 64-bit signed integer value.
|
BL_OBJECT_TYPE_UINT64 | Object represents a 64-bit unsigned integer value.
|
BL_OBJECT_TYPE_DOUBLE | Object represents a 64-bit floating point value.
|
BL_OBJECT_TYPE_STRING | Object is BLString .
|
BL_OBJECT_TYPE_ARRAY_OBJECT | Object is BLArray<T> where T is a BLObject compatible type.
|
BL_OBJECT_TYPE_ARRAY_INT8 | Object is BLArray<T> where T matches 8-bit signed integral type.
|
BL_OBJECT_TYPE_ARRAY_UINT8 | Object is BLArray<T> where T matches 8-bit unsigned integral type.
|
BL_OBJECT_TYPE_ARRAY_INT16 | Object is BLArray<T> where T matches 16-bit signed integral type.
|
BL_OBJECT_TYPE_ARRAY_UINT16 | Object is BLArray<T> where T matches 16-bit unsigned integral type.
|
BL_OBJECT_TYPE_ARRAY_INT32 | Object is BLArray<T> where T matches 32-bit signed integral type.
|
BL_OBJECT_TYPE_ARRAY_UINT32 | Object is BLArray<T> where T matches 32-bit unsigned integral type.
|
BL_OBJECT_TYPE_ARRAY_INT64 | Object is BLArray<T> where T matches 64-bit signed integral type.
|
BL_OBJECT_TYPE_ARRAY_UINT64 | Object is BLArray<T> where T matches 64-bit unsigned integral type.
|
BL_OBJECT_TYPE_ARRAY_FLOAT32 | Object is BLArray<T> where T matches 32-bit floating point type.
|
BL_OBJECT_TYPE_ARRAY_FLOAT64 | Object is BLArray<T> where T matches 64-bit floating point type.
|
BL_OBJECT_TYPE_ARRAY_STRUCT_1 | Object is BLArray<T> where T is a struct of size 1.
|
BL_OBJECT_TYPE_ARRAY_STRUCT_2 | Object is BLArray<T> where T is a struct of size 2.
|
BL_OBJECT_TYPE_ARRAY_STRUCT_3 | Object is BLArray<T> where T is a struct of size 3.
|
BL_OBJECT_TYPE_ARRAY_STRUCT_4 | Object is BLArray<T> where T is a struct of size 4.
|
BL_OBJECT_TYPE_ARRAY_STRUCT_6 | Object is BLArray<T> where T is a struct of size 6.
|
BL_OBJECT_TYPE_ARRAY_STRUCT_8 | Object is BLArray<T> where T is a struct of size 8.
|
BL_OBJECT_TYPE_ARRAY_STRUCT_10 | Object is BLArray<T> where T is a struct of size 10.
|
BL_OBJECT_TYPE_ARRAY_STRUCT_12 | Object is BLArray<T> where T is a struct of size 12.
|
BL_OBJECT_TYPE_ARRAY_STRUCT_16 | Object is BLArray<T> where T is a struct of size 16.
|
BL_OBJECT_TYPE_ARRAY_STRUCT_20 | Object is BLArray<T> where T is a struct of size 20.
|
BL_OBJECT_TYPE_ARRAY_STRUCT_24 | Object is BLArray<T> where T is a struct of size 24.
|
BL_OBJECT_TYPE_ARRAY_STRUCT_32 | Object is BLArray<T> where T is a struct of size 32.
|
BL_OBJECT_TYPE_CONTEXT | Object is BLContext .
|
BL_OBJECT_TYPE_IMAGE_CODEC | Object is BLImageCodec .
|
BL_OBJECT_TYPE_IMAGE_DECODER | Object is BLImageDecoder .
|
BL_OBJECT_TYPE_IMAGE_ENCODER | Object is BLImageEncoder .
|
BL_OBJECT_TYPE_FONT_FACE | Object is BLFontFace .
|
BL_OBJECT_TYPE_FONT_DATA | Object is BLFontData .
|
BL_OBJECT_TYPE_FONT_MANAGER | Object is BLFontManager .
|
BL_OBJECT_TYPE_MIN_ARRAY | Minimum object type of an array object.
|
BL_OBJECT_TYPE_MAX_ARRAY | Maximum object type of an array object.
|
BL_OBJECT_TYPE_MIN_STYLE | Minimum object type identifier that can be used as a style.
|
BL_OBJECT_TYPE_MAX_STYLE | Maximum object type identifier that can be used as a style.
|
BL_OBJECT_TYPE_MIN_VIRTUAL | Minimum object type of an object with virtual function table.
|
BL_OBJECT_TYPE_MAX_VIRTUAL | Maximum object type of an object with virtual function table.
|
BL_OBJECT_TYPE_MAX_VALUE | Maximum possible value of an object type, including identifiers reserved for the future.
|