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