Blender V4.5
prefetch.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10#include <cstddef>
11#include <cstdlib>
12#include <cstring>
13
14#include "MEM_guardedalloc.h"
15
16#include "DNA_scene_types.h"
17#include "DNA_screen_types.h"
18#include "DNA_sequence_types.h"
19#include "DNA_space_types.h"
20
21#include "BLI_listbase.h"
22#include "BLI_threads.h"
23#include "BLI_vector_set.hh"
24
25#include "IMB_imbuf.hh"
26#include "IMB_imbuf_types.hh"
27
28#include "BKE_anim_data.hh"
29#include "BKE_animsys.h"
30#include "BKE_context.hh"
31#include "BKE_global.hh"
32#include "BKE_layer.hh"
33#include "BKE_main.hh"
34
35#include "DEG_depsgraph.hh"
39
40#include "SEQ_channels.hh"
41#include "SEQ_prefetch.hh"
42#include "SEQ_relations.hh"
43#include "SEQ_render.hh"
44#include "SEQ_sequencer.hh"
45
46#include "SEQ_time.hh"
49#include "prefetch.hh"
50#include "render.hh"
51
52namespace blender::seq {
53
55 PrefetchJob *next = nullptr;
56 PrefetchJob *prev = nullptr;
57
58 Main *bmain = nullptr;
59 Main *bmain_eval = nullptr;
60 Scene *scene = nullptr;
61 Scene *scene_eval = nullptr;
62 Depsgraph *depsgraph = nullptr;
63
66
68
69 /* context */
72 ListBase *seqbasep = nullptr;
73
74 /* prefetch area */
75 float cfra = 0.0f;
77
78 /* Control: */
79 /* Set by prefetch. */
80 bool running = false;
81 bool waiting = false;
82 bool stop = false;
83 /* Set from outside. */
84 bool is_scrubbing = false;
85};
86
88{
89 if (scene && scene->ed) {
90 return scene->ed->prefetch_job;
91 }
92 return nullptr;
93}
94
96{
97 PrefetchJob *pfjob = seq_prefetch_job_get(scene);
98
99 if (!pfjob) {
100 return false;
101 }
102
103 return pfjob->running;
104}
105
106static void seq_prefetch_job_scrubbing_set(Scene *scene, bool is_scrubbing)
107{
108 PrefetchJob *pfjob = seq_prefetch_job_get(scene);
109
110 if (!pfjob) {
111 return;
112 }
113
114 pfjob->is_scrubbing = is_scrubbing;
115}
116
118{
119 PrefetchJob *pfjob = seq_prefetch_job_get(scene);
120
121 if (!pfjob) {
122 return false;
123 }
124
125 return pfjob->waiting;
126}
127
128static Strip *original_strip_get(const Strip *strip, ListBase *seqbase)
129{
130 LISTBASE_FOREACH (Strip *, strip_orig, seqbase) {
131 if (STREQ(strip->name, strip_orig->name)) {
132 return strip_orig;
133 }
134
135 if (strip_orig->type == STRIP_TYPE_META) {
136 Strip *match = original_strip_get(strip, &strip_orig->seqbase);
137 if (match != nullptr) {
138 return match;
139 }
140 }
141 }
142
143 return nullptr;
144}
145
146static Strip *original_strip_get(const Strip *strip, Scene *scene)
147{
148 Editing *ed = scene->ed;
149 return original_strip_get(strip, &ed->seqbase);
150}
151
153{
154 PrefetchJob *pfjob = seq_prefetch_job_get(context->scene);
155 return pfjob ? &pfjob->context : nullptr;
156}
157
159{
160 Scene *scene = context->scene;
161 if (context->is_prefetch_render) {
162 context = get_original_context(context);
163 if (context != nullptr) {
164 scene = context->scene;
165 }
166 }
167 return scene;
168}
169
171{
172 Scene *scene = context->scene;
173 if (context->is_prefetch_render) {
174 context = get_original_context(context);
175 if (context != nullptr) {
176 scene = context->scene;
177 strip = original_strip_get(strip, scene);
178 }
179 }
180 return scene;
181}
182
184{
185 bool full = is_cache_full(scene);
186 if (!full) {
187 return false;
188 }
189 bool evicted = final_image_cache_evict(scene);
190 return !evicted;
191}
192
193static float seq_prefetch_cfra(PrefetchJob *pfjob)
194{
195 return pfjob->cfra + pfjob->num_frames_prefetched;
196}
201
202void seq_prefetch_get_time_range(Scene *scene, int *r_start, int *r_end)
203{
204 /* When there is no prefetch job, return "impossible" negative values. */
205 *r_start = INT_MIN;
206 *r_end = INT_MIN;
207
208 PrefetchJob *pfjob = seq_prefetch_job_get(scene);
209 if (pfjob == nullptr) {
210 return;
211 }
212 if ((scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) == 0 || !pfjob->running) {
213 return;
214 }
215
216 *r_start = pfjob->cfra;
217 *r_end = seq_prefetch_cfra(pfjob);
218}
219
221{
222 if (pfjob->depsgraph != nullptr) {
224 }
225 pfjob->depsgraph = nullptr;
226 pfjob->scene_eval = nullptr;
227}
228
233
235{
236 Main *bmain = pfjob->bmain_eval;
237 Scene *scene = pfjob->scene;
238 ViewLayer *view_layer = BKE_view_layer_default_render(scene);
239
240 pfjob->depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER);
241 DEG_debug_name_set(pfjob->depsgraph, "SEQUENCER PREFETCH");
242
243 /* Make sure there is a correct evaluated scene pointer. */
245
246 /* Update immediately so we have proper evaluated scene. */
248
250 pfjob->scene_eval->ed->cache_flag = 0;
251}
252
254{
255 int cfra = pfjob->scene->r.cfra;
256
257 /* rebase */
258 if (cfra > pfjob->cfra) {
259 int delta = cfra - pfjob->cfra;
260 pfjob->cfra = cfra;
261 pfjob->num_frames_prefetched -= delta;
262
263 pfjob->num_frames_prefetched = std::max(pfjob->num_frames_prefetched, 1);
264 }
265
266 /* reset */
267 if (cfra < pfjob->cfra) {
268 pfjob->cfra = cfra;
269 pfjob->num_frames_prefetched = 1;
270 }
271}
272
274{
275 /* TODO(Richard): Use wm_jobs for prefetch, or pass main. */
276 for (Scene *scene = static_cast<Scene *>(G.main->scenes.first); scene;
277 scene = static_cast<Scene *>(scene->id.next))
278 {
279 prefetch_stop(scene);
280 }
281}
282
284{
285 PrefetchJob *pfjob;
286 pfjob = seq_prefetch_job_get(scene);
287
288 if (!pfjob) {
289 return;
290 }
291
292 pfjob->stop = true;
293
294 while (pfjob->running) {
296 }
297}
298
299static void seq_prefetch_update_context(const RenderData *context)
300{
301 PrefetchJob *pfjob;
302 pfjob = seq_prefetch_job_get(context->scene);
303
305 pfjob->depsgraph,
306 pfjob->scene_eval,
307 context->rectx,
308 context->recty,
309 context->preview_render_size,
310 false,
311 &pfjob->context_cpy);
312 pfjob->context_cpy.is_prefetch_render = true;
314
316 pfjob->depsgraph,
317 pfjob->scene,
318 context->rectx,
319 context->recty,
320 context->preview_render_size,
321 false,
322 &pfjob->context);
323 pfjob->context.is_prefetch_render = false;
324
325 /* Same ID as prefetch context, because context will be swapped, but we still
326 * want to assign this ID to cache entries created in this thread.
327 * This is to allow "temp cache" work correctly for both threads.
328 */
330}
331
333{
334 PrefetchJob *pfjob = seq_prefetch_job_get(scene);
335
336 if (!pfjob) {
337 return;
338 }
339
340 pfjob->scene = scene;
343}
344
346{
348 Editing *ed_eval = editing_get(pfjob->scene_eval);
349
350 if (ms_orig != nullptr) {
351 Strip *meta_eval = original_strip_get(ms_orig->parent_strip, pfjob->scene_eval);
352 active_seqbase_set(ed_eval, &meta_eval->seqbase);
353 }
354 else {
355 active_seqbase_set(ed_eval, &ed_eval->seqbase);
356 }
357}
358
359static void seq_prefetch_resume(Scene *scene)
360{
361 PrefetchJob *pfjob = seq_prefetch_job_get(scene);
362
363 if (pfjob && pfjob->waiting) {
365 }
366}
367
369{
370 PrefetchJob *pfjob = seq_prefetch_job_get(scene);
371 if (!pfjob) {
372 return;
373 }
374
375 prefetch_stop(scene);
376
377 BLI_threadpool_remove(&pfjob->threads, pfjob);
383 scene->ed->prefetch_job = nullptr;
384 MEM_delete(pfjob);
385}
386
388{
390 LISTBASE_FOREACH (Strip *, strip, seqbase) {
391 if (strip->type == STRIP_TYPE_SCENE && (strip->flag & SEQ_SCENE_STRIPS) == 0) {
392 strips.add(strip);
393 }
394 }
395 return strips;
396}
397
399 ListBase *channels,
400 ListBase *seqbase,
401 blender::Span<Strip *> scene_strips,
402 int timeline_frame)
403{
405 scene, channels, seqbase, timeline_frame, 0);
406
407 /* Iterate over rendered strips. */
408 for (Strip *strip : rendered_strips) {
409 if (strip->type == STRIP_TYPE_META &&
411 scene, &strip->channels, &strip->seqbase, scene_strips, timeline_frame))
412 {
413 return true;
414 }
415
416 if (strip->type == STRIP_TYPE_SCENE && (strip->flag & SEQ_SCENE_STRIPS) != 0 &&
417 strip->scene != nullptr)
418 {
419 const Scene *target_scene = strip->scene;
420 Editing *target_ed = editing_get(target_scene);
421 ListBase *target_seqbase = active_seqbase_get(target_ed);
422 blender::VectorSet<Strip *> target_scene_strips = query_scene_strips(target_seqbase);
423 int target_timeline_frame = give_frame_index(scene, strip, timeline_frame) +
424 target_scene->r.sfra;
425
427 channels_displayed_get(target_ed),
428 target_seqbase,
429 target_scene_strips,
430 target_timeline_frame))
431 {
432 return true;
433 }
434 }
435
436 /* Check if strip is effect of scene strip or uses it as modifier.
437 * This also checks if `strip == seq_scene`. */
438 for (Strip *seq_scene : scene_strips) {
439 if (relations_render_loop_check(strip, seq_scene)) {
440 return true;
441 }
442 }
443 }
444 return false;
445}
446
447/* Prefetch must avoid rendering scene strips, because rendering in background locks UI and can
448 * make it unresponsive for long time periods. */
449static bool seq_prefetch_must_skip_frame(PrefetchJob *pfjob, ListBase *channels, ListBase *seqbase)
450{
451 blender::VectorSet<Strip *> scene_strips = query_scene_strips(seqbase);
453 pfjob->scene_eval, channels, seqbase, scene_strips, seq_prefetch_cfra(pfjob)))
454 {
455 return true;
456 }
457 return false;
458}
459
461{
462 return seq_prefetch_is_cache_full(pfjob->scene) || pfjob->is_scrubbing ||
463 (seq_prefetch_cfra(pfjob) >= pfjob->scene->r.efra);
464}
465
467{
469 while (seq_prefetch_need_suspend(pfjob) &&
470 (pfjob->scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) && !pfjob->stop)
471 {
472 pfjob->waiting = true;
475 }
476 pfjob->waiting = false;
478}
479
480static void *seq_prefetch_frames(void *job)
481{
482 PrefetchJob *pfjob = (PrefetchJob *)job;
483
484 while (seq_prefetch_cfra(pfjob) <= pfjob->scene->r.efra) {
485 pfjob->scene_eval->ed->prefetch_job = nullptr;
486
489 AnimationEvalContext anim_eval_context = seq_prefetch_anim_eval_context(pfjob);
491 &pfjob->context_cpy.scene->id, adt, &anim_eval_context, ADT_RECALC_ALL, false);
492
493 /* This is quite hacky solution:
494 * We need cross-reference original scene with copy for cache.
495 * However depsgraph must not have this data, because it will try to kill this job.
496 * Scene copy don't reference original scene. Perhaps, this could be done by depsgraph.
497 * Set to nullptr before return!
498 */
499 pfjob->scene_eval->ed->prefetch_job = pfjob;
500
503 if (seq_prefetch_must_skip_frame(pfjob, channels, seqbase)) {
504 pfjob->num_frames_prefetched++;
505 /* Break instead of keep looping if the job should be terminated. */
506 if (!(pfjob->scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) || pfjob->stop) {
507 break;
508 }
509 continue;
510 }
511
512 ImBuf *ibuf = render_give_ibuf(&pfjob->context_cpy, seq_prefetch_cfra(pfjob), 0);
513 IMB_freeImBuf(ibuf);
514
515 /* Suspend thread if there is nothing to be prefetched. */
517
518 /* Avoid "collision" with main thread, but make sure to fetch at least few frames */
519 if (pfjob->num_frames_prefetched > 5 && (seq_prefetch_cfra(pfjob) - pfjob->scene->r.cfra) < 2)
520 {
521 break;
522 }
523
524 if (!(pfjob->scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) || pfjob->stop) {
525 break;
526 }
527
529 pfjob->num_frames_prefetched++;
530 }
531
532 pfjob->running = false;
533 pfjob->scene_eval->ed->prefetch_job = nullptr;
534
535 return nullptr;
536}
537
538static PrefetchJob *seq_prefetch_start_ex(const RenderData *context, float cfra)
539{
540 PrefetchJob *pfjob = seq_prefetch_job_get(context->scene);
541
542 if (!pfjob) {
543 if (!context->scene->ed) {
544 return nullptr;
545 }
546 pfjob = MEM_new<PrefetchJob>("PrefetchJob");
547 context->scene->ed->prefetch_job = pfjob;
548
552
553 pfjob->bmain_eval = BKE_main_new();
554 pfjob->scene = context->scene;
555 pfjob->seqbasep = context->scene->ed->seqbasep;
557 }
558 pfjob->bmain = context->bmain;
559
560 pfjob->cfra = cfra;
561 pfjob->num_frames_prefetched = 1;
562
563 pfjob->waiting = false;
564 pfjob->stop = false;
565 pfjob->running = true;
566
567 seq_prefetch_update_scene(context->scene);
570
571 BLI_threadpool_remove(&pfjob->threads, pfjob);
572 BLI_threadpool_insert(&pfjob->threads, pfjob);
573
574 return pfjob;
575}
576
577void seq_prefetch_start(const RenderData *context, float timeline_frame)
578{
579 Scene *scene = context->scene;
580 Editing *ed = scene->ed;
581 bool has_strips = bool(ed->seqbasep->first);
582
583 if (!context->is_prefetch_render && !context->is_proxy_render) {
584 bool playing = context->is_playing;
585 bool scrubbing = context->is_scrubbing;
586 bool running = seq_prefetch_job_is_running(scene);
587 seq_prefetch_job_scrubbing_set(scene, scrubbing);
588 seq_prefetch_resume(scene);
589
590 /* conditions to start:
591 * prefetch enabled, prefetch not running, not scrubbing, not playing,
592 * cache storage enabled, has strips to render, not rendering, not doing modal transform -
593 * important, see D7820. */
594 if ((ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) && !running && !scrubbing && !playing &&
595 (ed->cache_flag & SEQ_CACHE_ALL_TYPES) && has_strips && !G.is_rendering && !G.moving)
596 {
597 seq_prefetch_start_ex(context, timeline_frame);
598 }
599 }
600}
601
603{
604 bScreen *screen = CTX_wm_screen(C);
605 bool playing = screen->animtimer != nullptr;
606 bool scrubbing = screen->scrubbing;
607 bool running = seq_prefetch_job_is_running(scene);
608 bool suspended = seq_prefetch_job_is_waiting(scene);
609
610 SpaceSeq *sseq = CTX_wm_space_seq(C);
611 bool showing_cache = sseq->cache_overlay.flag & SEQ_CACHE_SHOW;
612
613 /* force redraw, when prefetching and using cache view. */
614 if (running && !playing && !suspended && showing_cache) {
615 return true;
616 }
617 /* Sometimes scrubbing flag is set when not scrubbing. In that case I want to catch "event" of
618 * stopping scrubbing */
619 if (scrubbing) {
620 return true;
621 }
622 return false;
623}
624
625} // namespace blender::seq
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:82
AnimationEvalContext BKE_animsys_eval_context_construct(struct Depsgraph *depsgraph, float eval_time) ATTR_WARN_UNUSED_RESULT
Definition anim_sys.cc:735
@ ADT_RECALC_ALL
void BKE_animsys_evaluate_animdata(struct ID *id, struct AnimData *adt, const struct AnimationEvalContext *anim_eval_context, eAnimData_Recalc recalc, bool flush_to_original)
bScreen * CTX_wm_screen(const bContext *C)
SpaceSeq * CTX_wm_space_seq(const bContext *C)
ViewLayer * BKE_view_layer_default_render(const Scene *scene)
Main * BKE_main_new()
Definition main.cc:48
void BKE_main_free(Main *bmain)
Definition main.cc:175
#define LISTBASE_FOREACH(type, var, list)
void BLI_mutex_end(ThreadMutex *mutex)
Definition threads.cc:360
void BLI_threadpool_remove(struct ListBase *threadbase, void *callerdata)
Definition threads.cc:197
void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex)
Definition threads.cc:580
void BLI_threadpool_init(struct ListBase *threadbase, void *(*do_thread)(void *), int tot)
Definition threads.cc:121
void BLI_mutex_init(ThreadMutex *mutex)
Definition threads.cc:340
pthread_cond_t ThreadCondition
void BLI_condition_end(ThreadCondition *cond)
Definition threads.cc:600
void BLI_threadpool_end(struct ListBase *threadbase)
Definition threads.cc:234
void BLI_condition_notify_one(ThreadCondition *cond)
Definition threads.cc:590
void BLI_condition_init(ThreadCondition *cond)
Definition threads.cc:575
void BLI_mutex_lock(ThreadMutex *mutex)
Definition threads.cc:345
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition threads.cc:350
void BLI_threadpool_insert(struct ListBase *threadbase, void *callerdata)
Definition threads.cc:184
pthread_mutex_t ThreadMutex
Definition BLI_threads.h:79
#define STREQ(a, b)
@ DAG_EVAL_RENDER
Depsgraph * DEG_graph_new(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
Definition depsgraph.cc:278
void DEG_graph_free(Depsgraph *graph)
Definition depsgraph.cc:306
void DEG_evaluate_on_framechange(Depsgraph *graph, float frame, DepsgraphEvaluateSyncWriteback sync_writeback=DEG_EVALUATE_SYNC_WRITEBACK_NO)
void DEG_graph_build_for_render_pipeline(Depsgraph *graph)
void DEG_debug_name_set(Depsgraph *depsgraph, const char *name)
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
@ SEQ_CACHE_ALL_TYPES
@ SEQ_CACHE_PREFETCH_ENABLE
@ STRIP_TYPE_SCENE
@ STRIP_TYPE_META
@ SEQ_SCENE_STRIPS
@ SEQ_CACHE_SHOW
void IMB_freeImBuf(ImBuf *ibuf)
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
bool add(const Key &key)
#define G(x, y, z)
static void seq_prefetch_update_active_seqbase(PrefetchJob *pfjob)
Definition prefetch.cc:345
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
void prefetch_stop(Scene *scene)
Definition prefetch.cc:283
static blender::VectorSet< Strip * > query_scene_strips(ListBase *seqbase)
Definition prefetch.cc:387
static PrefetchJob * seq_prefetch_job_get(Scene *scene)
Definition prefetch.cc:87
ImBuf * render_give_ibuf(const RenderData *context, float timeline_frame, int chanshown)
Definition render.cc:2002
bool seq_prefetch_job_is_running(Scene *scene)
Definition prefetch.cc:95
ListBase * channels_displayed_get(const Editing *ed)
Definition channels.cc:28
bool prefetch_need_redraw(const bContext *C, Scene *scene)
Definition prefetch.cc:602
bool relations_render_loop_check(Strip *strip_main, Strip *strip)
static void seq_prefetch_update_depsgraph(PrefetchJob *pfjob)
Definition prefetch.cc:229
static bool seq_prefetch_must_skip_frame(PrefetchJob *pfjob, ListBase *channels, ListBase *seqbase)
Definition prefetch.cc:449
static void seq_prefetch_init_depsgraph(PrefetchJob *pfjob)
Definition prefetch.cc:234
float give_frame_index(const Scene *scene, const Strip *strip, float timeline_frame)
Definition strip_time.cc:52
Editing * editing_get(const Scene *scene)
Definition sequencer.cc:272
void seq_prefetch_free(Scene *scene)
Definition prefetch.cc:368
static PrefetchJob * seq_prefetch_start_ex(const RenderData *context, float cfra)
Definition prefetch.cc:538
void active_seqbase_set(Editing *ed, ListBase *seqbase)
Definition sequencer.cc:429
@ SEQ_TASK_PREFETCH_RENDER
Definition SEQ_render.hh:25
static bool seq_prefetch_scene_strip_is_rendered(const Scene *scene, ListBase *channels, ListBase *seqbase, blender::Span< Strip * > scene_strips, int timeline_frame)
Definition prefetch.cc:398
static void seq_prefetch_resume(Scene *scene)
Definition prefetch.cc:359
static RenderData * get_original_context(const RenderData *context)
Definition prefetch.cc:152
void seq_prefetch_start(const RenderData *context, float timeline_frame)
Definition prefetch.cc:577
static float seq_prefetch_cfra(PrefetchJob *pfjob)
Definition prefetch.cc:193
MetaStack * meta_stack_active_get(const Editing *ed)
Definition sequencer.cc:452
static bool seq_prefetch_need_suspend(PrefetchJob *pfjob)
Definition prefetch.cc:460
void prefetch_stop_all()
Definition prefetch.cc:273
static void seq_prefetch_update_area(PrefetchJob *pfjob)
Definition prefetch.cc:253
static AnimationEvalContext seq_prefetch_anim_eval_context(PrefetchJob *pfjob)
Definition prefetch.cc:197
static bool seq_prefetch_job_is_waiting(Scene *scene)
Definition prefetch.cc:117
Scene * prefetch_get_original_scene_and_strip(const RenderData *context, const Strip *&strip)
Definition prefetch.cc:170
bool final_image_cache_evict(Scene *scene)
static void * seq_prefetch_frames(void *job)
Definition prefetch.cc:480
static void seq_prefetch_do_suspend(PrefetchJob *pfjob)
Definition prefetch.cc:466
bool is_cache_full(const Scene *scene)
static Strip * original_strip_get(const Strip *strip, ListBase *seqbase)
Definition prefetch.cc:128
static void seq_prefetch_update_context(const RenderData *context)
Definition prefetch.cc:299
ListBase * active_seqbase_get(const Editing *ed)
Definition sequencer.cc:420
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 void seq_prefetch_update_scene(Scene *scene)
Definition prefetch.cc:332
static void seq_prefetch_job_scrubbing_set(Scene *scene, bool is_scrubbing)
Definition prefetch.cc:106
Scene * prefetch_get_original_scene(const RenderData *context)
Definition prefetch.cc:158
static void seq_prefetch_free_depsgraph(PrefetchJob *pfjob)
Definition prefetch.cc:220
void seq_prefetch_get_time_range(Scene *scene, int *r_start, int *r_end)
Definition prefetch.cc:202
static bool seq_prefetch_is_cache_full(Scene *scene)
Definition prefetch.cc:183
ListBase seqbase
PrefetchJob * prefetch_job
struct Editing * ed
struct RenderData r
struct SequencerCacheOverlay cache_overlay
ListBase seqbase
char name[64]
struct wmTimer * animtimer
ThreadMutex prefetch_suspend_mutex
Definition prefetch.cc:64
ThreadCondition prefetch_suspend_cond
Definition prefetch.cc:65