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