65#if defined __DragonFly__ || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__
68#elif !defined _XOPEN_SOURCE && !defined _WIN32
69#define _XOPEN_SOURCE 700
73#define __STDC_FORMAT_MACROS
80#include "external/ThreadSafetyAnalysis.h"
92#include <sys/resource.h>
96#include <glib/gstdio.h>
97#include <glib/gi18n.h>
99#include <json-glib/json-glib.h>
104#include <sys/types.h>
120#define DT_MODULE_VERSION 23
125#define DT_CURRENT_PERFORMANCE_CONFIGURE_VERSION 11
126#define DT_PERF_INFOSIZE 4096
130#define DT_MODULE(MODVER) \
131 int dt_module_dt_version() \
133 return -DT_MODULE_VERSION; \
135 int dt_module_mod_version() \
140#define DT_MODULE(MODVER) \
141 int dt_module_dt_version() \
143 return DT_MODULE_VERSION; \
145 int dt_module_mod_version() \
151#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE) DT_MODULE(MODVER)
167#define STR_HELPER(x) #x
170#define STR(x) STR_HELPER(x)
172#define DT_IMAGE_DBLOCKS 64
178#define DT_RESTRICT restrict
182#define UNKNOWN_IMAGE -1
201#include <mach/mach.h>
202#include <sys/sysctl.h>
205#if defined(__DragonFly__) || defined(__FreeBSD__)
206typedef unsigned int u_int;
207#include <sys/sysctl.h>
208#include <sys/types.h>
210#if defined(__NetBSD__) || defined(__OpenBSD__)
211#include <sys/param.h>
212#include <sys/sysctl.h>
215#if defined(__aarch64__)
219#if defined(__x86_64__) || defined(__i386__)
220#include <xmmintrin.h>
226#ifndef dt_omp_nontemporal
230#if (__clang__+0 >= 10 || __GNUC__ >= 9)
231# define dt_omp_nontemporal(...) nontemporal(__VA_ARGS__)
234# define dt_omp_nontemporal(var, ...)
238#define OMP_PRAGMA(x) _Pragma(#x)
239#define __OMP_PARALLEL__(...) OMP_PRAGMA(omp parallel default(firstprivate) __VA_ARGS__)
240#define __OMP_PARALLEL_FOR__(...) OMP_PRAGMA(omp parallel for default(firstprivate) schedule(static) __VA_ARGS__)
241#define __OMP_PARALLEL_FOR_SIMD__(...) OMP_PRAGMA(omp parallel for simd default(firstprivate) schedule(simd:static) __VA_ARGS__)
242#define __OMP_FOR_SIMD__(...) OMP_PRAGMA(omp for simd schedule(simd:static) __VA_ARGS__)
243#define __OMP_FOR__(...) OMP_PRAGMA(omp for schedule(static) __VA_ARGS__)
244#define __OMP_SIMD__(...) OMP_PRAGMA(omp simd __VA_ARGS__)
245#define __OMP_DECLARE_SIMD__(...) OMP_PRAGMA(omp declare simd __VA_ARGS__)
250#define __OMP_PARALLEL_FOR_CPP__(...) OMP_PRAGMA(omp parallel for default(none) schedule(static) __VA_ARGS__)
254# define omp_get_max_threads() 1
255# define omp_get_thread_num() 0
257#define __OMP_PARALLEL__(...)
258#define __OMP_PARALLEL_FOR__(...)
259#define __OMP_PARALLEL_FOR_SIMD__(...)
260#define __OMP_FOR_SIMD__(...)
261#define __OMP_FOR__(...)
262#define __OMP_SIMD__(...)
263#define __OMP_DECLARE_SIMD__(...)
265#define __OMP_PARALLEL_FOR_CPP__(...)
281#define IS_NULL_PTR(p) \
283 __typeof__(p) _tmp = (p); \
285 (__builtin_classify_type(_tmp) == 5) ? 1 : -1 \
303#if __has_attribute(target_clones) && !defined(_WIN32) && !defined(NATIVE_ARCH) && !defined(_DEBUG)
316 #if defined(__APPLE__)
318 #if defined(__aarch64__) || defined(__arm64__)
319 #define __DT_CLONE_TARGETS__
321 #elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
331 #if defined(DT_APPLE_X86_TARGET_CLONES)
332 #define __DT_CLONE_TARGETS__ \
333 __attribute__((target_clones( \
341 #define __DT_CLONE_TARGETS__
345 #define __DT_CLONE_TARGETS__
348 #elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
349 #define __DT_CLONE_TARGETS__ \
350 __attribute__((target_clones( \
358 #elif defined(__PPC64__)
360 #define __DT_CLONE_TARGETS__ __attribute__((target_clones("default","cpu=power9")))
363 #define __DT_CLONE_TARGETS__
367 #define __DT_CLONE_TARGETS__
371#define DT_IS_ALIGNED(x) __builtin_assume_aligned(x, DT_CACHELINE_BYTES)
375#if defined(__APPLE__) && defined(__aarch64__)
376 #define DT_CACHELINE_BYTES 128
377 #define DT_CACHELINE_FLOATS 32
378 #define DT_CACHELINE_PIXELS 8
380 #define DT_CACHELINE_BYTES 64
381 #define DT_CACHELINE_FLOATS 16
382 #define DT_CACHELINE_PIXELS 4
388#define DT_ALIGNED_ARRAY __attribute__((aligned(DT_CACHELINE_BYTES)))
389#define DT_ALIGNED_PIXEL __attribute__((aligned(16)))
394 return (uintptr_t)pointer % byte_count == 0;
400 return ((
size % alignment) == 0) ?
size : ((
size - 1) / alignment + 1) * alignment;
413#if defined(__FreeBSD_version) && __FreeBSD_version < 700013
414 return malloc(aligned_size);
416 return _aligned_malloc(aligned_size, alignment);
419 if(posix_memalign(&ptr, alignment, aligned_size))
return NULL;
428#define DT_STRINGIFY_HELPER(x) #x
429#define DT_STRINGIFY(x) DT_STRINGIFY_HELPER(x)
433#define dt_pixelpipe_cache_alloc_align_cache(size, id) \
434 dt_pixelpipe_cache_alloc_align_cache_impl(darktable.pixelpipe_cache, (size), (id), __FILE__ ":" DT_STRINGIFY(__LINE__))
436#ifndef dt_pixelpipe_cache_alloc_align
437#define dt_pixelpipe_cache_alloc_align(size, pipe) \
438 dt_pixelpipe_cache_alloc_align_cache((size), (pipe)->type)
441#ifndef dt_pixelpipe_cache_alloc_align_float
442#define dt_pixelpipe_cache_alloc_align_float(pixels, pipe) \
443 ((float *)dt_pixelpipe_cache_alloc_align((size_t)(pixels) * sizeof(float), (pipe)))
446#ifndef dt_pixelpipe_cache_alloc_align_float_cache
447#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id) \
448 ((float *)dt_pixelpipe_cache_alloc_align_cache((size_t)(pixels) * sizeof(float), (id)))
453#define dt_pixelpipe_cache_free_align(mem) \
454 dt_pixelpipe_cache_free_align_cache(darktable.pixelpipe_cache, (void **)&(mem), __FILE__ ":" DT_STRINGIFY(__LINE__));
456#define dt_free(ptr) \
457 if(!IS_NULL_PTR(ptr)) \
459 g_free((void *)(ptr)); \
460 *(void **)(&(ptr)) = NULL; \
481#define dt_free_align(ptr) \
482 if(!IS_NULL_PTR(ptr)) \
484 dt_free_align_ptr((void *)(ptr)); \
485 *(void **)(&(ptr)) = NULL; \
491 if(buf) memset(buf, 0,
size);
500 float *
const buf = (
float*)
dt_alloc_align(pixels *
sizeof(
float));
501 if(buf) memset(buf, 0, pixels *
sizeof(
float));
524typedef float dt_aligned_pixel_simd_t
__attribute__((vector_size(16), aligned(16)));
531static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
532dt_simd_abs(
const dt_aligned_pixel_simd_t
value)
534 dt_aligned_pixel_simd_t
out =
value;
535 for(
int c = 0;
c < 4;
c++)
540static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
541dt_simd_max_zero(
const dt_aligned_pixel_simd_t
value)
543 dt_aligned_pixel_simd_t
out =
value;
544 for(
int c = 0;
c < 4;
c++)
549static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
550dt_simd_copysign(
const dt_aligned_pixel_simd_t magnitude,
const dt_aligned_pixel_simd_t
sign)
552 dt_aligned_pixel_simd_t
out = magnitude;
553 for(
int c = 0; c < 4; c++)
554 out[c] = copysignf(magnitude[c],
sign[c]);
558static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
559dt_simd_pow(
const dt_aligned_pixel_simd_t base,
const dt_aligned_pixel_simd_t
exponent)
561 dt_aligned_pixel_simd_t
out = base;
562 for(
int c = 0; c < 4; c++)
567static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
568dt_load_simd(
const float *
const pixel)
570 dt_aligned_pixel_simd_t
out;
571 __builtin_memcpy(&
out, pixel,
sizeof(
out));
578 __builtin_memcpy(pixel, &
value,
sizeof(
value));
581static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
582dt_load_simd_aligned(
const float *
const pixel)
584 const float *
const in = (
const float *
const)__builtin_assume_aligned(pixel, 16);
585 return dt_load_simd(in);
591 float *
const out = (
float *
const)__builtin_assume_aligned(pixel, 16);
596dt_store_simd_nontemporal(
float *
const pixel,
const dt_aligned_pixel_simd_t
value)
598 float *
const out = (
float *
const)__builtin_assume_aligned(pixel, 16);
600#if defined(__x86_64__) || defined(__i386__)
603 dt_aligned_pixel_simd_t simd;
605 } cast = { .simd =
value };
606 _mm_stream_ps(
out, cast.sse);
607#elif defined(__aarch64__)
610 dt_aligned_pixel_simd_t simd;
612 } cast = { .simd =
value };
613 vst1q_f32(
out, cast.neon);
614#elif (__clang__+0 > 7) && (__clang__+0 < 10)
621static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
622dt_mat3x4_mul_vec4(
const dt_aligned_pixel_simd_t in,
const dt_aligned_pixel_simd_t
row0,
623 const dt_aligned_pixel_simd_t
row1,
const dt_aligned_pixel_simd_t
row2)
627 dt_aligned_pixel_simd_t
out =
row0 * in[0];
635#ifdef DT_NO_VECTORIZATION
636#define DT_PIXEL_SIMD_CHANNELS 3
638#define DT_PIXEL_SIMD_CHANNELS 4
651#if defined(_OPENMP) && defined(OPENMP_SIMD_) && !defined(DT_NO_SIMD_HINTS)
653#define _DT_Pragma_(x) _Pragma(#x)
654#define _DT_Pragma(x) _DT_Pragma_(x)
655#define for_each_channel(_var, ...) \
656 _DT_Pragma(omp simd __VA_ARGS__) \
657 for (size_t _var = 0; _var < DT_PIXEL_SIMD_CHANNELS; _var++)
658#define for_four_channels(_var, ...) \
659 _DT_Pragma(omp simd __VA_ARGS__) \
660 for (size_t _var = 0; _var < 4; _var++)
662#define for_each_channel(_var, ...) \
663 for (size_t _var = 0; _var < DT_PIXEL_SIMD_CHANNELS; _var++)
664#define for_four_channels(_var, ...) \
665 for (size_t _var = 0; _var < 4; _var++)
678 float *
const __restrict__
out,
679 const float *
const __restrict__ in)
681 dt_store_simd_nontemporal(
out, dt_load_simd(in));
688static inline void copy_pixel(
float *
const __restrict__
out,
const float *
const __restrict__ in)
848int dt_init(
int argc,
char *argv[],
const gboolean init_gui,
const gboolean load_data);
885 for(
size_t k = 0;
k <
size /
sizeof(
unsigned char);
k++) {
886 unsigned char *
const item = (
unsigned char *
const)buffer +
k;
893static inline gboolean
dt_modifier_is(
const GdkModifierType
state,
const GdkModifierType desired_modifier_mask)
895 const GdkModifierType modifiers = gtk_accelerator_get_default_mod_mask();
897 return (
state & modifiers) == desired_modifier_mask;
904 const GdkModifierType modifiers = gtk_accelerator_get_default_mod_mask();
906 return (
state & (modifiers & desired_modifier_mask)) == desired_modifier_mask;
917 gettimeofday(&time, NULL);
918 return time.tv_sec - 1290608000 + (1.0 / 1000000.0) * time.tv_usec;
938#define g_list_is_singleton(list) ((list) && (!(list)->next))
945 if (!list)
return TRUE;
946 list = g_list_next(list);
954 return g_list_next(list) ? g_list_next(list) : list;
959 return g_list_next(list) ? g_list_next(list) : head;
966 return g_list_previous(list) ? g_list_previous(list) : g_list_last((GList*)list);
975int dt_load_from_string(
const gchar *image_to_load, gboolean open_image_in_dr, gboolean *single_image);
977#define dt_unreachable_codepath_with_desc(D) \
978 dt_unreachable_codepath_with_caller(D, __FILE__, __LINE__, __FUNCTION__)
979#define dt_unreachable_codepath() dt_unreachable_codepath_with_caller("unreachable", __FILE__, __LINE__, __FUNCTION__)
981 const int line,
const char *function)
983 fprintf(stderr,
"[dt_unreachable_codepath] {%s} %s:%d (%s) - we should not be here. please report this to "
986 __builtin_unreachable();
996 const size_t alloc_size =
n * objsize;
1005#ifndef dt_pixelpipe_cache_alloc_perthread
1006#define dt_pixelpipe_cache_alloc_perthread(n, objsize, padded_size) \
1007 ((void *)dt_pixelpipe_cache_alloc_perthread_impl((n), (objsize), (padded_size), __FILE__ ":" DT_STRINGIFY(__LINE__)))
1018#ifndef dt_pixelpipe_cache_calloc_perthread
1019#define dt_pixelpipe_cache_calloc_perthread(n, objsize, padded_size) \
1020 ((void *)dt_pixelpipe_cache_calloc_perthread_impl((n), (objsize), (padded_size), __FILE__ ":" DT_STRINGIFY(__LINE__)))
1029#ifndef dt_pixelpipe_cache_alloc_perthread_float
1030#define dt_pixelpipe_cache_alloc_perthread_float(n, padded_size) \
1031 ((float *)dt_pixelpipe_cache_alloc_perthread_float_impl((n), (padded_size), __FILE__ ":" DT_STRINGIFY(__LINE__)))
1035#define dt_get_perthread(buf, padsize) DT_IS_ALIGNED((buf) + ((padsize) * dt_get_thread_num()))
1038#define dt_get_bythread(buf, padsize, tnum) DT_IS_ALIGNED((buf) + ((padsize) * (tnum)))
1045 for(
size_t i = 0;
i <
size;
i++)
1046 hash = ((hash << 5) + hash) ^ str[
i];
1052#define DT_MAX_FILENAME_LEN 256
1062#define PATH_MAX 4096
1071#define DT_MAX_PATH_FOR_PARAMS 4096
1076 gchar **split = g_strsplit(
string, to_replace, -1);
1077 gchar *text = g_strjoinv(
"", split);
1099 PangoAttrList *attrs = NULL;
1100 gchar *plain = NULL;
1102 const gchar *underscore =
"_";
1103 gunichar mnemonic = underscore[0];
1104 if(!pango_parse_markup(s, -1, mnemonic, &attrs, &plain, NULL, NULL))
1107 pango_attr_list_unref(attrs);
const char ** description(struct dt_iop_module_t *self)
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)))
static const dt_aligned_pixel_simd_t const dt_aligned_pixel_simd_t row1
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.
void dt_show_times(const dt_times_t *start, const char *prefix)
static gchar * dt_string_replace(const char *string, const char *to_replace)
static float * dt_calloc_align_float(size_t pixels)
static void * dt_calloc_align(size_t size)
static gboolean dt_modifiers_include(const GdkModifierType state, const GdkModifierType desired_modifier_mask)
@ DT_DEBUG_CAMERA_SUPPORT
void dt_pixelpipe_cache_free_align_cache(struct dt_dev_pixelpipe_cache_t *cache, void **mem, const char *message)
void gboolean dt_supported_image(const gchar *filename)
check if file is a supported image
static void copy_pixel(float *const __restrict__ out, const float *const __restrict__ in)
static void dt_free_align_ptr(void *mem)
#define for_each_channel(_var,...)
float dt_boundingbox_t[4]
static float * dt_alloc_align_float(size_t pixels)
static size_t dt_round_size_sse(const size_t size)
void void dt_print_nts(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
static void * dt_check_sse_aligned(void *pointer)
static gchar * strip_markup(const char *s)
Remove Pango/Gtk markup and accels mnemonics from text labels. If the markup parsing fails,...
static void * dt_alloc_align_internal(size_t size)
void dt_print_mem_usage()
static void dt_free_gpointer(gpointer ptr)
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...
static void copy_pixel_nontemporal(float *const __restrict__ out, const float *const __restrict__ in)
void void void int dt_worker_threads()
static void * dt_pixelpipe_cache_alloc_perthread_impl(const size_t n, const size_t objsize, size_t *padded_size, const char *message)
static const GList * g_list_next_wraparound(const GList *list, const GList *head)
static const dt_aligned_pixel_simd_t sign
static int dt_get_thread_num()
void * dt_alloc_align(size_t size)
void dt_capabilities_remove(char *capability)
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
static void dt_get_times(dt_times_t *t)
int dt_init(int argc, char *argv[], const gboolean init_gui, const gboolean load_data)
static float * dt_pixelpipe_cache_alloc_perthread_float_impl(const size_t n, size_t *padded_size, const char *message)
#define omp_get_thread_num()
static const GList * g_list_prev_wraparound(const GList *list)
void void void dt_vprint(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
static gchar * delete_underscore(const char *s)
static uint64_t dt_hash(uint64_t hash, const char *str, size_t size)
size_t dt_get_mipmap_mem()
static size_t dt_round_size(const size_t size, const size_t alignment)
static void dt_unreachable_codepath_with_caller(const char *description, const char *file, const int line, const char *function)
int dt_load_from_string(const gchar *image_to_load, gboolean open_image_in_dr, gboolean *single_image)
#define DT_MODULE_VERSION
static const dt_aligned_pixel_simd_t const dt_aligned_pixel_simd_t const dt_aligned_pixel_simd_t row2
static GList * g_list_next_bounded(GList *list)
char * dt_version_major_minor()
void dt_configure_runtime_performance(dt_sys_resources_t *resources, gboolean init_gui)
static const dt_aligned_pixel_simd_t value
void dt_capabilities_add(char *capability)
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)
static void * dt_pixelpipe_cache_calloc_perthread_impl(const size_t n, const size_t objsize, size_t *padded_size, const char *message)
void dt_capabilities_cleanup()
static gboolean dt_is_aligned(const void *pointer, size_t byte_count)
static const dt_aligned_pixel_simd_t exponent
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)
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
size_t dt_get_available_mem()
int dt_capabilities_check(char *capability)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
#define DT_CACHELINE_BYTES
static gboolean g_list_shorter_than(const GList *list, unsigned len)
#define dt_pthread_rwlock_t
int getrusage(int who, struct rusage *usage)
float *const restrict const size_t k
float dt_aligned_pixel_t[4]
const float uint32_t state[4]
unsigned __int64 uint64_t
dt_pthread_mutex_t readFile_mutex
int32_t unmuted_signal_dbg_acts
struct dt_imageio_t * imageio
struct dt_dev_pixelpipe_cache_t * pixelpipe_cache
int32_t num_openmp_threads
struct dt_gui_gtk_t * gui
dt_pthread_rwlock_t database_threadsafe
struct dt_colorspaces_t * color_profiles
struct dt_collection_t * collection
struct dt_mipmap_cache_t * mipmap_cache
struct dt_selection_t * selection
dt_pthread_mutex_t exiv2_threadsafe
struct dt_sys_resources_t dtresources
dt_pthread_mutex_t plugin_threadsafe
dt_pthread_mutex_t capabilities_threadsafe
const struct dt_database_t * db
struct dt_control_signal_t * signals
struct dt_bauhaus_t * bauhaus
struct dt_opencl_t * opencl
struct dt_image_cache_t * image_cache
struct dt_develop_t * develop
struct dt_points_t * points
dt_pthread_mutex_t pipeline_threadsafe
struct dt_view_manager_t * view_manager
JsonParser * noiseprofile_parser
gboolean unmuted_signal_dbg[DT_SIGNAL_COUNT]
const struct dt_pwstorage_t * pwstorage
struct dt_control_t * control