Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
pixelpipe_raster_masks.c
Go to the documentation of this file.
1
15// This file is textually #included into pixelpipe_hb.c (see the doc block above), so
16// these guarded includes fold into that TU; they are named here because THIS file uses them.
17#include "common/glib_utils.h" // dt_string_replace
18#include "develop/pipeline_notify.h" // dt_pipeline_message
19
32 dt_dev_pixelpipe_iop_t *current_piece,
33 const dt_iop_module_t *target_module)
34{
35 gboolean success = TRUE;
36 gchar *clean_target_name = !IS_NULL_PTR(target_module)
37 ? dt_string_replace(target_module->name(), "_")
38 : g_strdup(_("export"));
39 gchar *target_name = !IS_NULL_PTR(target_module)
40 ? g_strdup_printf("%s (%s)", clean_target_name, target_module->multi_name)
41 : g_strdup(clean_target_name);
42
43 if(IS_NULL_PTR(source_piece)
44 || (!IS_NULL_PTR(target_module) && IS_NULL_PTR(current_piece)))
45 {
46 dt_print(DT_DEBUG_MASKS,"[raster masks] ERROR: source: %s, current: %s\n",
47 (!IS_NULL_PTR(source_piece)) ? "is defined" : "is undefined",
48 (!IS_NULL_PTR(current_piece)) ? "is defined" : "is undefined");
49
50 gchar *hint = NULL;
51 if(IS_NULL_PTR(source_piece))
52 {
53 hint = g_strdup_printf(
54 _("- Check if the module providing the masks for the module %s has not been deleted.\n"),
55 target_name);
56 }
57 else if(IS_NULL_PTR(current_piece))
58 {
59 gchar *clean_source_name = dt_string_replace(source_piece->module->name(), "_");
60 hint = g_strdup_printf(_("- Check if the module %s (%s) providing the masks has not been moved above %s.\n"),
61 clean_source_name,
62 source_piece->module->multi_name, clean_target_name);
63 dt_free(clean_source_name);
64 }
65
66 dt_pipeline_message(_("The %s module is trying to reuse a mask from a module but it can't be found.\n"
67 "\n%s"),
68 target_name, hint ? hint : "");
69 dt_free(hint);
70
71 dt_print(DT_DEBUG_MASKS, "[raster masks] no source module for module %s could be found\n", target_name);
72 success = FALSE;
73 }
74
75 if(success && !source_piece->enabled)
76 {
77 gchar *clean_source_name = dt_string_replace(source_piece->module->name(), "_");
78 gchar *source_name = g_strdup_printf("%s (%s)", clean_source_name, source_piece->module->multi_name);
79 dt_pipeline_message(_("The `%s` module is trying to reuse a mask from disabled module `%s`.\n"
80 "Disabled modules cannot provide their masks to other modules.\n"
81 "\n- Please enable `%s` or change the raster mask in `%s`."),
82 target_name, source_name, source_name, target_name);
83
84 dt_print(DT_DEBUG_MASKS, "[raster masks] module %s trying to reuse a mask from disabled instance of %s\n",
85 target_name, source_name);
86
87 dt_free(clean_source_name);
88 dt_free(source_name);
89 success = FALSE;
90 }
91
92 dt_free(clean_target_name);
93 dt_free(target_name);
94 return success;
95}
96
97float *dt_dev_get_raster_mask(dt_dev_pixelpipe_t *pipe, const dt_iop_module_t *raster_mask_source,
98 const int raster_mask_id, const dt_iop_module_t *target_module,
99 int *error)
100{
101 if(!IS_NULL_PTR(error)) *error = 0;
102
103 gchar *clean_target_name = !IS_NULL_PTR(target_module)
104 ? dt_string_replace(target_module->name(), "_")
105 : g_strdup(_("export"));
106 gchar *target_name = !IS_NULL_PTR(target_module)
107 ? g_strdup_printf("%s (%s)", clean_target_name, target_module->multi_name)
108 : g_strdup(clean_target_name);
109
110 if(IS_NULL_PTR(raster_mask_source))
111 {
112 dt_print(DT_DEBUG_MASKS, "[raster masks] The source module of the mask for %s was not found\n", target_name);
113 dt_free(clean_target_name);
114 dt_free(target_name);
115 return NULL;
116 }
117
118 float *raster_mask = NULL;
119
120 dt_dev_pixelpipe_iop_t *source_piece = NULL;
121 dt_dev_pixelpipe_iop_t *current_piece = NULL;
122 GList *source_iter = NULL;
123 for(source_iter = g_list_last(pipe->nodes); source_iter; source_iter = g_list_previous(source_iter))
124 {
125 dt_dev_pixelpipe_iop_t *candidate = (dt_dev_pixelpipe_iop_t *)source_iter->data;
126 if(candidate->module == target_module)
127 current_piece = candidate;
128 else if(candidate->module == raster_mask_source)
129 {
130 source_piece = candidate;
131 break;
132 }
133 }
134
135 const int err_ret = !_dt_dev_raster_mask_check(source_piece, current_piece, target_module);
136 if(!IS_NULL_PTR(error)) *error = err_ret;
137
138 if(!err_ret)
139 {
140 const uint64_t provider_hash = source_piece->global_hash;
141 const uint64_t raster_hash
142 = dt_dev_pixelpipe_raster_mask_hash(source_piece, raster_mask_id);
143
144 gchar *clean_source_name = dt_string_replace(source_piece->module->name(), "_");
145 gchar *source_name = g_strdup_printf("%s (%s)", clean_source_name, source_piece->module->multi_name);
146 dt_pixel_cache_entry_t *raster_entry = NULL;
147 void *cache_data = NULL;
148 const gboolean found = dt_dev_pixelpipe_cache_ref_entry_by_hash(
149 raster_hash, &cache_data, &raster_entry);
150
151 gchar *type = dt_pixelpipe_get_pipe_name(pipe->type);
152 if(found && !IS_NULL_PTR(cache_data) && !IS_NULL_PTR(raster_entry))
153 {
154 const size_t mask_size
155 = sizeof(float) * (size_t)source_piece->roi_out.width * source_piece->roi_out.height;
157 (size_t)source_piece->roi_out.width * source_piece->roi_out.height, pipe->type);
158 if(IS_NULL_PTR(raster_mask))
159 {
161 FALSE, raster_entry);
162 if(!IS_NULL_PTR(error)) *error = 1;
163 dt_free(clean_source_name);
164 dt_free(source_name);
165 dt_free(clean_target_name);
166 dt_free(target_name);
167 return NULL;
168 }
169
170 // The cache owns the canonical mask. Copy it under a read lock so the
171 // caller can freely distort and release its private working buffer.
173 TRUE, raster_entry);
174 memcpy(raster_mask, cache_data, mask_size);
176 FALSE, raster_entry);
178 FALSE, raster_entry);
179
181 "[raster masks] found cached mask id %i from %s for module %s"
182 " in pipe %s with hash %" PRIu64 "\n",
183 raster_mask_id, source_name, target_name, type, raster_hash);
184 dt_dev_pixelpipe_unset_reentry(pipe, provider_hash);
185 }
186 else
187 {
188 if(!IS_NULL_PTR(raster_entry))
190 FALSE, raster_entry);
191
193 "[raster masks] missing source=%s instance=%d target=%s instance=%d"
194 " requested_id=%d cache_hash=%" PRIu64 " source_enabled=%d pipe=%s\n",
195 source_piece->module->op, source_piece->module->multi_priority,
196 !IS_NULL_PTR(target_module) ? target_module->op : "export",
197 !IS_NULL_PTR(target_module) ? target_module->multi_priority : -1,
198 raster_mask_id, raster_hash, source_piece->enabled,
199 type);
200
202 "[raster masks] mask id %i from %s for module %s could not be found"
203 " in the global cache for pipe %s.\n",
204 raster_mask_id, source_name, target_name, type);
205
206 // A cache miss can still happen after LRU eviction. Cached provider
207 // pixels cannot reconstruct the side-band mask, so interactive pipes get
208 // one targeted provider retry; export callers pass no error pointer and
209 // simply report the missing mask.
210 if(!IS_NULL_PTR(error))
211 {
212 if(dt_dev_pixelpipe_set_reentry(pipe, provider_hash))
213 pipe->flush_cache = TRUE;
214 *error = 1;
215 }
216
217 dt_free(clean_source_name);
218 dt_free(source_name);
219 dt_free(clean_target_name);
220 dt_free(target_name);
221 return NULL;
222 }
223
224 for(GList *iter = g_list_next(source_iter); iter; iter = g_list_next(iter))
225 {
226 dt_dev_pixelpipe_iop_t *module = (dt_dev_pixelpipe_iop_t *)iter->data;
227
228 if(module->enabled
229 && !dt_dev_pixelpipe_activemodule_disables_currentmodule(module->module->dev, module->module))
230 {
231 if(module->module->distort_mask
232 && !(!strcmp(module->module->op, "finalscale")
233 && module->roi_in.width == 0
234 && module->roi_in.height == 0))
235 {
236 float *transformed_mask = dt_pixelpipe_cache_alloc_align_float_cache(
237 (size_t)module->roi_out.width * module->roi_out.height, 0);
238 if(IS_NULL_PTR(transformed_mask))
239 {
240 dt_print(DT_DEBUG_MASKS, "[raster masks] could not allocate memory for transformed mask\n");
241 if(!IS_NULL_PTR(error)) *error = 1;
243 dt_free(clean_source_name);
244 dt_free(source_name);
245 dt_free(clean_target_name);
246 dt_free(target_name);
247 return NULL;
248 }
249
250 module->module->distort_mask(module->module, pipe, module, raster_mask, transformed_mask,
251 &module->roi_in, &module->roi_out);
253 raster_mask = transformed_mask;
254 dt_print(DT_DEBUG_MASKS, "[raster masks] doing transform\n");
255 }
256 else if(!module->module->distort_mask
257 && (module->roi_in.width != module->roi_out.width
258 || module->roi_in.height != module->roi_out.height
259 || module->roi_in.x != module->roi_out.x
260 || module->roi_in.y != module->roi_out.y))
261 dt_print(DT_DEBUG_MASKS, "FIXME: module `%s' changed the roi from %d x %d @ %d / %d to %d x %d | %d / %d but doesn't have "
262 "distort_mask() implemented!\n", module->module->op, module->roi_in.width,
263 module->roi_in.height, module->roi_in.x, module->roi_in.y,
264 module->roi_out.width, module->roi_out.height, module->roi_out.x,
265 module->roi_out.y);
266 }
267
268 if(module->module == target_module)
269 {
270 gchar *clean_module_name = dt_string_replace(module->module->name(), "_");
271 dt_print(DT_DEBUG_MASKS, "[raster masks] found mask id %i from %s for module %s (%s) in pipe %s\n",
272 raster_mask_id, source_name, clean_module_name,
273 module->module->multi_name, dt_pixelpipe_get_pipe_name(pipe->type));
274 dt_free(clean_module_name);
275 break;
276 }
277 }
278
279 dt_free(clean_source_name);
280 dt_free(source_name);
281 }
282
283 dt_free(clean_target_name);
284 dt_free(target_name);
285 return raster_mask;
286}
static void error(char *msg)
Definition ashift_lsd.c:202
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
gboolean dt_dev_pixelpipe_activemodule_disables_currentmodule(struct dt_develop_t *dev, struct dt_iop_module_t *current_module)
static gchar * dt_string_replace(const char *string, const char *to_replace)
Definition glib_utils.h:64
_lib_location_type_t type
Definition location.c:1
@ DT_DEBUG_DEV
Definition logging.h:53
@ DT_DEBUG_MASKS
Definition logging.h:62
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
#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
void dt_pipeline_message(const char *format,...)
Everything the pixel pipeline says to whoever is watching: messages for the user, and the busy banner...
uint64_t dt_dev_pixelpipe_raster_mask_hash(const dt_dev_pixelpipe_iop_t *piece, const int raster_mask_id)
Definition pixelpipe.c:53
void dt_dev_pixelpipe_cache_ref_count_entry(gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Increase/Decrease the reference count on the cache line as to prevent LRU item removal....
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.
gboolean dt_dev_pixelpipe_cache_ref_entry_by_hash(const uint64_t hash, void **data, dt_pixel_cache_entry_t **entry)
Resolve and retain an existing cache entry by hash.
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define dt_pixelpipe_cache_free_align(mem)
char * dt_pixelpipe_get_pipe_name(dt_dev_pixelpipe_type_t pipe_type)
gboolean dt_dev_pixelpipe_unset_reentry(dt_dev_pixelpipe_t *pipe, uint64_t hash)
Remove the re-entry pipeline flag, only if the object identifier is the one that set it....
gboolean dt_dev_pixelpipe_set_reentry(dt_dev_pixelpipe_t *pipe, uint64_t hash)
Set the re-entry pipeline flag, only if no object is already capturing it.
static gboolean _dt_dev_raster_mask_check(dt_dev_pixelpipe_iop_t *source_piece, dt_dev_pixelpipe_iop_t *current_piece, const dt_iop_module_t *target_module)
Check that the raster-mask provider/consumer relation is still valid in the current pipe.
float * dt_dev_get_raster_mask(dt_dev_pixelpipe_t *pipe, const dt_iop_module_t *raster_mask_source, const int raster_mask_id, const dt_iop_module_t *target_module, int *error)
unsigned __int64 uint64_t
Definition strptime.c:75
struct dt_iop_module_t *void * data
dt_dev_pixelpipe_type_t type
char multi_name[128]
Definition imageop.h:387
dt_dev_operation_t op
Definition imageop.h:259
int width
Definition format.h:50
int height
Definition format.h:50