Blender V4.5
render.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 * SPDX-FileCopyrightText: 2003-2024 Blender Authors
3 * SPDX-FileCopyrightText: 2005-2006 Peter Schlaile <peter [at] schlaile [dot] de>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later */
6
10
11#include <ctime>
12
13#include "MEM_guardedalloc.h"
14
15#include "DNA_defaults.h"
16#include "DNA_mask_types.h"
17#include "DNA_scene_types.h"
18#include "DNA_sequence_types.h"
19#include "DNA_space_types.h"
20
21#include "BLI_linklist.h"
22#include "BLI_listbase.h"
23#include "BLI_math_geom.h"
24#include "BLI_math_matrix.hh"
25#include "BLI_path_utils.hh"
26#include "BLI_rect.h"
27#include "BLI_task.hh"
28
29#include "BKE_anim_data.hh"
30#include "BKE_animsys.h"
31#include "BKE_fcurve.hh"
32#include "BKE_global.hh"
33#include "BKE_image.hh"
34#include "BKE_layer.hh"
35#include "BKE_lib_id.hh"
36#include "BKE_library.hh"
37#include "BKE_main.hh"
38#include "BKE_mask.h"
39#include "BKE_movieclip.h"
40#include "BKE_scene.hh"
41
42#include "DEG_depsgraph.hh"
44
46#include "IMB_imbuf.hh"
47#include "IMB_imbuf_types.hh"
48#include "IMB_metadata.hh"
49
50#include "MOV_read.hh"
51
52#include "RNA_prototypes.hh"
53
54#include "RE_engine.h"
55#include "RE_pipeline.h"
56
57#include "SEQ_channels.hh"
58#include "SEQ_effects.hh"
59#include "SEQ_iterator.hh"
60#include "SEQ_modifier.hh"
61#include "SEQ_offscreen.hh"
62#include "SEQ_proxy.hh"
63#include "SEQ_relations.hh"
64#include "SEQ_render.hh"
65#include "SEQ_sequencer.hh"
66#include "SEQ_time.hh"
67#include "SEQ_transform.hh"
68#include "SEQ_utils.hh"
69
73#include "effects/effects.hh"
74#include "multiview.hh"
75#include "prefetch.hh"
76#include "proxy.hh"
77#include "render.hh"
78#include "utils.hh"
79
80#include <algorithm>
81
82namespace blender::seq {
83
84static ImBuf *seq_render_strip_stack(const RenderData *context,
86 ListBase *channels,
87 ListBase *seqbasep,
88 float timeline_frame,
89 int chanshown);
90
92DrawViewFn view3d_fn = nullptr; /* nullptr in background mode */
93
94/* -------------------------------------------------------------------- */
97
98void seq_imbuf_assign_spaces(const Scene *scene, ImBuf *ibuf)
99{
100#if 0
101 /* Byte buffer is supposed to be in sequencer working space already. */
102 if (ibuf->rect != nullptr) {
104 }
105#endif
106 if (ibuf->float_buffer.data != nullptr) {
108 }
109}
110
111void seq_imbuf_to_sequencer_space(const Scene *scene, ImBuf *ibuf, bool make_float)
112{
113 /* Early output check: if both buffers are nullptr we have nothing to convert. */
114 if (ibuf->float_buffer.data == nullptr && ibuf->byte_buffer.data == nullptr) {
115 return;
116 }
117 /* Get common conversion settings. */
118 const char *to_colorspace = scene->sequencer_colorspace_settings.name;
119 /* Perform actual conversion logic. */
120 if (ibuf->float_buffer.data == nullptr) {
121 /* We are not requested to give float buffer and byte buffer is already
122 * in thee required colorspace. Can skip doing anything here.
123 */
124 const char *from_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
125 if (!make_float && STREQ(from_colorspace, to_colorspace)) {
126 return;
127 }
128
129 IMB_alloc_float_pixels(ibuf, 4, false);
131 ibuf->byte_buffer.data,
132 ibuf->x,
133 ibuf->y,
134 ibuf->channels,
135 from_colorspace,
136 to_colorspace);
137 /* We don't need byte buffer anymore. */
139 }
140 else {
141 const char *from_colorspace = IMB_colormanagement_get_float_colorspace(ibuf);
142 /* Unknown input color space, can't perform conversion. */
143 if (from_colorspace == nullptr || from_colorspace[0] == '\0') {
144 return;
145 }
146 /* We don't want both byte and float buffers around: they'll either run
147 * out of sync or conversion of byte buffer will lose precision in there.
148 */
149 if (ibuf->byte_buffer.data != nullptr) {
151 }
153 ibuf->x,
154 ibuf->y,
155 ibuf->channels,
156 from_colorspace,
157 to_colorspace,
158 true);
159 }
160 seq_imbuf_assign_spaces(scene, ibuf);
161}
162
164{
165 const char *from_colorspace = scene->sequencer_colorspace_settings.name;
166 const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(
168
169 if (!ibuf->float_buffer.data) {
170 return;
171 }
172
173 if (to_colorspace && to_colorspace[0] != '\0') {
175 ibuf->x,
176 ibuf->y,
177 ibuf->channels,
178 from_colorspace,
179 to_colorspace,
180 true);
182 }
183}
184
185void render_pixel_from_sequencer_space_v4(const Scene *scene, float pixel[4])
186{
187 const char *from_colorspace = scene->sequencer_colorspace_settings.name;
188 const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(
190
191 if (to_colorspace && to_colorspace[0] != '\0') {
192 IMB_colormanagement_transform_v4(pixel, from_colorspace, to_colorspace);
193 }
194 else {
195 /* if no color management enables fallback to legacy conversion */
196 srgb_to_linearrgb_v4(pixel, pixel);
197 }
198}
199
201
202/* -------------------------------------------------------------------- */
205
207 Depsgraph *depsgraph,
208 Scene *scene,
209 int rectx,
210 int recty,
211 int preview_render_size,
212 int for_render,
213 RenderData *r_context)
214{
215 r_context->bmain = bmain;
216 r_context->depsgraph = depsgraph;
217 r_context->scene = scene;
218 r_context->rectx = rectx;
219 r_context->recty = recty;
220 r_context->preview_render_size = preview_render_size;
221 r_context->ignore_missing_media = false;
222 r_context->for_render = for_render;
223 r_context->motion_blur_samples = 0;
224 r_context->motion_blur_shutter = 0;
225 r_context->skip_cache = false;
226 r_context->is_proxy_render = false;
227 r_context->view_id = 0;
228 r_context->gpu_offscreen = nullptr;
229 r_context->gpu_viewport = nullptr;
230 r_context->task_id = SEQ_TASK_MAIN_RENDER;
231 r_context->is_prefetch_render = false;
232}
233
234StripElem *render_give_stripelem(const Scene *scene, const Strip *strip, int timeline_frame)
235{
236 StripElem *se = strip->data->stripdata;
237
238 if (strip->type == STRIP_TYPE_IMAGE) {
239 /* only IMAGE strips use the whole array, MOVIE strips use only the first element,
240 * all other strips don't use this...
241 */
242
243 int frame_index = round_fl_to_int(give_frame_index(scene, strip, timeline_frame));
244
245 if (frame_index == -1 || se == nullptr) {
246 return nullptr;
247 }
248
249 se += frame_index + strip->anim_startofs;
250 }
251 return se;
252}
253
255 ListBase *channels,
256 ListBase *seqbase,
257 const int timeline_frame,
258 const int chanshown)
259{
260 VectorSet strips = query_rendered_strips(scene, channels, seqbase, timeline_frame, chanshown);
261 const int strip_count = strips.size();
262
263 if (UNLIKELY(strip_count > MAX_CHANNELS)) {
264 BLI_assert_msg(0, "Too many strips, this shouldn't happen");
265 return {};
266 }
267
268 Vector<Strip *> strips_vec = strips.extract_vector();
269 /* Sort strips by channel. */
270 std::sort(strips_vec.begin(), strips_vec.end(), [](const Strip *a, const Strip *b) {
271 return a->channel < b->channel;
272 });
273 return strips_vec;
274}
275
277{
278 Scene *scene = context->scene;
279 const int x = context->rectx;
280 const int y = context->recty;
281 const float2 offset{x * 0.5f, y * 0.5f};
282
284 const float scale = context->preview_render_size == SEQ_RENDER_SIZE_SCENE ?
285 float(scene->r.size) / 100.0f :
286 rendersize_to_scale_factor(context->preview_render_size);
287 return StripScreenQuad{float2(quad[0] * scale + offset),
288 float2(quad[1] * scale + offset),
289 float2(quad[2] * scale + offset),
290 float2(quad[3] * scale + offset)};
291}
292
293/* Is quad `a` fully contained (i.e. covered by) quad `b`? For that to happen,
294 * all corners of `a` have to be inside `b`. */
296{
297 return isect_point_quad_v2(a.v0, b.v0, b.v1, b.v2, b.v3) &&
298 isect_point_quad_v2(a.v1, b.v0, b.v1, b.v2, b.v3) &&
299 isect_point_quad_v2(a.v2, b.v0, b.v1, b.v2, b.v3) &&
300 isect_point_quad_v2(a.v3, b.v0, b.v1, b.v2, b.v3);
301}
302
303/* Tracking of "known to be opaque" strip quad coordinates, along with their
304 * order index within visible strips during rendering. */
305
310
313
314 /* Determine if the input strip is completely behind opaque strips that are
315 * above it. Current implementation is simple and only checks if strip is
316 * completely covered by any other strip. It does not detect case where
317 * a strip is not covered by a single strip, but is behind of the union
318 * of the strips above. */
319 bool is_occluded(const RenderData *context, const Strip *strip, int order_index) const
320 {
322 if (quad.is_empty()) {
323 /* Strip size is not initialized/valid, we can't know if it is occluded. */
324 return false;
325 }
326 for (const OpaqueQuad &q : opaques) {
327 if (q.order_index > order_index && is_quad_a_inside_b(quad, q.quad)) {
328 return true;
329 }
330 }
331 return false;
332 }
333
334 void add_occluder(const RenderData *context, const Strip *strip, int order_index)
335 {
337 if (!quad.is_empty()) {
338 opaques.append({quad, order_index});
339 }
340 }
341};
342
344
345/* -------------------------------------------------------------------- */
365
366static bool sequencer_use_transform(const Strip *strip)
367{
368 const StripTransform *transform = strip->data->transform;
369
370 if (transform->xofs != 0 || transform->yofs != 0 || transform->scale_x != 1 ||
371 transform->scale_y != 1 || transform->rotation != 0)
372 {
373 return true;
374 }
375
376 return false;
377}
378
379static bool sequencer_use_crop(const Strip *strip)
380{
381 const StripCrop *crop = strip->data->crop;
382 if (crop->left > 0 || crop->right > 0 || crop->top > 0 || crop->bottom > 0) {
383 return true;
384 }
385
386 return false;
387}
388
389static bool seq_input_have_to_preprocess(const RenderData *context,
390 Strip *strip,
391 float /*timeline_frame*/)
392{
393 float mul;
394
395 if (context && context->is_proxy_render) {
396 return false;
397 }
398
399 if ((strip->flag & (SEQ_FILTERY | SEQ_FLIPX | SEQ_FLIPY | SEQ_MAKE_FLOAT)) ||
401 {
402 return true;
403 }
404
405 mul = strip->mul;
406
407 if (strip->blend_mode == SEQ_BLEND_REPLACE) {
408 mul *= strip->blend_opacity / 100.0f;
409 }
410
411 if (mul != 1.0f) {
412 return true;
413 }
414
415 if (strip->sat != 1.0f) {
416 return true;
417 }
418
419 if (strip->modifiers.first) {
420 return true;
421 }
422
423 return false;
424}
425
432static bool seq_need_scale_to_render_size(const Strip *strip, bool is_proxy_image)
433{
434 if (is_proxy_image) {
435 return true;
436 }
437 if ((strip->type & STRIP_TYPE_EFFECT) != 0 || strip->type == STRIP_TYPE_MASK ||
438 strip->type == STRIP_TYPE_META ||
439 (strip->type == STRIP_TYPE_SCENE && ((strip->flag & SEQ_SCENE_STRIPS) != 0)))
440 {
441 return true;
442 }
443 return false;
444}
445
447 const ImBuf *in,
448 const ImBuf *out,
449 const float image_scale_factor,
450 const float preview_scale_factor)
451{
452 const StripTransform *transform = strip->data->transform;
453
454 /* This value is intentionally kept as integer. Otherwise images with odd dimensions would
455 * be translated to center of canvas by non-integer value, which would cause it to be
456 * interpolated. Interpolation with 0 user defined translation is unwanted behavior. */
457 const int3 image_center_offs((out->x - in->x) / 2, (out->y - in->y) / 2, 0);
458
459 const float2 translation(transform->xofs * preview_scale_factor,
460 transform->yofs * preview_scale_factor);
461 const float rotation = transform->rotation;
462 const float2 scale(transform->scale_x * image_scale_factor,
463 transform->scale_y * image_scale_factor);
464 const float2 pivot(in->x * transform->origin[0], in->y * transform->origin[1]);
465
467 translation + float2(image_center_offs), rotation, scale);
468 const float3x3 mat_pivot = math::from_origin_transform(matrix, pivot);
469 return math::invert(mat_pivot);
470}
471
472static void sequencer_image_crop_init(const Strip *strip,
473 const ImBuf *in,
474 float crop_scale_factor,
475 rctf *r_crop)
476{
477 const StripCrop *c = strip->data->crop;
478 const int left = c->left * crop_scale_factor;
479 const int right = c->right * crop_scale_factor;
480 const int top = c->top * crop_scale_factor;
481 const int bottom = c->bottom * crop_scale_factor;
482
483 BLI_rctf_init(r_crop, left, in->x - right, bottom, in->y - top);
484}
485
486static bool is_strip_covering_screen(const RenderData *context, const Strip *strip)
487{
488 /* The check is done by checking whether all corners of viewport fit inside
489 * of the transformed strip. If they do not, the strip does not cover
490 * whole screen. */
491 float x0 = 0.0f;
492 float y0 = 0.0f;
493 float x1 = float(context->rectx);
494 float y1 = float(context->recty);
495 float x_aspect = context->scene->r.xasp / context->scene->r.yasp;
496 if (x_aspect != 1.0f) {
497 float xmid = (x0 + x1) * 0.5f;
498 x0 = xmid - (xmid - x0) * x_aspect;
499 x1 = xmid + (x1 - xmid) * x_aspect;
500 }
502 if (quad.is_empty()) {
503 return false; /* Strip is zero size. */
504 }
505 StripScreenQuad screen{float2(x0, y0), float2(x1, y0), float2(x0, y1), float2(x1, y1)};
506
507 return is_quad_a_inside_b(screen, quad);
508}
509
510/* Automatic filter:
511 * - No scale, no rotation and non-fractional position: nearest.
512 * - Scale up by more than 2x: cubic mitchell.
513 * - Scale down by more than 2x: box.
514 * - Otherwise: bilinear. */
516{
517 const float sx = fabsf(transform->scale_x);
518 const float sy = fabsf(transform->scale_y);
519 if (sx > 2.0f && sy > 2.0f) {
521 }
522 if (sx < 0.5f && sy < 0.5f) {
523 return IMB_FILTER_BOX;
524 }
525 const float px = transform->xofs;
526 const float py = transform->yofs;
527 const float rot = transform->rotation;
528 if (sx == 1.0f && sy == 1.0f && roundf(px) == px && roundf(py) == py && rot == 0.0f) {
529 return IMB_FILTER_NEAREST;
530 }
531 return IMB_FILTER_BILINEAR;
532}
533
535 ImBuf *in, ImBuf *out, const RenderData *context, Strip *strip, const bool is_proxy_image)
536{
537 const Scene *scene = context->scene;
538 const float preview_scale_factor = context->preview_render_size == SEQ_RENDER_SIZE_SCENE ?
539 float(scene->r.size) / 100 :
540 rendersize_to_scale_factor(context->preview_render_size);
541 const bool do_scale_to_render_size = seq_need_scale_to_render_size(strip, is_proxy_image);
542 const float image_scale_factor = do_scale_to_render_size ? 1.0f : preview_scale_factor;
543
545 strip, in, out, image_scale_factor, preview_scale_factor);
546
547 /* Proxy image is smaller, so crop values must be corrected by proxy scale factor.
548 * Proxy scale factor always matches preview_scale_factor. */
549 rctf source_crop;
550 const float crop_scale_factor = do_scale_to_render_size ? preview_scale_factor : 1.0f;
551 sequencer_image_crop_init(strip, in, crop_scale_factor, &source_crop);
552
553 const StripTransform *transform = strip->data->transform;
555 switch (transform->filter) {
558 break;
561 break;
564 break;
567 break;
570 break;
573 break;
574 }
575
576 IMB_transform(in, out, IMB_TRANSFORM_MODE_CROP_SRC, filter, matrix, &source_crop);
577
578 if (is_strip_covering_screen(context, strip)) {
579 out->planes = in->planes;
580 }
581 else {
582 /* Strip is not covering full viewport, which means areas with transparency
583 * are introduced for sure. */
584 out->planes = R_IMF_PLANES_RGBA;
585 }
586}
587
588static void multiply_ibuf(ImBuf *ibuf, const float fmul, const bool multiply_alpha)
589{
590 BLI_assert_msg(ibuf->channels == 0 || ibuf->channels == 4,
591 "Sequencer only supports 4 channel images");
592 const size_t pixel_count = IMB_get_pixel_count(ibuf);
593 if (ibuf->byte_buffer.data != nullptr) {
594 threading::parallel_for(IndexRange(pixel_count), 64 * 1024, [&](IndexRange range) {
595 uchar *ptr = ibuf->byte_buffer.data + range.first() * 4;
596 const int imul = int(256.0f * fmul);
597 for ([[maybe_unused]] const int64_t i : range) {
598 ptr[0] = min_ii((imul * ptr[0]) >> 8, 255);
599 ptr[1] = min_ii((imul * ptr[1]) >> 8, 255);
600 ptr[2] = min_ii((imul * ptr[2]) >> 8, 255);
601 if (multiply_alpha) {
602 ptr[3] = min_ii((imul * ptr[3]) >> 8, 255);
603 }
604 ptr += 4;
605 }
606 });
607 }
608
609 if (ibuf->float_buffer.data != nullptr) {
610 threading::parallel_for(IndexRange(pixel_count), 64 * 1024, [&](IndexRange range) {
611 float *ptr = ibuf->float_buffer.data + range.first() * 4;
612 for ([[maybe_unused]] const int64_t i : range) {
613 ptr[0] *= fmul;
614 ptr[1] *= fmul;
615 ptr[2] *= fmul;
616 if (multiply_alpha) {
617 ptr[3] *= fmul;
618 }
619 ptr += 4;
620 }
621 });
622 }
623}
624
625static ImBuf *input_preprocess(const RenderData *context,
626 Strip *strip,
627 float timeline_frame,
628 ImBuf *ibuf,
629 const bool is_proxy_image)
630{
631 Scene *scene = context->scene;
632 ImBuf *preprocessed_ibuf = nullptr;
633
634 /* Deinterlace. */
635 if ((strip->flag & SEQ_FILTERY) && !ELEM(strip->type, STRIP_TYPE_MOVIE, STRIP_TYPE_MOVIECLIP)) {
636 /* Change original image pointer to avoid another duplication in SEQ_USE_TRANSFORM. */
637 preprocessed_ibuf = IMB_makeSingleUser(ibuf);
638 ibuf = preprocessed_ibuf;
639
640 IMB_filtery(preprocessed_ibuf);
641 }
642
643 if (sequencer_use_crop(strip) || sequencer_use_transform(strip) || context->rectx != ibuf->x ||
644 context->recty != ibuf->y)
645 {
646 const int x = context->rectx;
647 const int y = context->recty;
648 preprocessed_ibuf = IMB_allocImBuf(
650
651 sequencer_preprocess_transform_crop(ibuf, preprocessed_ibuf, context, strip, is_proxy_image);
652
653 seq_imbuf_assign_spaces(scene, preprocessed_ibuf);
654 IMB_metadata_copy(preprocessed_ibuf, ibuf);
655 IMB_freeImBuf(ibuf);
656 }
657
658 /* Duplicate ibuf if we still have original. */
659 if (preprocessed_ibuf == nullptr) {
660 preprocessed_ibuf = IMB_makeSingleUser(ibuf);
661 }
662
663 if (strip->flag & SEQ_FLIPX) {
664 IMB_flipx(preprocessed_ibuf);
665 }
666
667 if (strip->flag & SEQ_FLIPY) {
668 IMB_flipy(preprocessed_ibuf);
669 }
670
671 if (strip->sat != 1.0f) {
672 IMB_saturation(preprocessed_ibuf, strip->sat);
673 }
674
675 if (strip->flag & SEQ_MAKE_FLOAT) {
676 if (!preprocessed_ibuf->float_buffer.data) {
677 seq_imbuf_to_sequencer_space(scene, preprocessed_ibuf, true);
678 }
679
680 if (preprocessed_ibuf->byte_buffer.data) {
681 IMB_free_byte_pixels(preprocessed_ibuf);
682 }
683 }
684
685 float mul = strip->mul;
686 if (strip->blend_mode == SEQ_BLEND_REPLACE) {
687 mul *= strip->blend_opacity / 100.0f;
688 }
689
690 if (mul != 1.0f) {
691 const bool multiply_alpha = (strip->flag & SEQ_MULTIPLY_ALPHA);
692 multiply_ibuf(preprocessed_ibuf, mul, multiply_alpha);
693 }
694
695 if (strip->modifiers.first) {
696 modifier_apply_stack(context, strip, preprocessed_ibuf, timeline_frame);
697 }
698
699 return preprocessed_ibuf;
700}
701
703 Strip *strip,
704 ImBuf *ibuf,
705 float timeline_frame,
706 bool use_preprocess,
707 const bool is_proxy_image)
708{
709 if (context->is_proxy_render == false &&
710 (ibuf->x != context->rectx || ibuf->y != context->recty))
711 {
712 use_preprocess = true;
713 }
714
715 /* Proxies and non-generator effect strips are not stored in cache. */
716 const bool is_effect_with_inputs = (strip->type & STRIP_TYPE_EFFECT) != 0 &&
717 (effect_get_num_inputs(strip->type) != 0 ||
718 (strip->type == STRIP_TYPE_ADJUSTMENT));
719 if (!is_proxy_image && !is_effect_with_inputs) {
720 Scene *orig_scene = prefetch_get_original_scene(context);
721 if (orig_scene->ed->cache_flag & SEQ_CACHE_STORE_RAW) {
722 source_image_cache_put(context, strip, timeline_frame, ibuf);
723 }
724 }
725
726 if (use_preprocess) {
727 ibuf = input_preprocess(context, strip, timeline_frame, ibuf, is_proxy_image);
728 }
729
730 return ibuf;
731}
732
735 Strip *strip,
736 float timeline_frame)
737{
738 Scene *scene = context->scene;
739 float fac;
740 int i;
742 const FCurve *fcu = nullptr;
743 ImBuf *ibuf[2];
744 Strip *input[2];
745 ImBuf *out = nullptr;
746
747 ibuf[0] = ibuf[1] = nullptr;
748
749 input[0] = strip->input1;
750 input[1] = strip->input2;
751
752 if (!sh.execute) {
753 /* effect not supported in this version... */
754 out = IMB_allocImBuf(context->rectx, context->recty, 32, IB_byte_data);
755 return out;
756 }
757
758 if (strip->flag & SEQ_USE_EFFECT_DEFAULT_FADE) {
759 sh.get_default_fac(scene, strip, timeline_frame, &fac);
760 }
761 else {
762 fcu = id_data_find_fcurve(&scene->id, strip, &RNA_Strip, "effect_fader", 0, nullptr);
763 if (fcu) {
764 fac = evaluate_fcurve(fcu, timeline_frame);
765 }
766 else {
767 fac = strip->effect_fader;
768 }
769 }
770
771 StripEarlyOut early_out = sh.early_out(strip, fac);
772
773 switch (early_out) {
775 out = sh.execute(context, strip, timeline_frame, fac, nullptr, nullptr);
776 break;
778 for (i = 0; i < 2; i++) {
779 /* Speed effect requires time remapping of `timeline_frame` for input(s). */
780 if (input[0] && strip->type == STRIP_TYPE_SPEED) {
781 float target_frame = strip_speed_effect_target_frame_get(
782 scene, strip, timeline_frame, i);
783
784 /* Only convert to int when interpolation is not used. */
785 SpeedControlVars *s = reinterpret_cast<SpeedControlVars *>(strip->effectdata);
786 if ((s->flags & SEQ_SPEED_USE_INTERPOLATION) != 0) {
787 target_frame = std::floor(target_frame);
788 }
789
790 ibuf[i] = seq_render_strip(context, state, input[0], target_frame);
791 }
792 else { /* Other effects. */
793 if (input[i]) {
794 ibuf[i] = seq_render_strip(context, state, input[i], timeline_frame);
795 }
796 }
797 }
798
799 if (ibuf[0] && (ibuf[1] || effect_get_num_inputs(strip->type) == 1)) {
800 out = sh.execute(context, strip, timeline_frame, fac, ibuf[0], ibuf[1]);
801 }
802 break;
804 if (input[0]) {
805 out = seq_render_strip(context, state, input[0], timeline_frame);
806 }
807 break;
809 if (input[1]) {
810 out = seq_render_strip(context, state, input[1], timeline_frame);
811 }
812 break;
813 }
814
815 for (i = 0; i < 2; i++) {
816 IMB_freeImBuf(ibuf[i]);
817 }
818
819 if (out == nullptr) {
820 out = IMB_allocImBuf(context->rectx, context->recty, 32, IB_byte_data);
821 }
822
823 return out;
824}
825
827
828/* -------------------------------------------------------------------- */
831
833{
834 /* Load the combined/RGB layer, if this is a multi-layer image. */
836
837 /* Combined layer might be non-4 channels, however the rest
838 * of sequencer assumes RGBA everywhere. Convert to 4 channel if needed. */
839 if (ibuf->float_buffer.data != nullptr && ibuf->channels != 4) {
840 float *dst = MEM_malloc_arrayN<float>(4 * size_t(ibuf->x) * size_t(ibuf->y), __func__);
842 ibuf->float_buffer.data,
843 ibuf->channels,
846 false,
847 ibuf->x,
848 ibuf->y,
849 ibuf->x,
850 ibuf->x);
852 ibuf->channels = 4;
853 }
854}
855
860 Strip *strip,
861 char *filepath,
862 char *prefix,
863 const char *ext,
864 int view_id)
865{
866 ImBuf *ibuf = nullptr;
867
869 if (strip->alpha_mode == SEQ_ALPHA_PREMUL) {
871 }
872
873 if (prefix[0] == '\0') {
875 }
876 else {
877 char filepath_view[FILE_MAX];
878 BKE_scene_multiview_view_prefix_get(context->scene, filepath, prefix, &ext);
879 seq_multiview_name(context->scene, view_id, prefix, ext, filepath_view, FILE_MAX);
881 filepath_view, flag, strip->data->colorspace_settings.name);
882 }
883
884 if (ibuf == nullptr) {
885 return nullptr;
886 }
888
889 /* We don't need both (speed reasons)! */
890 if (ibuf->float_buffer.data != nullptr && ibuf->byte_buffer.data != nullptr) {
892 }
893
894 /* All sequencer color is done in SRGB space, linear gives odd cross-fades. */
895 seq_imbuf_to_sequencer_space(context->scene, ibuf, false);
896
897 return ibuf;
898}
899
901 Strip *strip,
902 int totfiles,
903 const char *filepath,
904 char *r_prefix,
905 const char *r_ext)
906{
907 if (totfiles > 1) {
908 BKE_scene_multiview_view_prefix_get(scene, filepath, r_prefix, &r_ext);
909 if (r_prefix[0] == '\0') {
910 return false;
911 }
912 }
913 else {
914 r_prefix[0] = '\0';
915 }
916
917 return (strip->flag & SEQ_USE_VIEWS) != 0 && (scene->r.scemode & R_MULTIVIEW) != 0;
918}
919
920static ImBuf *create_missing_media_image(const RenderData *context, int width, int height)
921{
922 if (context->ignore_missing_media) {
923 return nullptr;
924 }
925 if (context->scene == nullptr || context->scene->ed == nullptr ||
926 (context->scene->ed->show_missing_media_flag & SEQ_EDIT_SHOW_MISSING_MEDIA) == 0)
927 {
928 return nullptr;
929 }
930
931 ImBuf *ibuf = IMB_allocImBuf(max_ii(width, 1), max_ii(height, 1), 32, IB_byte_data);
932 float col[4] = {0.85f, 0.0f, 0.75f, 1.0f};
933 IMB_rectfill(ibuf, col);
934 return ibuf;
935}
936
938 Strip *strip,
939 int timeline_frame,
940 bool *r_is_proxy_image)
941{
942 char filepath[FILE_MAX];
943 const char *ext = nullptr;
944 char prefix[FILE_MAX];
945 ImBuf *ibuf = nullptr;
946
947 StripElem *s_elem = render_give_stripelem(context->scene, strip, timeline_frame);
948 if (s_elem == nullptr) {
949 return nullptr;
950 }
951
952 BLI_path_join(filepath, sizeof(filepath), strip->data->dirpath, s_elem->filename);
953 BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&context->scene->id));
954
955 /* Try to get a proxy image. */
956 ibuf = seq_proxy_fetch(context, strip, timeline_frame);
957 if (ibuf != nullptr) {
958 *r_is_proxy_image = true;
959 return ibuf;
960 }
961
962 /* Proxy not found, render original. */
963 const int totfiles = seq_num_files(context->scene, strip->views_format, true);
964 bool is_multiview_render = seq_image_strip_is_multiview_render(
965 context->scene, strip, totfiles, filepath, prefix, ext);
966
967 if (is_multiview_render) {
968 int totviews = BKE_scene_multiview_num_views_get(&context->scene->r);
969 ImBuf **ibufs_arr = MEM_calloc_arrayN<ImBuf *>(totviews, "Sequence Image Views Imbufs");
970
971 for (int view_id = 0; view_id < totfiles; view_id++) {
972 ibufs_arr[view_id] = seq_render_image_strip_view(
973 context, strip, filepath, prefix, ext, view_id);
974 }
975
976 if (ibufs_arr[0] == nullptr) {
977 return nullptr;
978 }
979
980 if (strip->views_format == R_IMF_VIEWS_STEREO_3D) {
981 IMB_ImBufFromStereo3d(strip->stereo3d_format, ibufs_arr[0], &ibufs_arr[0], &ibufs_arr[1]);
982 }
983
984 for (int view_id = 0; view_id < totviews; view_id++) {
985 RenderData localcontext = *context;
986 localcontext.view_id = view_id;
987
988 if (view_id != context->view_id) {
989 ibufs_arr[view_id] = seq_render_preprocess_ibuf(
990 &localcontext, strip, ibufs_arr[view_id], timeline_frame, true, false);
991 }
992 }
993
994 /* Return the original requested ImBuf. */
995 ibuf = ibufs_arr[context->view_id];
996
997 /* Remove the others (decrease their refcount). */
998 for (int view_id = 0; view_id < totviews; view_id++) {
999 if (ibufs_arr[view_id] != ibuf) {
1000 IMB_freeImBuf(ibufs_arr[view_id]);
1001 }
1002 }
1003
1004 MEM_freeN(ibufs_arr);
1005 }
1006 else {
1007 ibuf = seq_render_image_strip_view(context, strip, filepath, prefix, ext, context->view_id);
1008 }
1009
1010 blender::seq::media_presence_set_missing(context->scene, strip, ibuf == nullptr);
1011 if (ibuf == nullptr) {
1012 return create_missing_media_image(context, s_elem->orig_width, s_elem->orig_height);
1013 }
1014
1015 s_elem->orig_width = ibuf->x;
1016 s_elem->orig_height = ibuf->y;
1017
1018 return ibuf;
1019}
1020
1022 Strip *strip,
1023 int timeline_frame)
1024{
1025 char filepath[PROXY_MAXFILE];
1026 StripProxy *proxy = strip->data->proxy;
1027
1028 if (proxy->anim == nullptr) {
1029 if (seq_proxy_get_custom_file_filepath(strip, filepath, context->view_id)) {
1030 proxy->anim = openanim(filepath, IB_byte_data, 0, strip->data->colorspace_settings.name);
1031 }
1032 if (proxy->anim == nullptr) {
1033 return nullptr;
1034 }
1035 }
1036
1037 int frameno = round_fl_to_int(give_frame_index(context->scene, strip, timeline_frame)) +
1038 strip->anim_startofs;
1039 return MOV_decode_frame(proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE);
1040}
1041
1043{
1044 bool use_timecodes = (strip->flag & SEQ_USE_PROXY) != 0;
1045 if (!use_timecodes) {
1046 return IMB_TC_NONE;
1047 }
1048 return IMB_Timecode_Type(strip->data->proxy ? IMB_Timecode_Type(strip->data->proxy->tc) :
1049 IMB_TC_NONE);
1050}
1051
1056 Strip *strip,
1057 float timeline_frame,
1058 StripAnim *sanim,
1059 bool *r_is_proxy_image)
1060{
1061 ImBuf *ibuf = nullptr;
1062 IMB_Proxy_Size psize = IMB_Proxy_Size(rendersize_to_proxysize(context->preview_render_size));
1063 const int frame_index = round_fl_to_int(give_frame_index(context->scene, strip, timeline_frame));
1064
1065 if (can_use_proxy(context, strip, psize)) {
1066 /* Try to get a proxy image.
1067 * Movie proxies are handled by ImBuf module with exception of `custom file` setting. */
1068 if (context->scene->ed->proxy_storage != SEQ_EDIT_PROXY_DIR_STORAGE &&
1070 {
1071 ibuf = seq_render_movie_strip_custom_file_proxy(context, strip, timeline_frame);
1072 }
1073 else {
1074 ibuf = MOV_decode_frame(sanim->anim,
1075 frame_index + strip->anim_startofs,
1077 psize);
1078 }
1079
1080 if (ibuf != nullptr) {
1081 *r_is_proxy_image = true;
1082 }
1083 }
1084
1085 /* Fetching for requested proxy size failed, try fetching the original instead. */
1086 if (ibuf == nullptr) {
1087 ibuf = MOV_decode_frame(sanim->anim,
1088 frame_index + strip->anim_startofs,
1091 }
1092 if (ibuf == nullptr) {
1093 return nullptr;
1094 }
1095
1096 seq_imbuf_to_sequencer_space(context->scene, ibuf, false);
1097
1098 /* We don't need both (speed reasons)! */
1099 if (ibuf->float_buffer.data != nullptr && ibuf->byte_buffer.data != nullptr) {
1101 }
1102
1103 return ibuf;
1104}
1105
1107 Strip *strip,
1108 float timeline_frame,
1109 bool *r_is_proxy_image)
1110{
1111 /* Load all the videos. */
1112 strip_open_anim_file(context->scene, strip, false);
1113
1114 ImBuf *ibuf = nullptr;
1115 StripAnim *sanim = static_cast<StripAnim *>(strip->anims.first);
1116 const int totfiles = seq_num_files(context->scene, strip->views_format, true);
1117 bool is_multiview_render = (strip->flag & SEQ_USE_VIEWS) != 0 &&
1118 (context->scene->r.scemode & R_MULTIVIEW) != 0 &&
1119 BLI_listbase_count_is_equal_to(&strip->anims, totfiles);
1120
1121 if (is_multiview_render) {
1122 ImBuf **ibuf_arr;
1123 int totviews = BKE_scene_multiview_num_views_get(&context->scene->r);
1124 ibuf_arr = MEM_calloc_arrayN<ImBuf *>(totviews, "Sequence Image Views Imbufs");
1125 int ibuf_view_id;
1126
1127 for (ibuf_view_id = 0, sanim = static_cast<StripAnim *>(strip->anims.first); sanim;
1128 sanim = sanim->next, ibuf_view_id++)
1129 {
1130 if (sanim->anim) {
1131 ibuf_arr[ibuf_view_id] = seq_render_movie_strip_view(
1132 context, strip, timeline_frame, sanim, r_is_proxy_image);
1133 }
1134 }
1135
1136 if (strip->views_format == R_IMF_VIEWS_STEREO_3D) {
1137 if (ibuf_arr[0] == nullptr) {
1138 /* Probably proxy hasn't been created yet. */
1139 MEM_freeN(ibuf_arr);
1140 return nullptr;
1141 }
1142
1143 IMB_ImBufFromStereo3d(strip->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
1144 }
1145
1146 for (int view_id = 0; view_id < totviews; view_id++) {
1147 RenderData localcontext = *context;
1148 localcontext.view_id = view_id;
1149
1150 if (view_id != context->view_id && ibuf_arr[view_id]) {
1151 ibuf_arr[view_id] = seq_render_preprocess_ibuf(
1152 &localcontext, strip, ibuf_arr[view_id], timeline_frame, true, false);
1153 }
1154 }
1155
1156 /* Return the original requested ImBuf. */
1157 ibuf = ibuf_arr[context->view_id];
1158
1159 /* Remove the others (decrease their refcount). */
1160 for (int view_id = 0; view_id < totviews; view_id++) {
1161 if (ibuf_arr[view_id] != ibuf) {
1162 IMB_freeImBuf(ibuf_arr[view_id]);
1163 }
1164 }
1165
1166 MEM_freeN(ibuf_arr);
1167 }
1168 else {
1169 ibuf = seq_render_movie_strip_view(context, strip, timeline_frame, sanim, r_is_proxy_image);
1170 }
1171
1172 blender::seq::media_presence_set_missing(context->scene, strip, ibuf == nullptr);
1173 if (ibuf == nullptr) {
1175 context, strip->data->stripdata->orig_width, strip->data->stripdata->orig_height);
1176 }
1177
1178 if (*r_is_proxy_image == false) {
1179 if (sanim && sanim->anim) {
1180 strip->data->stripdata->orig_fps = MOV_get_fps(sanim->anim);
1181 }
1182 strip->data->stripdata->orig_width = ibuf->x;
1183 strip->data->stripdata->orig_height = ibuf->y;
1184 }
1185
1186 return ibuf;
1187}
1188
1190{
1191 ImBuf *ibuf = nullptr;
1192 float tloc[2], tscale, tangle;
1194 ibuf = BKE_movieclip_get_stable_ibuf(strip->clip, &user, 0, tloc, &tscale, &tangle);
1195 }
1196 else {
1198 strip->clip, &user, strip->clip->flag, MOVIECLIP_CACHE_SKIP);
1199 }
1200 return ibuf;
1201}
1202
1204 Strip *strip,
1205 float frame_index,
1206 bool *r_is_proxy_image)
1207{
1208 ImBuf *ibuf = nullptr;
1210 IMB_Proxy_Size psize = IMB_Proxy_Size(rendersize_to_proxysize(context->preview_render_size));
1211
1212 if (!strip->clip) {
1213 return nullptr;
1214 }
1215
1217 frame_index + strip->anim_startofs + strip->clip->start_frame);
1218
1220 switch (psize) {
1221 case IMB_PROXY_NONE:
1223 break;
1224 case IMB_PROXY_100:
1226 break;
1227 case IMB_PROXY_75:
1229 break;
1230 case IMB_PROXY_50:
1232 break;
1233 case IMB_PROXY_25:
1235 break;
1236 }
1237
1240 }
1241
1242 /* Try to get a proxy image. */
1243 ibuf = seq_get_movieclip_ibuf(strip, user);
1244
1245 /* If clip doesn't use proxies, it will fall back to full size render of original file. */
1246 if (ibuf != nullptr && psize != IMB_PROXY_NONE && BKE_movieclip_proxy_enabled(strip->clip)) {
1247 *r_is_proxy_image = true;
1248 }
1249
1250 /* If proxy is not found, grab full-size frame. */
1251 if (ibuf == nullptr) {
1253 ibuf = seq_get_movieclip_ibuf(strip, user);
1254 }
1255
1256 return ibuf;
1257}
1258
1259ImBuf *seq_render_mask(const RenderData *context, Mask *mask, float frame_index, bool make_float)
1260{
1261 /* TODO: add option to rasterize to alpha imbuf? */
1262 ImBuf *ibuf = nullptr;
1263 float *maskbuf;
1264 int i;
1265
1266 if (!mask) {
1267 return nullptr;
1268 }
1269
1270 AnimData *adt;
1271 Mask *mask_temp;
1272 MaskRasterHandle *mr_handle;
1273
1274 mask_temp = (Mask *)BKE_id_copy_ex(
1275 nullptr, &mask->id, nullptr, LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA);
1276
1277 BKE_mask_evaluate(mask_temp, mask->sfra + frame_index, true);
1278
1279 /* anim-data */
1280 adt = BKE_animdata_from_id(&mask->id);
1282 context->depsgraph, mask->sfra + frame_index);
1283 BKE_animsys_evaluate_animdata(&mask_temp->id, adt, &anim_eval_context, ADT_RECALC_ANIM, false);
1284
1285 maskbuf = MEM_malloc_arrayN<float>(size_t(context->rectx) * size_t(context->recty), __func__);
1286
1287 mr_handle = BKE_maskrasterize_handle_new();
1288
1290 mr_handle, mask_temp, context->rectx, context->recty, true, true, true);
1291
1292 BKE_id_free(nullptr, &mask_temp->id);
1293
1294 BKE_maskrasterize_buffer(mr_handle, context->rectx, context->recty, maskbuf);
1295
1297
1298 if (make_float) {
1299 /* pixels */
1300 const float *fp_src;
1301 float *fp_dst;
1302
1303 ibuf = IMB_allocImBuf(
1304 context->rectx, context->recty, 32, IB_float_data | IB_uninitialized_pixels);
1305
1306 fp_src = maskbuf;
1307 fp_dst = ibuf->float_buffer.data;
1308 i = context->rectx * context->recty;
1309 while (--i) {
1310 fp_dst[0] = fp_dst[1] = fp_dst[2] = *fp_src;
1311 fp_dst[3] = 1.0f;
1312
1313 fp_src += 1;
1314 fp_dst += 4;
1315 }
1316 }
1317 else {
1318 /* pixels */
1319 const float *fp_src;
1320 uchar *ub_dst;
1321
1322 ibuf = IMB_allocImBuf(
1323 context->rectx, context->recty, 32, IB_byte_data | IB_uninitialized_pixels);
1324
1325 fp_src = maskbuf;
1326 ub_dst = ibuf->byte_buffer.data;
1327 i = context->rectx * context->recty;
1328 while (--i) {
1329 ub_dst[0] = ub_dst[1] = ub_dst[2] = uchar(*fp_src * 255.0f); /* already clamped */
1330 ub_dst[3] = 255;
1331
1332 fp_src += 1;
1333 ub_dst += 4;
1334 }
1335 }
1336
1337 MEM_freeN(maskbuf);
1338
1339 return ibuf;
1340}
1341
1342static ImBuf *seq_render_mask_strip(const RenderData *context, Strip *strip, float frame_index)
1343{
1344 bool make_float = (strip->flag & SEQ_MAKE_FLOAT) != 0;
1345
1346 return seq_render_mask(context, strip->mask, frame_index, make_float);
1347}
1348
1350 Strip *strip,
1351 float frame_index,
1352 float timeline_frame)
1353{
1354 ImBuf *ibuf = nullptr;
1355 double frame;
1356 Object *camera;
1357
1358 struct {
1359 int scemode;
1360 int timeline_frame;
1361 float subframe;
1362 int mode;
1363 } orig_data;
1364
1365 /* Old info:
1366 * Hack! This function can be called from do_render_seq(), in that case
1367 * the strip->scene can already have a Render initialized with same name,
1368 * so we have to use a default name. (compositor uses scene name to
1369 * find render).
1370 * However, when called from within the UI (image preview in sequencer)
1371 * we do want to use scene Render, that way the render result is defined
1372 * for display in render/image-window
1373 *
1374 * Hmm, don't see, why we can't do that all the time,
1375 * and since G.is_rendering is uhm, gone... (Peter)
1376 */
1377
1378 /* New info:
1379 * Using the same name for the renders works just fine as the do_render_seq()
1380 * render is not used while the scene strips are rendered.
1381 *
1382 * However rendering from UI (through sequencer_preview_area_draw) can crash in
1383 * very many cases since other renders (material preview, an actual render etc.)
1384 * can be started while this sequence preview render is running. The only proper
1385 * solution is to make the sequencer preview render a proper job, which can be
1386 * stopped when needed. This would also give a nice progress bar for the preview
1387 * space so that users know there's something happening.
1388 *
1389 * As a result the active scene now only uses OpenGL rendering for the sequencer
1390 * preview. This is far from nice, but is the only way to prevent crashes at this
1391 * time.
1392 *
1393 * -jahka
1394 */
1395
1396 const bool is_rendering = G.is_rendering;
1397 bool is_preview = !context->for_render && (context->scene->r.seq_prev_type) != OB_RENDER;
1398
1399 bool have_comp = false;
1400 bool use_gpencil = true;
1401 /* do we need to re-evaluate the frame after rendering? */
1402 bool is_frame_update = false;
1403 Scene *scene;
1404
1405 /* don't refer to strip->scene above this point!, it can be nullptr */
1406 if (strip->scene == nullptr) {
1407 return create_missing_media_image(context, context->rectx, context->recty);
1408 }
1409
1410 /* Prevent rendering scene recursively. */
1411 if (strip->scene == context->scene) {
1412 return nullptr;
1413 }
1414
1415 scene = strip->scene;
1416 frame = double(scene->r.sfra) + double(frame_index) + double(strip->anim_startofs);
1417
1418#if 0 /* UNUSED */
1419 have_seq = (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first;
1420#endif
1421 have_comp = (scene->r.scemode & R_DOCOMP) && scene->use_nodes && scene->nodetree;
1422
1423 /* Get view layer for the strip. */
1424 ViewLayer *view_layer = BKE_view_layer_default_render(scene);
1425 /* Depsgraph will be nullptr when doing rendering. */
1426 Depsgraph *depsgraph = nullptr;
1427
1428 orig_data.scemode = scene->r.scemode;
1429 orig_data.timeline_frame = scene->r.cfra;
1430 orig_data.subframe = scene->r.subframe;
1431 orig_data.mode = scene->r.mode;
1432
1433 BKE_scene_frame_set(scene, frame);
1434
1435 if (strip->scene_camera) {
1436 camera = strip->scene_camera;
1437 }
1438 else {
1440 camera = scene->camera;
1441 }
1442
1443 if (have_comp == false && camera == nullptr) {
1444 goto finally;
1445 }
1446
1447 if (strip->flag & SEQ_SCENE_NO_ANNOTATION) {
1448 use_gpencil = false;
1449 }
1450
1451 /* prevent eternal loop */
1452 scene->r.scemode &= ~R_DOSEQ;
1453
1454 /* stooping to new low's in hackyness :( */
1455 scene->r.mode |= R_NO_CAMERA_SWITCH;
1456
1457 is_frame_update = (orig_data.timeline_frame != scene->r.cfra) ||
1458 (orig_data.subframe != scene->r.subframe);
1459
1460 if (view3d_fn && is_preview && camera) {
1461 char err_out[256] = "unknown";
1462 int width, height;
1463 BKE_render_resolution(&scene->r, false, &width, &height);
1464 const char *viewname = BKE_scene_multiview_render_view_name_get(&scene->r, context->view_id);
1465
1466 uint draw_flags = V3D_OFSDRAW_NONE;
1467 draw_flags |= (use_gpencil) ? V3D_OFSDRAW_SHOW_ANNOTATION : 0;
1468 draw_flags |= (context->scene->r.seq_flag & R_SEQ_OVERRIDE_SCENE_SETTINGS) ?
1470 0;
1471
1472 /* for old scene this can be uninitialized,
1473 * should probably be added to do_versions at some point if the functionality stays */
1474 if (context->scene->r.seq_prev_type == 0) {
1475 context->scene->r.seq_prev_type = 3 /* == OB_SOLID */;
1476 }
1477
1478 /* opengl offscreen render */
1479 depsgraph = BKE_scene_ensure_depsgraph(context->bmain, scene, view_layer);
1481 Object *camera_eval = DEG_get_evaluated(depsgraph, camera);
1483 ibuf = view3d_fn(
1484 /* set for OpenGL render (nullptr when scrubbing) */
1485 depsgraph,
1486 scene_eval,
1487 &context->scene->display.shading,
1488 eDrawType(context->scene->r.seq_prev_type),
1489 camera_eval,
1490 width,
1491 height,
1493 eV3DOffscreenDrawFlag(draw_flags),
1494 scene->r.alphamode,
1495 viewname,
1496 context->gpu_offscreen,
1497 context->gpu_viewport,
1498 err_out);
1499 if (ibuf == nullptr) {
1500 fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out);
1501 }
1502 }
1503 else {
1504 Render *re = RE_GetSceneRender(scene);
1505 const int totviews = BKE_scene_multiview_num_views_get(&scene->r);
1506 ImBuf **ibufs_arr;
1507
1508 /*
1509 * XXX: this if can be removed when sequence preview rendering uses the job system
1510 *
1511 * Disable rendered preview for sequencer while rendering - invoked render job will
1512 * conflict with already running render
1513 *
1514 * When rendering from command line renderer is called from main thread, in this
1515 * case it's always safe to render scene here
1516 */
1517
1518 if (is_preview && (is_rendering && !G.background)) {
1519 goto finally;
1520 }
1521
1522 ibufs_arr = MEM_calloc_arrayN<ImBuf *>(totviews, "Sequence Image Views Imbufs");
1523
1524 if (re == nullptr) {
1525 re = RE_NewSceneRender(scene);
1526 }
1527
1528 const float subframe = frame - floorf(frame);
1529
1530 RE_RenderFrame(re,
1531 context->bmain,
1532 scene,
1533 have_comp ? nullptr : view_layer,
1534 camera,
1535 floorf(frame),
1536 subframe,
1537 false);
1538
1539 /* restore previous state after it was toggled on & off by RE_RenderFrame */
1540 G.is_rendering = is_rendering;
1541
1542 for (int view_id = 0; view_id < totviews; view_id++) {
1543 RenderData localcontext = *context;
1544 RenderResult rres;
1545
1546 localcontext.view_id = view_id;
1547
1548 RE_AcquireResultImage(re, &rres, view_id);
1549
1550 /* TODO: Share the pixel data with the original image buffer from the render result using
1551 * implicit sharing. */
1552 if (rres.ibuf && rres.ibuf->float_buffer.data) {
1553 ibufs_arr[view_id] = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_float_data);
1554 memcpy(ibufs_arr[view_id]->float_buffer.data,
1555 rres.ibuf->float_buffer.data,
1556 sizeof(float[4]) * rres.rectx * rres.recty);
1557
1558 /* float buffers in the sequencer are not linear */
1559 seq_imbuf_to_sequencer_space(context->scene, ibufs_arr[view_id], false);
1560 }
1561 else if (rres.ibuf && rres.ibuf->byte_buffer.data) {
1562 ibufs_arr[view_id] = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_byte_data);
1563 memcpy(ibufs_arr[view_id]->byte_buffer.data,
1564 rres.ibuf->byte_buffer.data,
1565 4 * rres.rectx * rres.recty);
1566 }
1567 else {
1568 ibufs_arr[view_id] = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_byte_data);
1569 }
1570
1571 if (view_id != context->view_id) {
1572 Scene *orig_scene = prefetch_get_original_scene(context);
1573 if (orig_scene->ed->cache_flag & SEQ_CACHE_STORE_RAW) {
1574 source_image_cache_put(&localcontext, strip, timeline_frame, ibufs_arr[view_id]);
1575 }
1576 }
1577
1579 }
1580
1581 /* return the original requested ImBuf */
1582 ibuf = ibufs_arr[context->view_id];
1583
1584 /* "remove" the others (decrease their refcount) */
1585 for (int view_id = 0; view_id < totviews; view_id++) {
1586 if (ibufs_arr[view_id] != ibuf) {
1587 IMB_freeImBuf(ibufs_arr[view_id]);
1588 }
1589 }
1590 MEM_freeN(ibufs_arr);
1591 }
1592
1593finally:
1594 /* restore */
1595 scene->r.scemode = orig_data.scemode;
1596 scene->r.cfra = orig_data.timeline_frame;
1597 scene->r.subframe = orig_data.subframe;
1598
1599 if (is_frame_update && (depsgraph != nullptr)) {
1601 }
1602
1603 /* stooping to new low's in hackyness :( */
1604 scene->r.mode &= orig_data.mode | ~R_NO_CAMERA_SWITCH;
1605
1606 return ibuf;
1607}
1608
1614 Strip *strip,
1615 float frame_index)
1616{
1617 ImBuf *ibuf = nullptr;
1618 ListBase *seqbase = nullptr;
1619 ListBase *channels = nullptr;
1620 int offset;
1621
1622 seqbase = get_seqbase_from_strip(strip, &channels, &offset);
1623
1624 if (seqbase && !BLI_listbase_is_empty(seqbase)) {
1625
1626 frame_index += offset;
1627
1628 if (strip->flag & SEQ_SCENE_STRIPS && strip->scene) {
1629 BKE_animsys_evaluate_all_animation(context->bmain, context->depsgraph, frame_index);
1630 }
1631
1633 context->scene, frame_index, context->view_id, context->rectx, context->recty);
1634 ibuf = seq_render_strip_stack(context,
1635 state,
1636 channels,
1637 seqbase,
1638 /* scene strips don't have their start taken into account */
1639 frame_index,
1640 0);
1641 }
1642
1643 return ibuf;
1644}
1645
1647
1648/* -------------------------------------------------------------------- */
1651
1654 Strip *strip,
1655 float timeline_frame,
1656 bool *r_is_proxy_image)
1657{
1658 ImBuf *ibuf = nullptr;
1659 float frame_index = give_frame_index(context->scene, strip, timeline_frame);
1660 int type = (strip->type & STRIP_TYPE_EFFECT) ? STRIP_TYPE_EFFECT : strip->type;
1661 switch (type) {
1662 case STRIP_TYPE_META: {
1663 ibuf = do_render_strip_seqbase(context, state, strip, frame_index);
1664 break;
1665 }
1666
1667 case STRIP_TYPE_SCENE: {
1668 if (strip->flag & SEQ_SCENE_STRIPS) {
1669 if (strip->scene && (context->scene != strip->scene)) {
1670 /* recursive check */
1671 if (BLI_linklist_index(state->scene_parents, strip->scene) != -1) {
1672 break;
1673 }
1674 LinkNode scene_parent{};
1675 scene_parent.next = state->scene_parents;
1676 scene_parent.link = strip->scene;
1677 state->scene_parents = &scene_parent;
1678 /* end check */
1679
1680 /* Use the Scene sequence-strip's scene for the context when rendering the
1681 * scene's sequences (necessary for multi-cam selector among others). */
1682 RenderData local_context = *context;
1683 local_context.scene = strip->scene;
1684 local_context.skip_cache = true;
1685
1686 ibuf = do_render_strip_seqbase(&local_context, state, strip, frame_index);
1687
1688 /* step back in the list */
1689 state->scene_parents = state->scene_parents->next;
1690 }
1691 }
1692 else {
1693 /* scene can be nullptr after deletions */
1694 ibuf = seq_render_scene_strip(context, strip, frame_index, timeline_frame);
1695 }
1696
1697 break;
1698 }
1699
1700 case STRIP_TYPE_EFFECT: {
1701 ibuf = seq_render_effect_strip_impl(context, state, strip, timeline_frame);
1702 break;
1703 }
1704
1705 case STRIP_TYPE_IMAGE: {
1706 ibuf = seq_render_image_strip(context, strip, timeline_frame, r_is_proxy_image);
1707 break;
1708 }
1709
1710 case STRIP_TYPE_MOVIE: {
1711 ibuf = seq_render_movie_strip(context, strip, timeline_frame, r_is_proxy_image);
1712 break;
1713 }
1714
1715 case STRIP_TYPE_MOVIECLIP: {
1717 context, strip, round_fl_to_int(frame_index), r_is_proxy_image);
1718
1719 if (ibuf) {
1720 /* duplicate frame so movie cache wouldn't be confused by sequencer's stuff */
1721 ImBuf *i = IMB_dupImBuf(ibuf);
1722 IMB_freeImBuf(ibuf);
1723 ibuf = i;
1724
1725 if (ibuf->float_buffer.data) {
1726 seq_imbuf_to_sequencer_space(context->scene, ibuf, false);
1727 }
1728 }
1729
1730 break;
1731 }
1732
1733 case STRIP_TYPE_MASK: {
1734 /* ibuf is always new */
1735 ibuf = seq_render_mask_strip(context, strip, frame_index);
1736 break;
1737 }
1738 }
1739
1740 if (ibuf) {
1741 seq_imbuf_assign_spaces(context->scene, ibuf);
1742 }
1743
1744 return ibuf;
1745}
1746
1749 Strip *strip,
1750 float timeline_frame)
1751{
1752 bool use_preprocess = false;
1753 bool is_proxy_image = false;
1754
1755 ImBuf *ibuf = intra_frame_cache_get_preprocessed(context->scene, strip);
1756 if (ibuf != nullptr) {
1757 return ibuf;
1758 }
1759
1760 /* Proxies are not stored in cache. */
1761 if (!can_use_proxy(context, strip, rendersize_to_proxysize(context->preview_render_size))) {
1762 ibuf = seq::source_image_cache_get(context, strip, timeline_frame);
1763 }
1764
1765 if (ibuf == nullptr) {
1766 ibuf = do_render_strip_uncached(context, state, strip, timeline_frame, &is_proxy_image);
1767 }
1768
1769 if (ibuf) {
1770 use_preprocess = seq_input_have_to_preprocess(context, strip, timeline_frame);
1772 context, strip, ibuf, timeline_frame, use_preprocess, is_proxy_image);
1773 intra_frame_cache_put_preprocessed(context->scene, strip, ibuf);
1774 }
1775
1776 if (ibuf == nullptr) {
1777 ibuf = IMB_allocImBuf(context->rectx, context->recty, 32, IB_byte_data);
1778 seq_imbuf_assign_spaces(context->scene, ibuf);
1779 }
1780
1781 return ibuf;
1782}
1783
1788
1790{
1792 float fac = strip->blend_opacity / 100.0f;
1793 StripEarlyOut early_out = sh.early_out(strip, fac);
1794
1796 return early_out;
1797 }
1798
1800 if (early_out == StripEarlyOut::UseInput2) {
1802 }
1803 if (early_out == StripEarlyOut::UseInput1) {
1805 }
1806 }
1807 return early_out;
1808}
1809
1811 const RenderData *context, Strip *strip, float timeline_frame, ImBuf *ibuf1, ImBuf *ibuf2)
1812{
1813 ImBuf *out;
1815 BLI_assert(sh.execute != nullptr);
1816 float fac = strip->blend_opacity / 100.0f;
1817 int swap_input = seq_must_swap_input_in_blend_mode(strip);
1818
1819 if (swap_input) {
1820 out = sh.execute(context, strip, timeline_frame, fac, ibuf2, ibuf1);
1821 }
1822 else {
1823 out = sh.execute(context, strip, timeline_frame, fac, ibuf1, ibuf2);
1824 }
1825
1826 return out;
1827}
1828
1829static bool is_opaque_alpha_over(const Strip *strip)
1830{
1831 if (strip->blend_mode != STRIP_TYPE_ALPHAOVER) {
1832 return false;
1833 }
1834 if (strip->blend_opacity < 100.0f) {
1835 return false;
1836 }
1837 if (strip->mul < 1.0f && (strip->flag & SEQ_MULTIPLY_ALPHA) != 0) {
1838 return false;
1839 }
1840 LISTBASE_FOREACH (StripModifierData *, smd, &strip->modifiers) {
1841 /* Assume result is not opaque if there is an enabled Mask modifier. */
1842 if ((smd->flag & SEQUENCE_MODIFIER_MUTE) == 0 && smd->type == seqModifierType_Mask) {
1843 return false;
1844 }
1845 }
1846 return true;
1847}
1848
1851 ListBase *channels,
1852 ListBase *seqbasep,
1853 float timeline_frame,
1854 int chanshown)
1855{
1857 context->scene, channels, seqbasep, timeline_frame, chanshown);
1858 if (strips.is_empty()) {
1859 return nullptr;
1860 }
1861
1862 OpaqueQuadTracker opaques;
1863
1864 int64_t i;
1865 ImBuf *out = nullptr;
1866 for (i = strips.size() - 1; i >= 0; i--) {
1867 Strip *strip = strips[i];
1868
1869 out = intra_frame_cache_get_composite(context->scene, strip);
1870 if (out) {
1871 break;
1872 }
1873 if (strip->blend_mode == SEQ_BLEND_REPLACE) {
1874 out = seq_render_strip(context, state, strip, timeline_frame);
1875 break;
1876 }
1877
1879
1880 if (early_out == StripEarlyOut::DoEffect && opaques.is_occluded(context, strip, i)) {
1881 early_out = StripEarlyOut::UseInput1;
1882 }
1883
1884 /* "Alpha over" is default for all strips, and it can be optimized in some cases:
1885 * - If the whole image has no transparency, there's no need to do actual blending.
1886 * - Likewise, if we are at the bottom of the stack; the input can be used as-is.
1887 * - If we are rendering a strip that is known to be opaque, we mark it as an occluder,
1888 * so that strips below can check if they are completely hidden. */
1889 if (out == nullptr && early_out == StripEarlyOut::DoEffect && is_opaque_alpha_over(strip)) {
1890 ImBuf *test = seq_render_strip(context, state, strip, timeline_frame);
1891 if (ELEM(test->planes, R_IMF_PLANES_BW, R_IMF_PLANES_RGB) || i == 0) {
1892 early_out = StripEarlyOut::UseInput2;
1893 }
1894 else {
1895 early_out = StripEarlyOut::DoEffect;
1896 }
1897 /* Free the image. It is stored in cache, so this doesn't affect performance. */
1898 IMB_freeImBuf(test);
1899
1900 /* Check whether the raw (before preprocessing, which can add alpha) strip content
1901 * was opaque. */
1902 ImBuf *ibuf_raw = seq::source_image_cache_get(context, strip, timeline_frame);
1903 if (ibuf_raw != nullptr) {
1904 if (ibuf_raw->planes != R_IMF_PLANES_RGBA) {
1905 opaques.add_occluder(context, strip, i);
1906 }
1907 IMB_freeImBuf(ibuf_raw);
1908 }
1909 }
1910
1911 switch (early_out) {
1914 out = seq_render_strip(context, state, strip, timeline_frame);
1915 break;
1917 if (i == 0) {
1918 out = IMB_allocImBuf(context->rectx, context->recty, 32, IB_byte_data);
1919 seq_imbuf_assign_spaces(context->scene, out);
1920 }
1921 break;
1923 if (i == 0) {
1924 /* This is an effect at the bottom of the stack, so one of the inputs does not exist yet:
1925 * create one that is transparent black. Extra optimization for an alpha over strip at
1926 * the bottom, we can just return it instead of blending with black. */
1927 ImBuf *ibuf2 = seq_render_strip(context, state, strip, timeline_frame);
1928 const bool use_float = ibuf2 && ibuf2->float_buffer.data;
1929 ImBuf *ibuf1 = IMB_allocImBuf(
1930 context->rectx, context->recty, 32, use_float ? IB_float_data : IB_byte_data);
1931 seq_imbuf_assign_spaces(context->scene, ibuf1);
1932
1933 out = seq_render_strip_stack_apply_effect(context, strip, timeline_frame, ibuf1, ibuf2);
1934 IMB_metadata_copy(out, ibuf2);
1935
1936 intra_frame_cache_put_composite(context->scene, strip, out);
1937
1938 IMB_freeImBuf(ibuf1);
1939 IMB_freeImBuf(ibuf2);
1940 }
1941 break;
1942 }
1943
1944 if (out) {
1945 break;
1946 }
1947 }
1948
1949 i++;
1950 for (; i < strips.size(); i++) {
1951 Strip *strip = strips[i];
1952
1953 if (opaques.is_occluded(context, strip, i)) {
1954 continue;
1955 }
1956
1958 ImBuf *ibuf1 = out;
1959 ImBuf *ibuf2 = seq_render_strip(context, state, strip, timeline_frame);
1960
1961 out = seq_render_strip_stack_apply_effect(context, strip, timeline_frame, ibuf1, ibuf2);
1962
1963 IMB_freeImBuf(ibuf1);
1964 IMB_freeImBuf(ibuf2);
1965 }
1966
1967 intra_frame_cache_put_composite(context->scene, strip, out);
1968 }
1969
1970 return out;
1971}
1972
1973static void evict_caches_if_full(Scene *scene)
1974{
1975 if (!is_cache_full(scene)) {
1976 return;
1977 }
1978
1979 /* Cache is full, so we want to remove some images. We always try to remove one final image,
1980 * and some amount of source images for each final image, so that ratio of cached images
1981 * stays the same. Depending on the frame composition complexity, there can be lots of
1982 * source images cached for a single final frame; if we only removed one source image
1983 * we'd eventually have the cache still filled only with source images. */
1984 const size_t count_final = final_image_cache_get_image_count(scene);
1985 const size_t count_source = source_image_cache_get_image_count(scene);
1986 const size_t source_per_final = std::max<size_t>(
1987 divide_ceil_ul(count_source, std::max<size_t>(count_final, 1)), 1);
1988
1989 do {
1990 bool evicted_final = final_image_cache_evict(scene);
1991 bool evicted_source = false;
1992 for (size_t i = 0; i < source_per_final; i++) {
1993 evicted_source |= source_image_cache_evict(scene);
1994 }
1995 if (!evicted_final && !evicted_source) {
1996 break; /* Can't evict no more. */
1997 }
1998 } while (is_cache_full(scene));
1999}
2000
2001ImBuf *render_give_ibuf(const RenderData *context, float timeline_frame, int chanshown)
2002{
2003 Scene *scene = context->scene;
2004 Editing *ed = editing_get(scene);
2005 ListBase *seqbasep;
2006 ListBase *channels;
2007
2008 if (ed == nullptr) {
2009 return nullptr;
2010 }
2011
2012 if ((chanshown < 0) && !BLI_listbase_is_empty(&ed->metastack)) {
2013 int count = BLI_listbase_count(&ed->metastack);
2014 count = max_ii(count + chanshown, 0);
2015 seqbasep = ((MetaStack *)BLI_findlink(&ed->metastack, count))->oldbasep;
2016 channels = ((MetaStack *)BLI_findlink(&ed->metastack, count))->old_channels;
2017 chanshown = 0;
2018 }
2019 else {
2020 seqbasep = ed->seqbasep;
2021 channels = ed->displayed_channels;
2022 }
2023
2025 scene, timeline_frame, context->view_id, context->rectx, context->recty);
2026
2027 Scene *orig_scene = prefetch_get_original_scene(context);
2028 ImBuf *out = nullptr;
2029 if (!context->skip_cache && !context->is_proxy_render) {
2030 out = final_image_cache_get(orig_scene, seqbasep, timeline_frame, context->view_id, chanshown);
2031 }
2032
2034 scene, channels, seqbasep, timeline_frame, chanshown);
2035
2036 /* Make sure we only keep the `anim` data for strips that are in view. */
2037 relations_free_all_anim_ibufs(context->scene, timeline_frame);
2038
2040
2041 if (!strips.is_empty() && !out) {
2042 std::scoped_lock lock(seq_render_mutex);
2043 out = seq_render_strip_stack(context, &state, channels, seqbasep, timeline_frame, chanshown);
2044
2045 evict_caches_if_full(orig_scene);
2046
2047 if (out && (orig_scene->ed->cache_flag & SEQ_CACHE_STORE_FINAL_OUT) && !context->skip_cache &&
2048 !context->is_proxy_render)
2049 {
2051 orig_scene, seqbasep, timeline_frame, context->view_id, chanshown, out);
2052 }
2053 }
2054
2055 seq_prefetch_start(context, timeline_frame);
2056
2057 return out;
2058}
2059
2061 float timeline_frame,
2062 int chan_shown,
2063 ListBase *channels,
2064 ListBase *seqbasep)
2065{
2067
2068 return seq_render_strip_stack(context, &state, channels, seqbasep, timeline_frame, chan_shown);
2069}
2070
2071ImBuf *render_give_ibuf_direct(const RenderData *context, float timeline_frame, Strip *strip)
2072{
2074
2076 context->scene, timeline_frame, context->view_id, context->rectx, context->recty);
2077 ImBuf *ibuf = seq_render_strip(context, &state, strip, timeline_frame);
2078 return ibuf;
2079}
2080
2081bool render_is_muted(const ListBase *channels, const Strip *strip)
2082{
2083 SeqTimelineChannel *channel = channel_get_by_index(channels, strip->channel);
2084 return strip->flag & SEQ_MUTE || channel_is_muted(channel);
2085}
2086
2088
2089} // namespace blender::seq
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:82
void BKE_animsys_evaluate_all_animation(struct Main *main, struct Depsgraph *depsgraph, float ctime)
Definition anim_sys.cc:4010
AnimationEvalContext BKE_animsys_eval_context_construct(struct Depsgraph *depsgraph, float eval_time) ATTR_WARN_UNUSED_RESULT
Definition anim_sys.cc:735
@ ADT_RECALC_ANIM
void BKE_animsys_evaluate_animdata(struct ID *id, struct AnimData *adt, const struct AnimationEvalContext *anim_eval_context, eAnimData_Recalc recalc, bool flush_to_original)
float evaluate_fcurve(const FCurve *fcu, float evaltime)
FCurve * id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *prop_name, int index, bool *r_driven)
MovieReader * openanim(const char *filepath, int flags, int streamindex, char colorspace[IMA_MAX_SPACE])
ViewLayer * BKE_view_layer_default_render(const Scene *scene)
void BKE_id_free(Main *bmain, void *idv)
@ LIB_ID_COPY_LOCALIZE
@ LIB_ID_COPY_NO_ANIMDATA
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:767
void BKE_maskrasterize_handle_free(MaskRasterHandle *mr_handle)
MaskRasterHandle * BKE_maskrasterize_handle_new(void)
void BKE_mask_evaluate(struct Mask *mask, float ctime, bool do_newframe)
void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mask, int width, int height, bool do_aspect_correct, bool do_mask_aa, bool do_feather)
void BKE_maskrasterize_buffer(MaskRasterHandle *mr_handle, unsigned int width, unsigned int height, float *buffer)
Rasterize a buffer from a single mask (threaded execution).
struct ImBuf * BKE_movieclip_get_stable_ibuf(struct MovieClip *clip, const struct MovieClipUser *user, int postprocess_flag, float r_loc[2], float *r_scale, float *r_angle)
bool BKE_movieclip_proxy_enabled(struct MovieClip *clip)
#define MOVIECLIP_CACHE_SKIP
void BKE_movieclip_user_set_frame(struct MovieClipUser *user, int framenr)
void BKE_movieclip_convert_multilayer_ibuf(struct ImBuf *ibuf)
Definition movieclip.cc:516
struct ImBuf * BKE_movieclip_get_ibuf_flag(struct MovieClip *clip, const struct MovieClipUser *user, int flag, int cache_flag)
void BKE_render_resolution(const RenderData *r, const bool use_crop, int *r_width, int *r_height)
Definition scene.cc:2927
int BKE_scene_multiview_num_views_get(const RenderData *rd)
Definition scene.cc:2952
void BKE_scene_frame_set(Scene *scene, float frame)
Definition scene.cc:2386
void BKE_scene_multiview_view_prefix_get(Scene *scene, const char *filepath, char *r_prefix, const char **r_ext)
Definition scene.cc:3176
bool BKE_scene_camera_switch_update(Scene *scene)
Definition scene.cc:2267
Depsgraph * BKE_scene_ensure_depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer)
Definition scene.cc:3427
void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph)
Definition scene.cc:2697
const char * BKE_scene_multiview_render_view_name_get(const RenderData *rd, int view_id)
Definition scene.cc:3083
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
BLI_INLINE bool BLI_listbase_count_is_equal_to(const ListBase *listbase, const int count_cmp)
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
MINLINE int round_fl_to_int(float a)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
MINLINE uint64_t divide_ceil_ul(uint64_t a, uint64_t b)
MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4])
int isect_point_quad_v2(const float p[2], const float v1[2], const float v2[2], const float v3[2], const float v4[2])
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
#define FILE_MAX
#define BLI_path_join(...)
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax)
Definition rct.cc:404
unsigned char uchar
unsigned int uint
#define UNLIKELY(x)
#define ELEM(...)
#define STREQ(a, b)
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
#define DNA_struct_default_get(struct_name)
struct ListBase ListBase
@ MCLIP_PROXY_RENDER_SIZE_75
@ MCLIP_PROXY_RENDER_SIZE_100
@ MCLIP_PROXY_RENDER_SIZE_50
@ MCLIP_PROXY_RENDER_SIZE_FULL
@ MCLIP_PROXY_RENDER_SIZE_25
@ MCLIP_PROXY_RENDER_USE_FALLBACK_RENDER
@ MCLIP_PROXY_RENDER_UNDISTORT
eDrawType
@ OB_RENDER
@ R_IMF_PLANES_RGB
@ R_IMF_PLANES_RGBA
@ R_IMF_PLANES_BW
@ R_SEQ_OVERRIDE_SCENE_SETTINGS
@ R_NO_CAMERA_SWITCH
@ R_IMF_VIEWS_STEREO_3D
@ R_MULTIVIEW
@ R_DOSEQ
@ R_DOCOMP
@ SEQ_STORAGE_PROXY_CUSTOM_FILE
@ SEQ_ALPHA_PREMUL
@ SEQUENCE_MODIFIER_MUTE
@ SEQ_EDIT_PROXY_DIR_STORAGE
@ SEQ_MOVIECLIP_RENDER_UNDISTORTED
@ SEQ_MOVIECLIP_RENDER_STABILIZED
@ STRIP_TYPE_SCENE
@ STRIP_TYPE_MOVIECLIP
@ STRIP_TYPE_IMAGE
@ STRIP_TYPE_MOVIE
@ STRIP_TYPE_SPEED
@ STRIP_TYPE_EFFECT
@ STRIP_TYPE_ADJUSTMENT
@ STRIP_TYPE_META
@ STRIP_TYPE_MASK
@ STRIP_TYPE_ALPHAUNDER
@ STRIP_TYPE_ALPHAOVER
@ seqModifierType_Mask
@ SEQ_TRANSFORM_FILTER_CUBIC_BSPLINE
@ SEQ_TRANSFORM_FILTER_AUTO
@ SEQ_TRANSFORM_FILTER_CUBIC_MITCHELL
@ SEQ_TRANSFORM_FILTER_BILINEAR
@ SEQ_TRANSFORM_FILTER_BOX
@ SEQ_TRANSFORM_FILTER_NEAREST
@ SEQ_EDIT_SHOW_MISSING_MEDIA
@ SEQ_CACHE_STORE_RAW
@ SEQ_CACHE_STORE_FINAL_OUT
@ SEQ_SPEED_USE_INTERPOLATION
@ SEQ_FILTERY
@ SEQ_FLIPX
@ SEQ_MAKE_FLOAT
@ SEQ_SCENE_STRIPS
@ SEQ_USE_PROXY
@ SEQ_USE_EFFECT_DEFAULT_FADE
@ SEQ_FLIPY
@ SEQ_MULTIPLY_ALPHA
@ SEQ_USE_VIEWS
@ SEQ_SCENE_NO_ANNOTATION
@ SEQ_BLEND_REPLACE
@ SEQ_RENDER_SIZE_SCENE
eV3DOffscreenDrawFlag
@ V3D_OFSDRAW_NONE
@ V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS
@ V3D_OFSDRAW_SHOW_ANNOTATION
void IMB_colormanagement_transform_byte_to_float(float *float_buffer, unsigned char *byte_buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace)
void IMB_colormanagement_assign_byte_colorspace(ImBuf *ibuf, const char *name)
void IMB_colormanagement_assign_float_colorspace(ImBuf *ibuf, const char *name)
void IMB_colormanagement_transform_float(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace, bool predivide)
@ COLOR_ROLE_SCENE_LINEAR
const char * IMB_colormanagement_role_colorspace_name_get(int role)
const char * IMB_colormanagement_get_rect_colorspace(ImBuf *ibuf)
void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace)
const char * IMB_colormanagement_get_float_colorspace(ImBuf *ibuf)
void IMB_flipy(ImBuf *ibuf)
ImBuf * IMB_load_image_from_filepath(const char *filepath, const int flags, char r_colorspace[IM_MAX_SPACE]=nullptr)
Definition readimage.cc:204
void IMB_flipx(ImBuf *ibuf)
ImBuf * IMB_dupImBuf(const ImBuf *ibuf1)
void IMB_transform(const ImBuf *src, ImBuf *dst, eIMBTransformMode mode, eIMBInterpolationFilterMode filter, const blender::float3x3 &transform_matrix, const rctf *src_crop)
Transform source image buffer onto destination image buffer using a transform matrix.
ImBuf * IMB_makeSingleUser(ImBuf *ibuf)
void IMB_assign_float_buffer(ImBuf *ibuf, float *buffer_data, ImBufOwnership ownership)
void IMB_ImBufFromStereo3d(const Stereo3dFormat *s3d, ImBuf *ibuf_stereo3d, ImBuf **r_ibuf_left, ImBuf **r_ibuf_right)
@ IMB_TRANSFORM_MODE_CROP_SRC
Crop the source buffer.
Definition IMB_imbuf.hh:590
void IMB_buffer_float_from_float_threaded(float *rect_to, const float *rect_from, int channels_from, int profile_to, int profile_from, bool predivide, int width, int height, int stride_to, int stride_from)
void IMB_freeImBuf(ImBuf *ibuf)
void IMB_saturation(ImBuf *ibuf, float sat)
size_t IMB_get_pixel_count(const ImBuf *ibuf)
Get the length of the data of the given image buffer in pixels.
ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
void IMB_free_byte_pixels(ImBuf *ibuf)
void IMB_filtery(ImBuf *ibuf)
Definition filter.cc:63
void IMB_rectfill(ImBuf *drect, const float col[4])
Definition rectop.cc:979
bool IMB_alloc_float_pixels(ImBuf *ibuf, const unsigned int channels, bool initialize_pixels=true)
eIMBInterpolationFilterMode
Definition IMB_imbuf.hh:287
@ IMB_FILTER_NEAREST
Definition IMB_imbuf.hh:288
@ IMB_FILTER_CUBIC_BSPLINE
Definition IMB_imbuf.hh:290
@ IMB_FILTER_CUBIC_MITCHELL
Definition IMB_imbuf.hh:291
@ IMB_FILTER_BILINEAR
Definition IMB_imbuf.hh:289
@ IMB_FILTER_BOX
Definition IMB_imbuf.hh:292
IMB_Proxy_Size
@ IMB_PROXY_100
@ IMB_PROXY_75
@ IMB_PROXY_50
@ IMB_PROXY_25
@ IMB_PROXY_NONE
@ IB_TAKE_OWNERSHIP
#define IB_PROFILE_LINEAR_RGB
@ IB_float_data
@ IB_alphamode_premul
@ IB_byte_data
@ IB_uninitialized_pixels
@ IB_metadata
@ IB_multilayer
void IMB_metadata_copy(ImBuf *ibuf_dst, const ImBuf *ibuf_src)
Definition metadata.cc:59
Read Guarded memory(de)allocation.
IMB_Timecode_Type
Definition MOV_enums.hh:44
@ IMB_TC_NONE
Definition MOV_enums.hh:46
volatile int lock
BPy_StructRNA * depsgraph
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
long long int int64_t
static void mul(btAlignedObjectArray< T > &items, const Q &value)
constexpr int64_t first() const
int64_t size() const
int64_t size() const
bool is_empty() const
#define floorf(x)
#define fabsf(x)
#define rot(x, k)
blender::gpu::Batch * quad
uint col
uint top
#define input
#define in
#define out
#define filter
#define ID_BLEND_PATH_FROM_GLOBAL(_id)
int count
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
static ulong state[N]
static int left
#define G(x, y, z)
float MOV_get_fps(const MovieReader *anim)
ImBuf * MOV_decode_frame(MovieReader *anim, int position, IMB_Timecode_Type tc, IMB_Proxy_Size preview_size)
CartesianBasis invert(const CartesianBasis &basis)
MatT from_origin_transform(const MatT &transform, const VectorT origin)
MatT from_loc_rot_scale(const typename MatT::loc_type &location, const RotationT &rotation, const VecBase< typename MatT::base_type, ScaleDim > &scale)
bool render_is_muted(const ListBase *channels, const Strip *strip)
Definition render.cc:2081
static ImBuf * seq_render_image_strip_view(const RenderData *context, Strip *strip, char *filepath, char *prefix, const char *ext, int view_id)
Definition render.cc:859
static ImBuf * seq_render_movie_strip(const RenderData *context, Strip *strip, float timeline_frame, bool *r_is_proxy_image)
Definition render.cc:1106
void source_image_cache_put(const RenderData *context, const Strip *strip, float timeline_frame, ImBuf *image)
void render_new_render_data(Main *bmain, Depsgraph *depsgraph, Scene *scene, int rectx, int recty, int preview_render_size, int for_render, RenderData *r_context)
Definition render.cc:206
static IMB_Timecode_Type seq_render_movie_strip_timecode_get(Strip *strip)
Definition render.cc:1042
void intra_frame_cache_set_cur_frame(Scene *scene, float frame, int view_id, int width, int height)
Array< float2 > image_transform_final_quad_get(const Scene *scene, const Strip *strip)
static ImBuf * do_render_strip_seqbase(const RenderData *context, SeqRenderState *state, Strip *strip, float frame_index)
Definition render.cc:1612
void seq_imbuf_to_sequencer_space(const Scene *scene, ImBuf *ibuf, bool make_float)
Definition render.cc:111
EffectHandle strip_effect_handle_get(Strip *strip)
Definition effects.cc:249
ImBuf * render_give_ibuf(const RenderData *context, float timeline_frame, int chanshown)
Definition render.cc:2001
void seq_imbuf_assign_spaces(const Scene *scene, ImBuf *ibuf)
Definition render.cc:98
static ImBuf * input_preprocess(const RenderData *context, Strip *strip, float timeline_frame, ImBuf *ibuf, const bool is_proxy_image)
Definition render.cc:625
SeqTimelineChannel * channel_get_by_index(const ListBase *channels, const int channel_index)
Definition channels.cc:65
static ImBuf * do_render_strip_uncached(const RenderData *context, SeqRenderState *state, Strip *strip, float timeline_frame, bool *r_is_proxy_image)
Definition render.cc:1652
static ImBuf * seq_render_scene_strip(const RenderData *context, Strip *strip, float frame_index, float timeline_frame)
Definition render.cc:1349
static ImBuf * seq_render_movie_strip_view(const RenderData *context, Strip *strip, float timeline_frame, StripAnim *sanim, bool *r_is_proxy_image)
Definition render.cc:1055
void relations_free_all_anim_ibufs(Scene *scene, int timeline_frame)
static ImBuf * seq_render_effect_strip_impl(const RenderData *context, SeqRenderState *state, Strip *strip, float timeline_frame)
Definition render.cc:733
float give_frame_index(const Scene *scene, const Strip *strip, float timeline_frame)
Definition strip_time.cc:52
ImBuf * seq_render_give_ibuf_seqbase(const RenderData *context, float timeline_frame, int chan_shown, ListBase *channels, ListBase *seqbasep)
Definition render.cc:2060
static bool is_opaque_alpha_over(const Strip *strip)
Definition render.cc:1829
bool source_image_cache_evict(Scene *scene)
static bool seq_must_swap_input_in_blend_mode(Strip *strip)
Definition render.cc:1784
Editing * editing_get(const Scene *scene)
Definition sequencer.cc:272
static ImBuf * seq_render_image_strip(const RenderData *context, Strip *strip, int timeline_frame, bool *r_is_proxy_image)
Definition render.cc:937
double rendersize_to_scale_factor(int render_size)
Definition proxy.cc:87
static ImBuf * seq_render_strip_stack_apply_effect(const RenderData *context, Strip *strip, float timeline_frame, ImBuf *ibuf1, ImBuf *ibuf2)
Definition render.cc:1810
ImBuf * seq_proxy_fetch(const RenderData *context, Strip *strip, int timeline_frame)
Definition proxy.cc:203
static ImBuf * seq_get_movieclip_ibuf(Strip *strip, MovieClipUser user)
Definition render.cc:1189
static void multiply_ibuf(ImBuf *ibuf, const float fmul, const bool multiply_alpha)
Definition render.cc:588
ImBuf * intra_frame_cache_get_composite(Scene *scene, const Strip *strip)
static bool is_quad_a_inside_b(const StripScreenQuad &a, const StripScreenQuad &b)
Definition render.cc:295
int rendersize_to_proxysize(int render_size)
Definition proxy.cc:72
void strip_open_anim_file(Scene *scene, Strip *strip, bool openfile)
static ImBuf * seq_render_preprocess_ibuf(const RenderData *context, Strip *strip, ImBuf *ibuf, float timeline_frame, bool use_preprocess, const bool is_proxy_image)
Definition render.cc:702
size_t source_image_cache_get_image_count(const Scene *scene)
void seq_prefetch_start(const RenderData *context, float timeline_frame)
Definition prefetch.cc:574
ImBuf * intra_frame_cache_get_preprocessed(Scene *scene, const Strip *strip)
static bool seq_image_strip_is_multiview_render(Scene *scene, Strip *strip, int totfiles, const char *filepath, char *r_prefix, const char *r_ext)
Definition render.cc:900
static ImBuf * create_missing_media_image(const RenderData *context, int width, int height)
Definition render.cc:920
constexpr int MAX_CHANNELS
struct ImBuf *(*)(struct Depsgraph *, struct Scene *, struct View3DShading *, eDrawType, struct Object *, int, int, enum eImBufFlags, eV3DOffscreenDrawFlag, int, const char *, struct GPUOffScreen *, struct GPUViewport *, char *) DrawViewFn
static ImBuf * seq_render_movie_strip_custom_file_proxy(const RenderData *context, Strip *strip, int timeline_frame)
Definition render.cc:1021
static ImBuf * seq_render_mask_strip(const RenderData *context, Strip *strip, float frame_index)
Definition render.cc:1342
static bool is_strip_covering_screen(const RenderData *context, const Strip *strip)
Definition render.cc:486
static blender::Mutex seq_render_mutex
Definition render.cc:91
float strip_speed_effect_target_frame_get(Scene *scene, Strip *strip_speed, float timeline_frame, int input)
StripScreenQuad get_strip_screen_quad(const RenderData *context, const Strip *strip)
Definition render.cc:276
static StripEarlyOut strip_get_early_out_for_blend_mode(Strip *strip)
Definition render.cc:1789
DrawViewFn view3d_fn
Definition render.cc:92
static ImBuf * seq_render_strip_stack(const RenderData *context, SeqRenderState *state, ListBase *channels, ListBase *seqbasep, float timeline_frame, int chanshown)
Definition render.cc:1849
bool can_use_proxy(const RenderData *context, const Strip *strip, int psize)
Definition proxy.cc:192
ImBuf * source_image_cache_get(const RenderData *context, const Strip *strip, float timeline_frame)
void final_image_cache_put(Scene *scene, const ListBase *seqbasep, const float timeline_frame, const int view_id, const int display_channel, ImBuf *image)
bool final_image_cache_evict(Scene *scene)
ImBuf * seq_render_mask(const RenderData *context, Mask *mask, float frame_index, bool make_float)
Definition render.cc:1259
void render_pixel_from_sequencer_space_v4(const Scene *scene, float pixel[4])
Definition render.cc:185
ImBuf * final_image_cache_get(Scene *scene, const ListBase *seqbasep, const float timeline_frame, const int view_id, const int display_channel)
bool is_cache_full(const Scene *scene)
void intra_frame_cache_put_composite(Scene *scene, const Strip *strip, ImBuf *image)
static void evict_caches_if_full(Scene *scene)
Definition render.cc:1973
static float3x3 sequencer_image_crop_transform_matrix(const Strip *strip, const ImBuf *in, const ImBuf *out, const float image_scale_factor, const float preview_scale_factor)
Definition render.cc:446
VectorSet< Strip * > query_rendered_strips(const Scene *scene, ListBase *channels, ListBase *seqbase, const int timeline_frame, const int displayed_channel)
Definition iterator.cc:205
void render_imbuf_from_sequencer_space(const Scene *scene, ImBuf *ibuf)
Definition render.cc:163
size_t final_image_cache_get_image_count(const Scene *scene)
static bool seq_input_have_to_preprocess(const RenderData *context, Strip *strip, float)
Definition render.cc:389
bool channel_is_muted(const SeqTimelineChannel *channel)
Definition channels.cc:86
void media_presence_set_missing(Scene *scene, const Strip *strip, bool missing)
Vector< Strip * > seq_shown_strips_get(const Scene *scene, ListBase *channels, ListBase *seqbase, const int timeline_frame, const int chanshown)
Definition render.cc:254
static eIMBInterpolationFilterMode get_auto_filter(const StripTransform *transform)
Definition render.cc:515
static bool sequencer_use_crop(const Strip *strip)
Definition render.cc:379
static void sequencer_preprocess_transform_crop(ImBuf *in, ImBuf *out, const RenderData *context, Strip *strip, const bool is_proxy_image)
Definition render.cc:534
static void sequencer_image_crop_init(const Strip *strip, const ImBuf *in, float crop_scale_factor, rctf *r_crop)
Definition render.cc:472
static void convert_multilayer_ibuf(ImBuf *ibuf)
Definition render.cc:832
ListBase * get_seqbase_from_strip(Strip *strip, ListBase **r_channels, int *r_offset)
bool seq_proxy_get_custom_file_filepath(Strip *strip, char *filepath, const int view_id)
Definition proxy.cc:100
int seq_num_files(Scene *scene, char views_format, const bool is_multiview)
Definition multiview.cc:29
void modifier_apply_stack(const RenderData *context, const Strip *strip, ImBuf *ibuf, int timeline_frame)
static bool sequencer_use_transform(const Strip *strip)
Definition render.cc:366
EffectHandle strip_effect_get_sequence_blend(Strip *strip)
Definition effects.cc:264
static ImBuf * seq_render_movieclip_strip(const RenderData *context, Strip *strip, float frame_index, bool *r_is_proxy_image)
Definition render.cc:1203
Scene * prefetch_get_original_scene(const RenderData *context)
Definition prefetch.cc:158
ImBuf * seq_render_strip(const RenderData *context, SeqRenderState *state, Strip *strip, float timeline_frame)
Definition render.cc:1747
StripElem * render_give_stripelem(const Scene *scene, const Strip *strip, int timeline_frame)
Definition render.cc:234
static bool seq_need_scale_to_render_size(const Strip *strip, bool is_proxy_image)
Definition render.cc:432
ImBuf * render_give_ibuf_direct(const RenderData *context, float timeline_frame, Strip *strip)
Definition render.cc:2071
int effect_get_num_inputs(int strip_type)
Definition effects.cc:286
void intra_frame_cache_put_preprocessed(Scene *scene, const Strip *strip, ImBuf *image)
void seq_multiview_name(Scene *scene, const int view_id, const char *prefix, const char *ext, char *r_path, size_t r_size)
Definition multiview.cc:42
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
VecBase< float, 2 > float2
VecBase< int32_t, 3 > int3
MatBase< float, 3, 3 > float3x3
std::mutex Mutex
Definition BLI_mutex.hh:47
#define PROXY_MAXFILE
Definition proxy.hh:19
void RE_ReleaseResultImage(Render *re)
void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id)
void RE_RenderFrame(Render *re, Main *bmain, Scene *scene, ViewLayer *single_layer, Object *camera_override, const int frame, const float subframe, const bool write_still)
Render * RE_NewSceneRender(const Scene *scene)
Render * RE_GetSceneRender(const Scene *scene)
ListBase seqbase
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
unsigned char planes
void * link
struct LinkNode * next
void * first
struct ImBuf * ibuf
struct bNodeTree * nodetree
struct Editing * ed
struct RenderData r
struct Object * camera
ColorManagedColorspaceSettings sequencer_colorspace_settings
struct StripAnim * next
struct MovieReader * anim
StripProxy * proxy
StripCrop * crop
StripTransform * transform
StripElem * stripdata
char dirpath[768]
ColorManagedColorspaceSettings colorspace_settings
char filename[256]
struct MovieReader * anim
struct Object * scene_camera
struct Stereo3dFormat * stereo3d_format
struct Strip * input1
struct Mask * mask
StripData * data
struct Scene * scene
struct MovieClip * clip
void * effectdata
float effect_fader
float blend_opacity
ListBase modifiers
struct Strip * input2
ListBase anims
ImBuf *(* execute)(const RenderData *context, Strip *strip, float timeline_frame, float fac, ImBuf *ibuf1, ImBuf *ibuf2)
void(* get_default_fac)(const Scene *scene, const Strip *strip, float timeline_frame, float *fac)
StripEarlyOut(* early_out)(const Strip *strip, float fac)
bool is_occluded(const RenderData *context, const Strip *strip, int order_index) const
Definition render.cc:319
void add_occluder(const RenderData *context, const Strip *strip, int order_index)
Definition render.cc:334
Vector< OpaqueQuad, 4 > opaques
Definition render.cc:312
StripScreenQuad quad
Definition render.cc:307
GPUOffScreen * gpu_offscreen
Definition SEQ_render.hh:50
GPUViewport * gpu_viewport
Definition SEQ_render.hh:51
i
Definition text_draw.cc:230
PointerRNA * ptr
Definition wm_files.cc:4226
uint8_t flag
Definition wm_window.cc:139