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