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
791 context->scene, target_frame, context->view_id, context->rectx, context->recty);
792 ibuf[i] = seq_render_strip(context, state, input[0], target_frame);
793 }
794 else { /* Other effects. */
795 if (input[i]) {
796 ibuf[i] = seq_render_strip(context, state, input[i], timeline_frame);
797 }
798 }
799 }
800
801 if (ibuf[0] && (ibuf[1] || effect_get_num_inputs(strip->type) == 1)) {
802 out = sh.execute(context, strip, timeline_frame, fac, ibuf[0], ibuf[1]);
803 }
804 break;
806 if (input[0]) {
807 out = seq_render_strip(context, state, input[0], timeline_frame);
808 }
809 break;
811 if (input[1]) {
812 out = seq_render_strip(context, state, input[1], timeline_frame);
813 }
814 break;
815 }
816
817 for (i = 0; i < 2; i++) {
818 IMB_freeImBuf(ibuf[i]);
819 }
820
821 if (out == nullptr) {
822 out = IMB_allocImBuf(context->rectx, context->recty, 32, IB_byte_data);
823 }
824
825 return out;
826}
827
829
830/* -------------------------------------------------------------------- */
833
835{
836 /* Load the combined/RGB layer, if this is a multi-layer image. */
838
839 /* Combined layer might be non-4 channels, however the rest
840 * of sequencer assumes RGBA everywhere. Convert to 4 channel if needed. */
841 if (ibuf->float_buffer.data != nullptr && ibuf->channels != 4) {
842 float *dst = MEM_malloc_arrayN<float>(4 * size_t(ibuf->x) * size_t(ibuf->y), __func__);
844 ibuf->float_buffer.data,
845 ibuf->channels,
848 false,
849 ibuf->x,
850 ibuf->y,
851 ibuf->x,
852 ibuf->x);
854 ibuf->channels = 4;
855 }
856}
857
862 Strip *strip,
863 char *filepath,
864 char *prefix,
865 const char *ext,
866 int view_id)
867{
868 ImBuf *ibuf = nullptr;
869
871 if (strip->alpha_mode == SEQ_ALPHA_PREMUL) {
873 }
874
875 if (prefix[0] == '\0') {
877 }
878 else {
879 char filepath_view[FILE_MAX];
880 BKE_scene_multiview_view_prefix_get(context->scene, filepath, prefix, &ext);
881 seq_multiview_name(context->scene, view_id, prefix, ext, filepath_view, FILE_MAX);
883 filepath_view, flag, strip->data->colorspace_settings.name);
884 }
885
886 if (ibuf == nullptr) {
887 return nullptr;
888 }
890
891 /* We don't need both (speed reasons)! */
892 if (ibuf->float_buffer.data != nullptr && ibuf->byte_buffer.data != nullptr) {
894 }
895
896 /* All sequencer color is done in SRGB space, linear gives odd cross-fades. */
897 seq_imbuf_to_sequencer_space(context->scene, ibuf, false);
898
899 return ibuf;
900}
901
903 Strip *strip,
904 int totfiles,
905 const char *filepath,
906 char *r_prefix,
907 const char *r_ext)
908{
909 if (totfiles > 1) {
910 BKE_scene_multiview_view_prefix_get(scene, filepath, r_prefix, &r_ext);
911 if (r_prefix[0] == '\0') {
912 return false;
913 }
914 }
915 else {
916 r_prefix[0] = '\0';
917 }
918
919 return (strip->flag & SEQ_USE_VIEWS) != 0 && (scene->r.scemode & R_MULTIVIEW) != 0;
920}
921
922static ImBuf *create_missing_media_image(const RenderData *context, int width, int height)
923{
924 if (context->ignore_missing_media) {
925 return nullptr;
926 }
927 if (context->scene == nullptr || context->scene->ed == nullptr ||
928 (context->scene->ed->show_missing_media_flag & SEQ_EDIT_SHOW_MISSING_MEDIA) == 0)
929 {
930 return nullptr;
931 }
932
933 ImBuf *ibuf = IMB_allocImBuf(max_ii(width, 1), max_ii(height, 1), 32, IB_byte_data);
934 float col[4] = {0.85f, 0.0f, 0.75f, 1.0f};
935 IMB_rectfill(ibuf, col);
936 return ibuf;
937}
938
940 Strip *strip,
941 int timeline_frame,
942 bool *r_is_proxy_image)
943{
944 char filepath[FILE_MAX];
945 const char *ext = nullptr;
946 char prefix[FILE_MAX];
947 ImBuf *ibuf = nullptr;
948
949 StripElem *s_elem = render_give_stripelem(context->scene, strip, timeline_frame);
950 if (s_elem == nullptr) {
951 return nullptr;
952 }
953
954 BLI_path_join(filepath, sizeof(filepath), strip->data->dirpath, s_elem->filename);
955 BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&context->scene->id));
956
957 /* Try to get a proxy image. */
958 ibuf = seq_proxy_fetch(context, strip, timeline_frame);
959 if (ibuf != nullptr) {
960 *r_is_proxy_image = true;
961 return ibuf;
962 }
963
964 /* Proxy not found, render original. */
965 const int totfiles = seq_num_files(context->scene, strip->views_format, true);
966 bool is_multiview_render = seq_image_strip_is_multiview_render(
967 context->scene, strip, totfiles, filepath, prefix, ext);
968
969 if (is_multiview_render) {
970 int totviews = BKE_scene_multiview_num_views_get(&context->scene->r);
971 ImBuf **ibufs_arr = MEM_calloc_arrayN<ImBuf *>(totviews, "Sequence Image Views Imbufs");
972
973 for (int view_id = 0; view_id < totfiles; view_id++) {
974 ibufs_arr[view_id] = seq_render_image_strip_view(
975 context, strip, filepath, prefix, ext, view_id);
976 }
977
978 if (ibufs_arr[0] == nullptr) {
979 return nullptr;
980 }
981
982 if (strip->views_format == R_IMF_VIEWS_STEREO_3D) {
983 IMB_ImBufFromStereo3d(strip->stereo3d_format, ibufs_arr[0], &ibufs_arr[0], &ibufs_arr[1]);
984 }
985
986 for (int view_id = 0; view_id < totviews; view_id++) {
987 RenderData localcontext = *context;
988 localcontext.view_id = view_id;
989
990 if (view_id != context->view_id) {
991 ibufs_arr[view_id] = seq_render_preprocess_ibuf(
992 &localcontext, strip, ibufs_arr[view_id], timeline_frame, true, false);
993 }
994 }
995
996 /* Return the original requested ImBuf. */
997 ibuf = ibufs_arr[context->view_id];
998
999 /* Remove the others (decrease their refcount). */
1000 for (int view_id = 0; view_id < totviews; view_id++) {
1001 if (ibufs_arr[view_id] != ibuf) {
1002 IMB_freeImBuf(ibufs_arr[view_id]);
1003 }
1004 }
1005
1006 MEM_freeN(ibufs_arr);
1007 }
1008 else {
1009 ibuf = seq_render_image_strip_view(context, strip, filepath, prefix, ext, context->view_id);
1010 }
1011
1012 blender::seq::media_presence_set_missing(context->scene, strip, ibuf == nullptr);
1013 if (ibuf == nullptr) {
1014 return create_missing_media_image(context, s_elem->orig_width, s_elem->orig_height);
1015 }
1016
1017 s_elem->orig_width = ibuf->x;
1018 s_elem->orig_height = ibuf->y;
1019
1020 return ibuf;
1021}
1022
1024 Strip *strip,
1025 int timeline_frame)
1026{
1027 char filepath[PROXY_MAXFILE];
1028 StripProxy *proxy = strip->data->proxy;
1029
1030 if (proxy->anim == nullptr) {
1031 if (seq_proxy_get_custom_file_filepath(strip, filepath, context->view_id)) {
1032 proxy->anim = openanim(filepath, IB_byte_data, 0, strip->data->colorspace_settings.name);
1033 }
1034 if (proxy->anim == nullptr) {
1035 return nullptr;
1036 }
1037 }
1038
1039 int frameno = round_fl_to_int(give_frame_index(context->scene, strip, timeline_frame)) +
1040 strip->anim_startofs;
1041 return MOV_decode_frame(proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE);
1042}
1043
1045{
1046 bool use_timecodes = (strip->flag & SEQ_USE_PROXY) != 0;
1047 if (!use_timecodes) {
1048 return IMB_TC_NONE;
1049 }
1050 return IMB_Timecode_Type(strip->data->proxy ? IMB_Timecode_Type(strip->data->proxy->tc) :
1051 IMB_TC_NONE);
1052}
1053
1058 Strip *strip,
1059 float timeline_frame,
1060 StripAnim *sanim,
1061 bool *r_is_proxy_image)
1062{
1063 ImBuf *ibuf = nullptr;
1064 IMB_Proxy_Size psize = IMB_Proxy_Size(rendersize_to_proxysize(context->preview_render_size));
1065 const int frame_index = round_fl_to_int(give_frame_index(context->scene, strip, timeline_frame));
1066
1067 if (can_use_proxy(context, strip, psize)) {
1068 /* Try to get a proxy image.
1069 * Movie proxies are handled by ImBuf module with exception of `custom file` setting. */
1070 if (context->scene->ed->proxy_storage != SEQ_EDIT_PROXY_DIR_STORAGE &&
1072 {
1073 ibuf = seq_render_movie_strip_custom_file_proxy(context, strip, timeline_frame);
1074 }
1075 else {
1076 ibuf = MOV_decode_frame(sanim->anim,
1077 frame_index + strip->anim_startofs,
1079 psize);
1080 }
1081
1082 if (ibuf != nullptr) {
1083 *r_is_proxy_image = true;
1084 }
1085 }
1086
1087 /* Fetching for requested proxy size failed, try fetching the original instead. */
1088 if (ibuf == nullptr) {
1089 ibuf = MOV_decode_frame(sanim->anim,
1090 frame_index + strip->anim_startofs,
1093 }
1094 if (ibuf == nullptr) {
1095 return nullptr;
1096 }
1097
1098 seq_imbuf_to_sequencer_space(context->scene, ibuf, false);
1099
1100 /* We don't need both (speed reasons)! */
1101 if (ibuf->float_buffer.data != nullptr && ibuf->byte_buffer.data != nullptr) {
1103 }
1104
1105 return ibuf;
1106}
1107
1109 Strip *strip,
1110 float timeline_frame,
1111 bool *r_is_proxy_image)
1112{
1113 /* Load all the videos. */
1114 strip_open_anim_file(context->scene, strip, false);
1115
1116 ImBuf *ibuf = nullptr;
1117 StripAnim *sanim = static_cast<StripAnim *>(strip->anims.first);
1118 const int totfiles = seq_num_files(context->scene, strip->views_format, true);
1119 bool is_multiview_render = (strip->flag & SEQ_USE_VIEWS) != 0 &&
1120 (context->scene->r.scemode & R_MULTIVIEW) != 0 &&
1121 BLI_listbase_count_is_equal_to(&strip->anims, totfiles);
1122
1123 if (is_multiview_render) {
1124 ImBuf **ibuf_arr;
1125 int totviews = BKE_scene_multiview_num_views_get(&context->scene->r);
1126 ibuf_arr = MEM_calloc_arrayN<ImBuf *>(totviews, "Sequence Image Views Imbufs");
1127 int ibuf_view_id;
1128
1129 for (ibuf_view_id = 0, sanim = static_cast<StripAnim *>(strip->anims.first); sanim;
1130 sanim = sanim->next, ibuf_view_id++)
1131 {
1132 if (sanim->anim) {
1133 ibuf_arr[ibuf_view_id] = seq_render_movie_strip_view(
1134 context, strip, timeline_frame, sanim, r_is_proxy_image);
1135 }
1136 }
1137
1138 if (strip->views_format == R_IMF_VIEWS_STEREO_3D) {
1139 if (ibuf_arr[0] == nullptr) {
1140 /* Probably proxy hasn't been created yet. */
1141 MEM_freeN(ibuf_arr);
1142 return nullptr;
1143 }
1144
1145 IMB_ImBufFromStereo3d(strip->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
1146 }
1147
1148 for (int view_id = 0; view_id < totviews; view_id++) {
1149 RenderData localcontext = *context;
1150 localcontext.view_id = view_id;
1151
1152 if (view_id != context->view_id && ibuf_arr[view_id]) {
1153 ibuf_arr[view_id] = seq_render_preprocess_ibuf(
1154 &localcontext, strip, ibuf_arr[view_id], timeline_frame, true, false);
1155 }
1156 }
1157
1158 /* Return the original requested ImBuf. */
1159 ibuf = ibuf_arr[context->view_id];
1160
1161 /* Remove the others (decrease their refcount). */
1162 for (int view_id = 0; view_id < totviews; view_id++) {
1163 if (ibuf_arr[view_id] != ibuf) {
1164 IMB_freeImBuf(ibuf_arr[view_id]);
1165 }
1166 }
1167
1168 MEM_freeN(ibuf_arr);
1169 }
1170 else {
1171 ibuf = seq_render_movie_strip_view(context, strip, timeline_frame, sanim, r_is_proxy_image);
1172 }
1173
1174 blender::seq::media_presence_set_missing(context->scene, strip, ibuf == nullptr);
1175 if (ibuf == nullptr) {
1177 context, strip->data->stripdata->orig_width, strip->data->stripdata->orig_height);
1178 }
1179
1180 if (*r_is_proxy_image == false) {
1181 if (sanim && sanim->anim) {
1182 strip->data->stripdata->orig_fps = MOV_get_fps(sanim->anim);
1183 }
1184 strip->data->stripdata->orig_width = ibuf->x;
1185 strip->data->stripdata->orig_height = ibuf->y;
1186 }
1187
1188 return ibuf;
1189}
1190
1192{
1193 ImBuf *ibuf = nullptr;
1194 float tloc[2], tscale, tangle;
1196 ibuf = BKE_movieclip_get_stable_ibuf(strip->clip, &user, 0, tloc, &tscale, &tangle);
1197 }
1198 else {
1200 strip->clip, &user, strip->clip->flag, MOVIECLIP_CACHE_SKIP);
1201 }
1202 return ibuf;
1203}
1204
1206 Strip *strip,
1207 float frame_index,
1208 bool *r_is_proxy_image)
1209{
1210 ImBuf *ibuf = nullptr;
1212 IMB_Proxy_Size psize = IMB_Proxy_Size(rendersize_to_proxysize(context->preview_render_size));
1213
1214 if (!strip->clip) {
1215 return nullptr;
1216 }
1217
1219 frame_index + strip->anim_startofs + strip->clip->start_frame);
1220
1222 switch (psize) {
1223 case IMB_PROXY_NONE:
1225 break;
1226 case IMB_PROXY_100:
1228 break;
1229 case IMB_PROXY_75:
1231 break;
1232 case IMB_PROXY_50:
1234 break;
1235 case IMB_PROXY_25:
1237 break;
1238 }
1239
1242 }
1243
1244 /* Try to get a proxy image. */
1245 ibuf = seq_get_movieclip_ibuf(strip, user);
1246
1247 /* If clip doesn't use proxies, it will fall back to full size render of original file. */
1248 if (ibuf != nullptr && psize != IMB_PROXY_NONE && BKE_movieclip_proxy_enabled(strip->clip)) {
1249 *r_is_proxy_image = true;
1250 }
1251
1252 /* If proxy is not found, grab full-size frame. */
1253 if (ibuf == nullptr) {
1255 ibuf = seq_get_movieclip_ibuf(strip, user);
1256 }
1257
1258 return ibuf;
1259}
1260
1261ImBuf *seq_render_mask(const RenderData *context, Mask *mask, float frame_index, bool make_float)
1262{
1263 /* TODO: add option to rasterize to alpha imbuf? */
1264 ImBuf *ibuf = nullptr;
1265 float *maskbuf;
1266 int i;
1267
1268 if (!mask) {
1269 return nullptr;
1270 }
1271
1272 AnimData *adt;
1273 Mask *mask_temp;
1274 MaskRasterHandle *mr_handle;
1275
1276 mask_temp = (Mask *)BKE_id_copy_ex(
1277 nullptr, &mask->id, nullptr, LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA);
1278
1279 BKE_mask_evaluate(mask_temp, mask->sfra + frame_index, true);
1280
1281 /* anim-data */
1282 adt = BKE_animdata_from_id(&mask->id);
1284 context->depsgraph, mask->sfra + frame_index);
1285 BKE_animsys_evaluate_animdata(&mask_temp->id, adt, &anim_eval_context, ADT_RECALC_ANIM, false);
1286
1287 maskbuf = MEM_malloc_arrayN<float>(size_t(context->rectx) * size_t(context->recty), __func__);
1288
1289 mr_handle = BKE_maskrasterize_handle_new();
1290
1292 mr_handle, mask_temp, context->rectx, context->recty, true, true, true);
1293
1294 BKE_id_free(nullptr, &mask_temp->id);
1295
1296 BKE_maskrasterize_buffer(mr_handle, context->rectx, context->recty, maskbuf);
1297
1299
1300 if (make_float) {
1301 /* pixels */
1302 const float *fp_src;
1303 float *fp_dst;
1304
1305 ibuf = IMB_allocImBuf(
1306 context->rectx, context->recty, 32, IB_float_data | IB_uninitialized_pixels);
1307
1308 fp_src = maskbuf;
1309 fp_dst = ibuf->float_buffer.data;
1310 i = context->rectx * context->recty;
1311 while (--i) {
1312 fp_dst[0] = fp_dst[1] = fp_dst[2] = *fp_src;
1313 fp_dst[3] = 1.0f;
1314
1315 fp_src += 1;
1316 fp_dst += 4;
1317 }
1318 }
1319 else {
1320 /* pixels */
1321 const float *fp_src;
1322 uchar *ub_dst;
1323
1324 ibuf = IMB_allocImBuf(
1325 context->rectx, context->recty, 32, IB_byte_data | IB_uninitialized_pixels);
1326
1327 fp_src = maskbuf;
1328 ub_dst = ibuf->byte_buffer.data;
1329 i = context->rectx * context->recty;
1330 while (--i) {
1331 ub_dst[0] = ub_dst[1] = ub_dst[2] = uchar(*fp_src * 255.0f); /* already clamped */
1332 ub_dst[3] = 255;
1333
1334 fp_src += 1;
1335 ub_dst += 4;
1336 }
1337 }
1338
1339 MEM_freeN(maskbuf);
1340
1341 return ibuf;
1342}
1343
1344static ImBuf *seq_render_mask_strip(const RenderData *context, Strip *strip, float frame_index)
1345{
1346 bool make_float = (strip->flag & SEQ_MAKE_FLOAT) != 0;
1347
1348 return seq_render_mask(context, strip->mask, frame_index, make_float);
1349}
1350
1352 Strip *strip,
1353 float frame_index,
1354 float timeline_frame)
1355{
1356 ImBuf *ibuf = nullptr;
1357 double frame;
1358 Object *camera;
1359
1360 struct {
1361 int scemode;
1362 int timeline_frame;
1363 float subframe;
1364 int mode;
1365 } orig_data;
1366
1367 /* Old info:
1368 * Hack! This function can be called from do_render_seq(), in that case
1369 * the strip->scene can already have a Render initialized with same name,
1370 * so we have to use a default name. (compositor uses scene name to
1371 * find render).
1372 * However, when called from within the UI (image preview in sequencer)
1373 * we do want to use scene Render, that way the render result is defined
1374 * for display in render/image-window
1375 *
1376 * Hmm, don't see, why we can't do that all the time,
1377 * and since G.is_rendering is uhm, gone... (Peter)
1378 */
1379
1380 /* New info:
1381 * Using the same name for the renders works just fine as the do_render_seq()
1382 * render is not used while the scene strips are rendered.
1383 *
1384 * However rendering from UI (through sequencer_preview_area_draw) can crash in
1385 * very many cases since other renders (material preview, an actual render etc.)
1386 * can be started while this sequence preview render is running. The only proper
1387 * solution is to make the sequencer preview render a proper job, which can be
1388 * stopped when needed. This would also give a nice progress bar for the preview
1389 * space so that users know there's something happening.
1390 *
1391 * As a result the active scene now only uses OpenGL rendering for the sequencer
1392 * preview. This is far from nice, but is the only way to prevent crashes at this
1393 * time.
1394 *
1395 * -jahka
1396 */
1397
1398 const bool is_rendering = G.is_rendering;
1399 bool is_preview = !context->for_render && (context->scene->r.seq_prev_type) != OB_RENDER;
1400
1401 bool have_comp = false;
1402 bool use_gpencil = true;
1403 /* do we need to re-evaluate the frame after rendering? */
1404 bool is_frame_update = false;
1405 Scene *scene;
1406
1407 /* don't refer to strip->scene above this point!, it can be nullptr */
1408 if (strip->scene == nullptr) {
1409 return create_missing_media_image(context, context->rectx, context->recty);
1410 }
1411
1412 /* Prevent rendering scene recursively. */
1413 if (strip->scene == context->scene) {
1414 return nullptr;
1415 }
1416
1417 scene = strip->scene;
1418 frame = double(scene->r.sfra) + double(frame_index) + double(strip->anim_startofs);
1419
1420#if 0 /* UNUSED */
1421 have_seq = (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first;
1422#endif
1423 have_comp = (scene->r.scemode & R_DOCOMP) && scene->use_nodes && scene->nodetree;
1424
1425 /* Get view layer for the strip. */
1426 ViewLayer *view_layer = BKE_view_layer_default_render(scene);
1427 /* Depsgraph will be nullptr when doing rendering. */
1428 Depsgraph *depsgraph = nullptr;
1429
1430 orig_data.scemode = scene->r.scemode;
1431 orig_data.timeline_frame = scene->r.cfra;
1432 orig_data.subframe = scene->r.subframe;
1433 orig_data.mode = scene->r.mode;
1434
1435 BKE_scene_frame_set(scene, frame);
1436
1437 if (strip->scene_camera) {
1438 camera = strip->scene_camera;
1439 }
1440 else {
1442 camera = scene->camera;
1443 }
1444
1445 if (have_comp == false && camera == nullptr) {
1446 goto finally;
1447 }
1448
1449 if (strip->flag & SEQ_SCENE_NO_ANNOTATION) {
1450 use_gpencil = false;
1451 }
1452
1453 /* prevent eternal loop */
1454 scene->r.scemode &= ~R_DOSEQ;
1455
1456 /* stooping to new low's in hackyness :( */
1457 scene->r.mode |= R_NO_CAMERA_SWITCH;
1458
1459 is_frame_update = (orig_data.timeline_frame != scene->r.cfra) ||
1460 (orig_data.subframe != scene->r.subframe);
1461
1462 if (view3d_fn && is_preview && camera) {
1463 char err_out[256] = "unknown";
1464 int width, height;
1465 BKE_render_resolution(&scene->r, false, &width, &height);
1466 const char *viewname = BKE_scene_multiview_render_view_name_get(&scene->r, context->view_id);
1467
1468 uint draw_flags = V3D_OFSDRAW_NONE;
1469 draw_flags |= (use_gpencil) ? V3D_OFSDRAW_SHOW_ANNOTATION : 0;
1470 draw_flags |= (context->scene->r.seq_flag & R_SEQ_OVERRIDE_SCENE_SETTINGS) ?
1472 0;
1473
1474 /* for old scene this can be uninitialized,
1475 * should probably be added to do_versions at some point if the functionality stays */
1476 if (context->scene->r.seq_prev_type == 0) {
1477 context->scene->r.seq_prev_type = 3 /* == OB_SOLID */;
1478 }
1479
1480 /* opengl offscreen render */
1481 depsgraph = BKE_scene_ensure_depsgraph(context->bmain, scene, view_layer);
1483 Object *camera_eval = DEG_get_evaluated(depsgraph, camera);
1485 ibuf = view3d_fn(
1486 /* set for OpenGL render (nullptr when scrubbing) */
1487 depsgraph,
1488 scene_eval,
1489 &context->scene->display.shading,
1490 eDrawType(context->scene->r.seq_prev_type),
1491 camera_eval,
1492 width,
1493 height,
1495 eV3DOffscreenDrawFlag(draw_flags),
1496 scene->r.alphamode,
1497 viewname,
1498 context->gpu_offscreen,
1499 context->gpu_viewport,
1500 err_out);
1501 if (ibuf == nullptr) {
1502 fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out);
1503 }
1504 }
1505 else {
1506 Render *re = RE_GetSceneRender(scene);
1507 const int totviews = BKE_scene_multiview_num_views_get(&scene->r);
1508 ImBuf **ibufs_arr;
1509
1510 /*
1511 * XXX: this if can be removed when sequence preview rendering uses the job system
1512 *
1513 * Disable rendered preview for sequencer while rendering - invoked render job will
1514 * conflict with already running render
1515 *
1516 * When rendering from command line renderer is called from main thread, in this
1517 * case it's always safe to render scene here
1518 */
1519
1520 if (is_preview && (is_rendering && !G.background)) {
1521 goto finally;
1522 }
1523
1524 ibufs_arr = MEM_calloc_arrayN<ImBuf *>(totviews, "Sequence Image Views Imbufs");
1525
1526 if (re == nullptr) {
1527 re = RE_NewSceneRender(scene);
1528 }
1529
1530 const float subframe = frame - floorf(frame);
1531
1532 RE_RenderFrame(re,
1533 context->bmain,
1534 scene,
1535 have_comp ? nullptr : view_layer,
1536 camera,
1537 floorf(frame),
1538 subframe,
1539 false);
1540
1541 /* restore previous state after it was toggled on & off by RE_RenderFrame */
1542 G.is_rendering = is_rendering;
1543
1544 for (int view_id = 0; view_id < totviews; view_id++) {
1545 RenderData localcontext = *context;
1546 RenderResult rres;
1547
1548 localcontext.view_id = view_id;
1549
1550 RE_AcquireResultImage(re, &rres, view_id);
1551
1552 /* TODO: Share the pixel data with the original image buffer from the render result using
1553 * implicit sharing. */
1554 if (rres.ibuf && rres.ibuf->float_buffer.data) {
1555 ibufs_arr[view_id] = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_float_data);
1556 memcpy(ibufs_arr[view_id]->float_buffer.data,
1557 rres.ibuf->float_buffer.data,
1558 sizeof(float[4]) * rres.rectx * rres.recty);
1559
1560 /* float buffers in the sequencer are not linear */
1561 seq_imbuf_to_sequencer_space(context->scene, ibufs_arr[view_id], false);
1562 }
1563 else if (rres.ibuf && rres.ibuf->byte_buffer.data) {
1564 ibufs_arr[view_id] = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_byte_data);
1565 memcpy(ibufs_arr[view_id]->byte_buffer.data,
1566 rres.ibuf->byte_buffer.data,
1567 4 * rres.rectx * rres.recty);
1568 }
1569 else {
1570 ibufs_arr[view_id] = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_byte_data);
1571 }
1572
1573 if (view_id != context->view_id) {
1574 Scene *orig_scene = prefetch_get_original_scene(context);
1575 if (orig_scene->ed->cache_flag & SEQ_CACHE_STORE_RAW) {
1576 source_image_cache_put(&localcontext, strip, timeline_frame, ibufs_arr[view_id]);
1577 }
1578 }
1579
1581 }
1582
1583 /* return the original requested ImBuf */
1584 ibuf = ibufs_arr[context->view_id];
1585
1586 /* "remove" the others (decrease their refcount) */
1587 for (int view_id = 0; view_id < totviews; view_id++) {
1588 if (ibufs_arr[view_id] != ibuf) {
1589 IMB_freeImBuf(ibufs_arr[view_id]);
1590 }
1591 }
1592 MEM_freeN(ibufs_arr);
1593 }
1594
1595finally:
1596 /* restore */
1597 scene->r.scemode = orig_data.scemode;
1598 scene->r.cfra = orig_data.timeline_frame;
1599 scene->r.subframe = orig_data.subframe;
1600
1601 if (is_frame_update && (depsgraph != nullptr)) {
1603 }
1604
1605 /* stooping to new low's in hackyness :( */
1606 scene->r.mode &= orig_data.mode | ~R_NO_CAMERA_SWITCH;
1607
1608 return ibuf;
1609}
1610
1616 Strip *strip,
1617 float frame_index)
1618{
1619 ImBuf *ibuf = nullptr;
1620 ListBase *seqbase = nullptr;
1621 ListBase *channels = nullptr;
1622 int offset;
1623
1624 seqbase = get_seqbase_from_strip(strip, &channels, &offset);
1625
1626 if (seqbase && !BLI_listbase_is_empty(seqbase)) {
1627
1628 frame_index += offset;
1629
1630 if (strip->flag & SEQ_SCENE_STRIPS && strip->scene) {
1631 BKE_animsys_evaluate_all_animation(context->bmain, context->depsgraph, frame_index);
1632 }
1633
1635 context->scene, frame_index, context->view_id, context->rectx, context->recty);
1636 ibuf = seq_render_strip_stack(context,
1637 state,
1638 channels,
1639 seqbase,
1640 /* scene strips don't have their start taken into account */
1641 frame_index,
1642 0);
1643 }
1644
1645 return ibuf;
1646}
1647
1649
1650/* -------------------------------------------------------------------- */
1653
1656 Strip *strip,
1657 float timeline_frame,
1658 bool *r_is_proxy_image)
1659{
1660 ImBuf *ibuf = nullptr;
1661 float frame_index = give_frame_index(context->scene, strip, timeline_frame);
1662 int type = (strip->type & STRIP_TYPE_EFFECT) ? STRIP_TYPE_EFFECT : strip->type;
1663 switch (type) {
1664 case STRIP_TYPE_META: {
1665 ibuf = do_render_strip_seqbase(context, state, strip, frame_index);
1666 break;
1667 }
1668
1669 case STRIP_TYPE_SCENE: {
1670 if (strip->flag & SEQ_SCENE_STRIPS) {
1671 if (strip->scene && (context->scene != strip->scene)) {
1672 /* recursive check */
1673 if (BLI_linklist_index(state->scene_parents, strip->scene) != -1) {
1674 break;
1675 }
1676 LinkNode scene_parent{};
1677 scene_parent.next = state->scene_parents;
1678 scene_parent.link = strip->scene;
1679 state->scene_parents = &scene_parent;
1680 /* end check */
1681
1682 /* Use the Scene sequence-strip's scene for the context when rendering the
1683 * scene's sequences (necessary for multi-cam selector among others). */
1684 RenderData local_context = *context;
1685 local_context.scene = strip->scene;
1686 local_context.skip_cache = true;
1687
1688 ibuf = do_render_strip_seqbase(&local_context, state, strip, frame_index);
1689
1690 /* step back in the list */
1691 state->scene_parents = state->scene_parents->next;
1692 }
1693 }
1694 else {
1695 /* scene can be nullptr after deletions */
1696 ibuf = seq_render_scene_strip(context, strip, frame_index, timeline_frame);
1697 }
1698
1699 break;
1700 }
1701
1702 case STRIP_TYPE_EFFECT: {
1703 ibuf = seq_render_effect_strip_impl(context, state, strip, timeline_frame);
1704 break;
1705 }
1706
1707 case STRIP_TYPE_IMAGE: {
1708 ibuf = seq_render_image_strip(context, strip, timeline_frame, r_is_proxy_image);
1709 break;
1710 }
1711
1712 case STRIP_TYPE_MOVIE: {
1713 ibuf = seq_render_movie_strip(context, strip, timeline_frame, r_is_proxy_image);
1714 break;
1715 }
1716
1717 case STRIP_TYPE_MOVIECLIP: {
1719 context, strip, round_fl_to_int(frame_index), r_is_proxy_image);
1720
1721 if (ibuf) {
1722 /* duplicate frame so movie cache wouldn't be confused by sequencer's stuff */
1723 ImBuf *i = IMB_dupImBuf(ibuf);
1724 IMB_freeImBuf(ibuf);
1725 ibuf = i;
1726
1727 if (ibuf->float_buffer.data) {
1728 seq_imbuf_to_sequencer_space(context->scene, ibuf, false);
1729 }
1730 }
1731
1732 break;
1733 }
1734
1735 case STRIP_TYPE_MASK: {
1736 /* ibuf is always new */
1737 ibuf = seq_render_mask_strip(context, strip, frame_index);
1738 break;
1739 }
1740 }
1741
1742 if (ibuf) {
1743 seq_imbuf_assign_spaces(context->scene, ibuf);
1744 }
1745
1746 return ibuf;
1747}
1748
1751 Strip *strip,
1752 float timeline_frame)
1753{
1754 bool use_preprocess = false;
1755 bool is_proxy_image = false;
1756
1757 ImBuf *ibuf = intra_frame_cache_get_preprocessed(context->scene, strip);
1758 if (ibuf != nullptr) {
1759 return ibuf;
1760 }
1761
1762 /* Proxies are not stored in cache. */
1763 if (!can_use_proxy(context, strip, rendersize_to_proxysize(context->preview_render_size))) {
1764 ibuf = seq::source_image_cache_get(context, strip, timeline_frame);
1765 }
1766
1767 if (ibuf == nullptr) {
1768 ibuf = do_render_strip_uncached(context, state, strip, timeline_frame, &is_proxy_image);
1769 }
1770
1771 if (ibuf) {
1772 use_preprocess = seq_input_have_to_preprocess(context, strip, timeline_frame);
1774 context, strip, ibuf, timeline_frame, use_preprocess, is_proxy_image);
1775 intra_frame_cache_put_preprocessed(context->scene, strip, ibuf);
1776 }
1777
1778 if (ibuf == nullptr) {
1779 ibuf = IMB_allocImBuf(context->rectx, context->recty, 32, IB_byte_data);
1780 seq_imbuf_assign_spaces(context->scene, ibuf);
1781 }
1782
1783 return ibuf;
1784}
1785
1790
1792{
1794 float fac = strip->blend_opacity / 100.0f;
1795 StripEarlyOut early_out = sh.early_out(strip, fac);
1796
1798 return early_out;
1799 }
1800
1802 if (early_out == StripEarlyOut::UseInput2) {
1804 }
1805 if (early_out == StripEarlyOut::UseInput1) {
1807 }
1808 }
1809 return early_out;
1810}
1811
1813 const RenderData *context, Strip *strip, float timeline_frame, ImBuf *ibuf1, ImBuf *ibuf2)
1814{
1815 ImBuf *out;
1817 BLI_assert(sh.execute != nullptr);
1818 float fac = strip->blend_opacity / 100.0f;
1819 int swap_input = seq_must_swap_input_in_blend_mode(strip);
1820
1821 if (swap_input) {
1822 out = sh.execute(context, strip, timeline_frame, fac, ibuf2, ibuf1);
1823 }
1824 else {
1825 out = sh.execute(context, strip, timeline_frame, fac, ibuf1, ibuf2);
1826 }
1827
1828 return out;
1829}
1830
1831static bool is_opaque_alpha_over(const Strip *strip)
1832{
1833 if (strip->blend_mode != STRIP_TYPE_ALPHAOVER) {
1834 return false;
1835 }
1836 if (strip->blend_opacity < 100.0f) {
1837 return false;
1838 }
1839 if (strip->mul < 1.0f && (strip->flag & SEQ_MULTIPLY_ALPHA) != 0) {
1840 return false;
1841 }
1842 LISTBASE_FOREACH (StripModifierData *, smd, &strip->modifiers) {
1843 /* Assume result is not opaque if there is an enabled Mask modifier. */
1844 if ((smd->flag & SEQUENCE_MODIFIER_MUTE) == 0 && smd->type == seqModifierType_Mask) {
1845 return false;
1846 }
1847 }
1848 return true;
1849}
1850
1853 ListBase *channels,
1854 ListBase *seqbasep,
1855 float timeline_frame,
1856 int chanshown)
1857{
1859 context->scene, channels, seqbasep, timeline_frame, chanshown);
1860 if (strips.is_empty()) {
1861 return nullptr;
1862 }
1863
1864 OpaqueQuadTracker opaques;
1865
1866 int64_t i;
1867 ImBuf *out = nullptr;
1868 for (i = strips.size() - 1; i >= 0; i--) {
1869 Strip *strip = strips[i];
1870
1871 out = intra_frame_cache_get_composite(context->scene, strip);
1872 if (out) {
1873 break;
1874 }
1875 if (strip->blend_mode == SEQ_BLEND_REPLACE) {
1876 out = seq_render_strip(context, state, strip, timeline_frame);
1877 break;
1878 }
1879
1881
1882 if (early_out == StripEarlyOut::DoEffect && opaques.is_occluded(context, strip, i)) {
1883 early_out = StripEarlyOut::UseInput1;
1884 }
1885
1886 /* "Alpha over" is default for all strips, and it can be optimized in some cases:
1887 * - If the whole image has no transparency, there's no need to do actual blending.
1888 * - Likewise, if we are at the bottom of the stack; the input can be used as-is.
1889 * - If we are rendering a strip that is known to be opaque, we mark it as an occluder,
1890 * so that strips below can check if they are completely hidden. */
1891 if (out == nullptr && early_out == StripEarlyOut::DoEffect && is_opaque_alpha_over(strip)) {
1892 ImBuf *test = seq_render_strip(context, state, strip, timeline_frame);
1893 if (ELEM(test->planes, R_IMF_PLANES_BW, R_IMF_PLANES_RGB) || i == 0) {
1894 early_out = StripEarlyOut::UseInput2;
1895 }
1896 else {
1897 early_out = StripEarlyOut::DoEffect;
1898 }
1899 /* Free the image. It is stored in cache, so this doesn't affect performance. */
1900 IMB_freeImBuf(test);
1901
1902 /* Check whether the raw (before preprocessing, which can add alpha) strip content
1903 * was opaque. */
1904 ImBuf *ibuf_raw = seq::source_image_cache_get(context, strip, timeline_frame);
1905 if (ibuf_raw != nullptr) {
1906 if (ibuf_raw->planes != R_IMF_PLANES_RGBA) {
1907 opaques.add_occluder(context, strip, i);
1908 }
1909 IMB_freeImBuf(ibuf_raw);
1910 }
1911 }
1912
1913 switch (early_out) {
1916 out = seq_render_strip(context, state, strip, timeline_frame);
1917 break;
1919 if (i == 0) {
1920 out = IMB_allocImBuf(context->rectx, context->recty, 32, IB_byte_data);
1921 seq_imbuf_assign_spaces(context->scene, out);
1922 }
1923 break;
1925 if (i == 0) {
1926 /* This is an effect at the bottom of the stack, so one of the inputs does not exist yet:
1927 * create one that is transparent black. Extra optimization for an alpha over strip at
1928 * the bottom, we can just return it instead of blending with black. */
1929 ImBuf *ibuf2 = seq_render_strip(context, state, strip, timeline_frame);
1930 const bool use_float = ibuf2 && ibuf2->float_buffer.data;
1931 ImBuf *ibuf1 = IMB_allocImBuf(
1932 context->rectx, context->recty, 32, use_float ? IB_float_data : IB_byte_data);
1933 seq_imbuf_assign_spaces(context->scene, ibuf1);
1934
1935 out = seq_render_strip_stack_apply_effect(context, strip, timeline_frame, ibuf1, ibuf2);
1936 IMB_metadata_copy(out, ibuf2);
1937
1938 intra_frame_cache_put_composite(context->scene, strip, out);
1939
1940 IMB_freeImBuf(ibuf1);
1941 IMB_freeImBuf(ibuf2);
1942 }
1943 break;
1944 }
1945
1946 if (out) {
1947 break;
1948 }
1949 }
1950
1951 i++;
1952 for (; i < strips.size(); i++) {
1953 Strip *strip = strips[i];
1954
1955 if (opaques.is_occluded(context, strip, i)) {
1956 continue;
1957 }
1958
1960 ImBuf *ibuf1 = out;
1961 ImBuf *ibuf2 = seq_render_strip(context, state, strip, timeline_frame);
1962
1963 out = seq_render_strip_stack_apply_effect(context, strip, timeline_frame, ibuf1, ibuf2);
1964
1965 IMB_freeImBuf(ibuf1);
1966 IMB_freeImBuf(ibuf2);
1967 }
1968
1969 intra_frame_cache_put_composite(context->scene, strip, out);
1970 }
1971
1972 return out;
1973}
1974
1975static void evict_caches_if_full(Scene *scene)
1976{
1977 if (!is_cache_full(scene)) {
1978 return;
1979 }
1980
1981 /* Cache is full, so we want to remove some images. We always try to remove one final image,
1982 * and some amount of source images for each final image, so that ratio of cached images
1983 * stays the same. Depending on the frame composition complexity, there can be lots of
1984 * source images cached for a single final frame; if we only removed one source image
1985 * we'd eventually have the cache still filled only with source images. */
1986 const size_t count_final = final_image_cache_get_image_count(scene);
1987 const size_t count_source = source_image_cache_get_image_count(scene);
1988 const size_t source_per_final = std::max<size_t>(
1989 divide_ceil_ul(count_source, std::max<size_t>(count_final, 1)), 1);
1990
1991 do {
1992 bool evicted_final = final_image_cache_evict(scene);
1993 bool evicted_source = false;
1994 for (size_t i = 0; i < source_per_final; i++) {
1995 evicted_source |= source_image_cache_evict(scene);
1996 }
1997 if (!evicted_final && !evicted_source) {
1998 break; /* Can't evict no more. */
1999 }
2000 } while (is_cache_full(scene));
2001}
2002
2003ImBuf *render_give_ibuf(const RenderData *context, float timeline_frame, int chanshown)
2004{
2005 Scene *scene = context->scene;
2006 Editing *ed = editing_get(scene);
2007 ListBase *seqbasep;
2008 ListBase *channels;
2009
2010 if (ed == nullptr) {
2011 return nullptr;
2012 }
2013
2014 if ((chanshown < 0) && !BLI_listbase_is_empty(&ed->metastack)) {
2015 int count = BLI_listbase_count(&ed->metastack);
2016 count = max_ii(count + chanshown, 0);
2017 seqbasep = ((MetaStack *)BLI_findlink(&ed->metastack, count))->oldbasep;
2018 channels = ((MetaStack *)BLI_findlink(&ed->metastack, count))->old_channels;
2019 chanshown = 0;
2020 }
2021 else {
2022 seqbasep = ed->seqbasep;
2023 channels = ed->displayed_channels;
2024 }
2025
2027 scene, timeline_frame, context->view_id, context->rectx, context->recty);
2028
2029 Scene *orig_scene = prefetch_get_original_scene(context);
2030 ImBuf *out = nullptr;
2031 if (!context->skip_cache && !context->is_proxy_render) {
2032 out = final_image_cache_get(orig_scene, seqbasep, timeline_frame, context->view_id, chanshown);
2033 }
2034
2036 scene, channels, seqbasep, timeline_frame, chanshown);
2037
2038 /* Make sure we only keep the `anim` data for strips that are in view. */
2039 relations_free_all_anim_ibufs(context->scene, timeline_frame);
2040
2042
2043 if (!strips.is_empty() && !out) {
2044 std::scoped_lock lock(seq_render_mutex);
2045 out = seq_render_strip_stack(context, &state, channels, seqbasep, timeline_frame, chanshown);
2046
2047 evict_caches_if_full(orig_scene);
2048
2049 if (out && (orig_scene->ed->cache_flag & SEQ_CACHE_STORE_FINAL_OUT) && !context->skip_cache &&
2050 !context->is_proxy_render)
2051 {
2053 orig_scene, seqbasep, timeline_frame, context->view_id, chanshown, out);
2054 }
2055 }
2056
2057 seq_prefetch_start(context, timeline_frame);
2058
2059 return out;
2060}
2061
2063 float timeline_frame,
2064 int chan_shown,
2065 ListBase *channels,
2066 ListBase *seqbasep)
2067{
2069
2070 return seq_render_strip_stack(context, &state, channels, seqbasep, timeline_frame, chan_shown);
2071}
2072
2073ImBuf *render_give_ibuf_direct(const RenderData *context, float timeline_frame, Strip *strip)
2074{
2076
2078 context->scene, timeline_frame, context->view_id, context->rectx, context->recty);
2079 ImBuf *ibuf = seq_render_strip(context, &state, strip, timeline_frame);
2080 return ibuf;
2081}
2082
2083bool render_is_muted(const ListBase *channels, const Strip *strip)
2084{
2085 SeqTimelineChannel *channel = channel_get_by_index(channels, strip->channel);
2086 return strip->flag & SEQ_MUTE || channel_is_muted(channel);
2087}
2088
2090
2091} // 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)
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:767
@ LIB_ID_COPY_LOCALIZE
@ LIB_ID_COPY_NO_ANIMDATA
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_NO_CAMERA_SWITCH
@ R_SEQ_OVERRIDE_SCENE_SETTINGS
@ R_IMF_PLANES_RGB
@ R_IMF_PLANES_RGBA
@ R_IMF_PLANES_BW
@ R_IMF_VIEWS_STEREO_3D
@ R_MULTIVIEW
@ R_DOSEQ
@ R_DOCOMP
@ seqModifierType_Mask
@ SEQ_SPEED_USE_INTERPOLATION
@ SEQUENCE_MODIFIER_MUTE
@ SEQ_BLEND_REPLACE
@ SEQ_ALPHA_PREMUL
@ SEQ_STORAGE_PROXY_CUSTOM_FILE
@ SEQ_CACHE_STORE_RAW
@ SEQ_CACHE_STORE_FINAL_OUT
@ SEQ_EDIT_SHOW_MISSING_MEDIA
@ 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
@ 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_MOVIECLIP_RENDER_UNDISTORTED
@ SEQ_MOVIECLIP_RENDER_STABILIZED
@ 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_EDIT_PROXY_DIR_STORAGE
@ 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)
const char * IMB_colormanagement_role_colorspace_name_get(int role)
@ COLOR_ROLE_SCENE_LINEAR
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:2083
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:861
static ImBuf * seq_render_movie_strip(const RenderData *context, Strip *strip, float timeline_frame, bool *r_is_proxy_image)
Definition render.cc:1108
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:1044
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:1614
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:2003
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
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:1654
static ImBuf * seq_render_scene_strip(const RenderData *context, Strip *strip, float frame_index, float timeline_frame)
Definition render.cc:1351
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:1057
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:2062
static bool is_opaque_alpha_over(const Strip *strip)
Definition render.cc:1831
bool source_image_cache_evict(Scene *scene)
static bool seq_must_swap_input_in_blend_mode(Strip *strip)
Definition render.cc:1786
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:939
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:1812
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:1191
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:902
static ImBuf * create_missing_media_image(const RenderData *context, int width, int height)
Definition render.cc:922
constexpr int MAX_CHANNELS
static ImBuf * seq_render_movie_strip_custom_file_proxy(const RenderData *context, Strip *strip, int timeline_frame)
Definition render.cc:1023
static ImBuf * seq_render_mask_strip(const RenderData *context, Strip *strip, float frame_index)
Definition render.cc:1344
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:1791
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:1851
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:1261
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:1975
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:834
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:1205
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:1749
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:2073
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:4227
uint8_t flag
Definition wm_window.cc:139