Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
src/iop/drawlayer/cache.c
Go to the documentation of this file.
1/*
2 This file is part of the Ansel project.
3 Copyright (C) 2026 Aurélien PIERRE.
4
5 Ansel is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 Ansel is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Ansel. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#include "system/macros.h"
20#include "system/mem_alloc.h"
21#include "iop/drawlayer/cache.h"
22
23
24#include <string.h>
25
27void *dt_drawlayer_cache_alloc_temp_buffer(const size_t bytes, const char *name)
28{
29 if(bytes == 0) return NULL;
31}
32
34void dt_drawlayer_cache_free_temp_buffer(void **buffer, const char *name)
35{
36 if(IS_NULL_PTR(buffer) || !*buffer) return;
38}
39
41float *dt_drawlayer_cache_ensure_scratch_buffer(float **buffer, size_t *capacity_pixels, const size_t needed_pixels,
42 const char *name)
43{
44 if(IS_NULL_PTR(buffer) || IS_NULL_PTR(capacity_pixels) || needed_pixels == 0) return NULL;
45 if(*capacity_pixels < needed_pixels)
46 {
48 float *new_buffer = dt_drawlayer_cache_alloc_temp_buffer(needed_pixels * 4 * sizeof(float), name);
49 if(IS_NULL_PTR(new_buffer)) return NULL;
50 *buffer = new_buffer;
51 *capacity_pixels = needed_pixels;
52 }
53 return *buffer;
54}
55
57void dt_drawlayer_cache_clear_transparent_float(float *pixels, const size_t pixel_count)
58{
59 if(IS_NULL_PTR(pixels)) return;
60 memset(pixels, 0, pixel_count * 4 * sizeof(float));
61}
62
64void dt_drawlayer_cache_patch_clear(dt_drawlayer_cache_patch_t *patch, const char *external_alloc_name)
65{
66 if(IS_NULL_PTR(patch)) return;
67 if(patch->external_alloc)
68 {
69 if(patch->cache_entry)
71 void *buffer = patch->pixels;
72 dt_pixelpipe_cache_free_align_cache(&buffer, external_alloc_name);
73 }
74 else if(patch->cache_entry)
75 {
77 }
78 else
79 {
80 dt_free(patch->pixels);
81 }
82 memset(patch, 0, sizeof(*patch));
83}
84
87 const size_t pixel_count, const int width, const int height,
88 const char *name, int *created_out)
89{
90 if(IS_NULL_PTR(patch) || pixel_count == 0 || width <= 0 || height <= 0) return FALSE;
91
92 void *data = NULL;
93 dt_pixel_cache_entry_t *entry = NULL;
94 const int created = dt_dev_pixelpipe_cache_get(hash, pixel_count * 4 * sizeof(float),
95 name, DT_DEV_PIXELPIPE_NONE, TRUE, &data, &entry);
96 if(!IS_NULL_PTR(created_out)) *created_out = created;
97 if(IS_NULL_PTR(data) || IS_NULL_PTR(entry))
98 {
99 if(entry)
100 {
101 if(created) dt_dev_pixelpipe_cache_wrlock_entry(FALSE, entry);
103 }
104 return FALSE;
105 }
106
107 dt_drawlayer_cache_patch_clear(patch, "drawlayer patch");
108 patch->x = 0;
109 patch->y = 0;
110 patch->width = width;
111 patch->height = height;
112 patch->pixels = (float *)data;
113 patch->cache_entry = entry;
114 patch->cache_hash = hash;
115 patch->external_alloc = FALSE;
116
117 if(created) dt_dev_pixelpipe_cache_wrlock_entry(FALSE, entry);
118 return TRUE;
119}
120
123 const int height, const char *name)
124{
125 if(IS_NULL_PTR(mask) || width <= 0 || height <= 0) return FALSE;
126
127 const gboolean size_changed = (mask->width != width || mask->height != height || !mask->pixels);
128 if(size_changed)
129 {
131 mask->width = width;
132 mask->height = height;
133 mask->x = 0;
134 mask->y = 0;
135 mask->pixels = dt_drawlayer_cache_alloc_temp_buffer((size_t)width * height * sizeof(float), name);
136 mask->external_alloc = TRUE;
137 if(IS_NULL_PTR(mask->pixels))
138 {
139 mask->width = 0;
140 mask->height = 0;
141 return FALSE;
142 }
143
144 mask->cache_entry = dt_dev_pixelpipe_cache_ref_entry_for_host_ptr(mask->pixels);
145 mask->cache_hash = mask->cache_entry ? mask->cache_entry->hash : DT_PIXELPIPE_CACHE_HASH_INVALID;
146 if(IS_NULL_PTR(mask->cache_entry))
147 {
149 return FALSE;
150 }
151 }
152
153 memset(mask->pixels, 0, (size_t)width * height * sizeof(float));
154 return TRUE;
155}
156
163
170
177
184
187 dt_drawlayer_cache_patch_t *process_stroke_mask,
188 const int width,
189 const int height, const char *patch_buffer_name,
190 const char *mask_buffer_name)
191{
192 if(IS_NULL_PTR(process_patch) || !process_stroke_mask || width <= 0 || height <= 0)
193 return FALSE;
194
195 const gboolean size_changed = (process_patch->width != width || process_patch->height != height
196 || !process_patch->pixels);
197 if(size_changed)
198 {
199 dt_drawlayer_cache_patch_clear(process_patch, patch_buffer_name);
200 process_patch->width = width;
201 process_patch->height = height;
202 process_patch->x = 0;
203 process_patch->y = 0;
204 process_patch->pixels = dt_drawlayer_cache_alloc_temp_buffer((gsize)width * height * 4 * sizeof(float),
205 patch_buffer_name);
206 process_patch->external_alloc = TRUE;
207 if(IS_NULL_PTR(process_patch->pixels)) return FALSE;
208 process_patch->cache_entry
210 process_patch->cache_hash = process_patch->cache_entry ? process_patch->cache_entry->hash
212 if(IS_NULL_PTR(process_patch->cache_entry)) return FALSE;
213 }
214
215 const size_t mask_count = (size_t)width * height;
216 if(size_changed || process_stroke_mask->width != width || process_stroke_mask->height != height
217 || !process_stroke_mask->pixels)
218 {
219 dt_drawlayer_cache_patch_clear(process_stroke_mask, mask_buffer_name);
220 process_stroke_mask->width = width;
221 process_stroke_mask->height = height;
222 process_stroke_mask->x = 0;
223 process_stroke_mask->y = 0;
224 process_stroke_mask->pixels = dt_drawlayer_cache_alloc_temp_buffer(mask_count * sizeof(float),
225 mask_buffer_name);
226 process_stroke_mask->external_alloc = TRUE;
227 if(!process_stroke_mask->pixels)
228 {
229 process_stroke_mask->width = 0;
230 process_stroke_mask->height = 0;
231 return FALSE;
232 }
233 process_stroke_mask->cache_entry
235 process_stroke_mask->cache_hash = process_stroke_mask->cache_entry ? process_stroke_mask->cache_entry->hash
237 if(!process_stroke_mask->cache_entry)
238 {
239 process_stroke_mask->width = 0;
240 process_stroke_mask->height = 0;
241 return FALSE;
242 }
243 }
244
245 return TRUE;
246}
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
Patch/cache helpers for drawlayer process and preview buffers.
hash
Definition layers.h:90
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition macros.h:96
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
uint32_t width
Definition mipmap_cache.c:0
uint32_t height
Definition mipmap_cache.c:1
const char * name
Definition pdf.h:90
@ DT_DEV_PIXELPIPE_NONE
Definition pixelpipe.h:41
void dt_dev_pixelpipe_cache_wrlock_entry(gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Lock or release the write lock on the entry.
void * dt_pixelpipe_cache_alloc_align_cache_impl(size_t size, int id, const char *name)
Allocate aligned memory tracked by the pixelpipe cache. This allows LRU cache entries to be evicted i...
void dt_dev_pixelpipe_cache_ref_count_entry(gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Take or release one reference on a cache line. A referenced line is never evicted,...
void dt_dev_pixelpipe_cache_rdlock_entry(gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Lock or release the read lock on the entry.
int dt_dev_pixelpipe_cache_get(const uint64_t hash, const size_t size, const char *name, const int id, const gboolean alloc, void **data, dt_pixel_cache_entry_t **entry)
Get a cache line from the cache.
void dt_pixelpipe_cache_free_align_cache(void **mem, const char *message)
Free aligned memory allocated with dt_pixelpipe_cache_alloc_align_cache.
dt_pixel_cache_entry_t * dt_dev_pixelpipe_cache_ref_entry_for_host_ptr(void *host_ptr)
Resolve and retain the cache entry owning a host pointer.
#define DT_PIXELPIPE_CACHE_HASH_INVALID
void * dt_drawlayer_cache_alloc_temp_buffer(const size_t bytes, const char *name)
Allocate temporary aligned cache buffer.
float * dt_drawlayer_cache_ensure_scratch_buffer(float **buffer, size_t *capacity_pixels, const size_t needed_pixels, const char *name)
Ensure scratch RGBA float capacity in pixels.
void dt_drawlayer_cache_patch_wrunlock(const dt_drawlayer_cache_patch_t *patch)
Release write lock on shared patch cache entry.
void dt_drawlayer_cache_patch_wrlock(const dt_drawlayer_cache_patch_t *patch)
Acquire write lock on shared patch cache entry.
void dt_drawlayer_cache_patch_clear(dt_drawlayer_cache_patch_t *patch, const char *external_alloc_name)
Release patch storage and reset patch metadata.
gboolean dt_drawlayer_cache_ensure_mask_buffer(dt_drawlayer_cache_patch_t *mask, const int width, const int height, const char *name)
Ensure a float stroke-mask buffer exists and matches the requested size.
gboolean dt_drawlayer_cache_patch_alloc_shared(dt_drawlayer_cache_patch_t *patch, const uint64_t hash, const size_t pixel_count, const int width, const int height, const char *name, int *created_out)
Allocate patch storage from shared pixel cache entry.
gboolean dt_drawlayer_cache_ensure_process_patch_buffer(dt_drawlayer_cache_patch_t *process_patch, dt_drawlayer_cache_patch_t *process_stroke_mask, const int width, const int height, const char *patch_buffer_name, const char *mask_buffer_name)
Ensure process patch and process-stroke-mask backing buffers exist.
void dt_drawlayer_cache_free_temp_buffer(void **buffer, const char *name)
Free temporary aligned cache buffer.
void dt_drawlayer_cache_patch_rdlock(const dt_drawlayer_cache_patch_t *patch)
Acquire read lock on shared patch cache entry.
void dt_drawlayer_cache_patch_rdunlock(const dt_drawlayer_cache_patch_t *patch)
Release read lock on shared patch cache entry.
void dt_drawlayer_cache_clear_transparent_float(float *pixels, const size_t pixel_count)
Fill float RGBA buffer with transparent black.
unsigned __int64 uint64_t
Definition strptime.c:75
Generic float RGBA patch stored either in malloc memory or pixel cache.
dt_pixel_cache_entry_t * cache_entry
uint64_t hash