diff --git a/data/darktableconfig.xml.in b/data/darktableconfig.xml.in index 8e106a6e1557..e9c8f0c62d6f 100644 --- a/data/darktableconfig.xml.in +++ b/data/darktableconfig.xml.in @@ -1349,6 +1349,8 @@ + + @@ -1368,6 +1370,8 @@ + + @@ -1408,6 +1412,8 @@ + + never diff --git a/src/common/mipmap_cache.c b/src/common/mipmap_cache.c index 19cc83122ca4..aa528352f4ed 100644 --- a/src/common/mipmap_cache.c +++ b/src/common/mipmap_cache.c @@ -1,6 +1,6 @@ /* This file is part of darktable, - Copyright (C) 2011-2025 darktable developers. + Copyright (C) 2011-2026 darktable developers. darktable is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -466,7 +466,7 @@ static void _mipmap_cache_allocate_dynamic(void *data, dt_cache_entry_t *entry) // alloc mere minimum for the header + broken image buffer: if(!dsc) { - if(mip == DT_MIPMAP_8) + if(mip == DT_MIPMAP_LDR_MAX) { int imgfw= 0, imgfh= 0; // be sure that we have the right size values @@ -516,10 +516,10 @@ static void _mipmap_cache_allocate_dynamic(void *data, dt_cache_entry_t *entry) assert(dsc->size >= sizeof(*dsc)); int loaded_from_disk = 0; - if(mip < DT_MIPMAP_F) + if(mip <= DT_MIPMAP_LDR_MAX) { - if(cache->cachedir[0] && ((dt_conf_get_bool("cache_disk_backend") && mip < DT_MIPMAP_8) - || (dt_conf_get_bool("cache_disk_backend_full") && mip == DT_MIPMAP_8))) + if(cache->cachedir[0] && ((dt_conf_get_bool("cache_disk_backend") && mip < DT_MIPMAP_LDR_MAX) + || (dt_conf_get_bool("cache_disk_backend_full") && mip == DT_MIPMAP_LDR_MAX))) { // try and load from disk, if successful set flag char filename[PATH_MAX] = {0}; @@ -576,7 +576,7 @@ static void _mipmap_cache_allocate_dynamic(void *data, dt_cache_entry_t *entry) // to make sure quota is meaningful. if(mip >= DT_MIPMAP_F) entry->cost = 1; - else if(mip == DT_MIPMAP_8) + else if(mip == DT_MIPMAP_LDR_MAX) entry->cost = entry->data_size; else entry->cost = cache->buffer_size[mip]; @@ -603,7 +603,7 @@ static void _mipmap_cache_deallocate_dynamic(void *data, dt_cache_entry_t *entry { dt_mipmap_cache_t *cache = (dt_mipmap_cache_t *)data; const dt_mipmap_size_t mip = _get_size(entry->key); - if(mip < DT_MIPMAP_F) + if(mip <= DT_MIPMAP_LDR_MAX) { dt_mipmap_buffer_dsc_t *dsc = (dt_mipmap_buffer_dsc_t *)entry->data; // don't write skulls: @@ -613,8 +613,8 @@ static void _mipmap_cache_deallocate_dynamic(void *data, dt_cache_entry_t *entry { _mipmap_cache_unlink_ondisk_thumbnail(data, _get_imgid(entry->key), mip); } - else if(cache->cachedir[0] && ((dt_conf_get_bool("cache_disk_backend") && mip < DT_MIPMAP_8) - || (dt_conf_get_bool("cache_disk_backend_full") && mip == DT_MIPMAP_8))) + else if(cache->cachedir[0] && ((dt_conf_get_bool("cache_disk_backend") && mip < DT_MIPMAP_LDR_MAX) + || (dt_conf_get_bool("cache_disk_backend_full") && mip == DT_MIPMAP_LDR_MAX))) { // serialize to disk char filename[PATH_MAX] = {0}; @@ -705,25 +705,26 @@ void dt_mipmap_cache_init() { 1920, 1200 }, // mip4 - covers 1080p and 1600x1200 { 2560, 1600 }, // mip5 - covers 2560x1440 { 4096, 2560 }, // mip6 - covers 4K and UHD - { 5120, 3200 }, // mip7 - covers 5120x2880 panels - { 999999999, 999999999 }, // mip8 - used for full preview at full size + { 5120, 3200 }, // mip7 - covers 5K + { 6144, 3456 }, // mip8 - covers 6K + { 7680, 4320 }, // mip9 - covers 8K + { 999999999, 999999999 }, // mip10 - used for full preview at full size }; - // Set mipf to mip2 size as at most the user will be using an 8K screen and - // have a preview that's ~4x smaller + // Set mipf to mip3 size, which is ~4x smaller than a 6K screen screen const char *preview_downsample = dt_conf_get_string_const("preview_downsampling"); const float downsample = (!g_strcmp0(preview_downsample, "original")) ? 1.0f : (!g_strcmp0(preview_downsample, "to 1/2")) ? 0.5f : (!g_strcmp0(preview_downsample, "to 1/3")) ? 1/3.0f : 0.25f; - cache->max_width[DT_MIPMAP_F] = mipsizes[DT_MIPMAP_2][0] * downsample; - cache->max_height[DT_MIPMAP_F] = mipsizes[DT_MIPMAP_2][1] * downsample; - for(int k = DT_MIPMAP_F-1; k >= 0; k--) + cache->max_width[DT_MIPMAP_F] = mipsizes[DT_MIPMAP_3][0] * downsample; + cache->max_height[DT_MIPMAP_F] = mipsizes[DT_MIPMAP_3][1] * downsample; + for(int k = DT_MIPMAP_LDR_MAX; k >= 0; k--) { cache->max_width[k] = mipsizes[k][0]; cache->max_height[k] = mipsizes[k][1]; } - // header + buffer - for(int k = DT_MIPMAP_F-1; k >= 0; k--) + // header + buffer + for(int k = DT_MIPMAP_LDR_MAX; k >= 0; k--) cache->buffer_size[k] = sizeof(dt_mipmap_buffer_dsc_t) + (size_t)cache->max_width[k] * cache->max_height[k] * 4; @@ -1063,7 +1064,7 @@ void dt_mipmap_cache_get_with_caller(dt_mipmap_buffer_t *buf, const dt_imageio_retval_t ret = img ? img->load_status : DT_IMAGEIO_FILE_NOT_FOUND; dt_image_cache_read_release(img); dt_print(DT_DEBUG_PIPE, "[mipmap cache get] got a zero-sized ID=%d mip %d!", imgid, mip); - if(mip < DT_MIPMAP_F) + if(mip <= DT_MIPMAP_LDR_MAX) { switch(ret) { @@ -1130,7 +1131,7 @@ void dt_mipmap_cache_get_with_caller(dt_mipmap_buffer_t *buf, } } // couldn't find a smaller thumb, try larger ones only now (these will be slightly slower due to cairo rescaling): - dt_mipmap_size_t max_mip = (mip >= DT_MIPMAP_F) ? mip : DT_MIPMAP_F-1; + dt_mipmap_size_t max_mip = (mip >= DT_MIPMAP_F) ? mip : DT_MIPMAP_LDR_MAX; for(int k = mip+1; k <= max_mip; k++) { // already loaded? @@ -1196,7 +1197,7 @@ dt_mipmap_size_t dt_mipmap_cache_get_matching_size(const int32_t width, dt_mipmap_cache_t *cache = darktable.mipmap_cache; dt_mipmap_size_t best = DT_MIPMAP_NONE; assert(cache); - for(int k = DT_MIPMAP_0; k < DT_MIPMAP_F; k++) + for(int k = DT_MIPMAP_0; k <= DT_MIPMAP_LDR_MAX; k++) { best = k; if((cache->max_width[k] >= width) && (cache->max_height[k] >= height)) @@ -1215,6 +1216,8 @@ dt_mipmap_size_t dt_mipmap_cache_get_min_mip_from_pref(const char *value) if(strcmp(value, "WQXGA") == 0) return DT_MIPMAP_5; if(strcmp(value, "4K") == 0) return DT_MIPMAP_6; if(strcmp(value, "5K") == 0) return DT_MIPMAP_7; + if(strcmp(value, "6K") == 0) return DT_MIPMAP_8; + if(strcmp(value, "8K") == 0) return DT_MIPMAP_9; return DT_MIPMAP_NONE; } @@ -1223,7 +1226,7 @@ void dt_mipmap_cache_remove_at_size(const dt_imgid_t imgid, { dt_mipmap_cache_t *cache = darktable.mipmap_cache; assert(cache); - if(!cache || mip > DT_MIPMAP_8 || mip < DT_MIPMAP_0) return; + if(!cache || mip > DT_MIPMAP_LDR_MAX || mip < DT_MIPMAP_0) return; // get rid of all ldr thumbnails: const uint32_t key = _get_key(imgid, mip); dt_cache_entry_t *entry = dt_cache_testget(&_get_cache(cache, mip)->cache, key, 'w'); @@ -1246,7 +1249,7 @@ void dt_mipmap_cache_remove_at_size(const dt_imgid_t imgid, void dt_mipmap_cache_remove(const dt_imgid_t imgid) { - for(dt_mipmap_size_t k = DT_MIPMAP_0; k < DT_MIPMAP_F; k++) + for(dt_mipmap_size_t k = DT_MIPMAP_0; k <= DT_MIPMAP_LDR_MAX; k++) { dt_mipmap_cache_remove_at_size(imgid, k); } @@ -1266,7 +1269,7 @@ void dt_mipmap_cache_evict_at_size(const dt_imgid_t imgid, void dt_mipmap_cache_evict(const dt_imgid_t imgid) { dt_mipmap_cache_t *cache = darktable.mipmap_cache; - for(dt_mipmap_size_t k = DT_MIPMAP_0; k < DT_MIPMAP_F; k++) + for(dt_mipmap_size_t k = DT_MIPMAP_0; k <= DT_MIPMAP_LDR_MAX; k++) { const uint32_t key = _get_key(imgid, k); @@ -1533,7 +1536,7 @@ static void _init_8(uint8_t *buf, if(res) { //try to generate mip from larger mip - for(dt_mipmap_size_t k = size + 1; k < DT_MIPMAP_F; k++) + for(dt_mipmap_size_t k = size + 1; k <= DT_MIPMAP_LDR_MAX; k++) { dt_mipmap_buffer_t tmp; dt_mipmap_cache_get(&tmp, imgid, k, DT_MIPMAP_TESTLOCK, 'r'); @@ -1618,7 +1621,7 @@ void dt_mipmap_cache_copy_thumbnails(const dt_imgid_t dst_imgid, && dt_is_valid_imgid(src_imgid) && dt_is_valid_imgid(dst_imgid)) { - for(dt_mipmap_size_t mip = DT_MIPMAP_0; mip < DT_MIPMAP_F; mip++) + for(dt_mipmap_size_t mip = DT_MIPMAP_0; mip <= DT_MIPMAP_LDR_MAX; mip++) { // try and load from disk, if successful set flag char srcpath[PATH_MAX] = {0}; diff --git a/src/common/mipmap_cache.h b/src/common/mipmap_cache.h index 1c3aef8e3c63..54895b0fdba4 100644 --- a/src/common/mipmap_cache.h +++ b/src/common/mipmap_cache.h @@ -1,6 +1,6 @@ /* This file is part of darktable, - Copyright (C) 2011-2025 darktable developers. + Copyright (C) 2011-2026 darktable developers. darktable is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ G_BEGIN_DECLS // sizes stored in the mipmap cache, set to fixed values in mipmap_cache.c typedef enum dt_mipmap_size_t { + // 8 bit, downscaled, for lighttable thumbnails DT_MIPMAP_0 = 0, DT_MIPMAP_1, DT_MIPMAP_2, @@ -35,11 +36,18 @@ typedef enum dt_mipmap_size_t { DT_MIPMAP_6, DT_MIPMAP_7, DT_MIPMAP_8, + DT_MIPMAP_9, + // 8 bit, full resolution, for zoomed in thumbnail + DT_MIPMAP_10, + // float, downscaled, for preview pixelpipe DT_MIPMAP_F, + // float, full resolution, for full/export pixelpipe DT_MIPMAP_FULL, DT_MIPMAP_NONE } dt_mipmap_size_t; +static const dt_mipmap_size_t DT_MIPMAP_LDR_MAX = DT_MIPMAP_10; + // type to be passed to getter functions typedef enum dt_mipmap_get_flags_t { diff --git a/src/control/crawler.c b/src/control/crawler.c index f5bec053640a..71e39e90c658 100644 --- a/src/control/crawler.c +++ b/src/control/crawler.c @@ -861,7 +861,7 @@ static inline gboolean _lighttable_silent(void) static inline gboolean _valid_mip(dt_mipmap_size_t mip) { - return mip > DT_MIPMAP_0 && mip < DT_MIPMAP_8; + return mip > DT_MIPMAP_0 && mip < DT_MIPMAP_LDR_MAX; } static inline gboolean _still_thumbing(void) @@ -990,7 +990,7 @@ void dt_update_thumbs_thread(void *p) } // return if any thumbcache dir is not writable - for(dt_mipmap_size_t k = DT_MIPMAP_1; k <= DT_MIPMAP_7; k++) + for(dt_mipmap_size_t k = DT_MIPMAP_1; k <= DT_MIPMAP_LDR_MAX-1; k++) { char dirname[PATH_MAX] = { 0 }; snprintf(dirname, sizeof(dirname), "%s.d/%d", darktable.mipmap_cache->cachedir, k); diff --git a/src/dtgtk/thumbnail.c b/src/dtgtk/thumbnail.c index dc3e011729f1..1106832c1b61 100644 --- a/src/dtgtk/thumbnail.c +++ b/src/dtgtk/thumbnail.c @@ -467,7 +467,7 @@ static void _get_dimensions_for_img_to_fit(const dt_thumbnail_t *thumb, // decimal, so not enough accurate so we compute it from the larger // available mipmap float ar = 0.0f; - for(int k = DT_MIPMAP_7; k >= DT_MIPMAP_0; k--) + for(int k = DT_MIPMAP_LDR_MAX; k >= DT_MIPMAP_0; k--) { dt_mipmap_buffer_t tmp; dt_mipmap_cache_get(&tmp, thumb->imgid, k, DT_MIPMAP_TESTLOCK, 'r'); diff --git a/src/dtgtk/thumbtable.c b/src/dtgtk/thumbtable.c index 1037da19955a..2c3d3f6a36ff 100644 --- a/src/dtgtk/thumbtable.c +++ b/src/dtgtk/thumbtable.c @@ -1676,8 +1676,8 @@ static void _thumbs_ask_for_discard(dt_thumbtable_t *table) dt_mipmap_size_t embeddedl = dt_mipmap_cache_get_min_mip_from_pref(embedded); - int min_level = 8; - int max_level = 0; + int min_level = DT_MIPMAP_LDR_MAX; + int max_level = DT_MIPMAP_0; if(hql != table->pref_hq) { min_level = MIN(table->pref_hq, hql); @@ -1696,9 +1696,9 @@ static void _thumbs_ask_for_discard(dt_thumbtable_t *table) gchar *txt = g_strdup(_("you have changed the settings related to" " how thumbnails are generated.\n")); - if(max_level >= DT_MIPMAP_8 && min_level == DT_MIPMAP_0) + if(max_level >= DT_MIPMAP_LDR_MAX && min_level == DT_MIPMAP_0) dt_util_str_cat(&txt, _("all cached thumbnails need to be invalidated.\n\n")); - else if(max_level >= DT_MIPMAP_8) + else if(max_level >= DT_MIPMAP_LDR_MAX) dt_util_str_cat (&txt, _("cached thumbnails starting from level %d need to be invalidated.\n\n"), diff --git a/src/generate-cache/main.c b/src/generate-cache/main.c index eb75ab089217..94b384e3ee70 100644 --- a/src/generate-cache/main.c +++ b/src/generate-cache/main.c @@ -1,6 +1,6 @@ /* This file is part of darktable, - Copyright (C) 2015-2024 darktable developers. + Copyright (C) 2015-2026 darktable developers. darktable is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -181,12 +181,12 @@ int main(int argc, char *arg[]) else if((!strcmp(arg[k], "-m") || !strcmp(arg[k], "--max-mip")) && argc > k + 1) { k++; - max_mip = (dt_mipmap_size_t)MIN(MAX(atoi(arg[k]), DT_MIPMAP_0), DT_MIPMAP_8); + max_mip = (dt_mipmap_size_t)MIN(MAX(atoi(arg[k]), DT_MIPMAP_0), DT_MIPMAP_LDR_MAX); } else if(!strcmp(arg[k], "--min-mip") && argc > k + 1) { k++; - min_mip = (dt_mipmap_size_t)MIN(MAX(atoi(arg[k]), DT_MIPMAP_0), DT_MIPMAP_8); + min_mip = (dt_mipmap_size_t)MIN(MAX(atoi(arg[k]), DT_MIPMAP_0), DT_MIPMAP_LDR_MAX); } else if(!strcmp(arg[k], "--min-imgid") && argc > k + 1) {