Merge branch 'blender-v5.0-release'

This commit is contained in:
Aras Pranckevicius
2025-10-09 19:38:02 +03:00
16 changed files with 116 additions and 122 deletions

View File

@@ -414,17 +414,17 @@ Build with external audaspace library installed on the system \
(only enable if you know what you're doing!)"
OFF
)
option(WITH_RUBBERBAND "\
Build with Rubber Band for audio time-stretching and pitch-scaling (used by Audaspace)"
ON
)
mark_as_advanced(WITH_AUDASPACE)
mark_as_advanced(WITH_SYSTEM_AUDASPACE)
if(WITH_AUDASPACE AND NOT WITH_SYSTEM_AUDASPACE)
option(WITH_RUBBERBAND "\
Build with Rubber Band for audio time-stretching and pitch-scaling (used by Audaspace)"
ON
)
endif()
mark_as_advanced(WITH_RUBBERBAND)
set_and_warn_dependency(WITH_AUDASPACE WITH_SYSTEM_AUDASPACE OFF)
set_and_warn_dependency(WITH_AUDASPACE WITH_RUBBERBAND OFF)
set_and_warn_incompatible(WITH_SYSTEM_AUDASPACE WITH_RUBBERBAND OFF)
if(WITH_GHOST_X11)
option(WITH_X11_XINPUT "Enable X11 Xinput (tablet support and unicode input)" ON)
@@ -2840,7 +2840,6 @@ if(FIRST_RUN)
info_cfg_option(WITH_POTRACE)
info_cfg_option(WITH_PUGIXML)
info_cfg_option(WITH_QUADRIFLOW)
info_cfg_option(WITH_RUBBERBAND)
info_cfg_option(WITH_TBB)
info_cfg_option(WITH_USD)
info_cfg_option(WITH_MATERIALX)
@@ -2879,6 +2878,7 @@ if(FIRST_RUN)
info_cfg_text("Audio:")
info_cfg_option(WITH_AUDASPACE)
info_cfg_option(WITH_RUBBERBAND)
info_cfg_option(WITH_CODEC_FFMPEG)
info_cfg_option(WITH_CODEC_SNDFILE)
info_cfg_option(WITH_COREAUDIO)

View File

