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