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
426 return seq_prefetch_scene_strip_is_rendered(target_scene,
427 channels_displayed_get(target_ed),
428 target_seqbase,
429 target_scene_strips,
430 target_timeline_frame);
431 }
432
433 /* Check if strip is effect of scene strip or uses it as modifier.
434 * This also checks if `strip == seq_scene`. */
435 for (Strip *seq_scene : scene_strips) {
436 if (relations_render_loop_check(strip, seq_scene)) {
437 return true;
438 }
439 }
440 }
441 return false;
442}
443
444/* Prefetch must avoid rendering scene strips, because rendering in background locks UI and can
445 * make it unresponsive for long time periods. */
446static bool seq_prefetch_must_skip_frame(PrefetchJob *pfjob, ListBase *channels, ListBase *seqbase)
447{
448 blender::VectorSet<Strip *> scene_strips = query_scene_strips(seqbase);
450 pfjob->scene_eval, channels, seqbase, scene_strips, seq_prefetch_cfra(pfjob)))
451 {
452 return true;
453 }
454 return false;
455}
456
458{
459 return seq_prefetch_is_cache_full(pfjob->scene) || pfjob->is_scrubbing ||
460 (seq_prefetch_cfra(pfjob) >= pfjob->scene->r.efra);
461}
462
464{
466 while (seq_prefetch_need_suspend(pfjob) &&
467 (pfjob->scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) && !pfjob->stop)
468 {
469 pfjob->waiting = true;
472 }
473 pfjob->waiting = false;
475}
476
477static void *seq_prefetch_frames(void *job)
478{
479 PrefetchJob *pfjob = (PrefetchJob *)job;
480
481 while (seq_prefetch_cfra(pfjob) <= pfjob->scene->r.efra) {
482 pfjob->scene_eval->ed->prefetch_job = nullptr;
483
486 AnimationEvalContext anim_eval_context = seq_prefetch_anim_eval_context(pfjob);
488 &pfjob->context_cpy.scene->id, adt, &anim_eval_context, ADT_RECALC_ALL, false);
489
490 /* This is quite hacky solution:
491 * We need cross-reference original scene with copy for cache.
492 * However depsgraph must not have this data, because it will try to kill this job.
493 * Scene copy don't reference original scene. Perhaps, this could be done by depsgraph.
494 * Set to nullptr before return!
495 */
496 pfjob->scene_eval->ed->prefetch_job = pfjob;
497
500 if (seq_prefetch_must_skip_frame(pfjob, channels, seqbase)) {
501 pfjob->num_frames_prefetched++;
502 /* Break instead of keep looping if the job should be terminated. */
503 if (!(pfjob->scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) || pfjob->stop) {
504 break;
505 }
506 continue;
507 }
508
509 ImBuf *ibuf = render_give_ibuf(&pfjob->context_cpy, seq_prefetch_cfra(pfjob), 0);
510 IMB_freeImBuf(ibuf);
511
512 /* Suspend thread if there is nothing to be prefetched. */
514
515 /* Avoid "collision" with main thread, but make sure to fetch at least few frames */
516 if (pfjob->num_frames_prefetched > 5 && (seq_prefetch_cfra(pfjob) - pfjob->scene->r.cfra) < 2)
517 {
518 break;
519 }
520
521 if (!(pfjob->scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) || pfjob->stop) {
522 break;
523 }
524
526 pfjob->num_frames_prefetched++;
527 }
528
529 pfjob->running = false;
530 pfjob->scene_eval->ed->prefetch_job = nullptr;
531
532 return nullptr;
533}
534
535static PrefetchJob *seq_prefetch_start_ex(const RenderData *context, float cfra)
536{
537 PrefetchJob *pfjob = seq_prefetch_job_get(context->scene);
538
539 if (!pfjob) {
540 if (!context->scene->ed) {
541 return nullptr;
542 }
543 pfjob = MEM_new<PrefetchJob>("PrefetchJob");
544 context->scene->ed->prefetch_job = pfjob;
545
549
550 pfjob->bmain_eval = BKE_main_new();
551 pfjob->scene = context->scene;
552 pfjob->seqbasep = context->scene->ed->seqbasep;
554 }
555 pfjob->bmain = context->bmain;
556
557 pfjob->cfra = cfra;
558 pfjob->num_frames_prefetched = 1;
559
560 pfjob->waiting = false;
561 pfjob->stop = false;
562 pfjob->running = true;
563
564 seq_prefetch_update_scene(context->scene);
567
568 BLI_threadpool_remove(&pfjob->threads, pfjob);
569 BLI_threadpool_insert(&pfjob->threads, pfjob);
570
571 return pfjob;
572}
573
574void seq_prefetch_start(const RenderData *context, float timeline_frame)
575{
576 Scene *scene = context->scene;
577 Editing *ed = scene->ed;
578 bool has_strips = bool(ed->seqbasep->first);
579
580 if (!context->is_prefetch_render && !context->is_proxy_render) {
581 bool playing = context->is_playing;
582 bool scrubbing = context->is_scrubbing;
583 bool running = seq_prefetch_job_is_running(scene);
584 seq_prefetch_job_scrubbing_set(scene, scrubbing);
585 seq_prefetch_resume(scene);
586
587 /* conditions to start:
588 * prefetch enabled, prefetch not running, not scrubbing, not playing,
589 * cache storage enabled, has strips to render, not rendering, not doing modal transform -
590 * important, see D7820. */
591 if ((ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) && !running && !scrubbing && !playing &&
592 (ed->cache_flag & SEQ_CACHE_ALL_TYPES) && has_strips && !G.is_rendering && !G.moving)
593 {
594 seq_prefetch_start_ex(context, timeline_frame);
595 }
596 }
597}
598
600{
601 bScreen *screen = CTX_wm_screen(C);
602 bool playing = screen->animtimer != nullptr;
603 bool scrubbing = screen->scrubbing;
604 bool running = seq_prefetch_job_is_running(scene);
605 bool suspended = seq_prefetch_job_is_waiting(scene);
606
607 SpaceSeq *sseq = CTX_wm_space_seq(C);
608 bool showing_cache = sseq->cache_overlay.flag & SEQ_CACHE_SHOW;
609
610 /* force redraw, when prefetching and using cache view. */
611 if (running && !playing && !suspended && showing_cache) {
612 return true;
613 }
614 /* Sometimes scrubbing flag is set when not scrubbing. In that case I want to catch "event" of
615 * stopping scrubbing */
616 if (scrubbing) {
617 return true;
618 }
619 return false;
620}
621
622} // 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
@ SEQ_SCENE_STRIPS
@ STRIP_TYPE_SCENE
@ STRIP_TYPE_META
@ 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:599
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:446
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:535
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:574
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:457
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:477
static void seq_prefetch_do_suspend(PrefetchJob *pfjob)
Definition prefetch.cc:463
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