Blender V5.0
preview_cache.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2025 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "DNA_scene_types.h"
10#include "DNA_sequence_types.h"
11
12#include "GPU_texture.hh"
13
14#include "SEQ_preview_cache.hh"
15
16namespace blender::seq {
17
34
36 static constexpr int cache_size = 4;
39
41 {
42 clear();
43 }
44
45 void clear()
46 {
47 for (PreviewCacheItem &item : this->items) {
48 item.clear();
49 }
50 }
51};
52
54{
55 if (scene == nullptr || scene->ed == nullptr) {
56 return nullptr;
57 }
58 return scene->ed->runtime.preview_cache;
59}
60
62{
63 if (scene == nullptr || scene->ed == nullptr) {
64 return nullptr;
65 }
66 PreviewCache *&cache = scene->ed->runtime.preview_cache;
67 if (cache == nullptr) {
68 cache = MEM_new<PreviewCache>(__func__);
69 }
70 return cache;
71}
72
73gpu::Texture *preview_cache_get_gpu_texture(Scene *scene, int timeline_frame, int display_channel)
74{
75 PreviewCache *cache = query_preview_cache(scene);
76 if (cache == nullptr) {
77 return nullptr;
78 }
79 cache->tick_count++;
80 for (PreviewCacheItem &item : cache->items) {
81 if (item.timeline_frame == timeline_frame && item.display_channel == display_channel &&
82 item.texture != nullptr)
83 {
84 item.last_used = cache->tick_count;
85 return item.texture;
86 }
87 }
88 return nullptr;
89}
90
92 int timeline_frame,
93 int display_channel)
94{
95 PreviewCache *cache = query_preview_cache(scene);
96 if (cache == nullptr) {
97 return nullptr;
98 }
99 cache->tick_count++;
100 for (PreviewCacheItem &item : cache->items) {
101 if (item.timeline_frame == timeline_frame && item.display_channel == display_channel &&
102 item.display_texture != nullptr)
103 {
104 item.last_used = cache->tick_count;
105 return item.display_texture;
106 }
107 }
108 return nullptr;
109}
110
111static PreviewCacheItem *find_slot(PreviewCache *cache, int timeline_frame, int display_channel)
112{
113 cache->tick_count++;
114
115 /* Try to find an exact frame match. */
116 for (PreviewCacheItem &item : cache->items) {
117 if (item.timeline_frame == timeline_frame && item.display_channel == display_channel) {
118 return &item;
119 }
120 }
121
122 /* Find unused or least recently used slot. */
123 PreviewCacheItem *best_slot = nullptr;
124 int64_t best_score = -1;
125 for (PreviewCacheItem &item : cache->items) {
126 if (item.texture == nullptr && item.display_texture == nullptr) {
127 return &item;
128 }
129 int64_t score = cache->tick_count - item.last_used;
130 if (score >= best_score) {
131 best_score = score;
132 best_slot = &item;
133 }
134 }
135
136 return best_slot;
137}
138
140 int timeline_frame,
141 int display_channel,
143{
144 PreviewCache *cache = ensure_preview_cache(scene);
145 if (cache == nullptr || texture == nullptr) {
146 return;
147 }
148 PreviewCacheItem *slot = find_slot(cache, timeline_frame, display_channel);
149 if (slot == nullptr) {
150 return;
151 }
152
153 slot->timeline_frame = timeline_frame;
154 slot->display_channel = display_channel;
155 slot->last_used = cache->tick_count;
157 /* Free the display-space texture of this slot too. */
159 slot->texture = texture;
160}
161
163 int timeline_frame,
164 int display_channel,
166{
167 PreviewCache *cache = ensure_preview_cache(scene);
168 if (cache == nullptr || texture == nullptr) {
169 return;
170 }
171 PreviewCacheItem *slot = find_slot(cache, timeline_frame, display_channel);
172 if (slot == nullptr) {
173 return;
174 }
175
176 slot->timeline_frame = timeline_frame;
177 slot->display_channel = display_channel;
178 slot->last_used = cache->tick_count;
180 slot->display_texture = texture;
181}
182
184{
185 PreviewCache *cache = query_preview_cache(scene);
186 if (cache != nullptr) {
187 cache->clear();
188 }
189}
190
192{
193 PreviewCache *cache = query_preview_cache(scene);
194 if (cache != nullptr) {
195 MEM_SAFE_DELETE(scene->ed->runtime.preview_cache);
196 }
197}
198
199} // namespace blender::seq
#define GPU_TEXTURE_FREE_SAFE(texture)
long long int int64_t
TEX_TEMPLATE DataVec texture(T, FltCoord, float=0.0f) RET
void preview_cache_set_gpu_display_texture(Scene *scene, int timeline_frame, int display_channel, gpu::Texture *texture)
void preview_cache_destroy(Scene *scene)
gpu::Texture * preview_cache_get_gpu_texture(Scene *scene, int timeline_frame, int display_channel)
void preview_cache_set_gpu_texture(Scene *scene, int timeline_frame, int display_channel, gpu::Texture *texture)
static PreviewCache * ensure_preview_cache(Scene *scene)
static PreviewCache * query_preview_cache(Scene *scene)
void preview_cache_invalidate(Scene *scene)
static PreviewCacheItem * find_slot(PreviewCache *cache, int timeline_frame, int display_channel)
gpu::Texture * preview_cache_get_gpu_display_texture(Scene *scene, int timeline_frame, int display_channel)
PreviewCache * preview_cache
EditingRuntime runtime
struct Editing * ed
PreviewCacheItem items[cache_size]
static constexpr int cache_size