Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
darktable.h
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2009-2012 johannes hanika.
4 Copyright (C) 2010-2011 Henrik Andersson.
5 Copyright (C) 2010, 2012 Pascal de Bruijn.
6 Copyright (C) 2010 Richard Hughes.
7 Copyright (C) 2010-2020 Tobias Ellinghaus.
8 Copyright (C) 2011, 2014-2015 Bruce Guenter.
9 Copyright (C) 2011-2013, 2017 Ulrich Pegelow.
10 Copyright (C) 2012 Ammon Riley.
11 Copyright (C) 2012 Christian Himpel.
12 Copyright (C) 2012 Christian Tellefsen.
13 Copyright (C) 2012 James C. McPherson.
14 Copyright (C) 2012 Jean-Sébastien Pédron.
15 Copyright (C) 2012-2014 Jérémy Rosen.
16 Copyright (C) 2012 Moritz Lipp.
17 Copyright (C) 2012 Richard Wonka.
18 Copyright (C) 2012 Simon Spannagel.
19 Copyright (C) 2013, 2021 Aldric Renaudin.
20 Copyright (C) 2013, 2015, 2019-2021 Pascal Obry.
21 Copyright (C) 2013-2017 Roman Lebedev.
22 Copyright (C) 2014-2015 Pedro Côrte-Real.
23 Copyright (C) 2015 Matthias Gehre.
24 Copyright (C) 2016-2019 Peter Budai.
25 Copyright (C) 2016 Stuart Henderson.
26 Copyright (C) 2018-2020, 2022-2026 Aurélien PIERRE.
27 Copyright (C) 2018-2019 Edgardo Hoszowski.
28 Copyright (C) 2018 parafin.
29 Copyright (C) 2018 rawfiner.
30 Copyright (C) 2019-2020 Andreas Schneider.
31 Copyright (C) 2019-2022 Hanno Schwalm.
32 Copyright (C) 2019 Heiko Bauke.
33 Copyright (C) 2020 David-Tillmann Schaefer.
34 Copyright (C) 2020-2021 Diederik Ter Rahe.
35 Copyright (C) 2020-2021 Hubert Kowalski.
36 Copyright (C) 2020-2021 Ralf Brown.
37 Copyright (C) 2021 Hubert Figuière.
38 Copyright (C) 2021 Paolo DePetrillo.
39 Copyright (C) 2021 Robert Bridge.
40 Copyright (C) 2021 Roman Khatko.
41 Copyright (C) 2022 Martin Bařinka.
42 Copyright (C) 2022 Philippe Weyland.
43 Copyright (C) 2023-2025 Alynx Zhou.
44 Copyright (C) 2023 lologor.
45 Copyright (C) 2023 Luca Zulberti.
46
47 darktable is free software: you can redistribute it and/or modify
48 it under the terms of the GNU General Public License as published by
49 the Free Software Foundation, either version 3 of the License, or
50 (at your option) any later version.
51
52 darktable is distributed in the hope that it will be useful,
53 but WITHOUT ANY WARRANTY; without even the implied warranty of
54 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
55 GNU General Public License for more details.
56
57 You should have received a copy of the GNU General Public License
58 along with darktable. If not, see <http://www.gnu.org/licenses/>.
59*/
60
61#pragma once
62
63
64// just to be sure. the build system should set this for us already:
65#if defined __DragonFly__ || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__
66#define _WITH_DPRINTF
67#define _WITH_GETLINE
68#elif !defined _XOPEN_SOURCE && !defined _WIN32
69#define _XOPEN_SOURCE 700 // for localtime_r and dprintf
70#endif
71
72// needs to be defined before any system header includes for control/conf.h to work in C++ code
73#define __STDC_FORMAT_MACROS
74
75#if !defined(O_BINARY)
76// To have portable g_open() on *nix and on Windows
77#define O_BINARY 0
78#endif
79
80#include "external/ThreadSafetyAnalysis.h"
81
82#ifdef HAVE_CONFIG_H
83#include "config.h"
84#endif
85#include "common/database.h"
86#include "common/fp_mode.h"
87#include "common/dtpthread.h"
88#include "common/utility.h"
89#ifdef _WIN32
90#include "win/getrusage.h"
91#else
92#include <sys/resource.h>
93#endif
94#include <stdint.h>
95#include <glib.h>
96#include <glib/gstdio.h>
97#include <glib/gi18n.h>
98#include <inttypes.h>
99#include <json-glib/json-glib.h>
100#include <math.h>
101#include <sqlite3.h>
102#include <stdio.h>
103#include <sys/time.h>
104#include <sys/types.h>
105#include <unistd.h>
106
107#ifndef _RELEASE
108#include "common/poison.h"
109#endif
110
112
113// for signal debugging symbols
114#include "control/signal.h"
115
116#ifdef __cplusplus
117extern "C" {
118#endif
119
120#define DT_MODULE_VERSION 23 // version of dt's module interface
121
122// version of current performance configuration version
123// if you want to run an updated version of the performance configuration later
124// bump this number and make sure you have an updated logic in dt_configure_performance()
125#define DT_CURRENT_PERFORMANCE_CONFIGURE_VERSION 11
126#define DT_PERF_INFOSIZE 4096
127
128// every module has to define this:
129#ifdef _DEBUG
130#define DT_MODULE(MODVER) \
131 int dt_module_dt_version() \
132 { \
133 return -DT_MODULE_VERSION; \
134 } \
135 int dt_module_mod_version() \
136 { \
137 return MODVER; \
138 }
139#else
140#define DT_MODULE(MODVER) \
141 int dt_module_dt_version() \
142 { \
143 return DT_MODULE_VERSION; \
144 } \
145 int dt_module_mod_version() \
146 { \
147 return MODVER; \
148 }
149#endif
150
151#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE) DT_MODULE(MODVER)
152
153// ..to be able to compare it against this:
154static inline int dt_version()
155{
156#ifdef _DEBUG
157 return -DT_MODULE_VERSION;
158#else
159 return DT_MODULE_VERSION;
160#endif
161}
162
163// returns the darktable version as <major>.<minor>
165
170const char *dt_session_id(void);
171
176const char *dt_install_id(void);
177
178#undef STR_HELPER
179#define STR_HELPER(x) #x
180
181#undef STR
182#define STR(x) STR_HELPER(x)
183
184#define DT_IMAGE_DBLOCKS 64
185
186// When included by a C++ file, restrict qualifiers are not allowed
187#ifdef __cplusplus
188#define DT_RESTRICT
189#else
190#define DT_RESTRICT restrict
191#endif
192
193// Default code for imgid meaning the picture is unknown or invalid
194#define UNKNOWN_IMAGE -1
195
196#ifdef __cplusplus
197}
198#endif
199
200/********************************* */
201
208#if defined _WIN32
209#include "win/win.h"
210#endif
211
212#ifdef __APPLE__
213#include <mach/mach.h>
214#include <sys/sysctl.h>
215#endif
216
217#if defined(__DragonFly__) || defined(__FreeBSD__)
218typedef unsigned int u_int;
219#include <sys/sysctl.h>
220#include <sys/types.h>
221#endif
222#if defined(__NetBSD__) || defined(__OpenBSD__)
223#include <sys/param.h>
224#include <sys/sysctl.h>
225#endif
226
227#if defined(__aarch64__)
228#include <arm_neon.h>
229#endif
230
231#if defined(__x86_64__) || defined(__i386__)
232#include <xmmintrin.h> // needed for _mm_stream_ps
233#endif
234
235#ifdef _OPENMP
236# include <omp.h>
237
238#ifndef dt_omp_nontemporal
239// Clang 10+ supports the nontemporal() OpenMP directive
240// GCC 9 recognizes it as valid, but does not do anything with it
241// GCC 10+ ???
242#if (__clang__+0 >= 10 || __GNUC__ >= 9)
243# define dt_omp_nontemporal(...) nontemporal(__VA_ARGS__)
244#else
245// GCC7/8 only support OpenMP 4.5, which does not have the nontemporal() directive.
246# define dt_omp_nontemporal(var, ...)
247#endif
248#endif /* dt_omp_nontemporal */
249
250#define OMP_PRAGMA(x) _Pragma(#x)
251#define __OMP_PARALLEL__(...) OMP_PRAGMA(omp parallel default(firstprivate) __VA_ARGS__)
252#define __OMP_PARALLEL_FOR__(...) OMP_PRAGMA(omp parallel for default(firstprivate) schedule(static) __VA_ARGS__)
253#define __OMP_PARALLEL_FOR_SIMD__(...) OMP_PRAGMA(omp parallel for simd default(firstprivate) schedule(simd:static) __VA_ARGS__)
254#define __OMP_FOR_SIMD__(...) OMP_PRAGMA(omp for simd schedule(simd:static) __VA_ARGS__)
255#define __OMP_FOR__(...) OMP_PRAGMA(omp for schedule(static) __VA_ARGS__)
256#define __OMP_SIMD__(...) OMP_PRAGMA(omp simd __VA_ARGS__)
257#define __OMP_DECLARE_SIMD__(...) OMP_PRAGMA(omp declare simd __VA_ARGS__)
258
259// CLang 20 supports OpenMP 5.1 default(firstprivate) but only for C files.
260// C++ files still need to use default(none) until further notice.
261// Change that when baseline CLang is upgraded.
262#define __OMP_PARALLEL_FOR_CPP__(...) OMP_PRAGMA(omp parallel for default(none) schedule(static) __VA_ARGS__)
263
264#else /* _OPENMP */
265
266# define omp_get_max_threads() 1
267# define omp_get_thread_num() 0
268
269#define __OMP_PARALLEL__(...)
270#define __OMP_PARALLEL_FOR__(...)
271#define __OMP_PARALLEL_FOR_SIMD__(...)
272#define __OMP_FOR_SIMD__(...)
273#define __OMP_FOR__(...)
274#define __OMP_SIMD__(...)
275#define __OMP_DECLARE_SIMD__(...)
276
277#define __OMP_PARALLEL_FOR_CPP__(...)
278
279#endif /* _OPENMP */
280
281#ifdef __cplusplus
282extern "C" {
283#endif
284
293#define IS_NULL_PTR(p) \
294 ({ \
295 __typeof__(p) _tmp = (p); \
296 (void)sizeof(char[ \
297 (__builtin_classify_type(_tmp) == 5) ? 1 : -1 \
298 ]); \
299 _tmp == NULL; \
300 })
301
302
303static inline int dt_get_thread_num()
304{
305#ifdef _OPENMP
306 return omp_get_thread_num();
307#else
308 return 0;
309#endif
310}
311
312/* Create cloned functions for various CPU SSE generations */
313/* See for instructions https://hannes.hauswedell.net/post/2017/12/09/fmv/ */
314/* TL;DR : use only on SIMD functions containing low-level paralellized/vectorized loops */
315#if __has_attribute(target_clones) && !defined(_WIN32) && !defined(NATIVE_ARCH) && !defined(_DEBUG)
316
317 /*
318 * Apple note:
319 * - arm64 vs x86_64 is handled by the universal binary, not target_clones.
320 * - target_clones on Apple is only useful within one slice.
321 * - the x86-64-v2/v3/v4 strings are not accepted by all Apple Clang versions.
322 *
323 * Therefore:
324 * - on Apple arm64: disable clones here,
325 * - on Apple x86_64: require explicit opt-in once the toolchain is validated.
326 */
327
328 #if defined(__APPLE__)
329
330 #if defined(__aarch64__) || defined(__arm64__)
331 #define __DT_CLONE_TARGETS__
332
333 #elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
334
335 /*
336 * Enable this from your build system only after verifying that the local
337 * Apple Clang accepts:
338 * target_clones("default","arch=x86-64","arch=x86-64-v2","arch=x86-64-v3","arch=x86-64-v4")
339 *
340 * Example:
341 * -DDT_APPLE_X86_TARGET_CLONES=1
342 */
343 #if defined(DT_APPLE_X86_TARGET_CLONES)
344 #define __DT_CLONE_TARGETS__ \
345 __attribute__((target_clones( \
346 "default", \
347 "arch=x86-64", \
348 "arch=x86-64-v2", \
349 "arch=x86-64-v3", \
350 "arch=x86-64-v4" \
351 )))
352 #else
353 #define __DT_CLONE_TARGETS__
354 #endif
355
356 #else
357 #define __DT_CLONE_TARGETS__
358 #endif
359
360 #elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
361 #define __DT_CLONE_TARGETS__ \
362 __attribute__((target_clones( \
363 "default", \
364 "arch=x86-64", \
365 "arch=x86-64-v2", \
366 "arch=x86-64-v3", \
367 "arch=x86-64-v4" \
368 )))
369
370 #elif defined(__PPC64__)
371 /* __PPC64__ is the only macro tested for in is_supported_platform.h, other macros would fail there anyway. */
372 #define __DT_CLONE_TARGETS__ __attribute__((target_clones("default","cpu=power9")))
373
374 #else
375 #define __DT_CLONE_TARGETS__
376 #endif
377
378#else
379 #define __DT_CLONE_TARGETS__
380#endif
381
382/* Helper to force stack vectors to be aligned on DT_CACHELINE_BYTES blocks to enable AVX2 */
383#define DT_IS_ALIGNED(x) __builtin_assume_aligned(x, DT_CACHELINE_BYTES)
384
385// Configure the size of a CPU cacheline in bytes, floats, and pixels. On most current architectures,
386// a cacheline contains 64 bytes, but Apple Silicon (M-series processors) uses 128-byte cache lines.
387#if defined(__APPLE__) && defined(__aarch64__)
388 #define DT_CACHELINE_BYTES 128
389 #define DT_CACHELINE_FLOATS 32
390 #define DT_CACHELINE_PIXELS 8
391#else
392 #define DT_CACHELINE_BYTES 64
393 #define DT_CACHELINE_FLOATS 16
394 #define DT_CACHELINE_PIXELS 4
395#endif /* __APPLE__ && __aarch64__ */
396
397// Helper to force heap vectors to be aligned on 64 byte blocks to enable AVX2
398// If this is applied to a struct member and the struct is allocated on the heap, then it must be allocated
399// on a 64 byte boundary to avoid crashes or undefined behavior because of unaligned memory access.
400#define DT_ALIGNED_ARRAY __attribute__((aligned(DT_CACHELINE_BYTES)))
401#define DT_ALIGNED_PIXEL __attribute__((aligned(16)))
402
403
404static inline gboolean dt_is_aligned(const void *pointer, size_t byte_count)
405{
406 return (uintptr_t)pointer % byte_count == 0;
407}
408
409static inline size_t dt_round_size(const size_t size, const size_t alignment)
410{
411 // Round the size of a buffer to the closest higher multiple
412 return ((size % alignment) == 0) ? size : ((size - 1) / alignment + 1) * alignment;
413}
414
415static inline size_t dt_round_size_sse(const size_t size)
416{
417 // Round the size of a buffer to the closest 64 higher multiple
418 return dt_round_size(size, 64);
419}
420
421static inline void *dt_alloc_align_internal(size_t size)
422{
423 const size_t alignment = DT_CACHELINE_BYTES;
424 const size_t aligned_size = dt_round_size(size, alignment);
425#if defined(__FreeBSD_version) && __FreeBSD_version < 700013
426 return malloc(aligned_size);
427#elif defined(_WIN32)
428 return _aligned_malloc(aligned_size, alignment);
429#else
430 void *ptr = NULL;
431 if(posix_memalign(&ptr, alignment, aligned_size)) return NULL;
432 return ptr;
433#endif
434}
435
436void *dt_alloc_align(size_t size);
437
439
440#define DT_STRINGIFY_HELPER(x) #x
441#define DT_STRINGIFY(x) DT_STRINGIFY_HELPER(x)
442
444 const char *name);
445#define dt_pixelpipe_cache_alloc_align_cache(size, id) \
446 dt_pixelpipe_cache_alloc_align_cache_impl(darktable.pixelpipe_cache, (size), (id), __FILE__ ":" DT_STRINGIFY(__LINE__))
447
448#ifndef dt_pixelpipe_cache_alloc_align
449#define dt_pixelpipe_cache_alloc_align(size, pipe) \
450 dt_pixelpipe_cache_alloc_align_cache((size), (pipe)->type)
451#endif
452
453#ifndef dt_pixelpipe_cache_alloc_align_float
454#define dt_pixelpipe_cache_alloc_align_float(pixels, pipe) \
455 ((float *)dt_pixelpipe_cache_alloc_align((size_t)(pixels) * sizeof(float), (pipe)))
456#endif
457
458#ifndef dt_pixelpipe_cache_alloc_align_float_cache
459#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id) \
460 ((float *)dt_pixelpipe_cache_alloc_align_cache((size_t)(pixels) * sizeof(float), (id)))
461#endif
462
463#ifndef dt_pixelpipe_cache_alloc_align_int
464#define dt_pixelpipe_cache_alloc_align_int(count, pipe) \
465 ((int *)dt_pixelpipe_cache_alloc_align((size_t)(count) * sizeof(int), (pipe)))
466#endif
467
468#ifndef dt_pixelpipe_cache_alloc_align_double
469#define dt_pixelpipe_cache_alloc_align_double(count, pipe) \
470 ((double *)dt_pixelpipe_cache_alloc_align((size_t)(count) * sizeof(double), (pipe)))
471#endif
472
473void dt_pixelpipe_cache_free_align_cache(struct dt_dev_pixelpipe_cache_t *cache, void **mem, const char *message);
474
475#define dt_pixelpipe_cache_free_align(mem) \
476 dt_pixelpipe_cache_free_align_cache(darktable.pixelpipe_cache, (void **)&(mem), __FILE__ ":" DT_STRINGIFY(__LINE__));
477
478#define dt_free(ptr) \
479 if(!IS_NULL_PTR(ptr)) \
480 { \
481 g_free((void *)(ptr)); \
482 *(void **)(&(ptr)) = NULL; \
483 }
484
485static inline void dt_free_gpointer(gpointer ptr)
486{
487 g_free(ptr);
488 ptr = NULL;
489}
490
491#ifdef _WIN32
492 static inline void dt_free_align_ptr(void *mem)
493 {
494 _aligned_free(mem);
495 }
496#else
497 static inline void dt_free_align_ptr(void *mem)
498 {
499 dt_free(mem);
500 }
501#endif
502
503#define dt_free_align(ptr) \
504 if(!IS_NULL_PTR(ptr)) \
505 { \
506 dt_free_align_ptr((void *)(ptr)); \
507 *(void **)(&(ptr)) = NULL; \
508 }
509
510static inline void* dt_calloc_align(size_t size)
511{
512 void *buf = dt_alloc_align(size);
513 if(buf) memset(buf, 0, size);
514 return buf;
515}
516static inline float *dt_alloc_align_float(size_t pixels)
517{
518 return (float*)__builtin_assume_aligned(dt_alloc_align(pixels * sizeof(float)), DT_CACHELINE_BYTES);
519}
520static inline float *dt_calloc_align_float(size_t pixels)
521{
522 float *const buf = (float*)dt_alloc_align(pixels * sizeof(float));
523 if(buf) memset(buf, 0, pixels * sizeof(float));
524 return (float*)__builtin_assume_aligned(buf, DT_CACHELINE_BYTES);
525}
526static inline void * dt_check_sse_aligned(void * pointer)
527{
529 return __builtin_assume_aligned(pointer, DT_CACHELINE_BYTES);
530 else
531 return NULL;
532}
533
534// Most code in dt assumes that the compiler is capable of auto-vectorization. In some cases, this will yield
535// suboptimal code if the compiler in fact does NOT auto-vectorize. Uncomment the following line for such a
536// compiler.
537//#define DT_NO_VECTORIZATION
538
539// For some combinations of compiler and architecture, the compiler may actually emit inferior code if given
540// a hint to vectorize a loop. Uncomment the following line if such a combination is the compilation target.
541//#define DT_NO_SIMD_HINTS
542
543// utility type to ease declaration of aligned small arrays to hold a pixel (and document their purpose)
545// SIMD view matching dt_aligned_pixel_t layout, for explicit 4-float vector math.
546typedef float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)));
547
548static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t dt_simd_set1(const float value)
549{
550 return (dt_aligned_pixel_simd_t){ value, value, value, value };
551}
552
553static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
554dt_simd_abs(const dt_aligned_pixel_simd_t value)
555{
556 dt_aligned_pixel_simd_t out = value;
557 for(int c = 0; c < 4; c++)
558 out[c] = fabsf(value[c]);
559 return out;
560}
561
562static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
563dt_simd_max_zero(const dt_aligned_pixel_simd_t value)
564{
565 dt_aligned_pixel_simd_t out = value;
566 for(int c = 0; c < 4; c++)
567 out[c] = (isfinite(value[c])) ? MAX(value[c], 0.0f) : 0.f;
568 return out;
569}
570
571static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
572dt_simd_copysign(const dt_aligned_pixel_simd_t magnitude, const dt_aligned_pixel_simd_t sign)
573{
574 dt_aligned_pixel_simd_t out = magnitude;
575 for(int c = 0; c < 4; c++)
576 out[c] = copysignf(magnitude[c], sign[c]);
577 return out;
578}
579
580static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
581dt_simd_pow(const dt_aligned_pixel_simd_t base, const dt_aligned_pixel_simd_t exponent)
582{
583 dt_aligned_pixel_simd_t out = base;
584 for(int c = 0; c < 4; c++)
585 out[c] = powf(base[c], exponent[c]);
586 return out;
587}
588
589static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
590dt_load_simd(const float *const pixel)
591{
592 dt_aligned_pixel_simd_t out;
593 __builtin_memcpy(&out, pixel, sizeof(out));
594 return out;
595}
596
597static inline __attribute__((always_inline)) void
598dt_store_simd(float *const pixel, const dt_aligned_pixel_simd_t value)
599{
600 __builtin_memcpy(pixel, &value, sizeof(value));
601}
602
603static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
604dt_load_simd_aligned(const float *const pixel)
605{
606 const float *const in = (const float *const)__builtin_assume_aligned(pixel, 16);
607 return dt_load_simd(in);
608}
609
610static inline __attribute__((always_inline)) void
611dt_store_simd_aligned(float *const pixel, const dt_aligned_pixel_simd_t value)
612{
613 float *const out = (float *const)__builtin_assume_aligned(pixel, 16);
615}
616
617static inline __attribute__((always_inline)) void
618dt_store_simd_nontemporal(float *const pixel, const dt_aligned_pixel_simd_t value)
619{
620 float *const out = (float *const)__builtin_assume_aligned(pixel, 16);
621
622#if defined(__x86_64__) || defined(__i386__)
623 const union
624 {
625 dt_aligned_pixel_simd_t simd;
626 __m128 sse;
627 } cast = { .simd = value };
628 _mm_stream_ps(out, cast.sse);
629#elif defined(__aarch64__)
630 const union
631 {
632 dt_aligned_pixel_simd_t simd;
633 float32x4_t neon;
634 } cast = { .simd = value };
635 vst1q_f32(out, cast.neon);
636#elif (__clang__+0 > 7) && (__clang__+0 < 10)
637 for_each_channel(k,aligned(out:16)) __builtin_nontemporal_store(value[k], out[k]);
638#else
639 for_each_channel(k,aligned(out:16) dt_omp_nontemporal(out)) out[k] = value[k];
640#endif
641}
642
643static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
644dt_mat3x4_mul_vec4(const dt_aligned_pixel_simd_t in, const dt_aligned_pixel_simd_t row0,
645 const dt_aligned_pixel_simd_t row1, const dt_aligned_pixel_simd_t row2)
646{
647 // Keep the multiply first in each accumulation step so GCC contracts this
648 // into chained FMA instructions in the multiversioned FMA clones too.
649 dt_aligned_pixel_simd_t out = row0 * in[0];
650 out = row1 * in[1] + out;
651 return row2 * in[2] + out;
652}
653
654// To be able to vectorize per-pixel loops, we need to operate on all four channels, but if the compiler does
655// not auto-vectorize, doing so increases computation by 1/3 for a channel which typically is ignored anyway.
656// Select the appropriate number of channels over which to loop to produce the fastest code.
657#ifdef DT_NO_VECTORIZATION
658#define DT_PIXEL_SIMD_CHANNELS 3
659#else
660#define DT_PIXEL_SIMD_CHANNELS 4
661#endif
662
663// A macro which gives us a configurable shorthand to produce the optimal performance when processing all of the
664// channels in a pixel. Its first argument is the name of the variable to be used inside the 'for' loop it creates,
665// while the optional second argument is a set of OpenMP directives, typically specifying variable alignment.
666// If indexing off of the begining of any buffer allocated with dt's image or aligned allocation functions, the
667// alignment to specify is 64; otherwise, use 16, as there may have been an odd number of pixels from the start.
668// Sample usage:
669// for_each_channel(k,aligned(src,dest:16))
670// {
671// src[k] = dest[k] / 3.0f;
672// }
673#if defined(_OPENMP) && defined(OPENMP_SIMD_) && !defined(DT_NO_SIMD_HINTS)
674//https://stackoverflow.com/questions/45762357/how-to-concatenate-strings-in-the-arguments-of-pragma
675#define _DT_Pragma_(x) _Pragma(#x)
676#define _DT_Pragma(x) _DT_Pragma_(x)
677#define for_each_channel(_var, ...) \
678 _DT_Pragma(omp simd __VA_ARGS__) \
679 for (size_t _var = 0; _var < DT_PIXEL_SIMD_CHANNELS; _var++)
680#define for_four_channels(_var, ...) \
681 _DT_Pragma(omp simd __VA_ARGS__) \
682 for (size_t _var = 0; _var < 4; _var++)
683#else
684#define for_each_channel(_var, ...) \
685 for (size_t _var = 0; _var < DT_PIXEL_SIMD_CHANNELS; _var++)
686#define for_four_channels(_var, ...) \
687 for (size_t _var = 0; _var < 4; _var++)
688#endif
689
690
691// copy the RGB channels of a pixel using nontemporal stores if
692// possible; includes the 'alpha' channel as well if faster due to
693// vectorization, but subsequent code should ignore the value of the
694// alpha unless explicitly set afterwards (since it might not have
695// been copied). NOTE: nontemporal stores will actually be *slower*
696// if we immediately access the pixel again. This function should
697// only be used when processing an entire image before doing anything
698// else with the destination buffer.
699static inline void copy_pixel_nontemporal(
700 float *const __restrict__ out,
701 const float *const __restrict__ in)
702{
703 dt_store_simd_nontemporal(out, dt_load_simd(in));
704}
705
706
707// copy the RGB channels of a pixel; includes the 'alpha' channel as well if faster due to vectorization, but
708// subsequent code should ignore the value of the alpha unless explicitly set afterwards (since it might not have
709// been copied)
710static inline void copy_pixel(float *const __restrict__ out, const float *const __restrict__ in)
711{
712 for_each_channel(k,aligned(in,out:16)) out[k] = in[k];
713}
714
715/********************************* */
716
717struct dt_gui_gtk_t;
718struct dt_control_t;
719struct dt_develop_t;
720struct dt_mipmap_cache_t;
721struct dt_image_cache_t;
722struct dt_lib_t;
723struct dt_conf_t;
724struct dt_points_t;
725struct dt_imageio_t;
726struct dt_bauhaus_t;
727struct dt_undo_t;
728struct dt_colorspaces_t;
729struct dt_l10n_t;
730
731typedef float dt_boundingbox_t[4]; //(x,y) of upperleft, then (x,y) of lowerright
732
734{
735 DT_DEBUG_ALWAYS = 0, // always print regardless of debug flags
736 // powers of two, masking
739 DT_DEBUG_DEV = 1 << 2,
740 DT_DEBUG_GTK = 1 << 3,
745 DT_DEBUG_SQL = 1 << 8,
748 DT_DEBUG_NAN = 1 << 11,
749 DT_DEBUG_MASKS = 1 << 12,
750 DT_DEBUG_LUA = 1 << 13,
751 DT_DEBUG_INPUT = 1 << 14,
752 DT_DEBUG_PRINT = 1 << 15,
756 DT_DEBUG_UNDO = 1 << 19,
763 DT_DEBUG_PIPE = 1 << 26,
769
770// Uses the top (sign) bit of the int32_t `unmuted` mask. Defined as a macro
771// because 1 << 31 is not representable as an `int` enumerator. Enables the
772// high-level event supervisor (NDJSON tracing of history/pipeline/cache state).
773// See develop/supervisor.h.
774#define DT_DEBUG_SUPERVISOR ((int32_t)(1u << 31))
775
776typedef struct dt_sys_resources_t
777{
778 size_t total_memory; // All RAM on system
779 size_t mipmap_memory; // RAM allocated to mipmap cache
780 size_t headroom_memory; // RAM left to OS & other Apps
781 size_t pixelpipe_memory; // RAM used by the pixelpipe cache (approx.)
783
784typedef struct darktable_t
785{
787
788 int32_t unmuted;
789 GList *iop;
792
793 // Keep track of optional features that may depend on environnement
794 // ond compiling options : OpenCL, libsecret, kwallet
799 struct dt_lib_t *lib;
807 const struct dt_database_t *db;
819
820 // Protects from concurrent writing at export time
821 dt_pthread_mutex_t plugin_threadsafe;
822
823 // Protect appending/removing GList links to the darktable.capabilities list
824 dt_pthread_mutex_t capabilities_threadsafe;
825
826 // Exiv2 readMetadata() was not thread-safe prior to 0.27
827 // FIXME: Is it now ?
828 dt_pthread_mutex_t exiv2_threadsafe;
829
830 // RawSpeed readFile() method is apparently not thread-safe
831 dt_pthread_mutex_t readFile_mutex;
832
833 // Prevent concurrent export/thumbnail pipelines from runnnig at the same time
834 // It brings no additional performance since the CPU is our bottleneck,
835 // and CPU pixel code is already multi-threaded internally through OpenMP
836 dt_pthread_mutex_t pipeline_threadsafe;
837
838 // Building SQL transactions through `dt_database_start_transaction_debug()`
839 // from "too many" threads (like loading all thumbnails from a new collection)
840 // leads to SQL error:
841 // `BEGIN": cannot start a transaction within a transaction`
842 // Also, we need to ensure that image metadata/history reads & writes
843 // happen each in their all time, from all pipeline jobs/threads.
845
846 char *progname;
847 char *datadir;
848 char *sharedir;
851 char *tmpdir;
853 char *cachedir;
855 GList *guides;
857 GList *themes;
860 GTimeZone *utc_tz;
861 GDateTime *origin_gdt;
863
864 // Working message displayed over the main preview when working
867
868typedef struct
869{
870 double clock;
871 double user;
872} dt_times_t;
873
875
876int dt_init(int argc, char *argv[], const gboolean init_gui, const gboolean load_data);
877void dt_cleanup();
878void dt_print(dt_debug_thread_t thread, const char *msg, ...) __attribute__((format(printf, 2, 3)));
879/* same as above but without time stamp : nts = no time stamp */
880void dt_print_nts(dt_debug_thread_t thread, const char *msg, ...) __attribute__((format(printf, 2, 3)));
881/* same as above but requires additional DT_DEBUG_VERBOSE flag to be true */
882void dt_vprint(dt_debug_thread_t thread, const char *msg, ...) __attribute__((format(printf, 2, 3)));
883
884/* ------------------------------------------------------------------------------------------
885 * Widget-callback suppression (replaces the legacy raw `darktable.gui->reset` counter).
886 *
887 * Programmatic widget updates must not re-trigger their own "value-changed" handlers. Bracket
888 * such updates with dt_gui_freeze_begin()/dt_gui_freeze_end() (or the dt_gui_widget_freeze()
889 * scope guard), and open every widget callback with `if(dt_gui_widgets_suppressed()) return;`.
890 *
891 * The depth is managed centrally: it is mutated only on the GUI thread (off-thread begin/end
892 * are no-ops, so worker threads -- e.g. thumbnail/export reload_defaults -- can never race or
893 * drift it), clamped at >= 0, and any unbalanced end is logged with its file:line rather than
894 * silently drifting negative and disabling suppression for the rest of the session.
895 * ------------------------------------------------------------------------------------------ */
896gboolean dt_gui_widgets_suppressed(void);
897void dt_gui_freeze_begin_(const char *file, int line);
898void dt_gui_freeze_end_(const char *file, int line);
899void dt_gui_freeze_reset(void); // hard-reset depth to 0 (GUI init only)
900#define dt_gui_freeze_begin() dt_gui_freeze_begin_(__FILE__, __LINE__)
901#define dt_gui_freeze_end() dt_gui_freeze_end_(__FILE__, __LINE__)
902
903typedef struct { const char *file; int line; } dt_gui_freeze_token_t;
905{
906 dt_gui_freeze_end_(t->file, t->line);
907}
908// Scope guard: begins a freeze that is automatically ended when the enclosing block exits,
909// including via early return/goto/break. Use it for spans that contain an early exit (the
910// raw begin/end pair would leak the depth on such paths).
911#define DT_FREEZE_CAT_(a, b) a##b
912#define DT_FREEZE_CAT(a, b) DT_FREEZE_CAT_(a, b)
913#define dt_gui_widget_freeze() \
914 dt_gui_freeze_token_t DT_FREEZE_CAT(_dt_freeze_guard_, __LINE__) \
915 __attribute__((cleanup(dt_gui_freeze_release_))) = { __FILE__, __LINE__ }; \
916 dt_gui_freeze_begin_(__FILE__, __LINE__)
917
918// Number of workers, on top of reserved workers (1 for main preview, 1 for thumbnail in darkroom)
919// This is currently set to 2, so 4 workers total, without user config.
920// Workers will process a queue of jobs that they share together (except for reserved ones).
921// It is useless to use more than 2 workers
922// since those jobs very often lock some mutex that prevents concurrent running.
923// All jobs finding an idle worker will "start" immediately, as far as the OS knows from outside the program,
924// but may do nothing internally except for waiting a mutex locked by another worker/thread.
925// In that situation, we loose the ability to flush the queue, since jobs are "running".
926// So it's better to have few workers with long queues, rather
927// than many workers, to be able to control queued jobs.
929
930// Get the remaining memory available for pipeline allocations,
931// once we subtracted caches memory and headroom from system memory
932size_t dt_get_available_mem();
933
934// Get the maximum size for the whole mipmap cache
935size_t dt_get_mipmap_mem();
936
943static inline void memset_zero(void *const buffer, size_t size)
944{
945 // Same as memset_s in C11. memset might be optimized away by compilers, this will not.
946 // Not parallelized or vectorized since it's applied only on "small" tiles.
947 for(size_t k = 0; k < size / sizeof(unsigned char); k++) {
948 unsigned char *const item = (unsigned char *const)buffer + k;
949 *item = 0;
950 }
951}
952
953// check whether the specified mask of modifier keys exactly matches, among the set Shift+Control+(Alt/Meta).
954// ignores the state of any other shifting keys
955static inline gboolean dt_modifier_is(const GdkModifierType state, const GdkModifierType desired_modifier_mask)
956{
957 const GdkModifierType modifiers = gtk_accelerator_get_default_mod_mask();
958//TODO: on Macs, remap the GDK_CONTROL_MASK bit in desired_modifier_mask to be the bit for the Cmd key
959 return (state & modifiers) == desired_modifier_mask;
960}
961
962// check whether the given modifier state includes AT LEAST the specified mask of modifier keys
963static inline gboolean dt_modifiers_include(const GdkModifierType state, const GdkModifierType desired_modifier_mask)
964{
965//TODO: on Macs, remap the GDK_CONTROL_MASK bit in desired_modifier_mask to be the bit for the Cmd key
966 const GdkModifierType modifiers = gtk_accelerator_get_default_mod_mask();
967 // check whether all modifier bits of interest are turned on
968 return (state & (modifiers & desired_modifier_mask)) == desired_modifier_mask;
969}
970
971int dt_capabilities_check(char *capability);
972void dt_capabilities_add(char *capability);
973void dt_capabilities_remove(char *capability);
975
976static inline double dt_get_wtime(void)
977{
978 struct timeval time;
979 gettimeofday(&time, NULL);
980 return time.tv_sec - 1290608000 + (1.0 / 1000000.0) * time.tv_usec;
981}
982
983static inline void dt_get_times(dt_times_t *t)
984{
985 struct rusage ru;
986
988 t->clock = dt_get_wtime();
989 t->user = ru.ru_utime.tv_sec + ru.ru_utime.tv_usec * (1.0 / 1000000.0);
990}
991
992void dt_show_times(const dt_times_t *start, const char *prefix);
993
994void dt_show_times_f(const dt_times_t *start, const char *prefix, const char *suffix, ...) __attribute__((format(printf, 3, 4)));
995
997gboolean dt_supported_image(const gchar *filename);
998
999// a few macros and helper functions to speed up certain frequently-used GLib operations
1000#define g_list_is_singleton(list) ((list) && (!(list)->next))
1001static inline gboolean g_list_shorter_than(const GList *list, unsigned len)
1002{
1003 // instead of scanning the full list to compute its length and then comparing against the limit,
1004 // bail out as soon as the limit is reached. Usage: g_list_shorter_than(l,4) instead of g_list_length(l)<4
1005 while (len-- > 0)
1006 {
1007 if (!list) return TRUE;
1008 list = g_list_next(list);
1009 }
1010 return FALSE;
1011}
1012
1013// advance the list by one position, unless already at the final node
1014static inline GList *g_list_next_bounded(GList *list)
1015{
1016 return g_list_next(list) ? g_list_next(list) : list;
1017}
1018
1019static inline const GList *g_list_next_wraparound(const GList *list, const GList *head)
1020{
1021 return g_list_next(list) ? g_list_next(list) : head;
1022}
1023
1024static inline const GList *g_list_prev_wraparound(const GList *list)
1025{
1026 // return the prior element of the list, unless already on the first element; in that case, return the last
1027 // element of the list.
1028 return g_list_previous(list) ? g_list_previous(list) : g_list_last((GList*)list);
1029}
1030
1031void dt_print_mem_usage();
1032
1033void dt_configure_runtime_performance(dt_sys_resources_t *resources, gboolean init_gui);
1034
1035// helper function which loads whatever image_to_load points to: single image files or whole directories
1036// it tells you if it was a single image or a directory in single_image (when it's not NULL)
1037int dt_load_from_string(const gchar *image_to_load, gboolean open_image_in_dr, gboolean *single_image);
1038
1039#define dt_unreachable_codepath_with_desc(D) \
1040 dt_unreachable_codepath_with_caller(D, __FILE__, __LINE__, __FUNCTION__)
1041#define dt_unreachable_codepath() dt_unreachable_codepath_with_caller("unreachable", __FILE__, __LINE__, __FUNCTION__)
1042static inline void dt_unreachable_codepath_with_caller(const char *description, const char *file,
1043 const int line, const char *function)
1044{
1045 fprintf(stderr, "[dt_unreachable_codepath] {%s} %s:%d (%s) - we should not be here. please report this to "
1046 "the developers.",
1047 description, file, line, function);
1048 __builtin_unreachable();
1049}
1050
1051// Allocate a buffer for 'n' objects each of size 'objsize' bytes for each of the program's threads.
1052// Ensures that there is no false sharing among threads by aligning and rounding up the allocation to
1053// a multiple of the cache line size. Returns a pointer to the allocated pool and the adjusted number
1054// of objects in each thread's buffer. Use dt_get_perthread or dt_get_bythread (see below) to access
1055// a specific thread's buffer.
1056static inline void *dt_pixelpipe_cache_alloc_perthread_impl(const size_t n, const size_t objsize, size_t* padded_size, const char *message)
1057{
1058 const size_t alloc_size = n * objsize;
1059 const size_t cache_lines = (alloc_size + DT_CACHELINE_BYTES - 1) / DT_CACHELINE_BYTES;
1060 *padded_size = DT_CACHELINE_BYTES * cache_lines / objsize;
1061 const size_t total_bytes = DT_CACHELINE_BYTES * cache_lines * darktable.num_openmp_threads;
1062 void *buf = dt_pixelpipe_cache_alloc_align_cache_impl(darktable.pixelpipe_cache, total_bytes, 0, message);
1063 if(IS_NULL_PTR(buf)) return NULL;
1064 return __builtin_assume_aligned(buf, DT_CACHELINE_BYTES);
1065}
1066
1067#ifndef dt_pixelpipe_cache_alloc_perthread
1068#define dt_pixelpipe_cache_alloc_perthread(n, objsize, padded_size) \
1069 ((void *)dt_pixelpipe_cache_alloc_perthread_impl((n), (objsize), (padded_size), __FILE__ ":" DT_STRINGIFY(__LINE__)))
1070#endif
1071
1072static inline void *dt_pixelpipe_cache_calloc_perthread_impl(const size_t n, const size_t objsize, size_t* padded_size, const char *message)
1073{
1074 void *const buf = (float*)dt_pixelpipe_cache_alloc_perthread_impl(n, objsize, padded_size, message);
1075 if(IS_NULL_PTR(buf)) return NULL;
1076 memset(buf, 0, *padded_size * darktable.num_openmp_threads * objsize);
1077 return buf;
1078}
1079
1080#ifndef dt_pixelpipe_cache_calloc_perthread
1081#define dt_pixelpipe_cache_calloc_perthread(n, objsize, padded_size) \
1082 ((void *)dt_pixelpipe_cache_calloc_perthread_impl((n), (objsize), (padded_size), __FILE__ ":" DT_STRINGIFY(__LINE__)))
1083#endif
1084
1085// Same as dt_pixelpipe_cache_alloc_perthread, but the object is a float.
1086static inline float *dt_pixelpipe_cache_alloc_perthread_float_impl(const size_t n, size_t* padded_size, const char *message)
1087{
1088 return (float*)dt_pixelpipe_cache_alloc_perthread_impl(n, sizeof(float), padded_size, message);
1089}
1090
1091#ifndef dt_pixelpipe_cache_alloc_perthread_float
1092#define dt_pixelpipe_cache_alloc_perthread_float(n, padded_size) \
1093 ((float *)dt_pixelpipe_cache_alloc_perthread_float_impl((n), (padded_size), __FILE__ ":" DT_STRINGIFY(__LINE__)))
1094#endif
1095
1096// Given the buffer and object count returned by dt_pixelpipe_cache_alloc_perthread, return the current thread's private buffer.
1097#define dt_get_perthread(buf, padsize) DT_IS_ALIGNED((buf) + ((padsize) * dt_get_thread_num()))
1098// Given the buffer and object count returned by dt_pixelpipe_cache_alloc_perthread and a thread count in 0..darktable.num_openmp_threads,
1099// return a pointer to the indicated thread's private buffer.
1100#define dt_get_bythread(buf, padsize, tnum) DT_IS_ALIGNED((buf) + ((padsize) * (tnum)))
1101
1102// Cryptographic-strength hash of `str` representing its state, with negligible
1103// collision probability compared to a plain multiplicative hash.
1104// This is SipHash-2-4 (Aumasson & Bernstein, https://131002.net/siphash/), a
1105// keyed pseudo-random function with 64-bit output. The incoming `hash` is folded
1106// in as the key material, so calls can be chained to combine several buffers:
1107// hash = dt_hash(hash, a, sizeof(a));
1108// hash = dt_hash(hash, b, sizeof(b));
1109// `hash` should be seeded to 5381 (or any constant) on the first call, or carried
1110// over from a previous dt_hash() result.
1111// NOTE: the digest is computed over the raw bytes in native endianness, so it is
1112// stable within a run/machine but not portable across architectures of differing
1113// endianness (same constraint as the previous implementation when hashing structs).
1114#define DT_SIPROUND \
1115 do \
1116 { \
1117 v0 += v1; v1 = (v1 << 13) | (v1 >> 51); v1 ^= v0; v0 = (v0 << 32) | (v0 >> 32); \
1118 v2 += v3; v3 = (v3 << 16) | (v3 >> 48); v3 ^= v2; \
1119 v0 += v3; v3 = (v3 << 21) | (v3 >> 43); v3 ^= v0; \
1120 v2 += v1; v1 = (v1 << 17) | (v1 >> 47); v1 ^= v2; v2 = (v2 << 32) | (v2 >> 32); \
1121 } while(0)
1122
1123static inline uint64_t dt_hash(uint64_t hash, const char *str, size_t size)
1124{
1125 // Derive the 128-bit SipHash key from the chained seed so that chaining keeps
1126 // mixing prior state into the new digest. The second key word is a fixed
1127 // constant (fractional bits of the golden ratio) to add entropy.
1128 const uint64_t k0 = hash;
1129 const uint64_t k1 = 0x9e3779b97f4a7c15ULL;
1130
1131 uint64_t v0 = 0x736f6d6570736575ULL ^ k0;
1132 uint64_t v1 = 0x646f72616e646f6dULL ^ k1;
1133 uint64_t v2 = 0x6c7967656e657261ULL ^ k0;
1134 uint64_t v3 = 0x7465646279746573ULL ^ k1;
1135
1136 const uint8_t *in = (const uint8_t *)str;
1137 const size_t blocks = size & ~(size_t)7;
1138 size_t i = 0;
1139 for(; i < blocks; i += 8)
1140 {
1141 uint64_t m;
1142 __builtin_memcpy(&m, in + i, sizeof(m));
1143 v3 ^= m;
1146 v0 ^= m;
1147 }
1148
1149 // Tail: remaining 0..7 bytes plus the length in the top byte.
1150 uint64_t b = (uint64_t)size << 56;
1151 switch(size & 7)
1152 {
1153 case 7: b |= (uint64_t)in[i + 6] << 48; /* fall through */
1154 case 6: b |= (uint64_t)in[i + 5] << 40; /* fall through */
1155 case 5: b |= (uint64_t)in[i + 4] << 32; /* fall through */
1156 case 4: b |= (uint64_t)in[i + 3] << 24; /* fall through */
1157 case 3: b |= (uint64_t)in[i + 2] << 16; /* fall through */
1158 case 2: b |= (uint64_t)in[i + 1] << 8; /* fall through */
1159 case 1: b |= (uint64_t)in[i + 0]; /* fall through */
1160 case 0: break;
1161 }
1162 v3 ^= b;
1165 v0 ^= b;
1166
1167 // Finalization.
1168 v2 ^= 0xff;
1173
1174 return v0 ^ v1 ^ v2 ^ v3;
1175}
1176#undef DT_SIPROUND
1177
1179#define DT_MAX_FILENAME_LEN 256
1180
1181#ifndef PATH_MAX
1182/*
1183 * from /usr/include/linux/limits.h (Linux 3.16.5)
1184 * Some systems might not define it (e.g. Hurd)
1185 *
1186 * We do NOT depend on any specific value of this env variable.
1187 * If you want constant value across all systems, use DT_MAX_PATH_FOR_PARAMS!
1188 */
1189#define PATH_MAX 4096
1190#endif
1191
1192/*
1193 * ONLY TO BE USED FOR PARAMS!!! (e.g. dt_imageio_disk_t)
1194 *
1195 * WARNING: this should *NEVER* be changed, as it will break params,
1196 * created with previous DT_MAX_PATH_FOR_PARAMS.
1197 */
1198#define DT_MAX_PATH_FOR_PARAMS 4096
1199
1200static inline gchar *dt_string_replace(const char *string, const char *to_replace)
1201{
1202 if(IS_NULL_PTR(string) || IS_NULL_PTR(to_replace)) return NULL;
1203 gchar **split = g_strsplit(string, to_replace, -1);
1204 gchar *text = g_strjoinv("", split);
1205 g_strfreev(split);
1206 return text;
1207}
1208
1209// Remove underscore from GUI labels containing mnemonics
1210static inline gchar *delete_underscore(const char *s)
1211{
1212 return dt_string_replace(s, "_");
1213}
1214
1222static inline gchar *strip_markup(const char *s)
1223{
1224 if(IS_NULL_PTR(s)) return g_strdup("");
1225
1226 PangoAttrList *attrs = NULL;
1227 gchar *plain = NULL;
1228
1229 const gchar *underscore = "_";
1230 gunichar mnemonic = underscore[0];
1231 if(!pango_parse_markup(s, -1, mnemonic, &attrs, &plain, NULL, NULL))
1232 plain = delete_underscore(s);
1233
1234 pango_attr_list_unref(attrs);
1235 return plain;
1236}
1237
1246void dt_concat_path_file(char destination[PATH_MAX], const char path[PATH_MAX], const char *const file);
1247
1248#ifdef __cplusplus
1249}
1250#endif
1251
1252// clang-format off
1253// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
1254// vim: shiftwidth=2 expandtab tabstop=2 cindent
1255// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
1256// clang-format on
const char ** description(struct dt_iop_module_t *self)
Definition ashift.c:160
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
#define m
Definition basecurve.c:278
return vector dt_simd_set1(valid ?(scaling+NORM_MIN) :NORM_MIN)
dt_store_simd_aligned(out, dt_mat3x4_mul_vec4(vin, dt_colormatrix_row_to_simd(matrix, 0), dt_colormatrix_row_to_simd(matrix, 1), dt_colormatrix_row_to_simd(matrix, 2)))
char * name
static const dt_aligned_pixel_simd_t const dt_aligned_pixel_simd_t row1
Definition darktable.h:645
#define DT_ALIGNED_PIXEL
Definition darktable.h:401
dt_store_simd(out, value)
static void memset_zero(void *const buffer, size_t size)
Set the memory buffer to zero as a pack of unsigned char.
Definition darktable.h:943
void dt_show_times(const dt_times_t *start, const char *prefix)
Definition darktable.c:1638
static gchar * dt_string_replace(const char *string, const char *to_replace)
Definition darktable.h:1200
static float * dt_calloc_align_float(size_t pixels)
Definition darktable.h:520
#define DT_SIPROUND
Definition darktable.h:1114
static void * dt_calloc_align(size_t size)
Definition darktable.h:510
static gboolean dt_modifiers_include(const GdkModifierType state, const GdkModifierType desired_modifier_mask)
Definition darktable.h:963
dt_debug_thread_t
Definition darktable.h:734
@ DT_DEBUG_LIGHTTABLE
Definition darktable.h:747
@ DT_DEBUG_UNDO
Definition darktable.h:756
@ DT_DEBUG_INPUT
Definition darktable.h:751
@ DT_DEBUG_PRINT
Definition darktable.h:752
@ DT_DEBUG_OPENCL
Definition darktable.h:744
@ DT_DEBUG_GTK
Definition darktable.h:740
@ DT_DEBUG_PIPE
Definition darktable.h:763
@ DT_DEBUG_PIPECACHE
Definition darktable.h:742
@ DT_DEBUG_HISTORY
Definition darktable.h:762
@ DT_DEBUG_CAMERA_SUPPORT
Definition darktable.h:753
@ DT_DEBUG_NAN
Definition darktable.h:748
@ DT_DEBUG_DEMOSAIC
Definition darktable.h:759
@ DT_DEBUG_MEMORY
Definition darktable.h:746
@ DT_DEBUG_PERF
Definition darktable.h:741
@ DT_DEBUG_VERBOSE
Definition darktable.h:765
@ DT_DEBUG_PARAMS
Definition darktable.h:758
@ DT_DEBUG_CONTROL
Definition darktable.h:738
@ DT_DEBUG_COLORPROFILE
Definition darktable.h:766
@ DT_DEBUG_CACHE
Definition darktable.h:737
@ DT_DEBUG_ALWAYS
Definition darktable.h:735
@ DT_DEBUG_SIGNAL
Definition darktable.h:757
@ DT_DEBUG_PWSTORAGE
Definition darktable.h:743
@ DT_DEBUG_SHORTCUTS
Definition darktable.h:760
@ DT_DEBUG_IMAGEIO
Definition darktable.h:755
@ DT_DEBUG_DEV
Definition darktable.h:739
@ DT_DEBUG_NOCACHE_REUSE
Definition darktable.h:767
@ DT_DEBUG_IMPORT
Definition darktable.h:764
@ DT_DEBUG_IOPORDER
Definition darktable.h:754
@ DT_DEBUG_MASKS
Definition darktable.h:749
@ DT_DEBUG_TILING
Definition darktable.h:761
@ DT_DEBUG_SQL
Definition darktable.h:745
@ DT_DEBUG_LUA
Definition darktable.h:750
void dt_pixelpipe_cache_free_align_cache(struct dt_dev_pixelpipe_cache_t *cache, void **mem, const char *message)
void dt_cleanup()
Definition darktable.c:1366
int dt_worker_threads()
Definition darktable.c:1735
void gboolean dt_supported_image(const gchar *filename)
check if file is a supported image
Definition darktable.c:350
static void copy_pixel(float *const __restrict__ out, const float *const __restrict__ in)
Definition darktable.h:710
return out
Definition darktable.h:577
static void dt_free_align_ptr(void *mem)
Definition darktable.h:497
#define for_each_channel(_var,...)
Definition darktable.h:684
float dt_boundingbox_t[4]
Definition darktable.h:731
static float * dt_alloc_align_float(size_t pixels)
Definition darktable.h:516
static size_t dt_round_size_sse(const size_t size)
Definition darktable.h:415
void dt_gui_freeze_reset(void)
Definition gtk.c:229
void void dt_print_nts(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
static void dt_gui_freeze_release_(dt_gui_freeze_token_t *t)
Definition darktable.h:904
static void * dt_check_sse_aligned(void *pointer)
Definition darktable.h:526
const char * dt_install_id(void)
Definition darktable.c:328
static gchar * strip_markup(const char *s)
Remove Pango/Gtk markup and accels mnemonics from text labels. If the markup parsing fails,...
Definition darktable.h:1222
darktable_t darktable
Definition darktable.c:183
static void * dt_alloc_align_internal(size_t size)
Definition darktable.h:421
void dt_print_mem_usage()
Definition darktable.c:1859
void dt_gui_freeze_end_(const char *file, int line)
Definition gtk.c:212
static void dt_free_gpointer(gpointer ptr)
Definition darktable.h:485
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Enable aggressive floating-point arithmetic optimizations, in denormals handling. Set through user pr...
Definition darktable.h:546
static void copy_pixel_nontemporal(float *const __restrict__ out, const float *const __restrict__ in)
Definition darktable.h:699
static void * dt_pixelpipe_cache_alloc_perthread_impl(const size_t n, const size_t objsize, size_t *padded_size, const char *message)
Definition darktable.h:1056
static const GList * g_list_next_wraparound(const GList *list, const GList *head)
Definition darktable.h:1019
static const dt_aligned_pixel_simd_t sign
Definition darktable.h:573
static int dt_get_thread_num()
Definition darktable.h:303
void * dt_alloc_align(size_t size)
Definition darktable.c:484
#define dt_free(ptr)
Definition darktable.h:478
void dt_capabilities_remove(char *capability)
Definition darktable.c:1842
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
void void void gboolean dt_gui_widgets_suppressed(void)
Definition gtk.c:194
static void dt_get_times(dt_times_t *t)
Definition darktable.h:983
int dt_init(int argc, char *argv[], const gboolean init_gui, const gboolean load_data)
Definition darktable.c:489
static float * dt_pixelpipe_cache_alloc_perthread_float_impl(const size_t n, size_t *padded_size, const char *message)
Definition darktable.h:1086
#define omp_get_thread_num()
Definition darktable.h:267
static const GList * g_list_prev_wraparound(const GList *list)
Definition darktable.h:1024
void void void dt_vprint(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
static int dt_version()
Definition darktable.h:154
static gchar * delete_underscore(const char *s)
Definition darktable.h:1210
static uint64_t dt_hash(uint64_t hash, const char *str, size_t size)
Definition darktable.h:1123
size_t dt_get_mipmap_mem()
Definition darktable.c:1745
static size_t dt_round_size(const size_t size, const size_t alignment)
Definition darktable.h:409
static void dt_unreachable_codepath_with_caller(const char *description, const char *file, const int line, const char *function)
Definition darktable.h:1042
int dt_load_from_string(const gchar *image_to_load, gboolean open_image_in_dr, gboolean *single_image)
Definition darktable.c:366
const char * dt_session_id(void)
Definition darktable.c:314
#define DT_MODULE_VERSION
Definition darktable.h:120
static const dt_aligned_pixel_simd_t const dt_aligned_pixel_simd_t const dt_aligned_pixel_simd_t row2
Definition darktable.h:646
static GList * g_list_next_bounded(GList *list)
Definition darktable.h:1014
char * dt_version_major_minor()
Definition darktable.c:283
void dt_configure_runtime_performance(dt_sys_resources_t *resources, gboolean init_gui)
Definition darktable.c:1750
static const dt_aligned_pixel_simd_t value
Definition darktable.h:599
void dt_capabilities_add(char *capability)
Definition darktable.c:1831
void dt_concat_path_file(char destination[4096], const char path[4096], const char *const file)
Append a constant filename to a variable, stack-based, fixed-sized, directory, and add a / in-between...
static double dt_get_wtime(void)
Definition darktable.h:976
static void * dt_pixelpipe_cache_calloc_perthread_impl(const size_t n, const size_t objsize, size_t *padded_size, const char *message)
Definition darktable.h:1072
void dt_capabilities_cleanup()
Definition darktable.c:1852
static gboolean dt_is_aligned(const void *pointer, size_t byte_count)
Definition darktable.h:404
static const dt_aligned_pixel_simd_t exponent
Definition darktable.h:582
void * dt_pixelpipe_cache_alloc_align_cache_impl(struct dt_dev_pixelpipe_cache_t *cache, size_t size, int id, const char *name)
static gboolean dt_modifier_is(const GdkModifierType state, const GdkModifierType desired_modifier_mask)
Definition darktable.h:955
void dt_show_times_f(const dt_times_t *start, const char *prefix, const char *suffix,...) __attribute__((format(printf
static const dt_aligned_pixel_simd_t row0
Definition darktable.h:644
size_t dt_get_available_mem()
Definition darktable.c:1740
int dt_capabilities_check(char *capability)
Definition darktable.c:1818
#define PATH_MAX
Definition darktable.h:1189
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:293
#define DT_CACHELINE_BYTES
Definition darktable.h:392
void dt_gui_freeze_begin_(const char *file, int line)
Definition gtk.c:199
static gboolean g_list_shorter_than(const GList *list, unsigned len)
Definition darktable.h:1001
int getrusage(int who, struct rusage *usage)
Definition getrusage.c:56
#define RUSAGE_SELF
Definition getrusage.h:53
const int t
float *const restrict const size_t k
c< 3;c++) acc+=v_1[c] *v_2[c];return acc;}static inline float sqf(const float x){ return x *x;}static inline float euclidean_norm(const dt_aligned_pixel_t vector){ return fmaxf(sqrtf(sqf(vector[0])+sqf(vector[1])+sqf(vector[2])), 1.52587890625e-05f);}static inline void downscale_vector(dt_aligned_pixel_t vector, const float scaling){ const int valid=(scaling > 1.52587890625e-05f) &&!isnan(scaling);for(size_t c=0;c< 3;c++) vector[c]=(valid) ? vector[c]/(scaling+1.52587890625e-05f) :vector[c]/1.52587890625e-05f ;}static inline void upscale_vector(dt_aligned_pixel_t vector, const float scaling){ const int valid=(scaling > 1.52587890625e-05f) &&!isnan(scaling);for(size_t c=0;c< 3;c++) vector[c]=(valid) ? vector[c] *(scaling+1.52587890625e-05f) :vector[c] *1.52587890625e-05f ;}static inline float dt_log2f(const float f){ return logf(f)/logf(2.0f);}union float_int { float f;int k;};static inline float dt_fast_hypotf(const float x, const float y){ return sqrtf(x *x+y *y);}static inline float dt_fast_expf(const float x){ const int i1=0x3f800000u;const int i2=0x402DF854u;const int k0=i1+x *(i2 - i1);union float_int u;u.k=k0 > k0
Definition math.h:263
size_t size
Definition mipmap_cache.c:3
float dt_aligned_pixel_t[4]
@ DT_SIGNAL_COUNT
Definition signal.h:333
const float uint32_t state[4]
unsigned __int64 uint64_t
Definition strptime.c:75
struct dt_dbus_t * dbus
Definition darktable.h:814
struct dt_undo_t * undo
Definition darktable.h:815
char * tmpdir
Definition darktable.h:851
dt_pthread_mutex_t readFile_mutex
Definition darktable.h:831
char * cachedir
Definition darktable.h:853
struct dt_lib_t * lib
Definition darktable.h:799
int32_t unmuted_signal_dbg_acts
Definition darktable.h:858
struct dt_imageio_t * imageio
Definition darktable.h:812
struct dt_dev_pixelpipe_cache_t * pixelpipe_cache
Definition darktable.h:818
int32_t num_openmp_threads
Definition darktable.h:786
struct dt_l10n_t * l10n
Definition darktable.h:817
struct dt_gui_gtk_t * gui
Definition darktable.h:803
dt_pthread_rwlock_t database_threadsafe
Definition darktable.h:844
struct dt_colorspaces_t * color_profiles
Definition darktable.h:816
GList * capabilities
Definition darktable.h:795
GTimeZone * utc_tz
Definition darktable.h:860
char * sharedir
Definition darktable.h:848
struct dt_collection_t * collection
Definition darktable.h:809
struct dt_mipmap_cache_t * mipmap_cache
Definition darktable.h:804
struct dt_selection_t * selection
Definition darktable.h:810
GList * iop
Definition darktable.h:789
dt_pthread_mutex_t exiv2_threadsafe
Definition darktable.h:828
struct dt_sys_resources_t dtresources
Definition darktable.h:862
dt_pthread_mutex_t plugin_threadsafe
Definition darktable.h:821
char * moduledir
Definition darktable.h:849
dt_pthread_mutex_t capabilities_threadsafe
Definition darktable.h:824
GList * iop_order_list
Definition darktable.h:790
const struct dt_database_t * db
Definition darktable.h:807
GList * iop_order_rules
Definition darktable.h:791
struct dt_control_signal_t * signals
Definition darktable.h:802
struct dt_bauhaus_t * bauhaus
Definition darktable.h:806
struct dt_opencl_t * opencl
Definition darktable.h:813
char * configdir
Definition darktable.h:852
char * datadir
Definition darktable.h:847
GList * themes
Definition darktable.h:857
int32_t unmuted
Definition darktable.h:788
struct dt_image_cache_t * image_cache
Definition darktable.h:805
struct dt_develop_t * develop
Definition darktable.h:798
struct dt_points_t * points
Definition darktable.h:811
char * localedir
Definition darktable.h:850
dt_pthread_mutex_t pipeline_threadsafe
Definition darktable.h:836
struct dt_view_manager_t * view_manager
Definition darktable.h:800
char * kerneldir
Definition darktable.h:854
JsonParser * noiseprofile_parser
Definition darktable.h:796
GList * guides
Definition darktable.h:855
gboolean unmuted_signal_dbg[DT_SIGNAL_COUNT]
Definition darktable.h:859
char * main_message
Definition darktable.h:865
char * progname
Definition darktable.h:846
struct dt_conf_t * conf
Definition darktable.h:797
GDateTime * origin_gdt
Definition darktable.h:861
const struct dt_pwstorage_t * pwstorage
Definition darktable.h:808
double start_wtime
Definition darktable.h:856
struct dt_control_t * control
Definition darktable.h:801
const char * file
Definition darktable.h:903
Definition lib.h:54
size_t pixelpipe_memory
Definition darktable.h:781
double clock
Definition darktable.h:870
double user
Definition darktable.h:871
struct timeval ru_utime
Definition getrusage.h:34
#define MAX(a, b)
Definition thinplate.c:29