@@ -615,6 +615,9 @@ static bool buttons_context_path(
/* No pinned root, use scene as initial root. */
else if (mainb != BCONTEXT_TOOL) {
if (ELEM(mainb, BCONTEXT_STRIP, BCONTEXT_STRIP_MODIFIER)) {
if (!sequencer_scene) {
return false;
}
path->ptr[0] = RNA_id_pointer_create(&sequencer_scene->id);
}
else {

View File

@@ -23,9 +23,7 @@ struct ID;
namespace blender::seq {
struct SeqRenderState;
struct StripScreenQuad;
struct RenderData;
struct ModifierApplyContext;
struct StripModifierTypeInfo {
/**
@@ -56,12 +54,7 @@ struct StripModifierTypeInfo {
void (*copy_data)(StripModifierData *smd, StripModifierData *target);
/* Apply modifier on an image buffer. */
void (*apply)(const RenderData *render_data,
const Strip *strip,
const float transform[3][3],
StripModifierData *smd,
ImBuf *ibuf,
ImBuf *mask);
void (*apply)(ModifierApplyContext &context, StripModifierData *smd, ImBuf *mask);
/** Register the panel types for the modifier's UI. */
void (*panel_register)(ARegionType *region_type);

View File

@@ -52,11 +52,8 @@ struct BrightContrastApplyOp {
}
};
static void brightcontrast_apply(const RenderData * /*render_data*/,
const Strip * /*strip*/,
const float transform[3][3],
static void brightcontrast_apply(ModifierApplyContext &context,
StripModifierData *smd,
ImBuf *ibuf,
ImBuf *mask)
{
const BrightContrastModifierData *bcmd = (BrightContrastModifierData *)smd;
@@ -81,7 +78,7 @@ static void brightcontrast_apply(const RenderData * /*render_data*/,
op.add = op.mul * brightness + delta;
}
apply_modifier_op(op, ibuf, mask, float3x3(transform));
apply_modifier_op(op, context.image, mask, context.transform);
}
static void brightcontrast_panel_draw(const bContext *C, Panel *panel)

View File

@@ -254,18 +254,13 @@ static void colorBalance_init_data(StripModifierData *smd)
}
}
static void colorBalance_apply(const RenderData * /*render_data*/,
const Strip * /*strip*/,
const float transform[3][3],
StripModifierData *smd,
ImBuf *ibuf,
ImBuf *mask)
static void colorBalance_apply(ModifierApplyContext &context, StripModifierData *smd, ImBuf *mask)
{
const ColorBalanceModifierData *cbmd = (const ColorBalanceModifierData *)smd;
ColorBalanceApplyOp op;
op.init(*cbmd, ibuf->byte_buffer.data != nullptr);
apply_modifier_op(op, ibuf, mask, float3x3(transform));
op.init(*cbmd, context.image->byte_buffer.data != nullptr);
apply_modifier_op(op, context.image, mask, context.transform);
}
static void colorBalance_panel_draw(const bContext *C, Panel *panel)

View File

@@ -44,13 +44,14 @@ class CompositorContext : public compositor::Context {
ImBuf *image_buffer_;
ImBuf *mask_buffer_;
float3x3 xform_;
float2 result_translation_ = float2(0, 0);
public:
CompositorContext(const RenderData &render_data,
const SequencerCompositorModifierData *modifier_data,
ImBuf *image_buffer,
ImBuf *mask_buffer,
const Strip *strip)
const Strip &strip)
: compositor::Context(),
render_data_(render_data),
modifier_data_(modifier_data),
@@ -61,10 +62,15 @@ class CompositorContext : public compositor::Context {
if (mask_buffer) {
/* Note: do not use passed transform matrix since compositor coordinate
* space is not from the image corner, but rather centered on the image. */
xform_ = math::invert(image_transform_matrix_get(render_data.scene, strip));
xform_ = math::invert(image_transform_matrix_get(render_data.scene, &strip));
}
}
float2 get_result_translation() const
{
return result_translation_;
}
const Scene &get_scene() const override
{
return *render_data_.scene;
@@ -101,6 +107,7 @@ class CompositorContext : public compositor::Context {
compositor::Result get_output(compositor::Domain domain) override
{
result_translation_ = domain.transformation.location();
compositor::Result result = this->create_result(compositor::ResultType::Color);
if (domain.size.x != image_buffer_->x || domain.size.y != image_buffer_->y) {
/* Output size is different (e.g. image is blurred with expanded bounds);
@@ -119,18 +126,8 @@ class CompositorContext : public compositor::Context {
bool /*is_data*/,
compositor::ResultPrecision /*precision*/) override
{
compositor::Result result = this->create_result(compositor::ResultType::Color);
if (domain.size.x != image_buffer_->x || domain.size.y != image_buffer_->y) {
/* Output size is different (e.g. image is blurred with expanded bounds);
* need to allocate appropriately sized buffer. */
IMB_free_all_data(image_buffer_);
image_buffer_->x = domain.size.x;
image_buffer_->y = domain.size.y;
IMB_alloc_float_pixels(image_buffer_, 4, false);
}
result.wrap_external(image_buffer_->float_buffer.data,
int2(image_buffer_->x, image_buffer_->y));
return result;
/* Within compositor modifier, output and viewer output function the same. */
return get_output(domain);
}
compositor::Result get_input(StringRef name) override
@@ -199,11 +196,8 @@ static bool ensure_linear_float_buffer(ImBuf *ibuf)
return false;
}
static void compositor_modifier_apply(const RenderData *render_data,
const Strip *strip,
const float /*transform*/[3][3],
static void compositor_modifier_apply(ModifierApplyContext &context,
StripModifierData *strip_modifier_data,
ImBuf *image_buffer,
ImBuf *mask)
{
const SequencerCompositorModifierData *modifier_data =
@@ -218,13 +212,16 @@ static void compositor_modifier_apply(const RenderData *render_data,
ensure_linear_float_buffer(linear_mask);
}
const bool was_float_linear = ensure_linear_float_buffer(image_buffer);
const bool was_byte = image_buffer->float_buffer.data == nullptr;
const bool was_float_linear = ensure_linear_float_buffer(context.image);
const bool was_byte = context.image->float_buffer.data == nullptr;
CompositorContext context(*render_data, modifier_data, image_buffer, linear_mask, strip);
compositor::Evaluator evaluator(context);
CompositorContext com_context(
context.render_data, modifier_data, context.image, linear_mask, context.strip);
compositor::Evaluator evaluator(com_context);
evaluator.evaluate();
context.result_translation += com_context.get_result_translation();
if (mask != linear_mask) {
IMB_freeImBuf(linear_mask);
}
@@ -234,11 +231,11 @@ static void compositor_modifier_apply(const RenderData *render_data,
}
if (was_byte) {
IMB_byte_from_float(image_buffer);
IMB_free_float_pixels(image_buffer);
IMB_byte_from_float(context.image);
IMB_free_float_pixels(context.image);
}
else {
seq_imbuf_to_sequencer_space(render_data->scene, image_buffer, true);
seq_imbuf_to_sequencer_space(context.render_data.scene, context.image, true);
}
}

View File

@@ -69,12 +69,7 @@ struct CurvesApplyOp {
}
};
static void curves_apply(const RenderData * /*render_data*/,
const Strip * /*strip*/,
const float transform[3][3],
StripModifierData *smd,
ImBuf *ibuf,
ImBuf *mask)
static void curves_apply(ModifierApplyContext &context, StripModifierData *smd, ImBuf *mask)
{
CurvesModifierData *cmd = (CurvesModifierData *)smd;
@@ -88,7 +83,7 @@ static void curves_apply(const RenderData * /*render_data*/,
CurvesApplyOp op;
op.curve_mapping = &cmd->curve_mapping;
apply_modifier_op(op, ibuf, mask, float3x3(transform));
apply_modifier_op(op, context.image, mask, context.transform);
BKE_curvemapping_premultiply(&cmd->curve_mapping, true);
}

View File

@@ -104,12 +104,7 @@ struct HueCorrectApplyOp {
}
};
static void hue_correct_apply(const RenderData * /*render_data*/,
const Strip * /*strip*/,
const float transform[3][3],
StripModifierData *smd,
ImBuf *ibuf,
ImBuf *mask)
static void hue_correct_apply(ModifierApplyContext &context, StripModifierData *smd, ImBuf *mask)
{
HueCorrectModifierData *hcmd = (HueCorrectModifierData *)smd;
@@ -117,7 +112,7 @@ static void hue_correct_apply(const RenderData * /*render_data*/,
HueCorrectApplyOp op;
op.curve_mapping = &hcmd->curve_mapping;
apply_modifier_op(op, ibuf, mask, float3x3(transform));
apply_modifier_op(op, context.image, mask, context.transform);
}
static void hue_correct_panel_draw(const bContext *C, Panel *panel)

View File

@@ -53,11 +53,8 @@ struct MaskApplyOp {
}
};
static void maskmodifier_apply(const RenderData * /* render_data */,
const Strip * /*strip*/,
const float transform[3][3],
static void maskmodifier_apply(ModifierApplyContext &context,
StripModifierData * /*smd*/,
ImBuf *ibuf,
ImBuf *mask)
{
if (mask == nullptr || (mask->byte_buffer.data == nullptr && mask->float_buffer.data == nullptr))
@@ -66,10 +63,10 @@ static void maskmodifier_apply(const RenderData * /* render_data */,
}
MaskApplyOp op;
apply_modifier_op(op, ibuf, mask, float3x3(transform));
apply_modifier_op(op, context.image, mask, context.transform);
/* Image has gained transparency. */
ibuf->planes = R_IMF_PLANES_RGBA;
context.image->planes = R_IMF_PLANES_RGBA;
}
static void maskmodifier_panel_draw(const bContext *C, Panel *panel)

View File

@@ -281,19 +281,16 @@ static AreaLuminance tonemap_calc_input_luminance(const ImBuf *ibuf)
return lum;
}
static void tonemapmodifier_apply(const RenderData * /*render_data*/,
const Strip * /*strip*/,
const float transform[3][3],
static void tonemapmodifier_apply(ModifierApplyContext &context,
StripModifierData *smd,
ImBuf *ibuf,
ImBuf *mask)
{
const SequencerTonemapModifierData *tmmd = (const SequencerTonemapModifierData *)smd;
TonemapApplyOp op;
op.type = eModTonemapType(tmmd->type);
op.ibuf = ibuf;
op.lum = tonemap_calc_input_luminance(ibuf);
op.ibuf = context.image;
op.lum = tonemap_calc_input_luminance(context.image);
if (op.lum.pixel_count == 0) {
return; /* Strip is zero size or off-screen. */
}
@@ -311,7 +308,7 @@ static void tonemapmodifier_apply(const RenderData * /*render_data*/,
op.data.al = (al == 0.0f) ? 0.0f : (tmmd->key / al);
op.data.igm = (tmmd->gamma == 0.0f) ? 1.0f : (1.0f / tmmd->gamma);
apply_modifier_op(op, ibuf, mask, float3x3(transform));
apply_modifier_op(op, context.image, mask, context.transform);
}
static void tonemapmodifier_panel_draw(const bContext *C, Panel *panel)

View File

@@ -62,12 +62,7 @@ struct WhiteBalanceApplyOp {
}
};
static void whiteBalance_apply(const RenderData * /*render_data*/,
const Strip * /*strip*/,
const float transform[3][3],
StripModifierData *smd,
ImBuf *ibuf,
ImBuf *mask)
static void whiteBalance_apply(ModifierApplyContext &context, StripModifierData *smd, ImBuf *mask)
{
const WhiteBalanceModifierData *data = (const WhiteBalanceModifierData *)smd;
@@ -75,7 +70,7 @@ static void whiteBalance_apply(const RenderData * /*render_data*/,
op.multiplier[0] = (data->white_value[0] != 0.0f) ? 1.0f / data->white_value[0] : FLT_MAX;
op.multiplier[1] = (data->white_value[1] != 0.0f) ? 1.0f / data->white_value[1] : FLT_MAX;
op.multiplier[2] = (data->white_value[2] != 0.0f) ? 1.0f / data->white_value[2] : FLT_MAX;
apply_modifier_op(op, ibuf, mask, float3x3(transform));
apply_modifier_op(op, context.image, mask, context.transform);
}
static void whiteBalance_panel_draw(const bContext *C, Panel *panel)

View File

@@ -297,8 +297,8 @@ void store_pixel_raw(float4 pix, float *ptr)
/**
* \a timeline_frame is offset by \a fra_offset only in case we are using a real mask.
*/
static ImBuf *modifier_render_mask_input(const RenderData *context,
SeqRenderState *state,
static ImBuf *modifier_render_mask_input(const RenderData &context,
SeqRenderState &state,
int mask_input_type,
Strip *mask_strip,
Mask *mask_id,
@@ -309,7 +309,7 @@ static ImBuf *modifier_render_mask_input(const RenderData *context,
if (mask_input_type == STRIP_MASK_INPUT_STRIP) {
if (mask_strip) {
mask_input = seq_render_strip(context, state, mask_strip, timeline_frame);
mask_input = seq_render_strip(&context, &state, mask_strip, timeline_frame);
}
}
else if (mask_input_type == STRIP_MASK_INPUT_ID) {
@@ -317,9 +317,9 @@ static ImBuf *modifier_render_mask_input(const RenderData *context,
* fine, but if it is a byte image then we also just take that without
* extra memory allocations or conversions. All modifiers are expected
* to handle mask being either type. */
mask_input = seq_render_mask(context->depsgraph,
context->rectx,
context->recty,
mask_input = seq_render_mask(context.depsgraph,
context.rectx,
context.recty,
mask_id,
timeline_frame - fra_offset,
false);
@@ -464,18 +464,17 @@ static bool skip_modifier(Scene *scene, const StripModifierData *smd, int timeli
return strip_has_ended_skip || missing_data_skip;
}
void modifier_apply_stack(const RenderData *context,
SeqRenderState *state,
const Strip *strip,
const float3x3 &transform,
ImBuf *ibuf,
int timeline_frame)
void modifier_apply_stack(ModifierApplyContext &context, int timeline_frame)
{
if (strip->modifiers.first && (strip->flag & SEQ_USE_LINEAR_MODIFIERS)) {
render_imbuf_from_sequencer_space(context->scene, ibuf);
if (context.strip.modifiers.first == nullptr) {
return;
}
LISTBASE_FOREACH (StripModifierData *, smd, &strip->modifiers) {
if (context.strip.flag & SEQ_USE_LINEAR_MODIFIERS) {
render_imbuf_from_sequencer_space(context.render_data.scene, context.image);
}
LISTBASE_FOREACH (StripModifierData *, smd, &context.strip.modifiers) {
const StripModifierTypeInfo *smti = modifier_type_info_get(smd->type);
/* could happen if modifier is being removed or not exists in current version of blender */
@@ -488,31 +487,31 @@ void modifier_apply_stack(const RenderData *context,
continue;
}
if (smti->apply && !skip_modifier(context->scene, smd, timeline_frame)) {
if (smti->apply && !skip_modifier(context.render_data.scene, smd, timeline_frame)) {
int frame_offset;
if (smd->mask_time == STRIP_MASK_TIME_RELATIVE) {
frame_offset = strip->start;
frame_offset = context.strip.start;
}
else /* if (smd->mask_time == STRIP_MASK_TIME_ABSOLUTE) */ {
frame_offset = smd->mask_id ? ((Mask *)smd->mask_id)->sfra : 0;
}
ImBuf *mask = modifier_render_mask_input(context,
state,
ImBuf *mask = modifier_render_mask_input(context.render_data,
context.render_state,
smd->mask_input_type,
smd->mask_strip,
smd->mask_id,
timeline_frame,
frame_offset);
smti->apply(context, strip, transform.ptr(), smd, ibuf, mask);
smti->apply(context, smd, mask);
if (mask) {
IMB_freeImBuf(mask);
}
}
}
if (strip->modifiers.first && (strip->flag & SEQ_USE_LINEAR_MODIFIERS)) {
seq_imbuf_to_sequencer_space(context->scene, ibuf, false);
if (context.strip.flag & SEQ_USE_LINEAR_MODIFIERS) {
seq_imbuf_to_sequencer_space(context.render_data.scene, context.image, false);
}
}

View File

@@ -30,15 +30,36 @@ namespace blender::seq {
struct RenderData;
struct SeqRenderState;
/* `transform` is transformation from strip image local pixel coordinates
* to the full render area pixel coordinates. This is used to sample
* modifier masks (since masks are in full render area space). */
void modifier_apply_stack(const RenderData *context,
SeqRenderState *state,
const Strip *strip,
const float3x3 &transform,
ImBuf *ibuf,
int timeline_frame);
struct ModifierApplyContext {
ModifierApplyContext(const RenderData &render_data,
SeqRenderState &render_state,
const Strip &strip,
const float3x3 &transform,
ImBuf *image)
: render_data(render_data),
render_state(render_state),
strip(strip),
transform(transform),
image(image)
{
}
const RenderData &render_data;
SeqRenderState &render_state;
const Strip &strip;
/* Transformation from strip image local pixel coordinates to the
* full render area pixel coordinates.This is used to sample
* modifier masks (since masks are in full render area space). */
const float3x3 transform;
ImBuf *const image;
/* How much the resulting image should be translated, in pixels.
* Compositor modifier can have some nodes that translate the output
* image. */
float2 result_translation = float2(0, 0);
};
void modifier_apply_stack(ModifierApplyContext &context, int timeline_frame);
bool modifier_persistent_uids_are_valid(const Strip &strip);

View File

@@ -666,6 +666,7 @@ static ImBuf *input_preprocess(const RenderData *context,
const bool do_scale_to_render_size = seq_need_scale_to_render_size(strip, is_proxy_image);
const float image_scale_factor = do_scale_to_render_size ? preview_scale_factor : 1.0f;
float2 modifier_translation = float2(0, 0);
if (strip->modifiers.first) {
ibuf = IMB_makeSingleUser(ibuf);
float3x3 matrix = calc_strip_transform_matrix(scene,
@@ -676,11 +677,13 @@ static ImBuf *input_preprocess(const RenderData *context,
context->recty,
image_scale_factor,
preview_scale_factor);
modifier_apply_stack(context, state, strip, matrix, ibuf, timeline_frame);
ModifierApplyContext mod_context(*context, *state, *strip, matrix, ibuf);
modifier_apply_stack(mod_context, timeline_frame);
modifier_translation = mod_context.result_translation;
}
if (sequencer_use_crop(strip) || sequencer_use_transform(strip) || context->rectx != ibuf->x ||
context->recty != ibuf->y)
context->recty != ibuf->y || modifier_translation != float2(0, 0))
{
const int x = context->rectx;
const int y = context->recty;
@@ -696,6 +699,7 @@ static ImBuf *input_preprocess(const RenderData *context,
context->recty,
image_scale_factor,
preview_scale_factor);
matrix *= math::from_location<float3x3>(modifier_translation);
matrix = math::invert(matrix);
sequencer_preprocess_transform_crop(ibuf,
transformed_ibuf,

Binary file not shown.

Binary file not shown.