Files
test/source/blender/sequencer/intern/cache/intra_frame_cache.cc
John Kiril Swenson 35cab63eaf Cleanup: VSE: Rename Strip::machine to channel
This should make VSE code more readable and easier to understand from an
outside perspective.

The name was chosen to be `channel` rather than `channel_index` to keep
things short and concise -- it should be clear based on the context
whether we are talking about the strip's channel index (singular case,
`Strip::channel` or `SeqTimelineChannel::index`) vs. the channel list
(plural case, e.g. `Editing::channels`).

Pull Request: https://projects.blender.org/blender/blender/pulls/138919
2025-05-21 19:13:20 +02:00

179 lines
4.3 KiB
C++

/* SPDX-FileCopyrightText: 2025 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup sequencer
*/
#include "BLI_map.hh"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "IMB_imbuf.hh"
#include "intra_frame_cache.hh"
namespace blender::seq {
struct StripImageMap {
Map<const Strip *, ImBuf *> map_;
ImBuf *get(const Strip *strip) const;
void put(const Strip *strip, ImBuf *image);
void invalidate(const Strip *strip);
void clear();
};
struct IntraFrameCache {
StripImageMap preprocessed;
StripImageMap composite;
float timeline_frame = -1.0f;
int view_id = -1;
~IntraFrameCache()
{
preprocessed.clear();
composite.clear();
}
};
static IntraFrameCache *query_intra_frame_cache(Scene *scene)
{
if (scene == nullptr || scene->ed == nullptr) {
return nullptr;
}
return scene->ed->runtime.intra_frame_cache;
}
void intra_frame_cache_invalidate(Scene *scene)
{
IntraFrameCache *cache = query_intra_frame_cache(scene);
if (cache != nullptr) {
cache->preprocessed.clear();
cache->composite.clear();
cache->timeline_frame = -1.0f;
cache->view_id = -1;
}
}
void intra_frame_cache_invalidate(Scene *scene, const Strip *strip)
{
if (strip == nullptr) {
return;
}
IntraFrameCache *cache = query_intra_frame_cache(scene);
if (cache != nullptr) {
cache->preprocessed.invalidate(strip);
cache->composite.invalidate(strip);
}
}
void StripImageMap::invalidate(const Strip *strip)
{
/* Invalidate this strip, and all strips that are above it. */
for (auto it = this->map_.items().begin(); it != this->map_.items().end(); it++) {
const Strip *key = (*it).key;
if (key == strip || key->channel >= strip->channel) {
IMB_freeImBuf((*it).value);
this->map_.remove(it);
}
}
}
ImBuf *StripImageMap::get(const Strip *strip) const
{
ImBuf *image = this->map_.lookup_default(strip, nullptr);
if (image != nullptr) {
IMB_refImBuf(image);
}
return image;
}
void StripImageMap::put(const Strip *strip, ImBuf *image)
{
BLI_assert(strip != nullptr);
if (image == nullptr) {
return;
}
ImBuf *existing = this->map_.lookup_default(strip, nullptr);
if (existing != nullptr) {
IMB_freeImBuf(existing);
}
this->map_.add_overwrite(strip, image);
IMB_refImBuf(image);
}
void StripImageMap::clear()
{
for (const auto &item : this->map_.items()) {
IMB_freeImBuf(item.value);
}
this->map_.clear();
}
ImBuf *intra_frame_cache_get_preprocessed(Scene *scene, const Strip *strip)
{
IntraFrameCache *cache = query_intra_frame_cache(scene);
if (strip == nullptr || cache == nullptr) {
return nullptr;
}
return cache->preprocessed.get(strip);
}
ImBuf *intra_frame_cache_get_composite(Scene *scene, const Strip *strip)
{
IntraFrameCache *cache = query_intra_frame_cache(scene);
if (strip == nullptr || cache == nullptr) {
return nullptr;
}
return cache->composite.get(strip);
}
void intra_frame_cache_put_preprocessed(Scene *scene, const Strip *strip, ImBuf *image)
{
if (scene == nullptr || scene->ed == nullptr || strip == nullptr || image == nullptr) {
return;
}
IntraFrameCache *&cache = scene->ed->runtime.intra_frame_cache;
if (cache == nullptr) {
cache = MEM_new<IntraFrameCache>(__func__);
}
cache->preprocessed.put(strip, image);
}
void intra_frame_cache_put_composite(Scene *scene, const Strip *strip, ImBuf *image)
{
if (scene == nullptr || scene->ed == nullptr || strip == nullptr || image == nullptr) {
return;
}
IntraFrameCache *&cache = scene->ed->runtime.intra_frame_cache;
if (cache == nullptr) {
cache = MEM_new<IntraFrameCache>(__func__);
}
cache->composite.put(strip, image);
}
void intra_frame_cache_destroy(Scene *scene)
{
IntraFrameCache *cache = query_intra_frame_cache(scene);
if (cache != nullptr) {
MEM_SAFE_DELETE(scene->ed->runtime.intra_frame_cache);
}
}
void intra_frame_cache_set_cur_frame(Scene *scene, float frame, int view_id)
{
IntraFrameCache *cache = query_intra_frame_cache(scene);
if (cache != nullptr) {
if (cache->timeline_frame != frame || cache->view_id != view_id) {
cache->timeline_frame = frame;
cache->view_id = view_id;
cache->preprocessed.clear();
cache->composite.clear();
}
}
}
} // namespace blender::seq