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