2019-09-14 02:21:54 +02:00
|
|
|
/*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** \file
|
|
|
|
* \ingroup bke
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_anim_types.h"
|
2019-09-14 02:21:54 +02:00
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
#include "DNA_screen_types.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_sequence_types.h"
|
2019-09-14 02:21:54 +02:00
|
|
|
#include "DNA_windowmanager_types.h"
|
|
|
|
|
|
|
|
#include "BLI_listbase.h"
|
|
|
|
#include "BLI_threads.h"
|
|
|
|
|
|
|
|
#include "IMB_imbuf.h"
|
|
|
|
#include "IMB_imbuf_types.h"
|
|
|
|
|
2020-04-03 13:07:36 +02:00
|
|
|
#include "BKE_anim_data.h"
|
2019-09-14 02:21:54 +02:00
|
|
|
#include "BKE_animsys.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_context.h"
|
|
|
|
#include "BKE_layer.h"
|
2020-02-10 12:58:59 +01:00
|
|
|
#include "BKE_lib_id.h"
|
2019-09-14 02:21:54 +02:00
|
|
|
#include "BKE_main.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_scene.h"
|
2019-09-14 02:21:54 +02:00
|
|
|
#include "BKE_sequencer.h"
|
|
|
|
|
|
|
|
#include "DEG_depsgraph.h"
|
|
|
|
#include "DEG_depsgraph_build.h"
|
|
|
|
#include "DEG_depsgraph_debug.h"
|
|
|
|
#include "DEG_depsgraph_query.h"
|
|
|
|
|
|
|
|
typedef struct PrefetchJob {
|
|
|
|
struct PrefetchJob *next, *prev;
|
|
|
|
|
|
|
|
struct Main *bmain;
|
2019-10-02 22:04:48 +02:00
|
|
|
struct Main *bmain_eval;
|
2019-09-14 02:21:54 +02:00
|
|
|
struct Scene *scene;
|
|
|
|
struct Scene *scene_eval;
|
|
|
|
struct Depsgraph *depsgraph;
|
|
|
|
|
|
|
|
ThreadMutex prefetch_suspend_mutex;
|
|
|
|
ThreadCondition prefetch_suspend_cond;
|
|
|
|
|
|
|
|
ListBase threads;
|
|
|
|
|
|
|
|
/* context */
|
|
|
|
struct SeqRenderData context;
|
|
|
|
struct SeqRenderData context_cpy;
|
|
|
|
struct ListBase *seqbasep;
|
|
|
|
struct ListBase *seqbasep_cpy;
|
|
|
|
|
|
|
|
/* prefetch area */
|
|
|
|
float cfra;
|
|
|
|
int num_frames_prefetched;
|
|
|
|
|
|
|
|
/* control */
|
|
|
|
bool running;
|
|
|
|
bool waiting;
|
|
|
|
bool stop;
|
|
|
|
} PrefetchJob;
|
|
|
|
|
|
|
|
static bool seq_prefetch_is_playing(Main *bmain)
|
|
|
|
{
|
|
|
|
for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
|
|
|
|
if (screen->animtimer) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool seq_prefetch_is_scrubbing(Main *bmain)
|
|
|
|
{
|
|
|
|
|
|
|
|
for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
|
|
|
|
if (screen->scrubbing) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PrefetchJob *seq_prefetch_job_get(Scene *scene)
|
|
|
|
{
|
|
|
|
if (scene && scene->ed) {
|
|
|
|
return scene->ed->prefetch_job;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-10-02 22:04:48 +02:00
|
|
|
bool BKE_sequencer_prefetch_job_is_running(Scene *scene)
|
2019-09-14 02:21:54 +02:00
|
|
|
{
|
|
|
|
PrefetchJob *pfjob = seq_prefetch_job_get(scene);
|
|
|
|
|
|
|
|
if (!pfjob) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pfjob->running;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool seq_prefetch_job_is_waiting(Scene *scene)
|
|
|
|
{
|
|
|
|
PrefetchJob *pfjob = seq_prefetch_job_get(scene);
|
|
|
|
|
|
|
|
if (!pfjob) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pfjob->waiting;
|
|
|
|
}
|
|
|
|
|
2020-05-01 21:16:50 +02:00
|
|
|
static Sequence *sequencer_prefetch_get_original_sequence(Sequence *seq, ListBase *seqbase)
|
2019-09-14 02:21:54 +02:00
|
|
|
{
|
2020-05-01 21:16:50 +02:00
|
|
|
LISTBASE_FOREACH (Sequence *, seq_orig, seqbase) {
|
2019-09-14 02:21:54 +02:00
|
|
|
if (strcmp(seq->name, seq_orig->name) == 0) {
|
2020-05-01 21:16:50 +02:00
|
|
|
return seq_orig;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (seq_orig->type == SEQ_TYPE_META) {
|
|
|
|
Sequence *match = sequencer_prefetch_get_original_sequence(seq, &seq_orig->seqbase);
|
|
|
|
if (match != NULL) {
|
|
|
|
return match;
|
|
|
|
}
|
2019-09-14 02:21:54 +02:00
|
|
|
}
|
|
|
|
}
|
2020-05-01 21:16:50 +02:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* for cache context swapping */
|
|
|
|
Sequence *BKE_sequencer_prefetch_get_original_sequence(Sequence *seq, Scene *scene)
|
|
|
|
{
|
|
|
|
Editing *ed = scene->ed;
|
|
|
|
return sequencer_prefetch_get_original_sequence(seq, &ed->seqbase);
|
2019-09-14 02:21:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* for cache context swapping */
|
|
|
|
SeqRenderData *BKE_sequencer_prefetch_get_original_context(const SeqRenderData *context)
|
|
|
|
{
|
|
|
|
PrefetchJob *pfjob = seq_prefetch_job_get(context->scene);
|
|
|
|
|
|
|
|
return &pfjob->context;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool seq_prefetch_is_cache_full(Scene *scene)
|
|
|
|
{
|
|
|
|
PrefetchJob *pfjob = seq_prefetch_job_get(scene);
|
|
|
|
|
|
|
|
if (!BKE_sequencer_cache_is_full(pfjob->scene)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return BKE_sequencer_cache_recycle_item(pfjob->scene) == false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_sequencer_prefetch_get_time_range(Scene *scene, int *start, int *end)
|
|
|
|
{
|
|
|
|
PrefetchJob *pfjob = seq_prefetch_job_get(scene);
|
|
|
|
|
|
|
|
*start = pfjob->cfra;
|
|
|
|
*end = pfjob->cfra + pfjob->num_frames_prefetched;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void seq_prefetch_free_depsgraph(PrefetchJob *pfjob)
|
|
|
|
{
|
|
|
|
if (pfjob->depsgraph != NULL) {
|
|
|
|
DEG_graph_free(pfjob->depsgraph);
|
|
|
|
}
|
|
|
|
pfjob->depsgraph = NULL;
|
|
|
|
pfjob->scene_eval = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void seq_prefetch_update_depsgraph(PrefetchJob *pfjob)
|
|
|
|
{
|
|
|
|
DEG_evaluate_on_framechange(
|
2019-10-02 22:04:48 +02:00
|
|
|
pfjob->bmain_eval, pfjob->depsgraph, pfjob->cfra + pfjob->num_frames_prefetched);
|
2019-09-14 02:21:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void seq_prefetch_init_depsgraph(PrefetchJob *pfjob)
|
|
|
|
{
|
2019-10-02 22:04:48 +02:00
|
|
|
Main *bmain = pfjob->bmain_eval;
|
2019-09-14 02:21:54 +02:00
|
|
|
Scene *scene = pfjob->scene;
|
|
|
|
ViewLayer *view_layer = BKE_view_layer_default_render(scene);
|
|
|
|
|
|
|
|
pfjob->depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER);
|
|
|
|
DEG_debug_name_set(pfjob->depsgraph, "SEQUENCER PREFETCH");
|
|
|
|
|
|
|
|
/* Make sure there is a correct evaluated scene pointer. */
|
2019-10-02 22:04:48 +02:00
|
|
|
DEG_graph_build_for_render_pipeline(pfjob->depsgraph, bmain, scene, view_layer);
|
2019-09-14 02:21:54 +02:00
|
|
|
|
|
|
|
/* Update immediately so we have proper evaluated scene. */
|
|
|
|
seq_prefetch_update_depsgraph(pfjob);
|
|
|
|
|
|
|
|
pfjob->scene_eval = DEG_get_evaluated_scene(pfjob->depsgraph);
|
|
|
|
pfjob->scene_eval->ed->cache_flag = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void seq_prefetch_update_area(PrefetchJob *pfjob)
|
|
|
|
{
|
|
|
|
int cfra = pfjob->scene->r.cfra;
|
|
|
|
|
|
|
|
/* rebase */
|
|
|
|
if (cfra > pfjob->cfra) {
|
|
|
|
int delta = cfra - pfjob->cfra;
|
|
|
|
pfjob->cfra = cfra;
|
|
|
|
pfjob->num_frames_prefetched -= delta;
|
|
|
|
|
|
|
|
if (pfjob->num_frames_prefetched <= 1) {
|
|
|
|
pfjob->num_frames_prefetched = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* reset */
|
|
|
|
if (cfra < pfjob->cfra) {
|
|
|
|
pfjob->cfra = cfra;
|
|
|
|
pfjob->num_frames_prefetched = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-02 22:04:48 +02:00
|
|
|
/* Use also to update scene and context changes
|
|
|
|
* This function should almost always be called by cache invalidation, not directly.
|
|
|
|
*/
|
2019-09-14 02:21:54 +02:00
|
|
|
void BKE_sequencer_prefetch_stop(Scene *scene)
|
|
|
|
{
|
|
|
|
PrefetchJob *pfjob;
|
|
|
|
pfjob = seq_prefetch_job_get(scene);
|
|
|
|
|
|
|
|
if (!pfjob) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pfjob->stop = true;
|
|
|
|
|
|
|
|
while (pfjob->running) {
|
|
|
|
BLI_condition_notify_one(&pfjob->prefetch_suspend_cond);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void seq_prefetch_update_context(const SeqRenderData *context)
|
|
|
|
{
|
|
|
|
PrefetchJob *pfjob;
|
|
|
|
pfjob = seq_prefetch_job_get(context->scene);
|
|
|
|
|
2019-10-02 22:04:48 +02:00
|
|
|
BKE_sequencer_new_render_data(pfjob->bmain_eval,
|
2019-09-14 02:21:54 +02:00
|
|
|
pfjob->depsgraph,
|
|
|
|
pfjob->scene_eval,
|
|
|
|
context->rectx,
|
|
|
|
context->recty,
|
|
|
|
context->preview_render_size,
|
|
|
|
false,
|
|
|
|
&pfjob->context_cpy);
|
|
|
|
pfjob->context_cpy.is_prefetch_render = true;
|
|
|
|
pfjob->context_cpy.task_id = SEQ_TASK_PREFETCH_RENDER;
|
|
|
|
|
|
|
|
BKE_sequencer_new_render_data(pfjob->bmain,
|
|
|
|
pfjob->depsgraph,
|
|
|
|
pfjob->scene,
|
|
|
|
context->rectx,
|
|
|
|
context->recty,
|
|
|
|
context->preview_render_size,
|
|
|
|
false,
|
|
|
|
&pfjob->context);
|
|
|
|
pfjob->context.is_prefetch_render = false;
|
|
|
|
|
|
|
|
/* Same ID as prefetch context, because context will be swapped, but we still
|
|
|
|
* want to assign this ID to cache entries created in this thread.
|
|
|
|
* This is to allow "temp cache" work correctly for both threads.
|
|
|
|
*/
|
|
|
|
pfjob->context.task_id = SEQ_TASK_PREFETCH_RENDER;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void seq_prefetch_update_scene(Scene *scene)
|
|
|
|
{
|
|
|
|
PrefetchJob *pfjob = seq_prefetch_job_get(scene);
|
|
|
|
|
|
|
|
if (!pfjob) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
seq_prefetch_free_depsgraph(pfjob);
|
|
|
|
seq_prefetch_init_depsgraph(pfjob);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void seq_prefetch_resume(Scene *scene)
|
|
|
|
{
|
|
|
|
PrefetchJob *pfjob = seq_prefetch_job_get(scene);
|
|
|
|
|
|
|
|
if (pfjob && pfjob->waiting) {
|
|
|
|
BLI_condition_notify_one(&pfjob->prefetch_suspend_cond);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_sequencer_prefetch_free(Scene *scene)
|
|
|
|
{
|
|
|
|
PrefetchJob *pfjob = seq_prefetch_job_get(scene);
|
|
|
|
if (!pfjob) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BKE_sequencer_prefetch_stop(scene);
|
|
|
|
|
|
|
|
BLI_threadpool_remove(&pfjob->threads, pfjob);
|
|
|
|
BLI_threadpool_end(&pfjob->threads);
|
|
|
|
BLI_mutex_end(&pfjob->prefetch_suspend_mutex);
|
|
|
|
BLI_condition_end(&pfjob->prefetch_suspend_cond);
|
|
|
|
seq_prefetch_free_depsgraph(pfjob);
|
2019-10-02 22:04:48 +02:00
|
|
|
BKE_main_free(pfjob->bmain_eval);
|
2019-09-14 02:21:54 +02:00
|
|
|
MEM_freeN(pfjob);
|
|
|
|
scene->ed->prefetch_job = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *seq_prefetch_frames(void *job)
|
|
|
|
{
|
|
|
|
PrefetchJob *pfjob = (PrefetchJob *)job;
|
|
|
|
|
2019-10-02 22:04:48 +02:00
|
|
|
while (pfjob->cfra + pfjob->num_frames_prefetched <= pfjob->scene->r.efra) {
|
|
|
|
pfjob->scene_eval->ed->prefetch_job = NULL;
|
2019-09-14 02:21:54 +02:00
|
|
|
|
2020-04-27 00:34:10 +02:00
|
|
|
seq_prefetch_update_depsgraph(pfjob);
|
2019-10-02 22:04:48 +02:00
|
|
|
AnimData *adt = BKE_animdata_from_id(&pfjob->context_cpy.scene->id);
|
|
|
|
BKE_animsys_evaluate_animdata(pfjob->context_cpy.scene,
|
|
|
|
&pfjob->context_cpy.scene->id,
|
|
|
|
adt,
|
|
|
|
pfjob->cfra + pfjob->num_frames_prefetched,
|
|
|
|
ADT_RECALC_ALL,
|
|
|
|
false);
|
2019-09-14 02:21:54 +02:00
|
|
|
|
2019-10-02 22:04:48 +02:00
|
|
|
/* This is quite hacky solution:
|
|
|
|
* We need cross-reference original scene with copy for cache.
|
|
|
|
* However depsgraph must not have this data, because it will try to kill this job.
|
|
|
|
* Scene copy don't reference original scene. Perhaps, this could be done by depsgraph.
|
|
|
|
* Set to NULL before return!
|
|
|
|
*/
|
|
|
|
pfjob->scene_eval->ed->prefetch_job = pfjob;
|
|
|
|
|
2019-09-14 02:21:54 +02:00
|
|
|
ImBuf *ibuf = BKE_sequencer_give_ibuf(
|
|
|
|
&pfjob->context_cpy, pfjob->cfra + pfjob->num_frames_prefetched, 0);
|
|
|
|
BKE_sequencer_cache_free_temp_cache(
|
|
|
|
pfjob->scene, pfjob->context.task_id, pfjob->cfra + pfjob->num_frames_prefetched);
|
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
|
|
|
|
/* suspend thread */
|
|
|
|
BLI_mutex_lock(&pfjob->prefetch_suspend_mutex);
|
|
|
|
while ((seq_prefetch_is_cache_full(pfjob->scene) || seq_prefetch_is_scrubbing(pfjob->bmain)) &&
|
|
|
|
pfjob->scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE && !pfjob->stop) {
|
|
|
|
pfjob->waiting = true;
|
|
|
|
BLI_condition_wait(&pfjob->prefetch_suspend_cond, &pfjob->prefetch_suspend_mutex);
|
|
|
|
seq_prefetch_update_area(pfjob);
|
|
|
|
}
|
|
|
|
pfjob->waiting = false;
|
|
|
|
BLI_mutex_unlock(&pfjob->prefetch_suspend_mutex);
|
|
|
|
|
|
|
|
/* Avoid "collision" with main thread, but make sure to fetch at least few frames */
|
|
|
|
if (pfjob->num_frames_prefetched > 5 &&
|
|
|
|
(pfjob->cfra + pfjob->num_frames_prefetched - pfjob->scene->r.cfra) < 2) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(pfjob->scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) || pfjob->stop) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
seq_prefetch_update_area(pfjob);
|
|
|
|
pfjob->num_frames_prefetched++;
|
|
|
|
}
|
|
|
|
|
|
|
|
BKE_sequencer_cache_free_temp_cache(
|
|
|
|
pfjob->scene, pfjob->context.task_id, pfjob->cfra + pfjob->num_frames_prefetched);
|
|
|
|
pfjob->running = false;
|
|
|
|
pfjob->scene_eval->ed->prefetch_job = NULL;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-09-14 16:54:59 +02:00
|
|
|
static PrefetchJob *seq_prefetch_start(const SeqRenderData *context, float cfra)
|
2019-09-14 02:21:54 +02:00
|
|
|
{
|
2019-10-02 22:04:48 +02:00
|
|
|
PrefetchJob *pfjob = seq_prefetch_job_get(context->scene);
|
2019-09-14 02:21:54 +02:00
|
|
|
|
|
|
|
if (!pfjob) {
|
|
|
|
if (context->scene->ed) {
|
|
|
|
pfjob = (PrefetchJob *)MEM_callocN(sizeof(PrefetchJob), "PrefetchJob");
|
|
|
|
context->scene->ed->prefetch_job = pfjob;
|
|
|
|
|
|
|
|
BLI_threadpool_init(&pfjob->threads, seq_prefetch_frames, 1);
|
|
|
|
BLI_mutex_init(&pfjob->prefetch_suspend_mutex);
|
|
|
|
BLI_condition_init(&pfjob->prefetch_suspend_cond);
|
|
|
|
|
|
|
|
pfjob->bmain = context->bmain;
|
2019-10-02 22:04:48 +02:00
|
|
|
pfjob->bmain_eval = BKE_main_new();
|
2019-09-14 02:21:54 +02:00
|
|
|
|
|
|
|
pfjob->scene = context->scene;
|
|
|
|
seq_prefetch_init_depsgraph(pfjob);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
seq_prefetch_update_scene(context->scene);
|
|
|
|
seq_prefetch_update_context(context);
|
|
|
|
|
|
|
|
pfjob->cfra = cfra;
|
|
|
|
pfjob->num_frames_prefetched = 1;
|
|
|
|
|
|
|
|
pfjob->waiting = false;
|
|
|
|
pfjob->stop = false;
|
|
|
|
pfjob->running = true;
|
|
|
|
|
2020-01-26 16:35:58 +01:00
|
|
|
BLI_threadpool_remove(&pfjob->threads, pfjob);
|
2019-09-14 02:21:54 +02:00
|
|
|
BLI_threadpool_insert(&pfjob->threads, pfjob);
|
|
|
|
|
|
|
|
return pfjob;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Start or resume prefetching*/
|
|
|
|
void BKE_sequencer_prefetch_start(const SeqRenderData *context, float cfra, float cost)
|
|
|
|
{
|
|
|
|
Scene *scene = context->scene;
|
|
|
|
Editing *ed = scene->ed;
|
|
|
|
bool has_strips = (bool)ed->seqbasep->first;
|
|
|
|
|
|
|
|
if (!context->is_prefetch_render && !context->is_proxy_render) {
|
|
|
|
bool playing = seq_prefetch_is_playing(context->bmain);
|
|
|
|
bool scrubbing = seq_prefetch_is_scrubbing(context->bmain);
|
2019-10-02 22:04:48 +02:00
|
|
|
bool running = BKE_sequencer_prefetch_job_is_running(scene);
|
2019-09-14 02:21:54 +02:00
|
|
|
seq_prefetch_resume(scene);
|
|
|
|
/* conditions to start:
|
|
|
|
* prefetch enabled, prefetch not running, not scrubbing,
|
|
|
|
* not playing and rendering-expensive footage, cache storage enabled, has strips to render
|
|
|
|
*/
|
|
|
|
if ((ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) && !running && !scrubbing &&
|
|
|
|
!(playing && cost > 0.9) && ed->cache_flag & SEQ_CACHE_ALL_TYPES && has_strips) {
|
|
|
|
|
|
|
|
seq_prefetch_start(context, cfra);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BKE_sequencer_prefetch_need_redraw(Main *bmain, Scene *scene)
|
|
|
|
{
|
|
|
|
bool playing = seq_prefetch_is_playing(bmain);
|
|
|
|
bool scrubbing = seq_prefetch_is_scrubbing(bmain);
|
2019-10-02 22:04:48 +02:00
|
|
|
bool running = BKE_sequencer_prefetch_job_is_running(scene);
|
2019-09-14 02:21:54 +02:00
|
|
|
bool suspended = seq_prefetch_job_is_waiting(scene);
|
|
|
|
|
|
|
|
/* force redraw, when prefetching and using cache view. */
|
|
|
|
if (running && !playing && !suspended && scene->ed->cache_flag & SEQ_CACHE_VIEW_ENABLE) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
/* Sometimes scrubbing flag is set when not scrubbing. In that case I want to catch "event" of
|
|
|
|
* stopping scrubbing */
|
|
|
|
if (scrubbing) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|