Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
pixelpipe_hb.c
Go to the documentation of this file.
1/*
2 This file was part of darktable,
3 This file is part of Ansel,
4 Copyright (C) 2009-2021 darktable developers.
5 Copyright (C) 2023 Aurélien Pierre.
6
7 darktable is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 darktable is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with darktable. If not, see <http://www.gnu.org/licenses/>.
19*/
20#include "common/color_picker.h"
21#include "common/colorspaces.h"
22#include "common/darktable.h"
23#include "common/histogram.h"
24#include "common/imageio.h"
25#include "common/opencl.h"
26#include "common/iop_order.h"
27#include "control/control.h"
28#include "control/conf.h"
29#include "control/signal.h"
30#include "develop/blend.h"
31#include "develop/format.h"
33#include "develop/pixelpipe.h"
34#include "develop/tiling.h"
35#include "develop/masks.h"
36#include "gui/gtk.h"
37#include "libs/colorpicker.h"
38#include "libs/lib.h"
40
41#include <assert.h>
42#include <inttypes.h>
43#include <math.h>
44#include <stdint.h>
45#include <stdlib.h>
46#include <string.h>
47#include <strings.h>
48#include <unistd.h>
49
62
68
70
73
74static char *_pipe_type_to_str(int pipe_type)
75{
76 char *r = NULL;
77
78 switch(pipe_type & DT_DEV_PIXELPIPE_ANY)
79 {
81 r = "preview";
82 break;
84 r = "full";
85 break;
87 r = "thumbnail";
88 break;
90 r = "export";
91 break;
92 default:
93 r = "unknown";
94 }
95 return r;
96}
97
98inline static void _copy_buffer(const char *const restrict input, char *const restrict output,
99 const size_t height, const size_t o_width, const size_t i_width,
100 const size_t x_offset, const size_t y_offset,
101 const size_t stride, const size_t bpp)
102{
103#ifdef _OPENMP
104#pragma omp parallel for default(none) \
105 dt_omp_firstprivate(input, output, bpp, o_width, i_width, height, x_offset, y_offset, stride) \
106 schedule(static)
107#endif
108 for(size_t j = 0; j < height; j++)
109 memcpy(output + bpp * j * o_width,
110 input + bpp * (x_offset + (y_offset + j) * i_width),
111 stride);
112}
113
114
115inline static void _uint8_to_float(const uint8_t *const input, float *const output,
116 const size_t width, const size_t height, const size_t chan)
117{
118#ifdef _OPENMP
119#pragma omp parallel for simd default(none) \
120 aligned(input, output: 64) \
121 dt_omp_firstprivate(input, output, width, height, chan) \
122 schedule(static)
123#endif
124 for(size_t k = 0; k < height * width; k++)
125 {
126 const size_t index = k * chan;
127 // Warning: we take BGRa and put it back into RGBa
128 output[index + 0] = (float)input[index + 2] / 255.f;
129 output[index + 1] = (float)input[index + 1] / 255.f;
130 output[index + 2] = (float)input[index + 0] / 255.f;
131 output[index + 3] = 0.f;
132 }
133}
134
135
137 gboolean store_masks)
138{
139 const int res = dt_dev_pixelpipe_init_cached(pipe);
141 pipe->levels = levels;
142 pipe->store_all_raster_masks = store_masks;
143 return res;
144}
145
147{
148 const int res = dt_dev_pixelpipe_init_cached(pipe);
150 return res;
151}
152
154{
155 const int res = dt_dev_pixelpipe_init_cached(pipe);
157 return res;
158}
159
161{
162 // Init with the size of MIPMAP_F
163 const int res = dt_dev_pixelpipe_init_cached(pipe);
165
166 // Needed for caching
168 return res;
169}
170
172{
173 const int res = dt_dev_pixelpipe_init_cached(pipe);
175
176 // Needed for caching
178 return res;
179}
180
182{
183 pipe->devid = -1;
185 pipe->processed_width = pipe->backbuf_width = pipe->iwidth = 0;
186 pipe->processed_height = pipe->backbuf_height = pipe->iheight = 0;
187 pipe->nodes = NULL;
188 pipe->backbuf = NULL;
189 pipe->backbuf_scale = 0.0f;
190 pipe->backbuf_zoom_x = 0.0f;
191 pipe->backbuf_zoom_y = 0.0f;
192
193 pipe->output_backbuf = NULL;
194 pipe->output_backbuf_width = 0;
195 pipe->output_backbuf_height = 0;
197
198 pipe->rawdetail_mask_data = NULL;
200
201 pipe->processing = 0;
202 pipe->running = 0;
204 pipe->opencl_error = 0;
205 pipe->tiling = 0;
207 pipe->bypass_blendif = 0;
208 pipe->input_timestamp = 0;
210 dt_pthread_mutex_init(&(pipe->backbuf_mutex), NULL);
211 dt_pthread_mutex_init(&(pipe->busy_mutex), NULL);
213 pipe->icc_filename = NULL;
215 pipe->iop = NULL;
216 pipe->iop_order_list = NULL;
217 pipe->forms = NULL;
219 pipe->work_profile_info = NULL;
220 pipe->input_profile_info = NULL;
221 pipe->output_profile_info = NULL;
222
224 pipe->last_history_hash = 0;
225 pipe->flush_cache = FALSE;
226
228 return 1;
229}
230
233{
234 pipe->iwidth = width;
235 pipe->iheight = height;
236 pipe->imgid = imgid;
237 pipe->image = dev->image_storage;
238 pipe->size = size;
239
241 get_output_format(NULL, pipe, NULL, dev, &pipe->dsc);
242}
243
245 const gchar *icc_filename, dt_iop_color_intent_t icc_intent)
246{
247 pipe->icc_type = icc_type;
248 g_free(pipe->icc_filename);
249 pipe->icc_filename = g_strdup(icc_filename ? icc_filename : "");
250 pipe->icc_intent = icc_intent;
251}
252
254{
256 pipe->backbuf = NULL;
257 // blocks while busy and sets shutdown bit:
259 // so now it's safe to clean up cache:
264 g_free(pipe->icc_filename);
265 pipe->icc_filename = NULL;
266
267 g_free(pipe->output_backbuf);
268 pipe->output_backbuf = NULL;
269 pipe->output_backbuf_width = 0;
270 pipe->output_backbuf_height = 0;
272
274
275 if(pipe->forms)
276 {
277 g_list_free_full(pipe->forms, (void (*)(void *))dt_masks_free_form);
278 pipe->forms = NULL;
279 }
280}
281
282
284{
285 if(pipe->reentry_hash == 0)
286 {
287 pipe->reentry = TRUE;
288 pipe->reentry_hash = hash;
289 dt_print(DT_DEBUG_DEV, "[dev_pixelpipe] re-entry flag set for %" PRIu64 "\n", hash);
290 return TRUE;
291 }
292
293 return FALSE;
294}
295
296
298{
299 if(pipe->reentry_hash == hash)
300 {
301 pipe->reentry = FALSE;
302 pipe->reentry_hash = 0;
303 dt_print(DT_DEBUG_DEV, "[dev_pixelpipe] re-entry flag unset for %" PRIu64 "\n", hash);
304 return TRUE;
305 }
306
307 return FALSE;
308}
309
311{
312 return pipe->reentry;
313}
314
316{
317 pipe->reentry = FALSE;
318 pipe->reentry_hash = 0;
319 pipe->flush_cache = FALSE;
320 dt_print(DT_DEBUG_DEV, "[dev_pixelpipe] re-entry flag reset\n");
321}
322
324{
325 // destroy all nodes
326 for(GList *nodes = pipe->nodes; nodes; nodes = g_list_next(nodes))
327 {
329 // printf("cleanup module `%s'\n", piece->module->name());
330 piece->module->cleanup_pipe(piece->module, pipe, piece);
331 free(piece->blendop_data);
332 piece->blendop_data = NULL;
333 free(piece->histogram);
334 piece->histogram = NULL;
335 g_hash_table_destroy(piece->raster_masks);
336 piece->raster_masks = NULL;
337 free(piece);
338 }
339 g_list_free(pipe->nodes);
340 pipe->nodes = NULL;
341 // also cleanup iop here
342 if(pipe->iop)
343 {
344 g_list_free(pipe->iop);
345 pipe->iop = NULL;
346 }
347 // and iop order
348 g_list_free_full(pipe->iop_order_list, free);
349 pipe->iop_order_list = NULL;
350}
351
353{
354 // check that the pipe was actually properly cleaned up after the last run
355 g_assert(pipe->nodes == NULL);
356 g_assert(pipe->iop == NULL);
357 g_assert(pipe->iop_order_list == NULL);
359
360 // for all modules in dev:
361 // TODO: don't add deprecated modules that are not enabled are not added to pipeline.
362 // currently, that loads 84 modules of which a solid third are not used anymore.
363 // if(module->flags() & IOP_FLAGS_DEPRECATED && !(module->enabled)) continue;
364 pipe->iop = g_list_copy(dev->iop);
365 for(GList *modules = pipe->iop; modules; modules = g_list_next(modules))
366 {
367 dt_iop_module_t *module = (dt_iop_module_t *)modules->data;
369 piece->enabled = module->enabled;
370 piece->request_histogram = DT_REQUEST_ONLY_IN_GUI;
371 piece->histogram_params.roi = NULL;
372 piece->histogram_params.bins_count = 256;
373 piece->histogram_stats.bins_count = 0;
374 piece->histogram_stats.pixels = 0;
375 piece->colors
376 = ((module->default_colorspace(module, pipe, NULL) == IOP_CS_RAW) && (dt_image_is_raw(&pipe->image)))
377 ? 1
378 : 4;
379 piece->iwidth = pipe->iwidth;
380 piece->iheight = pipe->iheight;
381 piece->module = module;
382 piece->pipe = pipe;
383 piece->data = NULL;
384 piece->hash = 0;
385 piece->blendop_hash = 0;
386 piece->global_hash = 0;
387 piece->global_mask_hash = 0;
388 piece->bypass_cache = FALSE;
389 piece->process_cl_ready = 0;
390 piece->process_tiling_ready = 0;
391 piece->raster_masks = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, dt_free_align_ptr);
392 memset(&piece->processed_roi_in, 0, sizeof(piece->processed_roi_in));
393 memset(&piece->processed_roi_out, 0, sizeof(piece->processed_roi_out));
394
395 // dsc_mask is static, single channel float image
396 memset(&piece->dsc_mask, 0, sizeof(piece->dsc_mask));
397 piece->dsc_mask.channels = 1;
398 piece->dsc_mask.datatype = TYPE_FLOAT;
399 piece->dsc_mask.filters = 0;
400
401 dt_iop_init_pipe(piece->module, pipe, piece);
402 pipe->nodes = g_list_append(pipe->nodes, piece);
403 }
404}
405
407{
408 // Start with a hash that is unique, image-wise.
409 return dt_hash(5381, (const char *)&pipe->image.filename, DT_MAX_FILENAME_LEN);
410}
411
412static uint64_t _node_hash(dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *roi_out, const int pos)
413{
414 // to be called at runtime, not at pipe init.
415
416 // Only at the first step of pipe, we don't have a module because we init the base buffer.
417 if(piece)
418 return piece->global_hash;
419 else
420 {
421 // This is used for the first step of the pipe, before modules, when initing base buffer
422 // We need to take care of the ROI manually
423 uint64_t hash = _default_pipe_hash(pipe);
424 hash = dt_hash(hash, (const char *)roi_out, sizeof(dt_iop_roi_t));
425 return dt_hash(hash, (const char *)&pos, sizeof(int));
426 }
427}
428
429
431{
432 /* Traverse the pipeline node by node and compute the cumulative (global) hash of each module.
433 * This hash takes into account the hashes of the previous modules and the size of the current ROI.
434 * It is used to map pipeline cache states to current parameters.
435 * It represents the state of internal modules params as well as their position in the pipe and their output size.
436 * It is to be called at pipe init, not at runtime.
437 */
438
439 // bernstein hash (djb2)
440 uint64_t hash = _default_pipe_hash(pipe);
441 uint64_t distort_hash = _default_pipe_hash(pipe);
442 distort_hash = dt_hash(distort_hash, (const char *)&distort_hash, sizeof(uint64_t));
443
444 // Bypassing cache contaminates downstream modules.
445 gboolean bypass_cache = FALSE;
446
447 for(GList *node = g_list_first(pipe->nodes); node; node = g_list_next(node))
448 {
450 if(!piece->enabled) continue;
451
452 // Combine with the previous bypass states
453 bypass_cache |= piece->module->bypass_cache;
454 piece->bypass_cache = bypass_cache;
455
456 // Combine with the previous modules hashes
457 uint64_t local_hash = piece->hash;
458
459 // Panning and zooming change the ROI. Some GUI modes (crop in editing mode) too.
460 // dt_dev_get_roi_in() should have run before
461 local_hash = dt_hash(local_hash, (const char *)&piece->planned_roi_in, sizeof(dt_iop_roi_t));
462 local_hash = dt_hash(local_hash, (const char *)&piece->planned_roi_out, sizeof(dt_iop_roi_t));
463
464 fprintf(stdout, "%s: ROI in: %ix%i, ROI out: %ix%i\n", piece->module->op, piece->planned_roi_in.width,
466
467 // Mask preview display doesn't re-commit params, so we need to keep that of it here
468 // Too much GUI stuff interleaved with pipeline stuff...
469 // Note that mask display applies only to main preview in darkroom. We don't check it here.
470 // Just ensure to not call a preview pipe recompute on GUI toggle state...
471 local_hash = dt_hash(local_hash, (const char *)&piece->module->request_mask_display, sizeof(int));
472
473 // If the cache bypass is on, the corresponding cache lines will be freed immediately after use,
474 // we need to track that. It somewhat overlaps module->request_mask_display, but...
475 local_hash = dt_hash(local_hash, (const char *)&piece->bypass_cache, sizeof(gboolean));
476
477 // Update global hash for this stage
478 hash = dt_hash(hash, (const char *)&local_hash, sizeof(uint64_t));
479 piece->global_hash = hash;
480
481 dt_print(DT_DEBUG_PIPE, "[pixelpipe] global hash for %s (%s) in pipe %i with hash %" PRIu64 "\n", piece->module->op, piece->module->multi_name, pipe->type, hash);
482
483 // Mask hash: raster masks are affected by ROI out size and distortions.
484
485 // This could be achieved upon (piece->module->operation_tags() & IOP_TAG_CLIPPING) only
486 // but let's pretend that programmers are the idiots they are and assume mistakes were made.
487 distort_hash = dt_hash(distort_hash, (const char *)&piece->planned_roi_out, sizeof(dt_iop_roi_t));
488
489 // Distortions are not limited to changing ROI out (liquify)
490 // In this case, the nature of the distortion is represented by the internal params of the module.
491 if((piece->module->operation_tags() & IOP_TAG_DISTORT) == IOP_TAG_DISTORT)
492 distort_hash = dt_hash(distort_hash, (const char *)&piece->hash, sizeof(uint64_t));
493
494 piece->global_mask_hash = dt_hash(distort_hash, (const char *)&piece->blendop_hash, sizeof(uint64_t));
495 }
496}
497
499{
500 if(piece->module == hist->module)
501 {
502 piece->enabled = hist->enabled;
503 dt_iop_commit_params(hist->module, hist->params, hist->blend_params, pipe, piece);
504
505 if(piece->blendop_data)
506 {
507 const dt_develop_blend_params_t *const bp = (const dt_develop_blend_params_t *)piece->blendop_data;
508 if(bp->details != 0.0f)
510 }
511 return TRUE;
512 }
513 return FALSE;
514}
515
516// helper
518{
519 dt_dev_history_item_t *hist = (dt_dev_history_item_t *)history->data;
520 dt_dev_pixelpipe_iop_t *piece = NULL;
521
522 // Traverse the list of pipe nodes until we found the one matching our history item.
523 // We begin by the end, because it's expected that users will follow an editing history
524 // roughly similar to node order, so as history is growing, we shall have an higher
525 // probability of finding the last history item node at the end of the pipeline.
526 for(GList *nodes = g_list_last(pipe->nodes); nodes; nodes = g_list_previous(nodes))
527 {
528 piece = (dt_dev_pixelpipe_iop_t *)nodes->data;
529 if(_commit_history_to_node(pipe, piece, hist))
530 break;
531 }
532}
533
544void dt_dev_pixelpipe_synch_all_real(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, const char *caller_func)
545{
546 dt_print(DT_DEBUG_DEV, "[pixelpipe] synch all modules with defaults_params for pipe %i called from %s\n", pipe->type, caller_func);
547 dt_print(DT_DEBUG_DEV, "[pixelpipe] synch all modules with history for pipe %i called from %s\n", pipe->type, caller_func);
548
549 // go through all history items and adjust params
550 // note that we don't necessarily process the whole history, history_end is an user param.
551 const uint32_t history_end = dt_dev_get_history_end(dev);
552
553 for(GList *nodes = g_list_first(pipe->nodes); nodes; nodes = g_list_next(nodes))
554 {
556 piece->hash = 0;
557 piece->global_hash = 0;
558 piece->enabled = piece->module->default_enabled;
559 gboolean found_history = FALSE;
560
561 // now browse all history items from the end. Since each history item is a full snapshot of parameters,
562 // the latest history entry matching current node is the one we want, and we don't need to look for the previous.
563 for(GList *history = g_list_nth(dev->history, history_end - 1);
564 history;
565 history = g_list_previous(history))
566 {
567 dt_dev_history_item_t *hist = (dt_dev_history_item_t *)history->data;
568 if(_commit_history_to_node(pipe, piece, hist))
569 {
570 found_history = TRUE;
571 break;
572 }
573 }
574
575 // No history found, commit default params if module is enabled by default
576 if(!found_history && piece->enabled)
577 {
578 dt_iop_commit_params(piece->module, piece->module->default_params, piece->module->default_blendop_params,
579 pipe, piece);
580 dt_print(DT_DEBUG_PIPE, "[pixelpipe] info: committed default params for %s (%s) in pipe %i \n", piece->module->op, piece->module->multi_name, pipe->type);
581 }
582 }
583
584 // Keep track of the last history item to have been synced
585 GList *last_item = g_list_nth(dev->history, history_end - 1);
586 if(last_item)
587 {
588 dt_dev_history_item_t *last_hist = (dt_dev_history_item_t *)last_item->data;
589 pipe->last_history_hash = last_hist->hash;
590 }
591}
592
594{
595 // We can't be sure that there is only one history item to resync
596 // since the last history -> pipe nodes resync: on slow systems,
597 // user may have added more than one during a single pipe recompute.
598 // Note however that the sync_top method is only used when adding new history items
599 // on top. So we need to resync every history item from end to start, until
600 // we find the previously synchronized one. This uses history hashes.
601 GList *last_item = g_list_nth(dev->history, dt_dev_get_history_end(dev) - 1);
602 if(last_item)
603 {
604 GList *first_item = NULL;
605 for(GList *history = last_item; history; history = g_list_previous(history))
606 {
607 dt_dev_history_item_t *hist = (dt_dev_history_item_t *)history->data;
608 first_item = history;
609
610 if(hist->hash == pipe->last_history_hash)
611 {
612 // Note that this also takes care of the case where the
613 // last-known history item reference hasn't changed, but its internal
614 // parameters have.
615 break;
616 }
617 // if we don't find the hash again, we will just iterate over the whole history.
618 }
619
620 // We also need to care about the case where the history_end is not at the actual end of the history
621 // aka stop looping before we overflow the desired range of history.
622 GList *fence_item = g_list_nth(dev->history, dt_dev_get_history_end(dev));
623 // if the history end cursor is at the actual end of the history, dt_dev_get_history_end()
624 // returns an index that is outside of the range (equal to number of elements),
625 // so fence_item = NULL but the code works as expected since we check history != NULL
626 // first.
627 for(GList *history = first_item; history && history != fence_item; history = g_list_next(history))
628 {
629 dt_dev_history_item_t *hist = (dt_dev_history_item_t *)history->data;
630 dt_print(DT_DEBUG_DEV, "[pixelpipe] synch top history module `%s` (%s) for pipe %i\n", hist->module->op, hist->module->multi_name, pipe->type);
631 dt_dev_pixelpipe_synch(pipe, dev, history);
632 }
633
634 // Keep track of the last history item to have been synced
635 dt_dev_history_item_t *last_hist = (dt_dev_history_item_t *)last_item->data;
636 pipe->last_history_hash = last_hist->hash;
637 }
638 else
639 {
640 dt_print(DT_DEBUG_DEV, "[pixelpipe] synch top history module missing error for pipe %i\n", pipe->type);
641 }
642}
643
645{
646 dt_times_t start;
647 dt_get_times(&start);
648
649 // Read and write immediately to ensure cross-thread consistency of the value
650 // in case the GUI overwrites that while we are syncing history and nodes
651 const dt_dev_pixelpipe_change_t status = pipe->changed;
653
654 dt_print(DT_DEBUG_DEV, "[dt_dev_pixelpipe_change] pipeline state changing for pipe %i, flag %i\n", pipe->type, status);
655
656 // mask display off as a starting point
658 // and blendif active
659 pipe->bypass_blendif = 0;
660
661 // Init fucking details masks
662 const dt_image_t *img = &pipe->image;
664 if(dt_image_is_raw(img))
668
670
671 // case DT_DEV_PIPE_UNCHANGED: case DT_DEV_PIPE_ZOOMED:
672 if(status & DT_DEV_PIPE_REMOVE)
673 {
674 // modules have been added in between or removed. need to rebuild the whole pipeline.
678 }
679 else if(status & DT_DEV_PIPE_SYNCH)
680 {
681 // pipeline topology remains intact, only change all params.
683 }
684 else if(status & DT_DEV_PIPE_TOP_CHANGED)
685 {
686 // only top history item changed.
688 }
690
691 // Get the final output size of the pipe, for GUI coordinates mapping between image buffer and window
692 dt_dev_pixelpipe_get_roi_out(pipe, dev, pipe->iwidth, pipe->iheight, &pipe->processed_width,
693 &pipe->processed_height);
694
695 dt_show_times_f(&start, "[dt_dev_pixelpipe_change] pipeline resync on the current modules stack", "for pipe %i", pipe->type);
696}
697
700{
701 if(module) return module->output_format(module, pipe, piece, dsc);
702
703 // first input.
704 *dsc = pipe->image.buf_dsc;
705
706 if(!(dt_image_is_raw(&pipe->image)))
707 {
708 // image max is normalized before
709 for(int k = 0; k < 4; k++) dsc->processed_maximum[k] = 1.0f;
710 }
711}
712
713
714// helper to get per module histogram
715static void histogram_collect(dt_dev_pixelpipe_iop_t *piece, const void *pixel, const dt_iop_roi_t *roi,
716 uint32_t **histogram, uint32_t *histogram_max)
717{
719
720 dt_histogram_roi_t histogram_roi;
721
722 // if the current module does did not specified its own ROI, use the full ROI
723 if(histogram_params.roi == NULL)
724 {
725 histogram_roi = (dt_histogram_roi_t){
726 .width = roi->width, .height = roi->height, .crop_x = 0, .crop_y = 0, .crop_width = 0, .crop_height = 0
727 };
728
729 histogram_params.roi = &histogram_roi;
730 }
731
732 const dt_iop_colorspace_type_t cst = piece->module->input_colorspace(piece->module, piece->pipe, piece);
733
734 dt_histogram_helper(&histogram_params, &piece->histogram_stats, cst, piece->module->histogram_cst, pixel, histogram,
735 piece->module->histogram_middle_grey, dt_ioppr_get_pipe_work_profile_info(piece->pipe));
736 dt_histogram_max_helper(&piece->histogram_stats, cst, piece->module->histogram_cst, histogram, histogram_max);
737}
738
739dt_backbuf_t * _get_backuf(dt_develop_t *dev, const char *op)
740{
741 if(!strcmp(op, "demosaic"))
742 return &dev->raw_histogram;
743 else if(!strcmp(op, "colorout"))
744 return &dev->output_histogram;
745 else if(!strcmp(op, "gamma"))
746 return &dev->display_histogram;
747 else
748 return NULL;
749}
750
752 void *output, const dt_iop_roi_t *roi,
754 const uint64_t hash, const size_t bpp)
755{
756 // Runs only on full image but downscaled for perf, aka preview pipe
757 // Not an RGBa float buffer ?
758 if(!(bpp == 4 * sizeof(float))) return;
759
760 dt_backbuf_t *backbuf = _get_backuf(dev, module->op);
761 if(backbuf == NULL) return; // This module is not wired to global histograms
762 if(backbuf->hash == hash) return; // Hash didn't change, nothing to update.
763
764 // Prepare the buffer if needed
765 if(backbuf->buffer == NULL)
766 {
767 // Buffer uninited
768 backbuf->buffer = dt_alloc_align(roi->width * roi->height * bpp);
769 if(backbuf->buffer == NULL)
770 {
771 // Out of memory to allocate. Notify histogram
772 backbuf->hash = -1;
773 return;
774 }
775
776 backbuf->height = roi->height;
777 backbuf->width = roi->width;
778 backbuf->bpp = bpp;
779 }
780 else if((backbuf->height != roi->height) || (backbuf->width != roi->width) || (backbuf->bpp != bpp))
781 {
782 // Cached buffer size doesn't match current one.
783 // There is no reason yet why this should happen because the preview pipe doesn't change size during its lifetime.
784 // But let's future-proof it in case someone gets creative.
785 if(backbuf->buffer) dt_free_align(backbuf->buffer); // maybe write a dt_realloc_align routine ?
786 backbuf->buffer = dt_alloc_align(roi->width * roi->height * bpp);
787 if(backbuf->buffer == NULL)
788 {
789 // Out of memory to allocate. Notify histogram
790 backbuf->hash = -1;
791 return;
792 }
793
794 backbuf->height = roi->height;
795 backbuf->width = roi->width;
796 backbuf->bpp = bpp;
797 }
798
799 if(backbuf->buffer == NULL)
800 {
801 // Out of memory to allocate. Notify histogram
802 backbuf->hash = -1;
803 return;
804 }
805
806 // Integrity hash, mixing interal module params state, and params states of previous modules in pipe.
807 backbuf->hash = hash;
808
809 // Copy to histogram cache
810 dt_times_t start;
811 dt_get_times(&start);
812
813 if(output)
814 _copy_buffer(output, (char *)backbuf->buffer, roi->height, roi->width, roi->width, 0, 0, roi->width * bpp, bpp);
815 else
816 backbuf->hash = -1;
817
818 dt_show_times_f(&start, "[dev_pixelpipe]", "copying global histogram for %s", module->op);
819
820 // That's all. From there, histogram catches the "preview pipeline finished recomputing" signal and redraws if needed.
821 // We don't manage thread locks because there is only one writing point and one reading point, synchronized
822 // through signal & callback.
823
824 // Note that we don't compute the histogram here because, depending on the type of scope requested in GUI,
825 // intermediate color conversions might be needed (vectorscope) or various pixel binnings required (waveform).
826 // Color conversions and binning are deferred to the GUI thread, prior to drawing update.
827}
828
829
830// helper for per-module color picking
831static int pixelpipe_picker_helper(dt_iop_module_t *module, const dt_iop_roi_t *roi, dt_aligned_pixel_t picked_color,
832 dt_aligned_pixel_t picked_color_min, dt_aligned_pixel_t picked_color_max,
833 dt_pixelpipe_picker_source_t picker_source, int *box)
834{
835 const float wd = darktable.develop->preview_pipe->backbuf_width;
836 const float ht = darktable.develop->preview_pipe->backbuf_height;
837 const int width = roi->width;
838 const int height = roi->height;
840
841 dt_boundingbox_t fbox = { 0.0f };
842
843 // get absolute pixel coordinates in final preview image
844 if(sample->size == DT_LIB_COLORPICKER_SIZE_BOX)
845 {
846 for(int k = 0; k < 4; k += 2) fbox[k] = sample->box[k] * wd;
847 for(int k = 1; k < 4; k += 2) fbox[k] = sample->box[k] * ht;
848 }
849 else if(sample->size == DT_LIB_COLORPICKER_SIZE_POINT)
850 {
851 fbox[0] = fbox[2] = sample->point[0] * wd;
852 fbox[1] = fbox[3] = sample->point[1] * ht;
853 }
854
855 // transform back to current module coordinates
859
860 fbox[0] -= roi->x;
861 fbox[1] -= roi->y;
862 fbox[2] -= roi->x;
863 fbox[3] -= roi->y;
864
865 // re-order edges of bounding box
866 box[0] = fminf(fbox[0], fbox[2]);
867 box[1] = fminf(fbox[1], fbox[3]);
868 box[2] = fmaxf(fbox[0], fbox[2]);
869 box[3] = fmaxf(fbox[1], fbox[3]);
870
872 {
873 // if we are sampling one point, make sure that we actually sample it.
874 for(int k = 2; k < 4; k++) box[k] += 1;
875 }
876
877 // do not continue if box is completely outside of roi
878 if(box[0] >= width || box[1] >= height || box[2] < 0 || box[3] < 0) return 1;
879
880 // clamp bounding box to roi
881 for(int k = 0; k < 4; k += 2) box[k] = MIN(width - 1, MAX(0, box[k]));
882 for(int k = 1; k < 4; k += 2) box[k] = MIN(height - 1, MAX(0, box[k]));
883
884 // safety check: area needs to have minimum 1 pixel width and height
885 if(box[2] - box[0] < 1 || box[3] - box[1] < 1) return 1;
886
887 return 0;
888}
889
891 const float *pixel, const dt_iop_roi_t *roi, float *picked_color,
892 float *picked_color_min, float *picked_color_max,
893 const dt_iop_colorspace_type_t image_cst, dt_pixelpipe_picker_source_t picker_source)
894{
895 int box[4] = { 0 };
896
897 if(pixelpipe_picker_helper(module, roi, picked_color, picked_color_min, picked_color_max, picker_source, box))
898 {
899 for(int k = 0; k < 4; k++)
900 {
901 picked_color_min[k] = INFINITY;
902 picked_color_max[k] = -INFINITY;
903 picked_color[k] = 0.0f;
904 }
905
906 return;
907 }
908
909 dt_aligned_pixel_t min, max, avg;
910 for(int k = 0; k < 4; k++)
911 {
912 min[k] = INFINITY;
913 max[k] = -INFINITY;
914 avg[k] = 0.0f;
915 }
916
918 dt_color_picker_helper(dsc, pixel, roi, box, avg, min, max, image_cst,
919 dt_iop_color_picker_get_active_cst(module), profile);
920
921 for(int k = 0; k < 4; k++)
922 {
923 picked_color_min[k] = min[k];
924 picked_color_max[k] = max[k];
925 picked_color[k] = avg[k];
926 }
927}
928
929// returns 1 if blend process need the module default colorspace
930static gboolean _transform_for_blend(const dt_iop_module_t *const self, const dt_dev_pixelpipe_iop_t *const piece)
931{
933 if(d)
934 {
935 // check only if blend is active
936 if((self->flags() & IOP_FLAGS_SUPPORTS_BLENDING) && (d->mask_mode != DEVELOP_MASK_DISABLED))
937 {
938 return TRUE;
939 }
940 }
941 return FALSE;
942}
943
945{
946 const dt_iop_colorspace_type_t picker_cst =
948
949 switch(picker_cst)
950 {
951 case IOP_CS_RAW:
952 return IOP_CS_RAW;
953 case IOP_CS_LAB:
954 case IOP_CS_LCH:
955 return IOP_CS_LAB;
956 case IOP_CS_RGB:
957 case IOP_CS_HSL:
958 case IOP_CS_JZCZHZ:
959 return IOP_CS_RGB;
960 case IOP_CS_NONE:
961 // IOP_CS_NONE is used by temperature.c as it may work in RAW or RGB
962 // return the pipe color space to avoid any additional conversions
963 return cst;
964 default:
965 return picker_cst;
966 }
967}
968
970 float *input, const dt_iop_roi_t *roi_in,
971 dt_iop_buffer_dsc_t *input_format,
973{
974 // histogram collection for module
976 && (piece->request_histogram & DT_REQUEST_ON))
977 {
978 const dt_iop_order_iccprofile_info_t *const work_profile
979 = (input_format->cst != IOP_CS_RAW) ? dt_ioppr_get_pipe_work_profile_info(pipe) : NULL;
980
981 // transform to module input colorspace
982 dt_ioppr_transform_image_colorspace(module, input, input, roi_in->width, roi_in->height, input_format->cst,
983 module->input_colorspace(module, pipe, piece), &input_format->cst,
984 work_profile);
985
986 histogram_collect(piece, input, roi_in, &(piece->histogram), piece->histogram_max);
987
988 if(piece->histogram && (module->request_histogram & DT_REQUEST_ON))
989 {
990 const size_t buf_size = 4 * piece->histogram_stats.bins_count * sizeof(uint32_t);
991 module->histogram = realloc(module->histogram, buf_size);
992 memcpy(module->histogram, piece->histogram, buf_size);
993 module->histogram_stats = piece->histogram_stats;
994 memcpy(module->histogram_max, piece->histogram_max, sizeof(piece->histogram_max));
995 if(module->widget) dt_control_queue_redraw_widget(module->widget);
996 }
997 }
998 return;
999}
1000
1001#define KILL_SWITCH_ABORT \
1002 if(dt_atomic_get_int(&pipe->shutdown)) \
1003 { \
1004 if(*cl_mem_output != NULL) \
1005 { \
1006 dt_opencl_release_mem_object(*cl_mem_output); \
1007 *cl_mem_output = NULL; \
1008 } \
1009 dt_iop_nap(5000); \
1010 pipe->status = DT_DEV_PIXELPIPE_DIRTY; \
1011 return 1; \
1012 }
1013
1014// Once we have a cache, stopping computation before full completion
1015// has good chances of leaving it corrupted. So we invalidate it.
1016#define KILL_SWITCH_AND_FLUSH_CACHE \
1017 if(dt_atomic_get_int(&pipe->shutdown)) \
1018 { \
1019 dt_dev_pixelpipe_cache_remove(darktable.pixelpipe_cache, hash, TRUE, output_entry); \
1020 if(*cl_mem_output != NULL) \
1021 { \
1022 dt_opencl_release_mem_object(*cl_mem_output); \
1023 *cl_mem_output = NULL; \
1024 } \
1025 dt_iop_nap(5000); \
1026 pipe->status = DT_DEV_PIXELPIPE_DIRTY; \
1027 return 1; \
1028 }
1029
1031 float *input, dt_iop_buffer_dsc_t *input_format, const dt_iop_roi_t *roi_in,
1032 void **output, dt_iop_buffer_dsc_t **out_format, const dt_iop_roi_t *roi_out,
1035 dt_pixel_cache_entry_t *input_entry)
1036{
1037 // Fetch RGB working profile
1038 // if input is RAW, we can't color convert because RAW is not in a color space
1039 // so we send NULL to by-pass
1040 const dt_iop_order_iccprofile_info_t *const work_profile
1041 = (input_format->cst != IOP_CS_RAW) ? dt_ioppr_get_pipe_work_profile_info(pipe) : NULL;
1042
1043 // transform to module input colorspace
1045 dt_ioppr_transform_image_colorspace(module, input, input, roi_in->width, roi_in->height, input_format->cst,
1046 module->input_colorspace(module, pipe, piece), &input_format->cst,
1047 work_profile);
1049
1050 //fprintf(stdout, "input color space for %s : %i\n", module->op, module->input_colorspace(module, pipe, piece));
1051 const size_t in_bpp = dt_iop_buffer_dsc_to_bpp(input_format);
1052 const size_t bpp = dt_iop_buffer_dsc_to_bpp(*out_format);
1053
1054 const gboolean fitting = dt_tiling_piece_fits_host_memory(MAX(roi_in->width, roi_out->width),
1055 MAX(roi_in->height, roi_out->height), MAX(in_bpp, bpp),
1056 tiling->factor, tiling->overhead);
1057
1058 /* process module on cpu. use tiling if needed and possible. */
1060 if(!fitting && piece->process_tiling_ready)
1061 {
1062 module->process_tiling(module, piece, input, *output, roi_in, roi_out, in_bpp);
1064 *pixelpipe_flow &= ~(PIXELPIPE_FLOW_PROCESSED_ON_GPU);
1065 }
1066 else
1067 {
1068 if(!fitting)
1069 fprintf(stderr, "[pixelpipe_process_on_CPU] Warning: processes `%s' even if memory requirements are not met\n", module->op);
1070
1071 module->process(module, piece, input, *output, roi_in, roi_out);
1072 *pixelpipe_flow |= (PIXELPIPE_FLOW_PROCESSED_ON_CPU);
1074 }
1076
1077 // and save the output colorspace
1078 pipe->dsc.cst = module->output_colorspace(module, pipe, piece);
1079
1080 // blend needs input/output images with default colorspace
1081 if(_transform_for_blend(module, piece))
1082 {
1085 dt_ioppr_transform_image_colorspace(module, input, input, roi_in->width, roi_in->height,
1086 input_format->cst, blend_cst, &input_format->cst,
1087 work_profile);
1089
1090 dt_ioppr_transform_image_colorspace(module, *output, *output, roi_out->width, roi_out->height,
1091 pipe->dsc.cst, blend_cst, &pipe->dsc.cst,
1092 work_profile);
1093 }
1094
1095 /* process blending on CPU */
1096 int err = dt_develop_blend_process(module, piece, input, *output, roi_in, roi_out);
1097 *pixelpipe_flow |= (PIXELPIPE_FLOW_BLENDED_ON_CPU);
1098 *pixelpipe_flow &= ~(PIXELPIPE_FLOW_BLENDED_ON_GPU);
1099
1100 return err; //no errors
1101}
1102
1104{
1105 for(GList *node = g_list_last(pipe->nodes); node; node = g_list_previous(node))
1106 {
1108 if(piece->enabled) return piece;
1109 }
1110
1111 return NULL;
1112}
1113
1114static void _sample_color_picker(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, float *input,
1115 dt_iop_buffer_dsc_t *input_format, const dt_iop_roi_t *roi_in, void **output,
1116 dt_iop_buffer_dsc_t **out_format, const dt_iop_roi_t *roi_out,
1118{
1120 && module == dev->gui_module
1121 && dev->gui_module->enabled
1123 return;
1124
1125 // Fetch RGB working profile
1126 // if input is RAW, we can't color convert because RAW is not in a color space
1127 // so we send NULL to by-pass
1128 const dt_iop_order_iccprofile_info_t *const work_profile
1129 = (input_format->cst != IOP_CS_RAW) ? dt_ioppr_get_pipe_work_profile_info(pipe) : NULL;
1130
1131 // ensure that we are using the right color space
1132 dt_iop_colorspace_type_t picker_cst = _transform_for_picker(module, pipe->dsc.cst);
1133 dt_ioppr_transform_image_colorspace(module, input, input, roi_in->width, roi_in->height,
1134 input_format->cst, picker_cst, &input_format->cst,
1135 work_profile);
1136 dt_ioppr_transform_image_colorspace(module, *output, *output, roi_out->width, roi_out->height,
1137 pipe->dsc.cst, picker_cst, &pipe->dsc.cst,
1138 work_profile);
1139
1140 pixelpipe_picker(module, piece, &piece->dsc_in, (float *)input, roi_in, module->picked_color,
1141 module->picked_color_min, module->picked_color_max, input_format->cst, PIXELPIPE_PICKER_INPUT);
1142 pixelpipe_picker(module, piece, &pipe->dsc, (float *)(*output), roi_out, module->picked_output_color,
1145
1147}
1148
1149
1150#ifdef HAVE_OPENCL
1151
1152static void *_gpu_init_buffer(int devid, void *const host_ptr, const dt_iop_roi_t *roi, const size_t bpp,
1153 dt_iop_module_t *module, const char *message)
1154{
1155 // Need to use read-write mode because of in-place color space conversions
1156 void *cl_mem_input = dt_opencl_alloc_device_use_host_pointer(devid, roi->width, roi->height, bpp, host_ptr,
1157 CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR);
1158
1159 if(cl_mem_input == NULL)
1160 {
1161 dt_print(DT_DEBUG_OPENCL, "[opencl_pixelpipe] couldn't generate %s buffer for module %s\n", message,
1162 module->op);
1163 }
1164
1165 return cl_mem_input;
1166}
1167
1168
1169static void _gpu_clear_buffer(void **cl_mem_buffer)
1170{
1171 if(*cl_mem_buffer != NULL)
1172 {
1173 dt_opencl_release_mem_object(*cl_mem_buffer);
1174 *cl_mem_buffer = NULL;
1175 }
1176}
1177
1178static gboolean _check_zero_memory(void *cl_mem_pinned, void *host_ptr, dt_iop_module_t *module, const char *message)
1179{
1180 if(cl_mem_pinned == host_ptr)
1181 {
1182 //printf("✅ Zero-copy: GPU is using your host memory directly for %s %s\n", module->op, message);
1183 return TRUE;
1184 }
1185 else
1186 {
1187 printf("❌ Not zero-copy: OpenCL made a temporary device-side copy for %s %s\n", module->op, message);
1188 return FALSE;
1189 }
1190}
1191
1192
1193// mode : CL_MAP_WRITE = copy from host to device, CL_MAP_READ = copy from device to host
1194static int _cl_pinned_memory_copy(const int devid, void *host_ptr, void *cl_mem_buffer, const dt_iop_roi_t *roi,
1195 int cl_mode, size_t bpp, dt_iop_module_t *module, const char *message)
1196{
1197 void *cl_mem_pinned_input = dt_opencl_map_image(devid, cl_mem_buffer, TRUE, cl_mode, roi->width,
1198 roi->height, bpp);
1199 dt_opencl_unmap_mem_object(devid, cl_mem_buffer, cl_mem_pinned_input);
1200
1201 // Map/Unmap synchronizes host <-> device pixels if we have a zero-copy buffer.
1202 // If we couldn't get a zero-copy buffer, we need to manually copy pixels
1203 if(!_check_zero_memory(cl_mem_pinned_input, host_ptr, module, message))
1204 {
1205 cl_int err = CL_SUCCESS;
1206
1207 if(cl_mode == CL_MAP_WRITE)
1208 err = dt_opencl_write_host_to_device(devid, host_ptr, cl_mem_buffer, roi->width, roi->height, bpp);
1209 else if(cl_mode == CL_MAP_READ)
1210 err = dt_opencl_read_host_from_device(devid, host_ptr, cl_mem_buffer, roi->width, roi->height, bpp);
1211
1212 if(err != CL_SUCCESS)
1213 {
1214 dt_print(DT_DEBUG_OPENCL, "[opencl_pixelpipe] couldn't copy image to opencl device for module %s (%s)\n",
1215 module->op, message);
1216 return 1;
1217 }
1218 }
1219
1220 return 0;
1221}
1222
1223
1224static int pixelpipe_process_on_GPU(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev,
1225 float *input, void *cl_mem_input, dt_iop_buffer_dsc_t *input_format, const dt_iop_roi_t *roi_in,
1226 void **output, void **cl_mem_output, dt_iop_buffer_dsc_t **out_format, const dt_iop_roi_t *roi_out,
1229 const size_t in_bpp, const size_t bpp,
1230 dt_pixel_cache_entry_t *input_entry)
1231{
1232 // We don't have OpenCL or we couldn't lock a GPU: fallback to CPU processing
1233 if(!(dt_opencl_is_inited() && pipe->opencl_enabled && pipe->devid >= 0) || input == NULL || *output == NULL)
1234 goto error;
1235
1236 // Fetch RGB working profile
1237 // if input is RAW, we can't color convert because RAW is not in a color space
1238 // so we send NULL to by-pass
1239 const dt_iop_order_iccprofile_info_t *const work_profile
1240 = (input_format->cst != IOP_CS_RAW) ? dt_ioppr_get_pipe_work_profile_info(pipe) : NULL;
1241 gboolean success_opencl = TRUE;
1242 dt_iop_colorspace_type_t input_cst_cl = input_format->cst;
1243
1244 const float required_factor_cl = fmaxf(1.0f, (cl_mem_input != NULL) ? tiling->factor_cl - 1.0f : tiling->factor_cl);
1245 /* pre-check if there is enough space on device for non-tiled processing */
1246 const gboolean fits_on_device = dt_opencl_image_fits_device(pipe->devid, MAX(roi_in->width, roi_out->width),
1247 MAX(roi_in->height, roi_out->height), MAX(in_bpp, bpp),
1248 required_factor_cl, tiling->overhead);
1249
1250 /* general remark: in case of opencl errors within modules or out-of-memory on GPU, we transparently
1251 fall back to the respective cpu module and continue in pixelpipe. If we encounter errors we set
1252 pipe->opencl_error=1, return this function with value 1, and leave appropriate action to the calling
1253 function, which normally would restart pixelpipe without opencl.
1254 Late errors are sometimes detected when trying to get back data from device into host memory and
1255 are treated in the same manner. */
1256
1257 /* test for a possible opencl path after checking some module specific pre-requisites */
1258 gboolean possible_cl = (module->process_cl && piece->process_cl_ready
1259 && !((pipe->type & DT_DEV_PIXELPIPE_PREVIEW) == DT_DEV_PIXELPIPE_PREVIEW
1260 && (module->flags() & IOP_FLAGS_PREVIEW_NON_OPENCL))
1261 && (fits_on_device || piece->process_tiling_ready));
1262
1263 if(possible_cl && !fits_on_device)
1264 {
1265 const float cl_px = dt_opencl_get_device_available(pipe->devid) / (sizeof(float) * MAX(in_bpp, bpp) * ceilf(required_factor_cl));
1266 const float dx = MAX(roi_in->width, roi_out->width);
1267 const float dy = MAX(roi_in->height, roi_out->height);
1268 const float border = tiling->overlap + 1;
1269 /* tests for required gpu mem reflects the different tiling stategies.
1270 simple tiles over whole height or width or inside rectangles where we need at last the overlapping area.
1271 */
1272 const gboolean possible = (cl_px > dx * border) || (cl_px > dy * border) || (cl_px > border * border);
1273 if(!possible)
1274 {
1275 dt_print(DT_DEBUG_OPENCL | DT_DEBUG_TILING, "[dt_dev_pixelpipe_process_rec] CL: tiling impossible in module `%s'. avail=%.1fM, requ=%.1fM (%ix%i). overlap=%i\n",
1276 module->op, cl_px / 1e6f, dx*dy / 1e6f, (int)dx, (int)dy, (int)tiling->overlap);
1277 goto error;
1278 }
1279 }
1280
1281 // Not enough memory for one-shot processing, or no tiling support, or tiling support
1282 // but still not enough memory for tiling (due to boundary overlap).
1283 if(!possible_cl) goto error;
1284
1285 if(fits_on_device)
1286 {
1287 /* image is small enough -> try to directly process entire image with opencl */
1288
1289 /* input is not on gpu memory -> copy it there */
1290 if(cl_mem_input == NULL)
1291 {
1293 cl_mem_input = _gpu_init_buffer(pipe->devid, input, roi_in, in_bpp, module, "input");
1294 int fail = (cl_mem_input == NULL);
1295
1296 if(!fail && _cl_pinned_memory_copy(pipe->devid, input, cl_mem_input, roi_in, CL_MAP_WRITE, in_bpp, module,
1297 "initial input"))
1298 fail = TRUE;
1299
1301
1302 if(fail) goto error;
1303 }
1304
1305 // Allocate GPU memory for output
1306 *cl_mem_output = _gpu_init_buffer(pipe->devid, *output, roi_out, bpp, module, "output");
1307 if(*cl_mem_output == NULL) goto error;
1308
1309 // transform to input colorspace if we got our input in a different colorspace
1310 if(!dt_ioppr_transform_image_colorspace_cl(
1311 module, piece->pipe->devid, cl_mem_input, cl_mem_input, roi_in->width, roi_in->height, input_cst_cl,
1312 module->input_colorspace(module, pipe, piece), &input_cst_cl, work_profile))
1313 goto error;
1314
1315 /* now call process_cl of module; module should emit meaningful messages in case of error */
1316 if(!module->process_cl(module, piece, cl_mem_input, *cl_mem_output, roi_in, roi_out))
1317 goto error;
1318
1319 *pixelpipe_flow |= (PIXELPIPE_FLOW_PROCESSED_ON_GPU);
1321
1322 // and save the output colorspace
1323 pipe->dsc.cst = module->output_colorspace(module, pipe, piece);
1324
1325 // blend needs input/output images with default colorspace
1326 if(_transform_for_blend(module, piece))
1327 {
1329 success_opencl &= dt_ioppr_transform_image_colorspace_cl(
1330 module, piece->pipe->devid, cl_mem_input, cl_mem_input, roi_in->width, roi_in->height, input_cst_cl,
1331 blend_cst, &input_cst_cl, work_profile);
1332 success_opencl &= dt_ioppr_transform_image_colorspace_cl(
1333 module, piece->pipe->devid, *cl_mem_output, *cl_mem_output, roi_out->width, roi_out->height,
1334 pipe->dsc.cst, blend_cst, &pipe->dsc.cst, work_profile);
1335
1336 if(!success_opencl)
1337 {
1338 dt_print(DT_DEBUG_OPENCL, "[opencl_pixelpipe] couldn't transform blending colorspace for module %s\n",
1339 module->op);
1340 goto error;
1341 }
1342 }
1343
1344 /* process blending */
1345 if(dt_develop_blend_process_cl(module, piece, cl_mem_input, *cl_mem_output, roi_in, roi_out))
1346 goto error;
1347
1348 *pixelpipe_flow |= (PIXELPIPE_FLOW_BLENDED_ON_GPU);
1349 *pixelpipe_flow &= ~(PIXELPIPE_FLOW_BLENDED_ON_CPU);
1350
1351 if(_cl_pinned_memory_copy(pipe->devid, *output, *cl_mem_output, roi_out, CL_MAP_READ, bpp, module,
1352 "output input"))
1353 goto error;
1354
1355 // Because we color-converted the input several times in place,
1356 // we need to update the colorspace metadata. But since it's shared
1357 // between RAM pixel cache and GPU buffer, then we need to resync GPU buffer with cache.
1358 if(input_format->cst != input_cst_cl)
1359 {
1361 input_format->cst = input_cst_cl;
1362 int fail = _cl_pinned_memory_copy(pipe->devid, input, cl_mem_input, roi_in, CL_MAP_READ, in_bpp, module,
1363 "color-converted input");
1365 if(fail) goto error;
1366 }
1367 }
1368 else if(piece->process_tiling_ready)
1369 {
1370 /* image is too big for direct opencl processing -> try to process image via tiling */
1371 _gpu_clear_buffer(&cl_mem_input);
1372
1373 // transform to module input colorspace
1375 dt_ioppr_transform_image_colorspace(module, input, input, roi_in->width, roi_in->height, input_format->cst,
1376 module->input_colorspace(module, pipe, piece), &input_format->cst,
1377 work_profile);
1379
1380 /* now call process_tiling_cl of module; module should emit meaningful messages in case of error */
1382 int fail = !module->process_tiling_cl(module, piece, input, *output, roi_in, roi_out, in_bpp);
1384
1385 if(fail) goto error;
1386
1388 *pixelpipe_flow &= ~(PIXELPIPE_FLOW_PROCESSED_ON_CPU);
1389
1390 // and save the output colorspace
1391 pipe->dsc.cst = module->output_colorspace(module, pipe, piece);
1392
1393 // blend needs input/output images with default colorspace
1394 if(_transform_for_blend(module, piece))
1395 {
1397
1399 dt_ioppr_transform_image_colorspace(module, input, input, roi_in->width, roi_in->height,
1400 input_format->cst, blend_cst, &input_format->cst,
1401 work_profile);
1403
1404 dt_ioppr_transform_image_colorspace(module, *output, *output, roi_out->width, roi_out->height,
1405 pipe->dsc.cst, blend_cst, &pipe->dsc.cst,
1406 work_profile);
1407 }
1408
1409 /* do process blending on cpu (this is anyhow fast enough) */
1410 dt_develop_blend_process(module, piece, input, *output, roi_in, roi_out);
1411 *pixelpipe_flow |= (PIXELPIPE_FLOW_BLENDED_ON_CPU);
1412 *pixelpipe_flow &= ~(PIXELPIPE_FLOW_BLENDED_ON_GPU);
1413 }
1414 else
1415 {
1416 dt_print(DT_DEBUG_OPENCL, "[opencl_pixelpipe] could not run module '%s' on gpu. falling back to cpu path\n",
1417 module->op);
1418
1419 goto error;
1420 }
1421
1422 // if (rand() % 20 == 0) success_opencl = FALSE; // Test code: simulate spurious failures
1423
1424 // clean up OpenCL input memory and resync pipeline
1425 _gpu_clear_buffer(&cl_mem_input);
1426
1427 // Wait for kernels and copies to complete before accessing the cache again and releasing the locks
1428 dt_opencl_finish(pipe->devid);
1429
1430 // don't free cl_mem_output here, as it will be the input for the next module
1431 // the last module in the pipe will need to be freed by the pipeline process function
1432 return 0;
1433
1434 // any error in OpenCL ends here
1435 // free everything and fall back to CPU processing
1436error:;
1437
1438 _gpu_clear_buffer(cl_mem_output);
1439 _gpu_clear_buffer(&cl_mem_input);
1440
1441 dt_opencl_finish(pipe->devid);
1442 if(input != NULL && *output != NULL)
1443 return pixelpipe_process_on_CPU(pipe, dev, input, input_format, roi_in, output, out_format, roi_out, module,
1444 piece, tiling, pixelpipe_flow, input_entry);
1445 else
1446 return 1;
1447}
1448#endif
1449
1450
1451static void _print_perf_debug(dt_dev_pixelpipe_t *pipe, const dt_pixelpipe_flow_t pixelpipe_flow, dt_dev_pixelpipe_iop_t *piece, dt_iop_module_t *module, dt_times_t *start)
1452{
1453 char histogram_log[32] = "";
1454 if(!(pixelpipe_flow & PIXELPIPE_FLOW_HISTOGRAM_NONE))
1455 {
1456 snprintf(histogram_log, sizeof(histogram_log), ", collected histogram on %s",
1457 (pixelpipe_flow & PIXELPIPE_FLOW_HISTOGRAM_ON_GPU
1458 ? "GPU"
1459 : pixelpipe_flow & PIXELPIPE_FLOW_HISTOGRAM_ON_CPU ? "CPU" : ""));
1460 }
1461
1462 gchar *module_label = dt_history_item_get_name(module);
1464 start, "[dev_pixelpipe]", "processed `%s' on %s%s%s, blended on %s [%s]", module_label,
1465 pixelpipe_flow & PIXELPIPE_FLOW_PROCESSED_ON_GPU
1466 ? "GPU"
1467 : pixelpipe_flow & PIXELPIPE_FLOW_PROCESSED_ON_CPU ? "CPU" : "",
1468 pixelpipe_flow & PIXELPIPE_FLOW_PROCESSED_WITH_TILING ? " with tiling" : "",
1469 (!(pixelpipe_flow & PIXELPIPE_FLOW_HISTOGRAM_NONE) && (piece->request_histogram & DT_REQUEST_ON))
1470 ? histogram_log
1471 : "",
1472 pixelpipe_flow & PIXELPIPE_FLOW_BLENDED_ON_GPU
1473 ? "GPU"
1474 : pixelpipe_flow & PIXELPIPE_FLOW_BLENDED_ON_CPU ? "CPU" : "",
1475 _pipe_type_to_str(pipe->type));
1476 g_free(module_label);
1477}
1478
1479
1480static void _print_nan_debug(dt_dev_pixelpipe_t *pipe, void *cl_mem_output, void *output, const dt_iop_roi_t *roi_out, dt_iop_buffer_dsc_t *out_format, dt_iop_module_t *module, const size_t bpp)
1481{
1482 if((darktable.unmuted & DT_DEBUG_NAN) && strcmp(module->op, "gamma") != 0)
1483 {
1484 gchar *module_label = dt_history_item_get_name(module);
1485
1486 if(out_format->datatype == TYPE_FLOAT && out_format->channels == 4)
1487 {
1488 int hasinf = 0, hasnan = 0;
1489 dt_aligned_pixel_t min = { FLT_MAX };
1490 dt_aligned_pixel_t max = { FLT_MIN };
1491
1492 for(int k = 0; k < 4 * roi_out->width * roi_out->height; k++)
1493 {
1494 if((k & 3) < 3)
1495 {
1496 float f = ((float *)(output))[k];
1497 if(isnan(f))
1498 hasnan = 1;
1499 else if(isinf(f))
1500 hasinf = 1;
1501 else
1502 {
1503 min[k & 3] = fmin(f, min[k & 3]);
1504 max[k & 3] = fmax(f, max[k & 3]);
1505 }
1506 }
1507 }
1508 if(hasnan)
1509 fprintf(stderr, "[dev_pixelpipe] module `%s' outputs NaNs! [%s]\n", module_label,
1510 _pipe_type_to_str(pipe->type));
1511 if(hasinf)
1512 fprintf(stderr, "[dev_pixelpipe] module `%s' outputs non-finite floats! [%s]\n", module_label,
1513 _pipe_type_to_str(pipe->type));
1514 fprintf(stderr, "[dev_pixelpipe] module `%s' min: (%f; %f; %f) max: (%f; %f; %f) [%s]\n", module_label,
1515 min[0], min[1], min[2], max[0], max[1], max[2], _pipe_type_to_str(pipe->type));
1516 }
1517 else if(out_format->datatype == TYPE_FLOAT && out_format->channels == 1)
1518 {
1519 int hasinf = 0, hasnan = 0;
1520 float min = FLT_MAX;
1521 float max = FLT_MIN;
1522
1523 for(int k = 0; k < roi_out->width * roi_out->height; k++)
1524 {
1525 float f = ((float *)(output))[k];
1526 if(isnan(f))
1527 hasnan = 1;
1528 else if(isinf(f))
1529 hasinf = 1;
1530 else
1531 {
1532 min = fmin(f, min);
1533 max = fmax(f, max);
1534 }
1535 }
1536 if(hasnan)
1537 fprintf(stderr, "[dev_pixelpipe] module `%s' outputs NaNs! [%s]\n", module_label,
1538 _pipe_type_to_str(pipe->type));
1539 if(hasinf)
1540 fprintf(stderr, "[dev_pixelpipe] module `%s' outputs non-finite floats! [%s]\n", module_label,
1541 _pipe_type_to_str(pipe->type));
1542 fprintf(stderr, "[dev_pixelpipe] module `%s' min: (%f) max: (%f) [%s]\n", module_label, min, max,
1543 _pipe_type_to_str(pipe->type));
1544 }
1545
1546 g_free(module_label);
1547 }
1548}
1549
1550// return 1 on error
1551static int _init_base_buffer(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, void **output,
1552 void **cl_mem_output, dt_iop_buffer_dsc_t **out_format,
1553 dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out,
1554 const uint64_t hash,
1555 const gboolean bypass_cache,
1556 const size_t bufsize, const size_t bpp)
1557{
1558 // Note: dt_dev_pixelpipe_cache_get actually init/alloc *output
1559 dt_pixel_cache_entry_t *cache_entry;
1560 int new_entry = dt_dev_pixelpipe_cache_get(darktable.pixelpipe_cache, hash, bufsize, "base buffer", pipe->type,
1561 output, out_format, &cache_entry);
1562 if(cache_entry == NULL) return 1;
1563
1564 int err = 0;
1565
1566 if(bypass_cache || new_entry)
1567 {
1568 // Grab input buffer from mipmap cache.
1569 // We will have to copy it here and in pixelpipe cache because it can get evicted from mipmap cache
1570 // anytime after we release the lock, so it would not be thread-safe to just use a reference
1571 // to full-sized buffer. Otherwise, skip dt_dev_pixelpipe_cache_get and
1572 // *output = buf.buf for 1:1 at full resolution.
1575
1576 // Cache size has changed since we inited pipe input ?
1577 // Note: we know pipe->iwidth/iheight are non-zero or we would have not launched a pipe.
1578 // Note 2: there is no valid reason for a cacheline to change size during runtime.
1579 if(!buf.buf || buf.height != pipe->iheight || buf.width != pipe->iwidth || !*output)
1580 {
1581 // Nothing we can do, we need to recompute roi_in and roi_out from scratch
1582 // for all modules with new sizes. Exit on error and catch that in develop.
1584 err = 1;
1585 }
1586 else if(roi_in->scale == 1.0f)
1587 {
1588 // fast branch for 1:1 pixel copies.
1589 // last minute clamping to catch potential out-of-bounds in roi_in and roi_out
1590 const int in_x = MAX(roi_in->x, 0);
1591 const int in_y = MAX(roi_in->y, 0);
1592 const int cp_width = MIN(roi_out->width, pipe->iwidth - in_x);
1593 const int cp_height = MIN(roi_out->height, pipe->iheight - in_y);
1594
1595 if(cp_width > 0 && cp_height > 0)
1596 {
1597 _copy_buffer((const char *const)buf.buf, (char *const)*output, cp_height, roi_out->width,
1598 pipe->iwidth, in_x, in_y, bpp * cp_width, bpp);
1600 err = 0;
1601 }
1602 else
1603 {
1604 // Invalid dimensions
1606 err = 1;
1607 }
1608 }
1609 else if(bpp == 16)
1610 {
1611 // dt_iop_clip_and_zoom() expects 4 * float 32 only
1612 roi_in->x /= roi_out->scale;
1613 roi_in->y /= roi_out->scale;
1614 roi_in->width = pipe->iwidth;
1615 roi_in->height = pipe->iheight;
1616 roi_in->scale = 1.0f;
1617 dt_iop_clip_and_zoom(*output, (const float *const)buf.buf, roi_out, roi_in, roi_out->width, pipe->iwidth);
1619 err = 0;
1620 }
1621 else
1622 {
1623 fprintf(stdout,
1624 "Base buffer init: scale %f != 1.0 but the input has %li bytes per pixel. This case is not "
1625 "covered by the pipeline, please report the bug.\n",
1626 roi_out->scale, bpp);
1627
1629 err = 1;
1630 }
1631 }
1632 // else found in cache.
1633
1634 if(new_entry)
1636
1637 return err;
1638}
1639
1640static void _sample_all(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, void *input, void **output,
1641 const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out, dt_iop_buffer_dsc_t *input_format,
1643 const uint64_t input_hash, const uint64_t hash, const size_t in_bpp, const size_t bpp,
1644 dt_pixel_cache_entry_t *const input_entry, dt_pixel_cache_entry_t *const output_entry)
1645{
1646 if(!(dev->gui_attached && pipe == dev->preview_pipe
1648 && piece->enabled))
1649 return;
1650
1651 // Lock all buffers in write mode because we might be doing in-place color conversion
1654
1655 // Need to go first because we want module output RGB without color conversion.
1656 // Gamma outputs uint8_t so we take its input. We want float32.
1657 if(strcmp(module->op, "gamma") == 0)
1658 pixelpipe_get_histogram_backbuf(pipe, dev, input, roi_in, module, piece, input_hash, in_bpp);
1659 else
1660 pixelpipe_get_histogram_backbuf(pipe, dev, *output, roi_out, module, piece, hash, bpp);
1661
1662 // sample internal histogram on input and color pickers
1663 collect_histogram_on_CPU(pipe, dev, input, roi_in, input_format, module, piece);
1664 _sample_color_picker(pipe, dev, input, input_format, roi_in, output, output_format, roi_out, module, piece);
1665
1668}
1669
1670
1671// recursive helper for process:
1673 void **cl_mem_output, dt_iop_buffer_dsc_t **out_format,
1674 const dt_iop_roi_t *roi_out, GList *modules, GList *pieces, int pos)
1675{
1676 // The pipeline is executed recursively, from the end. For each module n, starting from the end,
1677 // if output is cached, take it, else if input is cached, take it, process it and output,
1678 // else recurse to the previous module n-1 to get a an input.
1680
1681 if(pipe->type == DT_DEV_PIXELPIPE_PREVIEW)
1682 dt_iop_nap(500);
1683
1684 dt_iop_roi_t roi_in = *roi_out;
1685
1686 void *input = NULL;
1687 void *cl_mem_input = NULL;
1688 *cl_mem_output = NULL;
1689 dt_iop_module_t *module = NULL;
1690 dt_dev_pixelpipe_iop_t *piece = NULL;
1691
1692 if(modules)
1693 {
1694 module = (dt_iop_module_t *)modules->data;
1695 piece = (dt_dev_pixelpipe_iop_t *)pieces->data;
1696 // skip this module?
1697 if(!piece->enabled)
1698 return dt_dev_pixelpipe_process_rec(pipe, dev, output, cl_mem_output, out_format, &roi_in,
1699 g_list_previous(modules), g_list_previous(pieces), pos - 1);
1700 }
1701
1703
1704 get_output_format(module, pipe, piece, dev, *out_format);
1705 const size_t bpp = dt_iop_buffer_dsc_to_bpp(*out_format);
1706 const size_t bufsize = (size_t)bpp * roi_out->width * roi_out->height;
1707 uint64_t hash = _node_hash(pipe, piece, roi_out, pos);
1708 const gboolean bypass_cache = (module) ? piece->bypass_cache : FALSE;
1709
1710 // 1) Fast-track:
1711 // If we have a cache entry for this hash, return it straight away,
1712 // don't recurse through pipeline and don't process.
1713 // We can't do it for the preview pipe because it needs to resync
1714 // the global histograms, so we will need to recurse through pipeline anyway.
1715 // This case is handled below.
1716 dt_pixel_cache_entry_t *existing_cache;
1718 && !bypass_cache && !pipe->reentry
1719 && dt_dev_pixelpipe_cache_get_existing(darktable.pixelpipe_cache, hash, output, out_format, &existing_cache))
1720 {
1721 // FIXME: on CPU path and GPU path with tiling, when 2 modules taking different color spaces are back to back,
1722 // the color conversion for the next is done in-place in the output of the previous. We should check
1723 // here if out_format->cst matches wathever we are expecting, and convert back if it doesn't.
1724 dt_print(DT_DEBUG_PIPE, "[dev_pixelpipe] found %" PRIu64 " (%s) for %s pipeline in cache\n", hash, module ? module->op : "noop",
1725 _pipe_type_to_str(pipe->type));
1726 return 0;
1727 }
1728
1729 // 2) no module means step 0 of the pipe : importing the input buffer
1730 if(!modules)
1731 {
1732 dt_times_t start;
1733 dt_get_times(&start);
1734
1735 if(_init_base_buffer(pipe, dev, output, cl_mem_output, out_format, &roi_in, roi_out, hash, bypass_cache, bufsize,
1736 bpp))
1737 return 1;
1738
1739 dt_show_times_f(&start, "[dev_pixelpipe]", "initing base buffer [%s]", _pipe_type_to_str(pipe->type));
1740 return 0;
1741 }
1742
1743 // 3) now recurse through the pipeline.
1744 // 3a) get the region of interest. It's already computed at init time in _get_roi_in()
1745 // so simply copy it.
1746 memcpy(&roi_in, &piece->planned_roi_in, sizeof(dt_iop_roi_t));
1747 // Otherwise, run this:
1748 // module->modify_roi_in(module, piece, roi_out, &roi_in);
1749
1750 // 3b) recurse to get actual data of input buffer
1751 dt_iop_buffer_dsc_t _input_format = { 0 };
1752 dt_iop_buffer_dsc_t *input_format = &_input_format;
1753
1754 piece = (dt_dev_pixelpipe_iop_t *)pieces->data;
1755 piece->processed_roi_in = roi_in;
1756 piece->processed_roi_out = *roi_out;
1757
1758 if(dt_dev_pixelpipe_process_rec(pipe, dev, &input, &cl_mem_input, &input_format, &roi_in,
1759 g_list_previous(modules), g_list_previous(pieces), pos - 1))
1760 return 1;
1761
1763
1764 const size_t in_bpp = dt_iop_buffer_dsc_to_bpp(input_format);
1765 piece->dsc_out = piece->dsc_in = *input_format;
1766 module->output_format(module, pipe, piece, &piece->dsc_out);
1767 **out_format = pipe->dsc = piece->dsc_out;
1768 const size_t out_bpp = dt_iop_buffer_dsc_to_bpp(*out_format);
1769
1770 // 3c) actually process this module BUT treat all bypasses first.
1771
1772 // special case: user requests to see channel data in the parametric mask of a module, or the blending
1773 // mask. In that case we skip all modules manipulating pixel content and only process image distorting
1774 // modules. Finally "gamma" is responsible for displaying channel/mask data accordingly.
1775 if(strcmp(module->op, "gamma") != 0
1777 && !(module->operation_tags() & IOP_TAG_DISTORT)
1778 && (in_bpp == out_bpp)
1779 && !memcmp(&roi_in, roi_out, sizeof(struct dt_iop_roi_t)))
1780 {
1781 // since we're not actually running the module, the output format is the same as the input format
1782 **out_format = pipe->dsc = piece->dsc_out = piece->dsc_in;
1783 *output = input;
1784 return 0;
1785 }
1786
1787 // Get cache lines for input and output, possibly allocating a new one for output
1788 dt_pixel_cache_entry_t *input_entry = NULL;
1790 if(input_entry == NULL) return 1;
1791
1792 dt_pixel_cache_entry_t *output_entry = NULL;
1793 char *name = g_strdup_printf("module %s (%s) for pipe %i", module->op, module->multi_name, pipe->type);
1794 gboolean new_entry = dt_dev_pixelpipe_cache_get(darktable.pixelpipe_cache, hash, bufsize, name, pipe->type,
1795 output, out_format, &output_entry);
1796 g_free(name);
1797 if(output_entry == NULL) return 1;
1798
1800
1801 // If we found an existing cache entry for this hash (= !new_entry), and
1802 // bypassing the cache is not requested by the pipe, stop before processing.
1803 // This is mostly for the preview pipe since we didn't stop the recursion earlier
1804 // at the last-found cache line.
1805 if(!pipe->reentry && !new_entry)
1806 {
1807 dt_print(DT_DEBUG_PIPE, "[pipeline] found %" PRIu64 " (%s) for %s pipeline in cache\n", hash, module ? module->op : "noop",
1808 _pipe_type_to_str(pipe->type));
1809
1810 // Sample all color pickers and histograms
1811 _sample_all(pipe, dev, input, output, &roi_in, roi_out, input_format, out_format, module,
1812 piece, input_hash, hash, in_bpp, bpp, input_entry, output_entry);
1813
1815
1816 if(pipe->type == DT_DEV_PIXELPIPE_PREVIEW)
1817 dt_iop_nap(500);
1818
1819 return 0;
1820 }
1821
1822 /* get tiling requirement of module */
1824 tiling.factor_cl = tiling.maxbuf_cl = -1; // set sentinel value to detect whether callback set sizes
1825 module->tiling_callback(module, piece, &roi_in, roi_out, &tiling);
1826 if (tiling.factor_cl < 0) tiling.factor_cl = tiling.factor; // default to CPU size if callback didn't set GPU
1827 if (tiling.maxbuf_cl < 0) tiling.maxbuf_cl = tiling.maxbuf;
1828
1829 /* does this module involve blending? */
1830 if(piece->blendop_data && ((dt_develop_blend_params_t *)piece->blendop_data)->mask_mode != DEVELOP_MASK_DISABLED)
1831 {
1832 /* get specific memory requirement for blending */
1833 dt_develop_tiling_t tiling_blendop = { 0 };
1834 tiling_callback_blendop(module, piece, &roi_in, roi_out, &tiling_blendop);
1835
1836 /* aggregate in structure tiling */
1837 tiling.factor = fmax(tiling.factor, tiling_blendop.factor);
1838 tiling.factor_cl = fmax(tiling.factor_cl, tiling_blendop.factor);
1839 tiling.maxbuf = fmax(tiling.maxbuf, tiling_blendop.maxbuf);
1840 tiling.maxbuf_cl = fmax(tiling.maxbuf_cl, tiling_blendop.maxbuf);
1841 tiling.overhead = fmax(tiling.overhead, tiling_blendop.overhead);
1842 }
1843
1844 /* remark: we do not do tiling for blendop step, neither in opencl nor on cpu. if overall tiling
1845 requirements (maximum of module and blendop) require tiling for opencl path, then following blend
1846 step is anyhow done on cpu. we assume that blending itself will never require tiling in cpu path,
1847 because memory requirements will still be low enough. */
1848
1849 assert(tiling.factor > 0.0f);
1850 assert(tiling.factor_cl > 0.0f);
1851
1852 // Actual pixel processing for this module
1853 int error = 0;
1854
1855 dt_times_t start;
1856 dt_get_times(&start);
1857
1858#ifdef HAVE_OPENCL
1859 error = pixelpipe_process_on_GPU(pipe, dev, input, cl_mem_input, input_format, &roi_in, output, cl_mem_output,
1860 out_format, roi_out, module, piece, &tiling, &pixelpipe_flow, in_bpp, bpp, input_entry);
1861#else
1862 error = pixelpipe_process_on_CPU(pipe, dev, input, input_format, &roi_in, output, out_format, roi_out, module,
1863 piece, &tiling, &pixelpipe_flow, input_entry);
1864#endif
1865
1866 _print_perf_debug(pipe, pixelpipe_flow, piece, module, &start);
1867
1868 // Flag to throw away the output as soon as we are done consuming it in this thread, at the next module.
1869 // Cache bypass is requested by modules like crop/perspective, when they show the full image,
1870 // and when doing anything transient.
1871 if(bypass_cache || pipe->reentry)
1873
1874 // in case we get this buffer from the cache in the future, cache some stuff:
1875 **out_format = piece->dsc_out = pipe->dsc;
1876
1877 // Unlock read and write locks, decrease reference count on input
1880
1881 if(error)
1882 {
1883 // No point in keeping garbled output
1886 dt_iop_nap(5000);
1887 return 1;
1888 }
1889
1891
1892 // Sample all color pickers and histograms
1893 _sample_all(pipe, dev, input, output, &roi_in, roi_out, input_format, out_format, module, piece, input_hash,
1894 hash, in_bpp, bpp, input_entry, output_entry);
1895
1896 // Print min/max/Nan in debug mode only
1897 if((darktable.unmuted & DT_DEBUG_NAN) && strcmp(module->op, "gamma") != 0)
1898 {
1900 _print_nan_debug(pipe, *cl_mem_output, *output, roi_out, *out_format, module, bpp);
1902 }
1903
1904 // And throw away the current input if it was flagged before as in the above
1905 // dt_dev_pixel_pipe_cache_auto_destroy_apply(darktable.pixelpipe_cache, input_hash, pipe->type, input_entry);
1906 // Note : for the last module of the pipeline, even if it's flagged for auto_destroy, it will not be
1907 // because it is the input of nothing (but the GUI backbuf). This is by design because we need something
1908 // to paint in UI.
1909
1911
1912 if(pipe->type == DT_DEV_PIXELPIPE_PREVIEW)
1913 dt_iop_nap(500);
1914
1915 return 0;
1916}
1917
1918
1920{
1921 GList *nodes = g_list_last(pipe->nodes);
1923 while(strcmp(piece->module->op, op))
1924 {
1925 piece->enabled = 0;
1926 piece = NULL;
1927 nodes = g_list_previous(nodes);
1928 if(!nodes) break;
1929 piece = (dt_dev_pixelpipe_iop_t *)nodes->data;
1930 }
1931}
1932
1934{
1935 GList *nodes = pipe->nodes;
1937 while(strcmp(piece->module->op, op))
1938 {
1939 piece->enabled = 0;
1940 piece = NULL;
1941 nodes = g_list_next(nodes);
1942 if(!nodes) break;
1943 piece = (dt_dev_pixelpipe_iop_t *)nodes->data;
1944 }
1945}
1946
1947#define KILL_SWITCH_PIPE \
1948 if(dt_atomic_get_int(&pipe->shutdown)) \
1949 { \
1950 if(pipe->devid >= 0) \
1951 { \
1952 dt_opencl_unlock_device(pipe->devid); \
1953 pipe->devid = -1; \
1954 } \
1955 pipe->status = DT_DEV_PIXELPIPE_DIRTY; \
1956 if(pipe->forms) g_list_free_full(pipe->forms, (void (*)(void *))dt_masks_free_form); \
1957 dt_iop_nap(5000); \
1958 return 1; \
1959 }
1960
1961
1963{
1964 switch(error)
1965 {
1966 case 1:
1967 dt_print(DT_DEBUG_OPENCL, "[opencl] Opencl errors; disabling opencl for %s pipeline!\n", _pipe_type_to_str(pipe->type));
1968 dt_control_log(_("Ansel discovered problems with your OpenCL setup; disabling OpenCL for %s pipeline!"), _pipe_type_to_str(pipe->type));
1969 break;
1970 case 2:
1972 "[opencl] Too many opencl errors; disabling opencl for this session!\n");
1973 dt_control_log(_("Ansel discovered problems with your OpenCL setup; disabling OpenCL for this session!"));
1974 break;
1975 default:
1976 break;
1977 }
1978}
1979
1980
1982 double scale)
1983{
1985 {
1986 fprintf(stderr, "[memory] before pixelpipe process\n");
1988 }
1989
1991
1992 dt_print(DT_DEBUG_DEV, "[pixelpipe] Started %s pipeline recompute at %i×%i px\n", _pipe_type_to_str(pipe->type), width, height);
1993
1994 // get a snapshot of the mask list
1995 pipe->forms = dt_masks_dup_forms_deep(dev->forms, NULL);
1996
1997 // go through the list of modules from the end:
1998 const guint pos = g_list_length(pipe->iop);
1999 GList *modules = g_list_last(pipe->iop);
2000 GList *pieces = g_list_last(pipe->nodes);
2001
2002 // Get the roi_out hash
2003 // Get the previous output size of the module, for cache invalidation.
2004 dt_iop_roi_t roi = (dt_iop_roi_t){ x, y, width, height, scale };
2005 dt_dev_pixelpipe_get_roi_in(pipe, dev, roi);
2007
2008 pipe->backbuf = NULL;
2009 pipe->opencl_enabled = dt_opencl_update_settings(); // update enabled flag and profile from preferences
2010 pipe->devid = (pipe->opencl_enabled) ? dt_opencl_lock_device(pipe->type)
2011 : -1; // try to get/lock opencl resource
2012
2013 if(pipe->devid > -1) dt_opencl_events_reset(pipe->devid);
2014 dt_print(DT_DEBUG_OPENCL, "[pixelpipe_process] [%s] using device %d\n", _pipe_type_to_str(pipe->type),
2015 pipe->devid);
2016
2018
2019 gboolean keep_running = TRUE;
2020 int opencl_error = 0;
2021 int err = 0;
2022
2023 while(keep_running)
2024 {
2025
2026#ifdef HAVE_OPENCL
2028#endif
2029
2030 // WARNING: buf will actually be a reference to a pixelpipe cache line, so it will be freed
2031 // when the cache line is flushed or invalidated.
2032 void *buf = NULL;
2033 void *cl_mem_out = NULL;
2034
2035 dt_iop_buffer_dsc_t _out_format = { 0 };
2036 dt_iop_buffer_dsc_t *out_format = &_out_format;
2037
2039
2040 dt_times_t start;
2041 dt_get_times(&start);
2042 err = dt_dev_pixelpipe_process_rec(pipe, dev, &buf, &cl_mem_out, &out_format, &roi, modules, pieces, pos);
2043 gchar *msg = g_strdup_printf("[pixelpipe] %s pipeline processing", _pipe_type_to_str(pipe->type));
2044 dt_show_times(&start, msg);
2045 g_free(msg);
2046
2047 // The pipeline has copied cl_mem_out into buf, so we can release it now.
2048 #ifdef HAVE_OPENCL
2049 _gpu_clear_buffer(&cl_mem_out);
2050 #endif
2051
2052 // get status summary of opencl queue by checking the eventlist
2053 const int oclerr = (pipe->devid > -1) ? dt_opencl_events_flush(pipe->devid, TRUE) != 0 : 0;
2054
2055 // Relinquish the CPU because we are in a realtime thread
2056 dt_iop_nap(5000);
2057
2058 // Check if we had opencl errors ....
2059 // remark: opencl errors can come in two ways: pipe->opencl_error is TRUE (and err is TRUE) OR oclerr is
2060 // TRUE
2061 keep_running = (oclerr || (err && pipe->opencl_error));
2062 if(keep_running)
2063 {
2064 // Log the error
2065 darktable.opencl->error_count++; // increase error count
2066 opencl_error = 1; // = any OpenCL error, next run goes to CPU
2067
2068 // Disable OpenCL for this pipe
2070 pipe->opencl_enabled = 0;
2071 pipe->opencl_error = 0;
2072 pipe->devid = -1;
2073
2075 {
2076 // Too many errors : dispable OpenCL for this session
2078 dt_capabilities_remove("opencl");
2079 opencl_error = 2; // = too many OpenCL errors, all runs go to CPU
2080 }
2081
2082 _print_opencl_errors(opencl_error, pipe);
2083 }
2084 else if(!dt_atomic_get_int(&pipe->shutdown))
2085 {
2086 // No opencl errors, no killswitch triggered: we should have a valid output buffer now.
2087
2088 // Store the back buffer hash and reference
2089 const dt_dev_pixelpipe_iop_t *last_module = _last_node_in_pipe(pipe);
2090 pipe->backbuf_hash = _node_hash(pipe, last_module, &roi, pos);
2091 pipe->backbuf = buf;
2092 pipe->backbuf_width = width;
2093 pipe->backbuf_height = height;
2094
2095 // Note : the last output (backbuf) of the pixelpipe cache is internally locked
2096 // Whatever consuming it will need to unlock it.
2097 }
2098 }
2099
2100 // release resources:
2101 if(pipe->forms)
2102 {
2103 g_list_free_full(pipe->forms, (void (*)(void *))dt_masks_free_form);
2104 pipe->forms = NULL;
2105 }
2106 if(pipe->devid >= 0)
2107 {
2109 pipe->devid = -1;
2110 }
2111
2112 // terminate
2114
2115 // If an intermediate module set that, be sure to reset it at the end
2116 pipe->flush_cache = FALSE;
2117 return err;
2118}
2119
2121{
2122 return (dev // don't segfault
2123 && dev->gui_module // don't segfault
2124 && dev->gui_module != current_module // current_module is not capturing editing mode
2125 && dev->gui_module->operation_tags_filter() & current_module->operation_tags());
2126 // current_module does operation(s) that active module doesn't want
2127}
2128
2130 const int width_in, const int height_in,
2131 int *width, int *height)
2132{
2133 dt_iop_roi_t roi_in = (dt_iop_roi_t){ 0, 0, width_in, height_in, 1.0 };
2134 dt_iop_roi_t roi_out;
2135 GList *modules = g_list_first(pipe->iop);
2136 GList *pieces = g_list_first(pipe->nodes);
2137 while(modules)
2138 {
2139 dt_iop_module_t *module = (dt_iop_module_t *)modules->data;
2141
2142 piece->buf_in = roi_in;
2143
2144 // skip this module?
2145 if(piece->enabled
2147 {
2148 module->modify_roi_out(module, piece, &roi_out, &roi_in);
2149 }
2150 else
2151 {
2152 // pass through regions of interest for gui post expose events
2153 roi_out = roi_in;
2154 }
2155
2156 piece->buf_out = roi_out;
2157 roi_in = roi_out;
2158
2159 modules = g_list_next(modules);
2160 pieces = g_list_next(pieces);
2161 }
2162 *width = roi_out.width;
2163 *height = roi_out.height;
2164}
2165
2166void dt_dev_pixelpipe_get_roi_in(dt_dev_pixelpipe_t *pipe, struct dt_develop_t *dev, const struct dt_iop_roi_t roi_out)
2167{
2168 // while module->modify_roi_out describes how the current module will change the size of
2169 // the output buffer depending on its parameters (pretty intuitive),
2170 // module->modify_roi_in describes "how much material" the current module needs from the previous one,
2171 // because some modules (lens correction) need a padding on their input.
2172 // The tricky part is therefore that the effect of the current module->modify_roi_in() needs to be repercuted
2173 // upstream in the pipeline for proper pipeline cache invalidation, so we need to browse the pipeline
2174 // backwards.
2175
2176 dt_iop_roi_t roi_out_temp = roi_out;
2177 dt_iop_roi_t roi_in;
2178 GList *modules = g_list_last(pipe->iop);
2179 GList *pieces = g_list_last(pipe->nodes);
2180 while(modules)
2181 {
2182 dt_iop_module_t *module = (dt_iop_module_t *)modules->data;
2184
2185 piece->planned_roi_out = roi_out_temp;
2186
2187 // skip this module?
2188 if(piece->enabled && !dt_dev_pixelpipe_activemodule_disables_currentmodule(dev, module))
2189 {
2190 module->modify_roi_in(module, piece, &roi_out_temp, &roi_in);
2191 }
2192 else
2193 {
2194 // pass through regions of interest for gui post expose events
2195 roi_in = roi_out_temp;
2196 }
2197
2198 piece->planned_roi_in = roi_in;
2199 roi_out_temp = roi_in;
2200
2201 modules = g_list_previous(modules);
2202 pieces = g_list_previous(pieces);
2203 }
2204}
2205
2216 *current_piece, const dt_iop_module_t *target_module)
2217{
2218 gboolean success = TRUE;
2219 gchar *clean_target_name = delete_underscore(target_module->name());
2220 gchar *target_name = g_strdup_printf("%s (%s)", clean_target_name, target_module->multi_name);
2221
2222 if(source_piece == NULL || current_piece == NULL)
2223 {
2224 fprintf(stderr,"[raster masks] ERROR: source: %s, current: %s\n",
2225 (source_piece != NULL) ? "is defined" : "is undefined",
2226 (current_piece != NULL) ? "is definded" : "is undefined");
2227
2228 gchar *hint = NULL;
2229 if(source_piece == NULL)
2230 {
2231 // The loop searching linked modules to the raster masks
2232 // terminated without finding the source module.
2233 // that means the source module has been deleted.
2234 hint = g_strdup_printf(
2235 _("\n- Check if the module providing the masks for the module %s has not been deleted.\n"),
2236 target_name);
2237 }
2238 else if(current_piece == NULL)
2239 {
2240 // The loop searching linked modules to the raster masks
2241 // has stopped when it finds the source module but before it has
2242 // found the current module:
2243 // That means the raster mask is above current module.
2244 hint = g_strdup_printf(_("\n- Check if the module %s (%s) providing the masks has not been moved above %s.\n"),
2245 delete_underscore(source_piece->module->name()), source_piece->module->multi_name, clean_target_name);
2246 }
2247
2248 dt_control_log(_("The %s module is trying to reuse a mask from a module but it can't be found.\n"
2249 "Masking in %s will be disabled until a mask is available.\n"
2250 "%s"),
2251 target_name, target_name, hint ? hint : "");
2252 g_free(hint);
2253
2254 fprintf(stderr, "[raster masks] no source module for module %s could be found\n", target_name);
2255 success = FALSE;
2256 }
2257
2258 if(success && !source_piece->enabled)
2259 {
2260 gchar *clean_source_name = delete_underscore(source_piece->module->name());
2261 gchar *source_name = g_strdup_printf("%s (%s)", clean_source_name, source_piece->module->multi_name);
2262 // there might be stale masks from disabled modules left over. don't use those!
2263 dt_control_log(_("The `%s` module is trying to reuse a mask from disabled module `%s`.\n"
2264 "Disabled modules cannot provide their masks to other modules.\n"
2265 "Masking in `%s` will be disabled until `%s` is re-enabled."),
2266 target_name, source_name, target_name, source_name);
2267
2268 fprintf(stderr, "[raster masks] module %s trying to reuse a mask from disabled instance of %s\n",
2269 target_name, source_name);
2270
2271 g_free(clean_source_name);
2272 g_free(source_name);
2273 success = FALSE;
2274 }
2275
2276 g_free(clean_target_name);
2277 g_free(target_name);
2278 return success;
2279}
2280
2281float *dt_dev_get_raster_mask(dt_dev_pixelpipe_t *pipe, const dt_iop_module_t *raster_mask_source,
2282 const int raster_mask_id, const dt_iop_module_t *target_module,
2283 gboolean *free_mask, int *error)
2284{
2285 // TODO: refactor this mess to limit for/if nesting
2286 if(error) *error = 0;
2287
2288 gchar *clean_target_name = delete_underscore(target_module->name());
2289 gchar *target_name = g_strdup_printf("%s (%s)", clean_target_name, target_module->multi_name);
2290
2291 if(!raster_mask_source)
2292 {
2293 fprintf(stderr, "[raster masks] The source module of the mask for %s was not found\n", target_name);
2294 g_free(clean_target_name);
2295 g_free(target_name);
2296 return NULL;
2297 }
2298
2299 *free_mask = FALSE;
2300 float *raster_mask = NULL;
2301
2302 // Find the module objects associated with mask provider and consumer
2303 dt_dev_pixelpipe_iop_t *source_piece = NULL;
2304 dt_dev_pixelpipe_iop_t *current_piece = NULL;
2305 GList *source_iter = NULL;
2306 for(source_iter = g_list_last(pipe->nodes); source_iter; source_iter = g_list_previous(source_iter))
2307 {
2308 dt_dev_pixelpipe_iop_t *candidate = (dt_dev_pixelpipe_iop_t *)source_iter->data;
2309 if(candidate->module == target_module)
2310 {
2311 current_piece = candidate;
2312 }
2313 else if(candidate->module == raster_mask_source)
2314 {
2315 source_piece = candidate;
2316 break;
2317 }
2318 }
2319
2320 int err_ret = !_dt_dev_raster_mask_check(source_piece, current_piece, target_module);
2321
2322 // Pass on the error to the returning pointer
2323 if(error) *error = err_ret;
2324
2325 if(!err_ret)
2326 {
2327 const uint64_t raster_hash = current_piece->global_mask_hash;
2328
2329 gchar *clean_source_name = delete_underscore(source_piece->module->name());
2330 gchar *source_name = g_strdup_printf("%s (%s)", clean_source_name, source_piece->module->multi_name);
2331 raster_mask = g_hash_table_lookup(source_piece->raster_masks, GINT_TO_POINTER(raster_mask_id));
2332
2333 // Print debug stuff
2334 if(raster_mask)
2335 {
2337 "[raster masks] found in %s mask id %i from %s (%s) for module %s (%s) in pipe %i with hash %" PRIu64 "\n",
2338 "internal",
2339 raster_mask_id, source_name, source_piece->module->multi_name, target_name, target_module->multi_name,
2340 pipe->type, raster_hash);
2341
2342 // Disable re-entry if any
2343 dt_dev_pixelpipe_unset_reentry(pipe, raster_hash);
2344 }
2345 else
2346 {
2347 fprintf(stderr,
2348 "[raster masks] mask id %i from %s for module %s could not be found in pipe %i. Pipe re-entry will be attempted.\n",
2349 raster_mask_id, source_name, target_name, pipe->type);
2350
2351 // Ask for a pipeline re-entry and flush all cache
2352 if(dt_dev_pixelpipe_set_reentry(pipe, raster_hash))
2353 pipe->flush_cache = TRUE;
2354
2355 // This should terminate the pipeline now:
2356 if(error) *error = 1;
2357
2358 g_free(clean_target_name);
2359 g_free(target_name);
2360 return NULL;
2361 }
2362
2363 // If we fetch the raster mask again, straight from its provider, we need to distort it
2364 for(GList *iter = g_list_next(source_iter); iter; iter = g_list_next(iter))
2365 {
2366 // Pass the raster mask through all distortion steps between the provider and the consumer
2367 dt_dev_pixelpipe_iop_t *module = (dt_dev_pixelpipe_iop_t *)iter->data;
2368
2369 if(module->enabled
2370 && !dt_dev_pixelpipe_activemodule_disables_currentmodule(module->module->dev, module->module))
2371 {
2372 if(module->module->distort_mask
2373 && !(!strcmp(module->module->op, "finalscale") // hack against pipes not using finalscale
2374 && module->processed_roi_in.width == 0
2375 && module->processed_roi_in.height == 0))
2376 {
2377 float *transformed_mask = dt_alloc_align_float((size_t)module->processed_roi_out.width
2378 * module->processed_roi_out.height);
2379 if(!transformed_mask)
2380 {
2381 fprintf(stderr, "[raster masks] could not allocate memory for transformed mask\n");
2382 if(error) *error = 1;
2383 g_free(clean_target_name);
2384 g_free(target_name);
2385 return NULL;
2386 }
2387
2388 module->module->distort_mask(module->module,
2389 module,
2390 raster_mask,
2391 transformed_mask,
2392 &module->processed_roi_in,
2393 &module->processed_roi_out);
2394 if(*free_mask) dt_free_align(raster_mask);
2395 *free_mask = TRUE;
2396 raster_mask = transformed_mask;
2397 fprintf(stdout, "doing transform\n");
2398 }
2399 else if(!module->module->distort_mask &&
2400 (module->processed_roi_in.width != module->processed_roi_out.width ||
2401 module->processed_roi_in.height != module->processed_roi_out.height ||
2402 module->processed_roi_in.x != module->processed_roi_out.x ||
2403 module->processed_roi_in.y != module->processed_roi_out.y))
2404 fprintf(stderr, "FIXME: module `%s' changed the roi from %d x %d @ %d / %d to %d x %d | %d / %d but doesn't have "
2405 "distort_mask() implemented!\n", module->module->op, module->processed_roi_in.width,
2406 module->processed_roi_in.height, module->processed_roi_in.x, module->processed_roi_in.y,
2407 module->processed_roi_out.width, module->processed_roi_out.height, module->processed_roi_out.x,
2408 module->processed_roi_out.y);
2409 }
2410
2411 if(module->module == target_module)
2412 {
2413 dt_print(DT_DEBUG_MASKS, "[raster masks] found mask id %i from %s for module %s (%s) in pipe %i\n",
2414 raster_mask_id, source_name, delete_underscore(module->module->name()),
2415 module->module->multi_name, pipe->type);
2416 break;
2417 }
2418 }
2419 }
2420
2421 g_free(clean_target_name);
2422 g_free(target_name);
2423 return raster_mask;
2424}
2425
2431
2432gboolean dt_dev_write_rawdetail_mask(dt_dev_pixelpipe_iop_t *piece, float *const rgb, const dt_iop_roi_t *const roi_in, const int mode)
2433{
2434 dt_dev_pixelpipe_t *p = piece->pipe;
2435 if((p->want_detail_mask & DT_DEV_DETAIL_MASK_REQUIRED) == 0)
2436 {
2437 if(p->rawdetail_mask_data)
2439 return FALSE;
2440 }
2441 if((p->want_detail_mask & ~DT_DEV_DETAIL_MASK_REQUIRED) != mode) return FALSE;
2442
2444
2445 const int width = roi_in->width;
2446 const int height = roi_in->height;
2447 float *mask = dt_alloc_align_float((size_t)width * height);
2448 float *tmp = dt_alloc_align_float((size_t)width * height);
2449 if((mask == NULL) || (tmp == NULL)) goto error;
2450
2451 p->rawdetail_mask_data = mask;
2452 memcpy(&p->rawdetail_mask_roi, roi_in, sizeof(dt_iop_roi_t));
2453
2454 dt_aligned_pixel_t wb = { piece->pipe->dsc.temperature.coeffs[0],
2455 piece->pipe->dsc.temperature.coeffs[1],
2456 piece->pipe->dsc.temperature.coeffs[2] };
2457 if((p->want_detail_mask & ~DT_DEV_DETAIL_MASK_REQUIRED) == DT_DEV_DETAIL_MASK_RAWPREPARE)
2458 {
2459 wb[0] = wb[1] = wb[2] = 1.0f;
2460 }
2461 dt_masks_calc_rawdetail_mask(rgb, mask, tmp, width, height, wb);
2462 dt_free_align(tmp);
2463 dt_print(DT_DEBUG_MASKS, "[dt_dev_write_rawdetail_mask] %i (%ix%i)\n", mode, roi_in->width, roi_in->height);
2464 return FALSE;
2465
2466 error:
2467 fprintf(stderr, "[dt_dev_write_rawdetail_mask] couldn't write detail mask\n");
2468 dt_free_align(mask);
2469 dt_free_align(tmp);
2470 return TRUE;
2471}
2472
2473#ifdef HAVE_OPENCL
2474gboolean dt_dev_write_rawdetail_mask_cl(dt_dev_pixelpipe_iop_t *piece, cl_mem in, const dt_iop_roi_t *const roi_in, const int mode)
2475{
2476 dt_dev_pixelpipe_t *p = piece->pipe;
2477 if((p->want_detail_mask & DT_DEV_DETAIL_MASK_REQUIRED) == 0)
2478 {
2479 if(p->rawdetail_mask_data)
2481 return FALSE;
2482 }
2483
2484 if((p->want_detail_mask & ~DT_DEV_DETAIL_MASK_REQUIRED) != mode) return FALSE;
2485
2487
2488 const int width = roi_in->width;
2489 const int height = roi_in->height;
2490
2491 cl_mem out = NULL;
2492 cl_mem tmp = NULL;
2493 float *mask = NULL;
2494 const int devid = p->devid;
2495
2496 cl_int err = CL_SUCCESS;
2498 if(mask == NULL) goto error;
2499 out = dt_opencl_alloc_device(devid, width, height, sizeof(float));
2500 if(out == NULL) goto error;
2501 tmp = dt_opencl_alloc_device_buffer(devid, sizeof(float) * width * height);
2502 if(tmp == NULL) goto error;
2503
2504 {
2505 const int kernel = darktable.opencl->blendop->kernel_calc_Y0_mask;
2506 dt_aligned_pixel_t wb = { piece->pipe->dsc.temperature.coeffs[0],
2507 piece->pipe->dsc.temperature.coeffs[1],
2508 piece->pipe->dsc.temperature.coeffs[2] };
2509 if((p->want_detail_mask & ~DT_DEV_DETAIL_MASK_REQUIRED) == DT_DEV_DETAIL_MASK_RAWPREPARE)
2510 {
2511 wb[0] = wb[1] = wb[2] = 1.0f;
2512 }
2513 size_t sizes[3] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid), 1 };
2514 dt_opencl_set_kernel_arg(devid, kernel, 0, sizeof(cl_mem), &tmp);
2515 dt_opencl_set_kernel_arg(devid, kernel, 1, sizeof(cl_mem), &in);
2516 dt_opencl_set_kernel_arg(devid, kernel, 2, sizeof(int), &width);
2517 dt_opencl_set_kernel_arg(devid, kernel, 3, sizeof(int), &height);
2518 dt_opencl_set_kernel_arg(devid, kernel, 4, sizeof(float), &wb[0]);
2519 dt_opencl_set_kernel_arg(devid, kernel, 5, sizeof(float), &wb[1]);
2520 dt_opencl_set_kernel_arg(devid, kernel, 6, sizeof(float), &wb[2]);
2521 err = dt_opencl_enqueue_kernel_2d(devid, kernel, sizes);
2522 if(err != CL_SUCCESS) goto error;
2523 }
2524 {
2525 size_t sizes[3] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid), 1 };
2526 const int kernel = darktable.opencl->blendop->kernel_write_scharr_mask;
2527 dt_opencl_set_kernel_arg(devid, kernel, 0, sizeof(cl_mem), &tmp);
2528 dt_opencl_set_kernel_arg(devid, kernel, 1, sizeof(cl_mem), &out);
2529 dt_opencl_set_kernel_arg(devid, kernel, 2, sizeof(int), &width);
2530 dt_opencl_set_kernel_arg(devid, kernel, 3, sizeof(int), &height);
2531 err = dt_opencl_enqueue_kernel_2d(devid, kernel, sizes);
2532 if(err != CL_SUCCESS) goto error;
2533 }
2534
2535 {
2536 err = dt_opencl_read_host_from_device(devid, mask, out, width, height, sizeof(float));
2537 if(err != CL_SUCCESS) goto error;
2538 }
2539
2540 p->rawdetail_mask_data = mask;
2541 memcpy(&p->rawdetail_mask_roi, roi_in, sizeof(dt_iop_roi_t));
2542
2545 dt_print(DT_DEBUG_MASKS, "[dt_dev_write_rawdetail_mask_cl] mode %i (%ix%i)", mode, roi_in->width, roi_in->height);
2546 return FALSE;
2547
2548 error:
2549 fprintf(stderr, "[dt_dev_write_rawdetail_mask_cl] couldn't write detail mask: %i\n", err);
2553 dt_free_align(mask);
2554 return TRUE;
2555}
2556#endif
2557
2558// this expects a mask prepared by the demosaicer and distorts the mask through all pipeline modules
2559// until target
2560float *dt_dev_distort_detail_mask(const dt_dev_pixelpipe_t *pipe, float *src, const dt_iop_module_t *target_module)
2561{
2562 if(!pipe->rawdetail_mask_data) return NULL;
2563 gboolean valid = FALSE;
2564 const int check = pipe->want_detail_mask & ~DT_DEV_DETAIL_MASK_REQUIRED;
2565
2566 GList *source_iter;
2567 for(source_iter = pipe->nodes; source_iter; source_iter = g_list_next(source_iter))
2568 {
2569 const dt_dev_pixelpipe_iop_t *candidate = (dt_dev_pixelpipe_iop_t *)source_iter->data;
2570 if(((!strcmp(candidate->module->op, "demosaic")) && candidate->enabled) && (check == DT_DEV_DETAIL_MASK_DEMOSAIC))
2571 {
2572 valid = TRUE;
2573 break;
2574 }
2575 if(((!strcmp(candidate->module->op, "rawprepare")) && candidate->enabled) && (check == DT_DEV_DETAIL_MASK_RAWPREPARE))
2576 {
2577 valid = TRUE;
2578 break;
2579 }
2580 }
2581
2582 if(!valid) return NULL;
2583 dt_vprint(DT_DEBUG_MASKS, "[dt_dev_distort_detail_mask] (%ix%i) for module %s\n", pipe->rawdetail_mask_roi.width, pipe->rawdetail_mask_roi.height, target_module->op);
2584
2585 float *resmask = src;
2586 float *inmask = src;
2587 if(source_iter)
2588 {
2589 for(GList *iter = source_iter; iter; iter = g_list_next(iter))
2590 {
2591 dt_dev_pixelpipe_iop_t *module = (dt_dev_pixelpipe_iop_t *)iter->data;
2592 if(module->enabled
2593 && !dt_dev_pixelpipe_activemodule_disables_currentmodule(module->module->dev, module->module))
2594 {
2595 if(module->module->distort_mask
2596 && !(!strcmp(module->module->op, "finalscale") // hack against pipes not using finalscale
2597 && module->processed_roi_in.width == 0
2598 && module->processed_roi_in.height == 0))
2599 {
2600 float *tmp = dt_alloc_align_float((size_t)module->processed_roi_out.width * module->processed_roi_out.height);
2601 dt_vprint(DT_DEBUG_MASKS, " %s %ix%i -> %ix%i\n", module->module->op, module->processed_roi_in.width, module->processed_roi_in.height, module->processed_roi_out.width, module->processed_roi_out.height);
2602 module->module->distort_mask(module->module, module, inmask, tmp, &module->processed_roi_in, &module->processed_roi_out);
2603 resmask = tmp;
2604 if(inmask != src) dt_free_align(inmask);
2605 inmask = tmp;
2606 }
2607 else if(!module->module->distort_mask &&
2608 (module->processed_roi_in.width != module->processed_roi_out.width ||
2609 module->processed_roi_in.height != module->processed_roi_out.height ||
2610 module->processed_roi_in.x != module->processed_roi_out.x ||
2611 module->processed_roi_in.y != module->processed_roi_out.y))
2612 fprintf(stderr, "FIXME: module `%s' changed the roi from %d x %d @ %d / %d to %d x %d | %d / %d but doesn't have "
2613 "distort_mask() implemented!\n", module->module->op, module->processed_roi_in.width,
2614 module->processed_roi_in.height, module->processed_roi_in.x, module->processed_roi_in.y,
2615 module->processed_roi_out.width, module->processed_roi_out.height, module->processed_roi_out.x,
2616 module->processed_roi_out.y);
2617
2618 if(module->module == target_module) break;
2619 }
2620 }
2621 }
2622 return resmask;
2623}
2624
2625// clang-format off
2626// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
2627// vim: shiftwidth=2 expandtab tabstop=2 cindent
2628// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
2629// clang-format on
static void error(char *msg)
Definition ashift_lsd.c:191
#define TRUE
Definition ashift_lsd.c:151
#define FALSE
Definition ashift_lsd.c:147
void dt_atomic_set_int(dt_atomic_int *var, int value)
Definition atomic.h:45
int dt_atomic_get_int(dt_atomic_int *var)
Definition atomic.h:46
int levels(struct dt_imageio_module_data_t *data)
Definition avif.c:685
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
int dt_develop_blend_process(struct dt_iop_module_t *self, struct dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid, const struct dt_iop_roi_t *const roi_in, const struct dt_iop_roi_t *const roi_out)
Definition blend.c:426
dt_iop_colorspace_type_t dt_develop_blend_colorspace(const dt_dev_pixelpipe_iop_t *const piece, dt_iop_colorspace_type_t cst)
Definition blend.c:134
void tiling_callback_blendop(struct dt_iop_module_t *self, struct dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out, struct dt_develop_tiling_t *tiling)
Definition blend.c:1363
@ DEVELOP_MASK_DISABLED
Definition blend.h:94
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
dt_iop_colorspace_type_t
Definition color_conversion.h:24
@ IOP_CS_RAW
Definition color_conversion.h:26
@ IOP_CS_LCH
Definition color_conversion.h:29
@ IOP_CS_JZCZHZ
Definition color_conversion.h:31
@ IOP_CS_RGB
Definition color_conversion.h:28
@ IOP_CS_HSL
Definition color_conversion.h:30
@ IOP_CS_LAB
Definition color_conversion.h:27
@ IOP_CS_NONE
Definition color_conversion.h:25
void dt_color_picker_helper(const dt_iop_buffer_dsc_t *dsc, const float *const pixel, const dt_iop_roi_t *roi, const int *const box, dt_aligned_pixel_t picked_color, dt_aligned_pixel_t picked_color_min, dt_aligned_pixel_t picked_color_max, const dt_iop_colorspace_type_t image_cst, const dt_iop_colorspace_type_t picker_cst, const dt_iop_order_iccprofile_info_t *const profile)
Definition color_picker.c:605
dt_iop_colorspace_type_t dt_iop_color_picker_get_active_cst(dt_iop_module_t *module)
Definition color_picker_proxy.c:246
static float kernel(const float *x, const float *y)
Definition colorchecker.c:435
@ DT_LIB_COLORPICKER_SIZE_POINT
Definition colorpicker.h:26
@ DT_LIB_COLORPICKER_SIZE_BOX
Definition colorpicker.h:27
dt_iop_color_intent_t
Definition colorspaces.h:43
@ DT_INTENT_LAST
Definition colorspaces.h:48
dt_colorspaces_color_profile_type_t
Definition colorspaces.h:61
@ DT_COLORSPACE_NONE
Definition colorspaces.h:62
void dt_histogram_max_helper(const dt_dev_histogram_stats_t *const histogram_stats, const dt_iop_colorspace_type_t cst, const dt_iop_colorspace_type_t cst_to, uint32_t **histogram, uint32_t *histogram_max)
Definition common/histogram.c:396
void dt_histogram_helper(dt_dev_histogram_collection_params_t *histogram_params, dt_dev_histogram_stats_t *histogram_stats, const dt_iop_colorspace_type_t cst, const dt_iop_colorspace_type_t cst_to, const void *pixel, uint32_t **histogram, const int compensate_middle_grey, const dt_iop_order_iccprofile_info_t *const profile_info)
Definition common/histogram.c:365
gboolean dt_image_is_rawprepare_supported(const dt_image_t *img)
Definition common/image.c:190
int dt_image_is_raw(const dt_image_t *img)
Definition common/image.c:120
char * name
Definition common/metadata.c:41
void dt_control_log(const char *msg,...)
Definition control.c:424
void dt_control_queue_redraw_widget(GtkWidget *widget)
threadsafe request of redraw of specific widget. Use this function if you need to redraw a specific w...
Definition control.c:550
void dt_vprint(dt_debug_thread_t thread, const char *msg,...)
Definition darktable.c:1440
void dt_show_times(const dt_times_t *start, const char *prefix)
Definition darktable.c:1453
darktable_t darktable
Definition darktable.c:111
void dt_print_mem_usage()
Definition darktable.c:1706
void dt_capabilities_remove(char *capability)
Definition darktable.c:1689
void dt_show_times_f(const dt_times_t *start, const char *prefix, const char *suffix,...)
Definition darktable.c:1467
void dt_print(dt_debug_thread_t thread, const char *msg,...)
Definition darktable.c:1415
#define UNKNOWN_IMAGE
Definition darktable.h:139
@ DT_DEBUG_OPENCL
Definition darktable.h:478
@ DT_DEBUG_PIPE
Definition darktable.h:497
@ DT_DEBUG_NAN
Definition darktable.h:482
@ DT_DEBUG_MEMORY
Definition darktable.h:480
@ DT_DEBUG_DEV
Definition darktable.h:474
@ DT_DEBUG_MASKS
Definition darktable.h:483
@ DT_DEBUG_TILING
Definition darktable.h:495
float dt_boundingbox_t[4]
Definition darktable.h:467
static float * dt_alloc_align_float(size_t pixels)
Definition darktable.h:345
#define dt_free_align_ptr
Definition darktable.h:335
static void dt_get_times(dt_times_t *t)
Definition darktable.h:693
static gchar * delete_underscore(const char *s)
Definition darktable.h:845
static uint64_t dt_hash(uint64_t hash, const char *str, size_t size)
Definition darktable.h:805
#define dt_free_align(A)
Definition darktable.h:334
#define DT_MAX_FILENAME_LEN
Definition darktable.h:814
int32_t dt_dev_get_history_end(struct dt_develop_t *dev)
Definition develop.c:1392
size_t dt_iop_buffer_dsc_to_bpp(const struct dt_iop_buffer_dsc_t *dsc)
Definition develop/format.c:22
@ TYPE_FLOAT
Definition develop/format.h:31
int dt_dev_distort_backtransform_plus(dt_develop_t *dev, dt_dev_pixelpipe_t *pipe, const double iop_order, const int transf_direction, float *points, size_t points_count)
Definition develop.c:1226
gchar * dt_history_item_get_name(const struct dt_iop_module_t *module)
Definition develop.c:1120
@ DT_DEV_PIXELPIPE_DISPLAY_NONE
Definition develop.h:81
@ DT_DEV_TRANSFORM_DIR_FORW_INCL
Definition develop.h:73
@ DT_DEV_TRANSFORM_DIR_FORW_EXCL
Definition develop.h:74
@ DT_DEV_DETAIL_MASK_DEMOSAIC
Definition develop.h:110
@ DT_DEV_DETAIL_MASK_REQUIRED
Definition develop.h:109
@ DT_DEV_DETAIL_MASK_RAWPREPARE
Definition develop.h:111
@ DT_DEV_DETAIL_MASK_NONE
Definition develop.h:108
static int dt_pthread_mutex_unlock(dt_pthread_mutex_t *mutex) RELEASE(mutex) NO_THREAD_SAFETY_ANALYSIS
Definition dtpthread.h:319
static int dt_pthread_mutex_init(dt_pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
Definition dtpthread.h:304
static int dt_pthread_mutex_destroy(dt_pthread_mutex_t *mutex)
Definition dtpthread.h:324
static int dt_pthread_mutex_lock(dt_pthread_mutex_t *mutex) ACQUIRE(mutex) NO_THREAD_SAFETY_ANALYSIS
Definition dtpthread.h:309
static float f(const float t, const float c, const float x)
Definition graduatednd.c:173
int bpp
Definition imageio/format/pdf.c:76
@ IMAGEIO_RGB
Definition imageio.h:55
@ IMAGEIO_INT8
Definition imageio.h:47
void dt_iop_commit_params(dt_iop_module_t *module, dt_iop_params_t *params, dt_develop_blend_params_t *blendop_params, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition imageop.c:1722
void dt_iop_init_pipe(struct dt_iop_module_t *module, struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece)
Definition imageop.c:442
void dt_iop_nap(int32_t usec)
Definition imageop.c:2431
@ DT_REQUEST_COLORPICK_OFF
Definition imageop.h:137
@ IOP_FLAGS_SUPPORTS_BLENDING
Definition imageop.h:108
@ IOP_TAG_DISTORT
Definition imageop.h:92
void dt_iop_clip_and_zoom(float *out, const float *const in, const dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in, const int32_t out_stride, const int32_t in_stride)
Definition imageop_math.c:134
GList * dt_ioppr_iop_order_copy_deep(GList *iop_order_list)
Definition iop_order.c:1444
__DT_CLONE_TARGETS__ void dt_ioppr_transform_image_colorspace(struct dt_iop_module_t *self, const float *const image_in, float *const image_out, const int width, const int height, const int cst_from, const int cst_to, int *converted_cst, const dt_iop_order_iccprofile_info_t *const profile_info)
Definition iop_profile.c:1017
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_current_profile_info(dt_iop_module_t *module, struct dt_dev_pixelpipe_t *pipe)
Definition iop_profile.c:902
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_work_profile_info(struct dt_dev_pixelpipe_t *pipe)
Definition iop_profile.c:887
GList * dt_masks_dup_forms_deep(GList *forms, dt_masks_form_t *form)
Definition develop/masks/masks.c:71
void dt_masks_free_form(dt_masks_form_t *form)
Definition develop/masks/masks.c:982
void dt_masks_calc_rawdetail_mask(float *const src, float *const out, float *const tmp, const int width, const int height, const dt_aligned_pixel_t wb)
size_t size
Definition mipmap_cache.c:3
#define dt_mipmap_cache_get(A, B, C, D, E, F)
Definition mipmap_cache.h:110
@ DT_MIPMAP_BLOCKING
Definition mipmap_cache.h:50
#define dt_mipmap_cache_release(A, B)
Definition mipmap_cache.h:132
dt_mipmap_size_t
Definition mipmap_cache.h:30
mask
Definition dtstyle_to_xmp.py:54
str p
Definition extract_wb.py:157
Definition tiling.py:1
static int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
Definition opencl.h:560
static size_t dt_opencl_get_device_available(const int devid)
Definition opencl.h:589
static int dt_opencl_set_kernel_arg(const int dev, const int kernel, const size_t size, const void *arg)
Definition opencl.h:556
static void dt_opencl_events_reset(const int devid)
Definition opencl.h:608
static void dt_opencl_unlock_device(const int dev)
Definition opencl.h:524
static int dt_opencl_update_settings(void)
Definition opencl.h:580
static void dt_opencl_check_tuning(const int devid)
Definition opencl.h:593
static int dt_opencl_is_inited(void)
Definition opencl.h:569
#define DT_OPENCL_MAX_ERRORS
Definition opencl.h:30
static int dt_opencl_lock_device(const int dev)
Definition opencl.h:520
static int dt_opencl_events_flush(const int devid, const int reset)
Definition opencl.h:614
static gboolean dt_opencl_image_fits_device(const int devid, const size_t width, const size_t height, const unsigned bpp, const float factor, const size_t overhead)
Definition opencl.h:584
static gboolean dt_opencl_finish(const int devid)
Definition opencl.h:512
static void dt_opencl_release_mem_object(void *mem)
Definition opencl.h:601
@ DT_REQUEST_ON
Definition pixelpipe.h:42
@ DT_REQUEST_ONLY_IN_GUI
Definition pixelpipe.h:43
@ DT_DEV_PIXELPIPE_THUMBNAIL
Definition pixelpipe.h:33
@ DT_DEV_PIXELPIPE_ANY
Definition pixelpipe.h:34
@ DT_DEV_PIXELPIPE_EXPORT
Definition pixelpipe.h:30
@ DT_DEV_PIXELPIPE_PREVIEW
Definition pixelpipe.h:32
@ DT_DEV_PIXELPIPE_FULL
Definition pixelpipe.h:31
int dt_dev_pixelpipe_cache_remove(dt_dev_pixelpipe_cache_t *cache, const uint64_t hash, const gboolean force, dt_pixel_cache_entry_t *cache_entry)
Arbitrarily remove the cache entry matching hash. Entries having a reference count > 0 (inter-thread ...
Definition pixelpipe_cache.c:113
void dt_dev_pixelpipe_cache_ref_count_entry(dt_dev_pixelpipe_cache_t *cache, const uint64_t hash, gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Increase/Decrease the reference count on the cache line as to prevent LRU item removal....
Definition pixelpipe_cache.c:483
void dt_dev_pixelpipe_cache_rdlock_entry(dt_dev_pixelpipe_cache_t *cache, const uint64_t hash, gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Lock or release the read lock on the entry.
Definition pixelpipe_cache.c:514
void dt_dev_pixelpipe_cache_wrlock_entry(dt_dev_pixelpipe_cache_t *cache, const uint64_t hash, gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Lock or release the write lock on the entry.
Definition pixelpipe_cache.c:492
void dt_dev_pixelpipe_cache_print(dt_dev_pixelpipe_cache_t *cache)
Definition pixelpipe_cache.c:564
void dt_dev_pixel_pipe_cache_auto_destroy_apply(dt_dev_pixelpipe_cache_t *cache, const uint64_t hash, const int id, dt_pixel_cache_entry_t *cache_entry)
Definition pixelpipe_cache.c:548
uint64_t dt_dev_pixelpipe_cache_get_hash_data(dt_dev_pixelpipe_cache_t *cache, void *data, dt_pixel_cache_entry_t **entry)
Find the hash of the cache entry holding the buffer data.
Definition pixelpipe_cache.c:435
void dt_dev_pixelpipe_cache_flag_auto_destroy(dt_dev_pixelpipe_cache_t *cache, uint64_t hash, dt_pixel_cache_entry_t *cache_entry)
Flag the cache entry matching hash as "auto_destroy". This is useful for short-lived/disposable cache...
Definition pixelpipe_cache.c:536
int dt_dev_pixelpipe_cache_get_existing(dt_dev_pixelpipe_cache_t *cache, const uint64_t hash, void **data, dt_iop_buffer_dsc_t **dsc, dt_pixel_cache_entry_t **entry)
Get an existing cache line from the cache. This is similar to dt_dev_pixelpipe_cache_get,...
Definition pixelpipe_cache.c:351
int dt_dev_pixelpipe_cache_get(dt_dev_pixelpipe_cache_t *cache, const uint64_t hash, const size_t size, const char *name, const int id, void **data, dt_iop_buffer_dsc_t **dsc, dt_pixel_cache_entry_t **entry)
Get a cache line from the cache.
Definition pixelpipe_cache.c:296
static uint64_t _node_hash(dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *roi_out, const int pos)
Definition pixelpipe_hb.c:412
void dt_dev_pixelpipe_disable_before(dt_dev_pixelpipe_t *pipe, const char *op)
Definition pixelpipe_hb.c:1933
int dt_dev_pixelpipe_init_preview(dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:160
void dt_dev_pixelpipe_set_input(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, int32_t imgid, int width, int height, dt_mipmap_size_t size)
Definition pixelpipe_hb.c:231
static void _sample_all(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, void *input, void **output, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out, dt_iop_buffer_dsc_t *input_format, dt_iop_buffer_dsc_t **output_format, dt_iop_module_t *module, dt_dev_pixelpipe_iop_t *piece, const uint64_t input_hash, const uint64_t hash, const size_t in_bpp, const size_t bpp, dt_pixel_cache_entry_t *const input_entry, dt_pixel_cache_entry_t *const output_entry)
Definition pixelpipe_hb.c:1640
static void collect_histogram_on_CPU(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, float *input, const dt_iop_roi_t *roi_in, dt_iop_buffer_dsc_t *input_format, dt_iop_module_t *module, dt_dev_pixelpipe_iop_t *piece)
Definition pixelpipe_hb.c:969
gboolean _commit_history_to_node(dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_dev_history_item_t *hist)
Definition pixelpipe_hb.c:498
void dt_dev_pixelpipe_reset_reentry(dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:315
static dt_iop_colorspace_type_t _transform_for_picker(dt_iop_module_t *self, const dt_iop_colorspace_type_t cst)
Definition pixelpipe_hb.c:944
int dt_dev_pixelpipe_init_cached(dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:181
void dt_dev_pixelpipe_get_roi_out(dt_dev_pixelpipe_t *pipe, struct dt_develop_t *dev, const int width_in, const int height_in, int *width, int *height)
Definition pixelpipe_hb.c:2129
gboolean dt_dev_pixelpipe_has_reentry(dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:310
float * dt_dev_distort_detail_mask(const dt_dev_pixelpipe_t *pipe, float *src, const dt_iop_module_t *target_module)
Definition pixelpipe_hb.c:2560
dt_pixelpipe_flow_t
Definition pixelpipe_hb.c:51
@ PIXELPIPE_FLOW_HISTOGRAM_ON_GPU
Definition pixelpipe_hb.c:55
@ PIXELPIPE_FLOW_HISTOGRAM_NONE
Definition pixelpipe_hb.c:53
@ PIXELPIPE_FLOW_PROCESSED_ON_CPU
Definition pixelpipe_hb.c:56
@ PIXELPIPE_FLOW_PROCESSED_WITH_TILING
Definition pixelpipe_hb.c:58
@ PIXELPIPE_FLOW_PROCESSED_ON_GPU
Definition pixelpipe_hb.c:57
@ PIXELPIPE_FLOW_NONE
Definition pixelpipe_hb.c:52
@ PIXELPIPE_FLOW_BLENDED_ON_CPU
Definition pixelpipe_hb.c:59
@ PIXELPIPE_FLOW_HISTOGRAM_ON_CPU
Definition pixelpipe_hb.c:54
@ PIXELPIPE_FLOW_BLENDED_ON_GPU
Definition pixelpipe_hb.c:60
void dt_dev_pixelpipe_synch_top(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev)
Definition pixelpipe_hb.c:593
gboolean dt_dev_write_rawdetail_mask(dt_dev_pixelpipe_iop_t *piece, float *const rgb, const dt_iop_roi_t *const roi_in, const int mode)
Definition pixelpipe_hb.c:2432
void dt_dev_pixelpipe_disable_after(dt_dev_pixelpipe_t *pipe, const char *op)
Definition pixelpipe_hb.c:1919
void dt_dev_pixelpipe_synch_all_real(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, const char *caller_func)
Find the last history item matching each pipeline node (module), in the order of pipeline execution....
Definition pixelpipe_hb.c:544
dt_backbuf_t * _get_backuf(dt_develop_t *dev, const char *op)
Definition pixelpipe_hb.c:739
static void pixelpipe_picker(dt_iop_module_t *module, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc, const float *pixel, const dt_iop_roi_t *roi, float *picked_color, float *picked_color_min, float *picked_color_max, const dt_iop_colorspace_type_t image_cst, dt_pixelpipe_picker_source_t picker_source)
Definition pixelpipe_hb.c:890
static void _print_perf_debug(dt_dev_pixelpipe_t *pipe, const dt_pixelpipe_flow_t pixelpipe_flow, dt_dev_pixelpipe_iop_t *piece, dt_iop_module_t *module, dt_times_t *start)
Definition pixelpipe_hb.c:1451
void dt_dev_pixelpipe_synch(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, GList *history)
Definition pixelpipe_hb.c:517
dt_pixelpipe_picker_source_t
Definition pixelpipe_hb.c:64
@ PIXELPIPE_PICKER_INPUT
Definition pixelpipe_hb.c:65
@ PIXELPIPE_PICKER_OUTPUT
Definition pixelpipe_hb.c:66
static gboolean _transform_for_blend(const dt_iop_module_t *const self, const dt_dev_pixelpipe_iop_t *const piece)
Definition pixelpipe_hb.c:930
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)
Checks the validity of the raster mask source and target modules, outputs errors if necessary....
Definition pixelpipe_hb.c:2215
static void _print_nan_debug(dt_dev_pixelpipe_t *pipe, void *cl_mem_output, void *output, const dt_iop_roi_t *roi_out, dt_iop_buffer_dsc_t *out_format, dt_iop_module_t *module, const size_t bpp)
Definition pixelpipe_hb.c:1480
#define KILL_SWITCH_ABORT
Definition pixelpipe_hb.c:1001
void dt_dev_pixelpipe_set_icc(dt_dev_pixelpipe_t *pipe, dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename, dt_iop_color_intent_t icc_intent)
Definition pixelpipe_hb.c:244
void dt_dev_pixelpipe_create_nodes(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev)
Definition pixelpipe_hb.c:352
static void _print_opencl_errors(int error, dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:1962
static dt_dev_pixelpipe_iop_t * _last_node_in_pipe(dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:1103
int dt_dev_pixelpipe_init_export(dt_dev_pixelpipe_t *pipe, int32_t width, int32_t height, int levels, gboolean store_masks)
Definition pixelpipe_hb.c:136
void dt_dev_pixelpipe_get_roi_in(dt_dev_pixelpipe_t *pipe, struct dt_develop_t *dev, const struct dt_iop_roi_t roi_out)
Definition pixelpipe_hb.c:2166
static int pixelpipe_process_on_CPU(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, float *input, dt_iop_buffer_dsc_t *input_format, const dt_iop_roi_t *roi_in, void **output, dt_iop_buffer_dsc_t **out_format, const dt_iop_roi_t *roi_out, dt_iop_module_t *module, dt_dev_pixelpipe_iop_t *piece, dt_develop_tiling_t *tiling, dt_pixelpipe_flow_t *pixelpipe_flow, dt_pixel_cache_entry_t *input_entry)
Definition pixelpipe_hb.c:1030
static int dt_dev_pixelpipe_process_rec(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, void **output, void **cl_mem_output, dt_iop_buffer_dsc_t **out_format, const dt_iop_roi_t *roi_out, GList *modules, GList *pieces, int pos)
Definition pixelpipe_hb.c:1672
int dt_dev_pixelpipe_init_dummy(dt_dev_pixelpipe_t *pipe, int32_t width, int32_t height)
Definition pixelpipe_hb.c:153
static void get_output_format(dt_iop_module_t *module, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_develop_t *dev, dt_iop_buffer_dsc_t *dsc)
Definition pixelpipe_hb.c:698
static char * _pipe_type_to_str(int pipe_type)
Definition pixelpipe_hb.c:74
static void _sample_color_picker(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, float *input, dt_iop_buffer_dsc_t *input_format, const dt_iop_roi_t *roi_in, void **output, dt_iop_buffer_dsc_t **out_format, const dt_iop_roi_t *roi_out, dt_iop_module_t *module, dt_dev_pixelpipe_iop_t *piece)
Definition pixelpipe_hb.c:1114
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, gboolean *free_mask, int *error)
Definition pixelpipe_hb.c:2281
static uint64_t _default_pipe_hash(dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:406
#define KILL_SWITCH_PIPE
Definition pixelpipe_hb.c:1947
void dt_dev_pixelpipe_cleanup(dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:253
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....
Definition pixelpipe_hb.c:297
static void histogram_collect(dt_dev_pixelpipe_iop_t *piece, const void *pixel, const dt_iop_roi_t *roi, uint32_t **histogram, uint32_t *histogram_max)
Definition pixelpipe_hb.c:715
static void _copy_buffer(const char *const restrict input, char *const restrict output, const size_t height, const size_t o_width, const size_t i_width, const size_t x_offset, const size_t y_offset, const size_t stride, const size_t bpp)
Definition pixelpipe_hb.c:98
gboolean dt_dev_pixelpipe_activemodule_disables_currentmodule(struct dt_develop_t *dev, struct dt_iop_module_t *current_module)
Definition pixelpipe_hb.c:2120
int dt_dev_pixelpipe_init_thumbnail(dt_dev_pixelpipe_t *pipe, int32_t width, int32_t height)
Definition pixelpipe_hb.c:146
int dt_dev_pixelpipe_init(dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:171
static void _uint8_to_float(const uint8_t *const input, float *const output, const size_t width, const size_t height, const size_t chan)
Definition pixelpipe_hb.c:115
#define KILL_SWITCH_AND_FLUSH_CACHE
Definition pixelpipe_hb.c:1016
static void pixelpipe_get_histogram_backbuf(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, void *output, const dt_iop_roi_t *roi, dt_iop_module_t *module, dt_dev_pixelpipe_iop_t *piece, const uint64_t hash, const size_t bpp)
Definition pixelpipe_hb.c:751
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. Re-entered pipelines run w...
Definition pixelpipe_hb.c:283
void dt_dev_pixelpipe_change(dt_dev_pixelpipe_t *pipe, struct dt_develop_t *dev)
Definition pixelpipe_hb.c:644
static int pixelpipe_picker_helper(dt_iop_module_t *module, const dt_iop_roi_t *roi, dt_aligned_pixel_t picked_color, dt_aligned_pixel_t picked_color_min, dt_aligned_pixel_t picked_color_max, dt_pixelpipe_picker_source_t picker_source, int *box)
Definition pixelpipe_hb.c:831
void dt_pixelpipe_get_global_hash(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev)
Definition pixelpipe_hb.c:430
static int _init_base_buffer(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, void **output, void **cl_mem_output, dt_iop_buffer_dsc_t **out_format, dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out, const uint64_t hash, const gboolean bypass_cache, const size_t bufsize, const size_t bpp)
Definition pixelpipe_hb.c:1551
void dt_dev_clear_rawdetail_mask(dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:2426
int dt_dev_pixelpipe_process(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, int x, int y, int width, int height, double scale)
Definition pixelpipe_hb.c:1981
void dt_dev_pixelpipe_cleanup_nodes(dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:323
dt_dev_pixelpipe_change_t
Definition pixelpipe_hb.h:102
@ DT_DEV_PIPE_SYNCH
Definition pixelpipe_hb.h:106
@ DT_DEV_PIPE_TOP_CHANGED
Definition pixelpipe_hb.h:104
@ DT_DEV_PIPE_REMOVE
Definition pixelpipe_hb.h:105
@ DT_DEV_PIPE_UNCHANGED
Definition pixelpipe_hb.h:103
#define dt_dev_pixelpipe_synch_all(pipe, dev)
Definition pixelpipe_hb.h:287
@ DT_DEV_PIXELPIPE_DIRTY
Definition pixelpipe_hb.h:113
void output_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
Definition rawprepare.c:274
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
Definition signal.h:276
@ DT_SIGNAL_CONTROL_PICKERDATA_READY
This signal is raised when new color picker data are available in the pixelpipe. 1 module 2 piece no ...
Definition signal.h:229
unsigned __int64 uint64_t
Definition strptime.c:71
struct dt_lib_t * lib
Definition darktable.h:537
struct dt_dev_pixelpipe_cache_t * pixelpipe_cache
Definition darktable.h:556
struct dt_mipmap_cache_t * mipmap_cache
Definition darktable.h:542
struct dt_control_signal_t * signals
Definition darktable.h:540
struct dt_opencl_t * opencl
Definition darktable.h:551
int32_t unmuted
Definition darktable.h:526
struct dt_develop_t * develop
Definition darktable.h:536
Definition develop.h:132
size_t height
Definition develop.h:135
uint64_t hash
Definition develop.h:136
size_t width
Definition develop.h:134
void * buffer
Definition develop.h:133
size_t bpp
Definition develop.h:138
Definition colorpicker.h:42
dt_lib_colorpicker_size_t size
Definition colorpicker.h:49
dt_boundingbox_t box
Definition colorpicker.h:48
float point[2]
Definition colorpicker.h:47
Definition pixelpipe.h:48
const struct dt_histogram_roi_t * roi
Definition pixelpipe.h:50
uint32_t bins_count
Definition pixelpipe.h:61
Definition dev_history.h:30
uint64_t hash
Definition dev_history.h:42
dt_iop_params_t * params
Definition dev_history.h:33
char multi_name[128]
Definition dev_history.h:38
struct dt_develop_blend_params_t * blend_params
Definition dev_history.h:34
struct dt_iop_module_t *gboolean enabled
Definition dev_history.h:31
Definition pixelpipe_hb.h:46
gboolean enabled
Definition pixelpipe_hb.h:62
uint32_t histogram_max[4]
Definition pixelpipe_hb.h:68
dt_dev_request_flags_t request_histogram
Definition pixelpipe_hb.h:64
uint64_t blendop_hash
Definition pixelpipe_hb.h:74
struct dt_iop_module_t *struct dt_dev_pixelpipe_t * pipe
Definition pixelpipe_hb.h:48
uint64_t global_hash
Definition pixelpipe_hb.h:78
uint64_t hash
Definition pixelpipe_hb.h:73
dt_iop_buffer_dsc_t dsc_in
Definition pixelpipe_hb.h:93
uint32_t * histogram
Definition pixelpipe_hb.h:66
dt_dev_histogram_stats_t histogram_stats
Definition pixelpipe_hb.h:67
uint64_t global_mask_hash
Definition pixelpipe_hb.h:81
dt_iop_roi_t planned_roi_out
Definition pixelpipe_hb.h:88
gboolean bypass_cache
Definition pixelpipe_hb.h:96
int process_tiling_ready
Definition pixelpipe_hb.h:90
GHashTable * raster_masks
Definition pixelpipe_hb.h:98
dt_dev_histogram_collection_params_t histogram_params
Definition pixelpipe_hb.h:65
void * data
Definition pixelpipe_hb.h:49
void * blendop_data
Definition pixelpipe_hb.h:61
dt_iop_roi_t planned_roi_in
Definition pixelpipe_hb.h:88
Definition pixelpipe_hb.h:126
dt_colorspaces_color_profile_type_t icc_type
Definition pixelpipe_hb.h:198
struct dt_iop_order_iccprofile_info_t * work_profile_info
Definition pixelpipe_hb.h:144
struct dt_iop_order_iccprofile_info_t * input_profile_info
Definition pixelpipe_hb.h:146
int iwidth
Definition pixelpipe_hb.h:132
int want_detail_mask
Definition pixelpipe_hb.h:169
float backbuf_zoom_x
Definition pixelpipe_hb.h:158
GList * iop
Definition pixelpipe_hb.h:202
int opencl_error
Definition pixelpipe_hb.h:181
struct dt_iop_order_iccprofile_info_t * output_profile_info
Definition pixelpipe_hb.h:148
int running
Definition pixelpipe_hb.h:175
uint64_t backbuf_hash
Definition pixelpipe_hb.h:159
gchar * icc_filename
Definition pixelpipe_hb.h:199
int processed_width
Definition pixelpipe_hb.h:135
dt_dev_pixelpipe_change_t changed
Definition pixelpipe_hb.h:153
uint64_t last_history_hash
Definition pixelpipe_hb.h:213
dt_pthread_mutex_t busy_mutex
Definition pixelpipe_hb.h:160
gboolean flush_cache
Definition pixelpipe_hb.h:231
int mask_display
Definition pixelpipe_hb.h:185
float backbuf_scale
Definition pixelpipe_hb.h:157
GList * nodes
Definition pixelpipe_hb.h:151
dt_dev_pixelpipe_status_t status
Definition pixelpipe_hb.h:141
dt_imageio_levels_t levels
Definition pixelpipe_hb.h:192
gboolean reentry
Definition pixelpipe_hb.h:219
dt_mipmap_size_t size
Definition pixelpipe_hb.h:129
dt_iop_color_intent_t icc_intent
Definition pixelpipe_hb.h:200
dt_image_t image
Definition pixelpipe_hb.h:196
float * rawdetail_mask_data
Definition pixelpipe_hb.h:167
dt_atomic_int shutdown
Definition pixelpipe_hb.h:177
int output_backbuf_width
Definition pixelpipe_hb.h:163
dt_iop_buffer_dsc_t dsc
Definition pixelpipe_hb.h:139
uint64_t reentry_hash
Definition pixelpipe_hb.h:225
int opencl_enabled
Definition pixelpipe_hb.h:179
float backbuf_zoom_y
Definition pixelpipe_hb.h:158
int output_backbuf_height
Definition pixelpipe_hb.h:163
uint8_t * output_backbuf
Definition pixelpipe_hb.h:162
dt_dev_pixelpipe_type_t type
Definition pixelpipe_hb.h:190
int processed_height
Definition pixelpipe_hb.h:135
int32_t imgid
Definition pixelpipe_hb.h:128
size_t backbuf_width
Definition pixelpipe_hb.h:156
gboolean store_all_raster_masks
Definition pixelpipe_hb.h:208
dt_pthread_mutex_t backbuf_mutex
Definition pixelpipe_hb.h:160
int bypass_blendif
Definition pixelpipe_hb.h:187
int tiling
Definition pixelpipe_hb.h:183
int iheight
Definition pixelpipe_hb.h:132
struct dt_iop_roi_t rawdetail_mask_roi
Definition pixelpipe_hb.h:168
GList * forms
Definition pixelpipe_hb.h:206
void * backbuf
Definition pixelpipe_hb.h:155
int devid
Definition pixelpipe_hb.h:194
int processing
Definition pixelpipe_hb.h:173
int output_imgid
Definition pixelpipe_hb.h:171
GList * iop_order_list
Definition pixelpipe_hb.h:204
size_t backbuf_height
Definition pixelpipe_hb.h:156
int input_timestamp
Definition pixelpipe_hb.h:189
Definition blend.h:180
uint32_t mask_mode
Definition blend.h:183
float details
Definition blend.h:209
Definition develop.h:143
int32_t gui_attached
Definition develop.h:144
GList * iop_order_list
Definition develop.h:179
dt_image_t image_storage
Definition develop.h:164
dt_backbuf_t display_histogram
Definition develop.h:209
GList * iop
Definition develop.h:173
dt_backbuf_t output_histogram
Definition develop.h:208
struct dt_iop_module_t * gui_module
Definition develop.h:150
struct dt_dev_pixelpipe_t * preview_pipe
Definition develop.h:156
GList * history
Definition develop.h:169
dt_pthread_mutex_t history_mutex
Definition develop.h:167
dt_backbuf_t raw_histogram
Definition develop.h:207
GList * forms
Definition develop.h:189
Definition tiling.h:30
float factor
Definition tiling.h:32
unsigned overhead
Definition tiling.h:40
float maxbuf
Definition tiling.h:36
Definition histogram.h:35
int width
Definition histogram.h:36
Definition common/image.h:195
dt_iop_buffer_dsc_t buf_dsc
Definition common/image.h:234
char filename[DT_MAX_FILENAME_LEN]
Definition common/image.h:218
Definition develop/format.h:36
int cst
Definition develop/format.h:62
unsigned int channels
Definition develop/format.h:38
dt_iop_buffer_type_t datatype
Definition develop/format.h:40
dt_aligned_pixel_t processed_maximum
Definition develop/format.h:59
Definition imageop.h:182
dt_dev_request_colorpick_flags_t request_color_pick
Definition imageop.h:200
dt_aligned_pixel_t picked_output_color_min
Definition imageop.h:212
GtkWidget * widget
Definition imageop.h:268
char multi_name[128]
Definition imageop.h:294
struct dt_develop_t * dev
Definition imageop.h:227
GModule *dt_dev_operation_t op
Definition imageop.h:192
dt_dev_request_flags_t request_histogram
Definition imageop.h:202
int iop_order
Definition imageop.h:196
dt_aligned_pixel_t picked_output_color_max
Definition imageop.h:212
uint32_t histogram_max[4]
Definition imageop.h:218
dt_aligned_pixel_t picked_output_color
Definition imageop.h:212
gboolean enabled
Definition imageop.h:229
dt_aligned_pixel_t picked_color_min
Definition imageop.h:210
dt_aligned_pixel_t picked_color_max
Definition imageop.h:210
uint32_t * histogram
Definition imageop.h:214
dt_aligned_pixel_t picked_color
Definition imageop.h:210
Definition iop_profile.h:41
Definition imageop.h:32
int x
Definition imageop.h:33
double scale
Definition imageop.h:34
int width
Definition imageop.h:33
int height
Definition imageop.h:33
int y
Definition imageop.h:33
struct dt_iop_color_picker_t * picker_proxy
Definition libs/lib.h:54
struct dt_lib_module_t *struct dt_colorpicker_sample_t * primary_sample
Definition libs/lib.h:53
struct dt_lib_t::@51 proxy
struct dt_lib_t::@51::@52 colorpicker
Definition mipmap_cache.h:58
int32_t height
Definition mipmap_cache.h:61
uint8_t * buf
Definition mipmap_cache.h:63
int32_t width
Definition mipmap_cache.h:61
int error_count
Definition opencl.h:498
int stopped
Definition opencl.h:497
Definition pixelpipe_cache.c:30
Definition darktable.h:605
#define dt_alloc_align(B)
Definition tests/cache.c:22
#define MIN(a, b)
Definition thinplate.c:23
#define MAX(a, b)
Definition thinplate.c:20
int dt_tiling_piece_fits_host_memory(const size_t width, const size_t height, const unsigned bpp, const float factor, const size_t overhead)
Definition tiling.c:2045