Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
layers.c
Go to the documentation of this file.
1
20
29
30static void _layerio_append_error(GString *errors, const char *message)
31{
32 if(IS_NULL_PTR(errors) || IS_NULL_PTR(message) || message[0] == '\0') return;
33 if(errors->len > 0) g_string_append(errors, "; ");
34 g_string_append(errors, message);
35}
36
37static void _layerio_log_errors(GString *errors)
38{
39 if(IS_NULL_PTR(errors)) return;
40 if(errors->len > 0) dt_control_log("%s", errors->str);
41}
42
44{
47 if(IS_NULL_PTR(g)) return;
49
50 while(dt_bauhaus_combobox_length(g->controls.layer_select) > 0)
51 dt_bauhaus_combobox_remove_at(g->controls.layer_select, dt_bauhaus_combobox_length(g->controls.layer_select) - 1);
52
53 if(IS_NULL_PTR(self->dev))
54 {
55 dt_bauhaus_combobox_set(g->controls.layer_select, -1);
57 return;
58 }
59
60 char path[PATH_MAX] = { 0 };
61 char **names = NULL;
62 int count = 0;
63 if(dt_drawlayer_io_sidecar_path(self->dev->image_storage.id, path, sizeof(path)))
64 dt_drawlayer_io_list_layer_names(path, &names, &count);
65
66 int active = -1;
67 const int listed_count = count;
68 for(int i = 0; i < count; i++)
69 {
70 const char *page_name = names[i] ? names[i] : "";
71 dt_bauhaus_combobox_add(g->controls.layer_select, page_name);
72 if(params->layer_order == i || (params->layer_name[0] && !g_strcmp0(page_name, params->layer_name)))
73 active = i;
74 }
75
77 if(active >= 0)
78 dt_bauhaus_combobox_set(g->controls.layer_select, active);
79 else if(listed_count > 0 && !_layer_name_non_empty(params->layer_name))
80 dt_bauhaus_combobox_set(g->controls.layer_select, 0);
81 else
82 /* The combobox is reserved for layers that already exist in the TIFF
83 * sidecar. Keep unsaved or missing module attachments out of the shared
84 * list so switching layers never invents phantom entries. */
85 dt_bauhaus_combobox_set(g->controls.layer_select, -1);
87}
88
90{
91 if(IS_NULL_PTR(g)) return;
92 g->stroke.stroke_sample_count = 0;
93 g->stroke.stroke_event_index = 0;
94 g->stroke.last_dab_valid = FALSE;
98}
99
101{
102 /* Cache identity belongs to the module orchestration layer because it
103 * combines sidecar identity with GUI/module state (active image, selected
104 * layer, in-memory patch ownership). The low-level TIFF primitives stay in
105 * drawlayer/io.c. */
106 if(IS_NULL_PTR(g) || IS_NULL_PTR(key) || !g->process.cache_valid || IS_NULL_PTR(g->process.base_patch.pixels)) return FALSE;
107 if(g->process.cache_imgid != key->imgid || g->process.base_patch.width != key->layer_width
108 || g->process.base_patch.height != key->layer_height)
109 return FALSE;
110
111 /* Once a layer is cached in memory, `process()` should treat that payload as
112 * authoritative until we explicitly reload or flush it. The page index in the
113 * params is only a sidecar lookup hint and may legitimately drift after sidecar
114 * rewrites or page reordering. Layer names are unique and stable by design, so
115 * prefer them for cache identity. Falling back to the page index here causes
116 * `process()` to re-open the TIFF and re-scan directories even though the
117 * correct pixels are already in memory. */
118 const char *target_name = key->layer_name ? key->layer_name : "";
119 if(target_name[0] != '\0' || g->process.cache_layer_name[0] != '\0') return !g_strcmp0(g->process.cache_layer_name, target_name);
120
121 if(key->layer_order >= 0 && g->process.cache_layer_order >= 0)
122 return g->process.cache_layer_order == key->layer_order;
123 return TRUE;
124}
125
127{
128 /* Make sure `base_patch` mirrors the currently selected sidecar layer.
129 * The low-level TIFF read/write primitives live in drawlayer/io.c, while this
130 * function stays here because it orchestrates cache lifetime, widget state,
131 * prompting, and history/UI side effects around those I/O operations. */
134 if(IS_NULL_PTR(g) || IS_NULL_PTR(self->dev)) return FALSE;
135
136 _sanitize_params(self, params);
137 int layer_width = 0;
138 int layer_height = 0;
139 const int32_t imgid = self->dev->image_storage.id;
140 GMainContext *const ui_ctx = g_main_context_default();
141 const gboolean ui_thread = ui_ctx && g_main_context_is_owner(ui_ctx);
142 if(!_resolve_layer_geometry(self, NULL, NULL, &layer_width, &layer_height, NULL, NULL))
143 {
144 layer_width = self->dev->roi.raw_width;
145 layer_height = self->dev->roi.raw_height;
146 }
147 if(imgid <= 0 || layer_width <= 0 || layer_height <= 0) return FALSE;
148 if(!_layer_name_non_empty(params->layer_name))
149 {
151 dt_drawlayer_cache_patch_clear(&g->process.base_patch, "drawlayer patch");
152 g->process.cache_valid = FALSE;
153 g->process.cache_dirty = FALSE;
154 dt_drawlayer_paint_runtime_state_reset(&g->process.cache_dirty_rect);
155 g->process.cache_imgid = -1;
156 g->process.cache_layer_name[0] = '\0';
157 g->process.cache_layer_order = -1;
159 if(ui_thread) _refresh_layer_widgets(self);
160 return TRUE;
161 }
162 const drawlayer_layer_cache_key_t cache_key = {
163 .imgid = imgid,
164 .layer_width = layer_width,
165 .layer_height = layer_height,
166 .layer_name = params->layer_name,
167 .layer_order = params->layer_order,
168 };
169
170 GString *errors = g_string_new(NULL);
171
172 char current_profile[DRAWLAYER_PROFILE_SIZE] = { 0 };
173 const gboolean have_current_profile = _get_current_work_profile_key(self, self->dev->iop, self->dev->pipe,
174 current_profile, sizeof(current_profile));
175 if(!have_current_profile)
176 _layerio_append_error(errors, _("failed to resolve drawlayer working profile"));
177 else if(params->work_profile[0] == '\0')
178 g_strlcpy(params->work_profile, current_profile, sizeof(params->work_profile));
179 else if(g_strcmp0(params->work_profile, current_profile))
180 _layerio_append_error(errors, _("drawlayer working profile mismatch"));
181
182 if(_layer_cache_matches(g, &cache_key))
183 {
184 _layerio_log_errors(errors);
185 g_string_free(errors, TRUE);
186 return TRUE;
187 }
188
189 if(!_flush_layer_cache(self))
190 {
191 _layerio_append_error(errors, _("failed to write drawing layer sidecar"));
192 _layerio_log_errors(errors);
193 g_string_free(errors, TRUE);
194 return FALSE;
195 }
196 /* We are about to replace/rebind `g->process.base_patch`; drop all explicit extra
197 * refs from the previous entry first so counters never leak across entries. */
199
200 int created = 0;
201 if(!dt_drawlayer_cache_patch_alloc_shared(&g->process.base_patch,
202 _drawlayer_params_cache_hash(imgid, params, layer_width, layer_height),
203 (size_t)layer_width * layer_height, layer_width, layer_height,
204 "drawlayer sidecar cache", &created))
205 {
207 dt_drawlayer_cache_patch_clear(&g->process.base_patch, "drawlayer patch");
208 g->process.cache_valid = FALSE;
209 _layerio_log_errors(errors);
210 g_string_free(errors, TRUE);
211 return FALSE;
212 }
213 if(!dt_drawlayer_cache_ensure_mask_buffer(&g->process.stroke_mask, layer_width, layer_height,
214 "drawlayer stroke mask"))
215 {
217 dt_drawlayer_cache_patch_clear(&g->process.base_patch, "drawlayer patch");
218 g->process.cache_valid = FALSE;
219 _layerio_append_error(errors, _("failed to allocate drawlayer stroke mask"));
220 _layerio_log_errors(errors);
221 g_string_free(errors, TRUE);
222 return FALSE;
223 }
224 if(created)
225 {
226 dt_drawlayer_cache_patch_wrlock(&g->process.base_patch);
227 dt_drawlayer_cache_clear_transparent_float(g->process.base_patch.pixels, (size_t)layer_width * layer_height);
228 dt_drawlayer_cache_patch_wrunlock(&g->process.base_patch);
229 }
230
231 gboolean ok = TRUE;
232 gboolean cache_loaded = FALSE;
233 gboolean file_exists = FALSE;
234 char path[PATH_MAX] = { 0 };
235
236 if(!created)
237 {
238 cache_loaded = TRUE;
239 }
240 else if(!dt_drawlayer_io_sidecar_path(imgid, path, sizeof(path)))
241 {
243 dt_drawlayer_cache_patch_clear(&g->process.base_patch, "drawlayer patch");
244 g->process.cache_valid = FALSE;
245 _layerio_append_error(errors, _("failed to resolve drawlayer sidecar path"));
246 _layerio_log_errors(errors);
247 g_string_free(errors, TRUE);
248 return TRUE;
249 }
250
251 if(created) file_exists = g_file_test(path, G_FILE_TEST_EXISTS);
252
253 if(created && !file_exists)
254 {
255 cache_loaded = TRUE;
256 params->layer_order = -1;
257 params->sidecar_timestamp = 0;
258 }
259 else if(created)
260 {
261 const gboolean pending_new_layer = (params->layer_order < 0 && params->sidecar_timestamp == 0);
262 drawlayer_dir_info_t info = { 0 };
263 dt_drawlayer_io_layer_info_t io_info = { 0 };
264 if(!dt_drawlayer_io_find_layer(path, params->layer_name, -1, &io_info))
265 {
266 if(pending_new_layer)
267 {
268 cache_loaded = TRUE;
269 }
270 else
271 {
272 g_snprintf(g->session.missing_layer_error, sizeof(g->session.missing_layer_error),
273 _("The drawing layer \"%s\" was not found in the sidecar TIFF."),
274 params->layer_name);
275 params->layer_name[0] = '\0';
276 params->layer_order = -1;
277 params->sidecar_timestamp = 0;
278 memset(params->work_profile, 0, sizeof(params->work_profile));
280 dt_drawlayer_cache_patch_clear(&g->process.base_patch, "drawlayer patch");
281 g->process.cache_valid = FALSE;
282 g->process.cache_dirty = FALSE;
283 dt_drawlayer_paint_runtime_state_reset(&g->process.cache_dirty_rect);
284 g->process.cache_imgid = -1;
285 g->process.cache_layer_name[0] = '\0';
286 g->process.cache_layer_order = -1;
289 }
290 }
291 else
292 {
293 info.found = io_info.found;
294 info.index = io_info.index;
295 info.count = io_info.count;
296 info.width = io_info.width;
297 info.height = io_info.height;
298 g_strlcpy(info.name, io_info.name, sizeof(info.name));
299 g_strlcpy(info.work_profile, io_info.work_profile, sizeof(info.work_profile));
300 if(g) g->session.missing_layer_error[0] = '\0';
301 params->layer_order = info.index;
302 if(info.work_profile[0] != '\0' && params->work_profile[0] == '\0')
303 g_strlcpy(params->work_profile, info.work_profile, sizeof(params->work_profile));
304
305 if(have_current_profile && info.work_profile[0] != '\0' && g_strcmp0(info.work_profile, current_profile))
306 _layerio_append_error(errors, _("drawlayer sidecar profile mismatch"));
307
308 dt_drawlayer_cache_patch_wrlock(&g->process.base_patch);
309 dt_drawlayer_io_patch_t io_patch = {
310 .x = g->process.base_patch.x,
311 .y = g->process.base_patch.y,
312 .width = g->process.base_patch.width,
313 .height = g->process.base_patch.height,
314 .pixels = g->process.base_patch.pixels,
315 };
316 const gboolean loaded
317 = dt_drawlayer_io_load_layer(path, params->layer_name, info.index, layer_width, layer_height, &io_patch);
318 dt_drawlayer_cache_patch_wrunlock(&g->process.base_patch);
319 if(!loaded)
320 {
321 _layerio_append_error(errors, _("failed to read drawing layer sidecar"));
322 ok = FALSE;
323 }
324 else
325 {
326 params->sidecar_timestamp = _sidecar_timestamp_from_path(path);
327 cache_loaded = TRUE;
328 }
329 }
330 }
331
332 if(cache_loaded)
333 {
334 g->process.cache_valid = TRUE;
335 g->process.cache_dirty = FALSE;
336 dt_drawlayer_paint_runtime_state_reset(&g->process.cache_dirty_rect);
337 g->process.cache_imgid = imgid;
338 g_strlcpy(g->process.cache_layer_name, params->layer_name, sizeof(g->process.cache_layer_name));
339 g->process.cache_layer_order = params->layer_order;
340 if(ui_thread && g->controls.layer_select) _populate_layer_list(self);
341 if(created) _retain_base_patch_loaded_ref(g);
342 }
343 else if(_layer_name_non_empty(params->layer_name))
344 {
346 dt_drawlayer_cache_patch_clear(&g->process.base_patch, "drawlayer patch");
347 g->process.cache_valid = FALSE;
348 g->process.cache_dirty = FALSE;
349 dt_drawlayer_paint_runtime_state_reset(&g->process.cache_dirty_rect);
350 }
351
352 if(ui_thread && !cache_loaded) _refresh_layer_widgets(self);
353 _layerio_log_errors(errors);
354 g_string_free(errors, TRUE);
355 return ok || !cache_loaded;
356}
357
359{
361 const dt_iop_drawlayer_params_t *params = (const dt_iop_drawlayer_params_t *)self->params;
362 if(IS_NULL_PTR(g) || IS_NULL_PTR(self->dev) || !g->process.cache_valid || !g->process.cache_dirty || IS_NULL_PTR(g->process.base_patch.pixels)) return TRUE;
363 if(!_layer_name_non_empty(params ? params->layer_name : NULL)) return TRUE;
364 if(!_layer_name_non_empty(g->process.cache_layer_name)) return FALSE;
365 if(dt_drawlayer_worker_any_active(g->stroke.worker)) _wait_worker_idle(self, g->stroke.worker);
366
367 char path[PATH_MAX] = { 0 };
368 const int32_t flush_imgid = (g->process.cache_imgid > 0) ? g->process.cache_imgid : self->dev->image_storage.id;
369 if(flush_imgid <= 0) return TRUE;
370 if(!dt_drawlayer_io_sidecar_path(flush_imgid, path, sizeof(path))) return FALSE;
371
372 int final_order = g->process.cache_layer_order;
373 const char *work_profile = params ? params->work_profile : "";
374 dt_drawlayer_cache_patch_rdlock(&g->process.base_patch);
375 dt_drawlayer_io_patch_t io_patch = {
376 .x = g->process.base_patch.x,
377 .y = g->process.base_patch.y,
378 .width = g->process.base_patch.width,
379 .height = g->process.base_patch.height,
380 .pixels = g->process.base_patch.pixels,
381 };
382 const gboolean ok
383 = dt_drawlayer_io_store_layer(path, g->process.cache_layer_name, g->process.cache_layer_order, work_profile, &io_patch,
384 g->process.base_patch.width, g->process.base_patch.height, FALSE, &final_order);
385 dt_drawlayer_cache_patch_rdunlock(&g->process.base_patch);
386 if(!ok) return FALSE;
387
388 g->process.cache_layer_order = final_order;
389 g->process.cache_dirty = FALSE;
390 dt_drawlayer_paint_runtime_state_reset(&g->process.cache_dirty_rect);
391
393 if(mutable_params)
394 {
395 if(!g_strcmp0(mutable_params->layer_name, g->process.cache_layer_name)) mutable_params->layer_order = final_order;
396 mutable_params->sidecar_timestamp = _sidecar_timestamp_from_path(path);
397 _rekey_shared_base_patch(&g->process.base_patch, flush_imgid, mutable_params);
398 }
400 return TRUE;
401}
402
404{
406 if(IS_NULL_PTR(g) || IS_NULL_PTR(self->dev)) return FALSE;
407
409 if(!dt_drawlayer_compute_view_patch(self, 0.0f, &view)) return FALSE;
410
411 float wx0 = 0.0f, wy0 = 0.0f, wx1 = 0.0f, wy1 = 0.0f;
412 if(!dt_drawlayer_layer_bounds_to_widget_bounds(self, view.layer_x0, view.layer_y0, view.layer_x1,
413 view.layer_y1, &wx0, &wy0, &wx1, &wy1))
414 return FALSE;
415
416 const dt_drawlayer_damaged_rect_t live_view_rect = {
417 .valid = TRUE,
418 .nw = { (int)floorf(view.layer_x0), (int)floorf(view.layer_y0) },
419 .se = { (int)ceilf(view.layer_x1), (int)ceilf(view.layer_y1) },
420 };
421 const dt_drawlayer_damaged_rect_t preview_rect = {
422 .valid = TRUE,
423 .nw = { (int)floorf(wx0), (int)floorf(wy0) },
424 .se = { (int)ceilf(wx1), (int)ceilf(wy1) },
425 };
426
427 const gboolean same_view = (memcmp(&g->session.live_patch, &view.patch, sizeof(view.patch)) == 0
428 && memcmp(&g->session.live_view_rect, &live_view_rect, sizeof(live_view_rect)) == 0
429 && memcmp(&g->session.preview_rect, &preview_rect, sizeof(preview_rect)) == 0);
430
431 if(same_view)
432 {
433 g->session.last_view_x = self->dev->roi.x;
434 g->session.last_view_y = self->dev->roi.y;
435 g->session.last_view_scale = self->dev->roi.scaling;
436 return TRUE;
437 }
438
439 g->session.live_patch = view.patch;
440 g->session.live_view_rect = live_view_rect;
441 g->session.preview_rect = preview_rect;
442
444 g->session.last_view_x = self->dev->roi.x;
445 g->session.last_view_y = self->dev->roi.y;
446 g->session.last_view_scale = self->dev->roi.scaling;
447 return TRUE;
448}
449
451{
452 if(IS_NULL_PTR(self) || IS_NULL_PTR(self->dev) || IS_NULL_PTR(self->dev->pipe)) return;
453 const gboolean was_realtime = dt_dev_pixelpipe_get_realtime(self->dev->pipe);
455 if(was_realtime != state)
457 if(IS_NULL_PTR(self->dev->preview_pipe)) return;
458
459 self->dev->preview_pipe->pause = state;
460 if(state)
462}
463
465{
467 if(IS_NULL_PTR(g) || IS_NULL_PTR(self->dev)) return FALSE;
468
469 _pause_worker(self, g->stroke.worker);
470 if(!_ensure_widget_cache(self))
471 {
472 _resume_worker(self, g->stroke.worker);
473 return FALSE;
474 }
475
476 g->session.live_padding = _current_live_padding(self);
477 _resume_worker(self, g->stroke.worker);
478 return TRUE;
479}
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
void dt_atomic_set_int(dt_atomic_int *var, int value)
int dt_bauhaus_combobox_length(GtkWidget *widget)
Definition bauhaus.c:1645
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
Definition bauhaus.c:1782
void dt_bauhaus_combobox_remove_at(GtkWidget *widget, int pos)
Definition bauhaus.c:1615
void dt_bauhaus_combobox_add(GtkWidget *widget, const char *text)
Definition bauhaus.c:1556
const float i
Definition colorspaces_inline_conversions.h:440
const float g
Definition colorspaces_inline_conversions.h:674
char * key
Definition common/metadata.c:60
void dt_control_log(const char *msg,...)
Definition control.c:530
gboolean dt_drawlayer_compute_view_patch(dt_iop_module_t *self, const float padding, drawlayer_view_patch_info_t *view)
Definition coordinates.c:163
gboolean dt_drawlayer_layer_bounds_to_widget_bounds(dt_iop_module_t *self, const float x0, const float y0, const float x1, const float y1, float *left, float *top, float *right, float *bottom)
Definition coordinates.c:106
uint32_t view(const dt_view_t *self)
Definition darkroom.c:191
darktable_t darktable
Definition darktable.c:173
#define PATH_MAX
Definition darktable.h:1061
#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 darktable.h:281
#define dt_dev_pixelpipe_resync_history_main(dev)
Definition dev_pixelpipe.h:68
static gboolean _rekey_shared_base_patch(drawlayer_patch_t *patch, const int32_t imgid, const dt_iop_drawlayer_params_t *params)
Definition drawlayer.c:421
static void _retain_base_patch_loaded_ref(dt_iop_drawlayer_gui_data_t *g)
Definition drawlayer.c:469
#define _flush_layer_cache
Definition drawlayer.c:118
#define _current_live_padding
Definition drawlayer.c:125
#define _release_all_base_patch_extra_refs
Definition drawlayer.c:122
static int64_t _sidecar_timestamp_from_path(const char *path)
Definition drawlayer.c:1014
static gboolean _get_current_work_profile_key(dt_iop_module_t *self, GList *iop_list, dt_dev_pixelpipe_t *pipe, char *key, const size_t key_size)
Definition drawlayer.c:302
static gboolean _layer_name_non_empty(const char *name)
Definition drawlayer.c:293
static void _sanitize_params(dt_iop_module_t *self, dt_iop_drawlayer_params_t *params)
Definition drawlayer.c:1395
static void _refresh_layer_widgets(dt_iop_module_t *self)
Definition drawlayer.c:1558
gboolean dt_drawlayer_io_find_layer(const char *path, const char *target_name, const int target_order, dt_drawlayer_io_layer_info_t *info)
Find target layer metadata in sidecar TIFF.
Definition io.c:684
gboolean dt_drawlayer_io_sidecar_path(const int32_t imgid, char *path, const size_t path_size)
Build absolute sidecar path from image id.
Definition io.c:673
gboolean dt_drawlayer_io_list_layer_names(const char *path, char ***names, int *count)
List all TIFF layer page names.
Definition io.c:1008
gboolean dt_drawlayer_io_load_layer(const char *path, const char *target_name, const int target_order, const int layer_width, const int layer_height, dt_drawlayer_io_patch_t *patch)
Load one sidecar layer patch into float RGBA destination patch.
Definition io.c:698
gboolean dt_drawlayer_io_store_layer(const char *path, const char *target_name, const int target_order, const char *work_profile, const dt_drawlayer_io_patch_t *patch, const int layer_width, const int layer_height, const gboolean delete_target, int *final_order)
Store/update/delete one layer entry in sidecar TIFF.
Definition io.c:904
void dt_drawlayer_io_free_layer_names(char ***names, int *count)
Free array returned by dt_drawlayer_io_list_layer_names.
Definition io.c:1046
void dt_drawlayer_paint_runtime_state_reset(dt_drawlayer_damaged_rect_t *state)
Reset stroke-damage accumulator to empty/invalid.
Definition iop/drawlayer/paint.c:802
gboolean dt_drawlayer_flush_layer_cache(dt_iop_module_t *self)
Definition layers.c:358
gboolean dt_drawlayer_sync_widget_cache(dt_iop_module_t *self)
Definition layers.c:464
static gboolean _layer_cache_matches(const dt_iop_drawlayer_gui_data_t *g, const drawlayer_layer_cache_key_t *key)
Definition layers.c:100
static void _layerio_log_errors(GString *errors)
Definition layers.c:37
void dt_drawlayer_set_pipeline_realtime_mode(dt_iop_module_t *self, const gboolean state)
Definition layers.c:450
static void _reset_stroke_session(dt_iop_drawlayer_gui_data_t *g)
Definition layers.c:89
static gboolean _ensure_widget_cache(dt_iop_module_t *self)
Definition layers.c:403
static void _populate_layer_list(dt_iop_module_t *self)
Definition layers.c:43
static void _layerio_append_error(GString *errors, const char *message)
Definition layers.c:30
gboolean dt_drawlayer_ensure_layer_cache(dt_iop_module_t *self)
Definition layers.c:126
gboolean dt_dev_pixelpipe_get_realtime(const dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:461
void dt_dev_pixelpipe_set_realtime(dt_dev_pixelpipe_t *pipe, gboolean state)
Definition pixelpipe_hb.c:455
void dt_drawlayer_process_state_reset_stroke(dt_drawlayer_process_state_t *state)
Definition runtime.c:938
void dt_drawlayer_process_state_invalidate(dt_drawlayer_process_state_t *state)
Definition runtime.c:945
const float uint32_t state[4]
Definition src/develop/noise_generator.h:72
void dt_drawlayer_cache_patch_wrunlock(const dt_drawlayer_cache_patch_t *patch)
Release write lock on shared patch cache entry.
Definition src/iop/drawlayer/cache.c:180
void dt_drawlayer_cache_patch_wrlock(const dt_drawlayer_cache_patch_t *patch)
Acquire write lock on shared patch cache entry.
Definition src/iop/drawlayer/cache.c:173
void dt_drawlayer_cache_patch_clear(dt_drawlayer_cache_patch_t *patch, const char *external_alloc_name)
Release patch storage and reset patch metadata.
Definition src/iop/drawlayer/cache.c:65
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.
Definition src/iop/drawlayer/cache.c:123
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.
Definition src/iop/drawlayer/cache.c:87
void dt_drawlayer_cache_patch_rdlock(const dt_drawlayer_cache_patch_t *patch)
Acquire read lock on shared patch cache entry.
Definition src/iop/drawlayer/cache.c:159
void dt_drawlayer_cache_patch_rdunlock(const dt_drawlayer_cache_patch_t *patch)
Release read lock on shared patch cache entry.
Definition src/iop/drawlayer/cache.c:166
void dt_drawlayer_cache_clear_transparent_float(float *pixels, const size_t pixel_count)
Fill float RGBA buffer with transparent black.
Definition src/iop/drawlayer/cache.c:58
#define DRAWLAYER_NAME_SIZE
Definition src/iop/drawlayer/common.h:10
#define DRAWLAYER_PROFILE_SIZE
Definition src/iop/drawlayer/common.h:11
struct dt_gui_gtk_t * gui
Definition darktable.h:774
Definition layers.c:11
char work_profile[DRAWLAYER_PROFILE_SIZE]
Definition layers.c:18
int count
Definition layers.c:14
char name[DRAWLAYER_NAME_SIZE]
Definition layers.c:17
uint32_t height
Definition layers.c:16
int index
Definition layers.c:13
gboolean found
Definition layers.c:12
uint32_t width
Definition layers.c:15
Definition layers.c:22
int layer_height
Definition layers.c:25
int layer_width
Definition layers.c:24
const char * layer_name
Definition layers.c:26
int layer_order
Definition layers.c:27
int32_t imgid
Definition layers.c:23
Definition coordinates.h:19
dt_atomic_int shutdown
Definition pixelpipe_hb.h:276
gboolean pause
Definition pixelpipe_hb.h:365
dt_image_t image_storage
Definition develop.h:248
float x
Definition develop.h:186
GList * iop
Definition develop.h:268
int32_t raw_height
Definition develop.h:217
float y
Definition develop.h:186
struct dt_dev_pixelpipe_t * preview_pipe
Definition develop.h:236
int32_t raw_width
Definition develop.h:217
float scaling
Definition develop.h:182
struct dt_dev_pixelpipe_t * pipe
Definition develop.h:236
struct dt_develop_t::@18 roi
Integer axis-aligned rectangle in buffer coordinates.
Definition iop/drawlayer/paint.h:87
gboolean valid
Definition iop/drawlayer/paint.h:88
Metadata returned when probing one layer directory in sidecar TIFF.
Definition io.h:45
uint32_t height
Definition io.h:50
char work_profile[256]
Definition io.h:52
uint32_t width
Definition io.h:49
char name[64]
Definition io.h:51
int count
Definition io.h:48
int index
Definition io.h:47
gboolean found
Definition io.h:46
Float RGBA patch used by drawlayer I/O routines.
Definition io.h:35
int width
Definition io.h:38
int x
Definition io.h:36
int32_t reset
Definition gtk.h:143
int32_t id
Definition image.h:285
Definition runtime.h:254
Definition src/iop/drawlayer/common.h:14
char layer_name[64]
Definition src/iop/drawlayer/common.h:16
int layer_order
Definition src/iop/drawlayer/common.h:19
int64_t sidecar_timestamp
Definition src/iop/drawlayer/common.h:18
Definition imageop.h:245
struct dt_develop_t * dev
Definition imageop.h:297
dt_iop_gui_data_t * gui_data
Definition imageop.h:312
dt_iop_params_t * params
Definition imageop.h:308
static void _pause_worker(dt_iop_module_t *self, dt_drawlayer_worker_t *rt)
Pause worker processing after current callback returns.
Definition worker.c:1429
void dt_drawlayer_worker_reset_backend_path(dt_drawlayer_worker_t *worker)
Reset worker-owned backend damage accumulator.
Definition worker.c:1603
gboolean dt_drawlayer_worker_any_active(const dt_drawlayer_worker_t *worker)
Public status query: TRUE when any worker still has pending activity.
Definition worker.c:1551
void dt_drawlayer_worker_reset_live_publish(dt_drawlayer_worker_t *worker)
Reset worker-owned transient live-publish state.
Definition worker.c:1611
static void _resume_worker(dt_iop_module_t *self, dt_drawlayer_worker_t *rt)
Resume worker processing and wake sleeping thread.
Definition worker.c:1444
static gboolean _wait_worker_idle(dt_iop_module_t *self, dt_drawlayer_worker_t *rt)
Wait until worker queue is drained and not busy.
Definition worker.c:1260