From 4502522a7aee093c923e79a65e4684ea2634af30 Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Tue, 2 May 2023 19:42:23 -0500 Subject: [PATCH] player: use XDG_CACHE_HOME by default This adds cache as a possible path for mpv to internally pick (~/.cache/mpv for non-darwin unix-like systems, the usual config directory for everyone else). For gpu shader cache and icc cache, controlling whether or not to write such files is done with the new --gpu-shader-cache and --icc-cache options respectively. Additionally, --cache-on-disk no longer requires explicitly setting the --cache-dir option. The old options, --cache-dir, --gpu-shader-cache-dir, and --icc-cache-dir simply set an override for the directory to save cache files. If unset, then the cache is saved in XDG_CACHE_HOME. --- DOCS/interface-changes.rst | 7 +++++++ DOCS/man/mpv.rst | 2 ++ DOCS/man/options.rst | 30 +++++++++++++++++++----------- common/global.h | 1 + demux/cache.c | 8 +++++--- options/path.c | 7 ++++++- osdep/path-unix.c | 11 +++++++++++ osdep/path.h | 1 + video/out/gpu/lcms.c | 12 +++++++++--- video/out/gpu/lcms.h | 1 + video/out/gpu/shader_cache.c | 7 ++++++- video/out/gpu/shader_cache.h | 2 +- video/out/gpu/video.c | 4 +++- video/out/gpu/video.h | 1 + video/out/vo_gpu_next.c | 18 ++++++++++++++---- 15 files changed, 87 insertions(+), 25 deletions(-) diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst index 028759f261..a842b7a155 100644 --- a/DOCS/interface-changes.rst +++ b/DOCS/interface-changes.rst @@ -64,6 +64,13 @@ Interface changes - `--save-position-on-quit` and its associated commands now store state files in the XDG_STATE_HOME directory by default. This only has an effect on linux/bsd systems. + - mpv now implictly saves cache files in XDG_CACHE_HOME by default. This only has + an effect if the user enables options that would lead to cache being stored and + only makes a difference on linux/bsd systems. + - `--cache-on-disk` no longer requires explictly setting the `--cache-dir` option + - add `--icc-cache` and `--gpu-shader-cache` options to control whether or not to + save cache files for these features; explictly setting `--icc-cache-dir` and + `--gpu-shader-cache` is no longer required --- mpv 0.35.0 --- - add the `--vo=gpu-next` video output driver, as well as the options `--allow-delayed-peak-detect`, `--builtin-scalers`, diff --git a/DOCS/man/mpv.rst b/DOCS/man/mpv.rst index 63042e2925..a468fabba3 100644 --- a/DOCS/man/mpv.rst +++ b/DOCS/man/mpv.rst @@ -461,6 +461,8 @@ Name Meaning ``~~desktop/`` the path to the desktop (win32, macOS) ``~~exe_dir/`` win32 only: the path to the directory containing the exe (for config file purposes; ``$MPV_HOME`` overrides it) +``~~cache/`` the path to application cache data (``~/.cache/mpv/``) + On some platforms, this will be the same as ``~~home/``. ``~~state/`` the path to application state data (``~/.local/state/mpv/``) On some platforms, this will be the same as ``~~home/``. ``~~old_home/`` do not use diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 96b969ba11..f366bc995d 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -4771,8 +4771,6 @@ Cache This makes sense only with ``--cache``. If the normal cache is disabled, this option is ignored. - You need to set ``--cache-dir`` to use this. - The cache file is append-only. Even if the player appears to prune data, the file space freed by it is not reused. The cache file is deleted when playback is closed. @@ -4795,7 +4793,8 @@ Cache continue to use the cache file that was opened first. ``--cache-dir=`` - Directory where to create temporary files (default: none). + Directory where to create temporary files. Cache is stored in the system's + cache directory (usually ``~/.cache/mpv``) if this is unset. Currently, this is used for ``--cache-on-disk`` only. @@ -6634,15 +6633,20 @@ them. Applications using libmpv with the render API need to provide the ICC profile via ``MPV_RENDER_PARAM_ICC_PROFILE``. -``--icc-cache-dir=`` - Store and load the 3D LUTs created from the ICC profile in this directory. - This can be used to speed up loading, since LittleCMS 2 can take a while to - create a 3D LUT. Note that these files contain uncompressed LUTs. Their - size depends on the ``--icc-3dlut-size``, and can be very big. +``--icc-cache`` + Store and load 3D LUTs created from the ICC profile on disk in the + cache directory. This can be used to speed up loading, since LittleCMS + 2 can take a while to create a 3D LUT. Note that these files contain + uncompressed LUTs. Their size depends on the ``--icc-3dlut-size``, and + can be very big. NOTE: This is not cleaned automatically, so old, unused cache files may stick around indefinitely. +``--icc-cache-dir`` + The directory where icc cache is stored. Cache is stored in the system's + cache directory (usually ``~/.cache/mpv``) if this is unset. + ``--icc-intent=`` Specifies the ICC intent used for the color transformation (when using ``--icc-profile``). @@ -6775,9 +6779,9 @@ them. This option might be silently removed in the future. -``--gpu-shader-cache-dir=`` - Store and load compiled GLSL shaders in this directory. Normally, shader - compilation is very fast, so this is usually not needed. It mostly matters +``--gpu-shader-cache`` + Store and load compiled GLSL shaders in the cache directory. Normally, shader + compilation is very fast, so this is not usually needed. It mostly matters for GPU APIs that require internally recompiling shaders to other languages, for example anything based on ANGLE or Vulkan. Enabling this can improve startup performance on these platforms. @@ -6785,6 +6789,10 @@ them. NOTE: This is not cleaned automatically, so old, unused cache files may stick around indefinitely. +``--gpu-shader-cache-dir`` + The directory where gpu shader cache is stored. Cache is stored in the system's + cache directory (usually ``~/.cache/mpv``) if this is unset. + Miscellaneous ------------- diff --git a/common/global.h b/common/global.h index a7e4c4cee8..09b59593b0 100644 --- a/common/global.h +++ b/common/global.h @@ -10,6 +10,7 @@ struct mpv_global { struct mp_client_api *client_api; char *configdir; struct stats_base *stats; + bool no_cachedir; bool no_statedir; }; diff --git a/demux/cache.c b/demux/cache.c index f48598807c..08ac193cdf 100644 --- a/demux/cache.c +++ b/demux/cache.c @@ -100,10 +100,12 @@ struct demux_cache *demux_cache_create(struct mpv_global *global, cache->fd = -1; char *cache_dir = cache->opts->cache_dir; - if (!(cache_dir && cache_dir[0])) { - MP_ERR(cache, "No cache data directory supplied.\n"); - goto fail; + if (cache_dir && cache_dir[0]) { + cache_dir = mp_get_user_path(NULL, global, cache_dir); + } else { + cache_dir = mp_find_user_file(NULL, global, "cache", ""); } + mp_mkdirp(cache_dir); cache->filename = mp_path_join(cache, cache_dir, "mpv-cache-XXXXXX.dat"); cache->fd = mp_mkostemps(cache->filename, 4, O_CLOEXEC); diff --git a/options/path.c b/options/path.c index 4ea7269d01..e1aaa48907 100644 --- a/options/path.c +++ b/options/path.c @@ -74,7 +74,7 @@ static const char *mp_get_platform_path(void *talloc_ctx, { assert(talloc_ctx); - bool config_dir = strcmp(type, "state") != 0; + bool config_dir = strcmp(type, "cache") != 0 && strcmp(type, "state") != 0; if (global->configdir && config_dir) { for (int n = 0; n < MP_ARRAY_SIZE(config_dirs); n++) { if (strcmp(config_dirs[n], type) == 0) @@ -84,6 +84,8 @@ static const char *mp_get_platform_path(void *talloc_ctx, // Return the native config path if the platform doesn't support the // type we are trying to fetch. + if (strcmp(type, "cache") == 0 && global->no_cachedir) + type = "home"; if (strcmp(type, "state") == 0 && global->no_statedir) type = "home"; @@ -102,7 +104,10 @@ void mp_init_paths(struct mpv_global *global, struct MPOpts *opts) // Check if the platform has unique directories that differ from // the standard config directory. void *tmp = talloc_new(NULL); + const char *cache = mp_get_platform_path(tmp, global, "cache"); const char *state = mp_get_platform_path(tmp, global, "state"); + if (!cache) + global->no_cachedir = true; if (!state) global->no_statedir = true; talloc_free(tmp); diff --git a/osdep/path-unix.c b/osdep/path-unix.c index 34187b430e..5dc5cb2836 100644 --- a/osdep/path-unix.c +++ b/osdep/path-unix.c @@ -27,11 +27,13 @@ static pthread_once_t path_init_once = PTHREAD_ONCE_INIT; static char mpv_home[512]; static char old_home[512]; +static char mpv_cache[512]; static char mpv_state[512]; static void path_init(void) { char *home = getenv("HOME"); + char *xdg_cache = getenv("XDG_CACHE_HOME"); char *xdg_config = getenv("XDG_CONFIG_HOME"); char *xdg_state = getenv("XDG_STATE_HOME"); @@ -45,6 +47,12 @@ static void path_init(void) if (home && home[0]) snprintf(old_home, sizeof(old_home), "%s/.mpv", home); + if (xdg_cache && xdg_cache[0]) { + snprintf(mpv_cache, sizeof(mpv_cache), "%s/mpv", xdg_cache); + } else if (home && home[0]) { + snprintf(mpv_cache, sizeof(mpv_cache), "%s/.cache/mpv", home); + } + if (xdg_state && xdg_state[0]) { snprintf(mpv_state, sizeof(mpv_state), "%s/mpv", xdg_state); } else if (home && home[0]) { @@ -55,6 +63,7 @@ static void path_init(void) // config dir only. Also do not use any other XDG directories. if (mp_path_exists(old_home) && !mp_path_exists(mpv_home)) { snprintf(mpv_home, sizeof(mpv_home), "%s", old_home); + snprintf(mpv_cache, sizeof(mpv_cache), "%s", old_home); snprintf(mpv_state, sizeof(mpv_state), "%s", old_home); old_home[0] = '\0'; } @@ -67,6 +76,8 @@ const char *mp_get_platform_path_unix(void *talloc_ctx, const char *type) return mpv_home; if (strcmp(type, "old_home") == 0) return old_home; + if (strcmp(type, "cache") == 0) + return mpv_cache; if (strcmp(type, "state") == 0) return mpv_state; if (strcmp(type, "global") == 0) diff --git a/osdep/path.h b/osdep/path.h index d678b12072..2c00ea56eb 100644 --- a/osdep/path.h +++ b/osdep/path.h @@ -15,6 +15,7 @@ // implemented on every platform. Unlike some other type values that are // platform specific (like "osxbundle"), the value of "home" is returned // instead if these types are not explicitly defined. +// "cache" the native mpv-specific user cache dir // "state" the native mpv-specific user state dir // // It is allowed to return a static string, so the caller must set talloc_ctx diff --git a/video/out/gpu/lcms.c b/video/out/gpu/lcms.c index bbf857d968..be65dc965e 100644 --- a/video/out/gpu/lcms.c +++ b/video/out/gpu/lcms.c @@ -332,7 +332,7 @@ bool gl_lcms_get_lut3d(struct gl_lcms *p, struct lut3d **result_lut3d, cmsContext cms = NULL; char *cache_file = NULL; - if (p->opts->cache_dir && p->opts->cache_dir[0]) { + if (p->opts->cache) { // Gamma is included in the header to help uniquely identify it, // because we may change the parameter in the future or make it // customizable, same for the primaries. @@ -352,7 +352,13 @@ bool gl_lcms_get_lut3d(struct gl_lcms *p, struct lut3d **result_lut3d, av_sha_final(sha, hash); av_free(sha); - char *cache_dir = mp_get_user_path(tmp, p->global, p->opts->cache_dir); + char *cache_dir = p->opts->cache_dir; + if (cache_dir && cache_dir[0]) { + cache_dir = mp_get_user_path(NULL, p->global, cache_dir); + } else { + cache_dir = mp_find_user_file(NULL, p->global, "cache", ""); + } + cache_file = talloc_strdup(tmp, ""); for (int i = 0; i < sizeof(hash); i++) cache_file = talloc_asprintf_append(cache_file, "%02X", hash[i]); @@ -494,13 +500,13 @@ const struct m_sub_options mp_icc_conf = { {"use-embedded-icc-profile", OPT_BOOL(use_embedded)}, {"icc-profile", OPT_STRING(profile), .flags = M_OPT_FILE}, {"icc-profile-auto", OPT_BOOL(profile_auto)}, + {"icc-cache", OPT_BOOL(cache)}, {"icc-cache-dir", OPT_STRING(cache_dir), .flags = M_OPT_FILE}, {"icc-intent", OPT_INT(intent)}, {"icc-force-contrast", OPT_CHOICE(contrast, {"no", 0}, {"inf", -1}), M_RANGE(0, 1000000)}, {"icc-3dlut-size", OPT_STRING_VALIDATE(size_str, validate_3dlut_size_opt)}, {"3dlut-size", OPT_REPLACED("icc-3dlut-size")}, - {"icc-cache", OPT_REMOVED("see icc-cache-dir")}, {"icc-contrast", OPT_REMOVED("see icc-force-contrast")}, {0} }, diff --git a/video/out/gpu/lcms.h b/video/out/gpu/lcms.h index bd4b16175a..442c829333 100644 --- a/video/out/gpu/lcms.h +++ b/video/out/gpu/lcms.h @@ -13,6 +13,7 @@ struct mp_icc_opts { bool use_embedded; char *profile; bool profile_auto; + bool cache; char *cache_dir; char *size_str; int intent; diff --git a/video/out/gpu/shader_cache.c b/video/out/gpu/shader_cache.c index 9eedb1cd07..a046831f80 100644 --- a/video/out/gpu/shader_cache.c +++ b/video/out/gpu/shader_cache.c @@ -557,9 +557,14 @@ static void update_uniform(struct gl_shader_cache *sc, struct sc_entry *e, } } -void gl_sc_set_cache_dir(struct gl_shader_cache *sc, const char *dir) +void gl_sc_set_cache_dir(struct gl_shader_cache *sc, char *dir) { talloc_free(sc->cache_dir); + if (dir && dir[0]) { + dir = mp_get_user_path(NULL, sc->global, dir); + } else { + dir = mp_find_user_file(NULL, sc->global, "cache", ""); + } sc->cache_dir = talloc_strdup(sc, dir); } diff --git a/video/out/gpu/shader_cache.h b/video/out/gpu/shader_cache.h index 3c87513b2b..7c51c7aead 100644 --- a/video/out/gpu/shader_cache.h +++ b/video/out/gpu/shader_cache.h @@ -63,4 +63,4 @@ struct mp_pass_perf gl_sc_dispatch_compute(struct gl_shader_cache *sc, // The application can call this on errors, to reset the current shader. This // is normally done implicitly by gl_sc_dispatch_* void gl_sc_reset(struct gl_shader_cache *sc); -void gl_sc_set_cache_dir(struct gl_shader_cache *sc, const char *dir); +void gl_sc_set_cache_dir(struct gl_shader_cache *sc, char *dir); diff --git a/video/out/gpu/video.c b/video/out/gpu/video.c index cfd864680b..2d16d8435e 100644 --- a/video/out/gpu/video.c +++ b/video/out/gpu/video.c @@ -465,6 +465,7 @@ const struct m_sub_options gl_video_conf = { {"gpu-tex-pad-x", OPT_INT(tex_pad_x), M_RANGE(0, 4096)}, {"gpu-tex-pad-y", OPT_INT(tex_pad_y), M_RANGE(0, 4096)}, {"", OPT_SUBSTRUCT(icc_opts, mp_icc_conf)}, + {"gpu-shader-cache", OPT_BOOL(shader_cache)}, {"gpu-shader-cache-dir", OPT_STRING(shader_cache_dir), .flags = M_OPT_FILE}, {"gpu-hwdec-interop", OPT_STRING_VALIDATE(hwdec_interop, ra_hwdec_validate_opt)}, @@ -4099,7 +4100,8 @@ static void reinit_from_options(struct gl_video *p) check_gl_features(p); uninit_rendering(p); - gl_sc_set_cache_dir(p->sc, p->opts.shader_cache_dir); + if (p->opts.shader_cache) + gl_sc_set_cache_dir(p->sc, p->opts.shader_cache_dir); p->ra->use_pbo = p->opts.pbo; gl_video_setup_hooks(p); reinit_osd(p); diff --git a/video/out/gpu/video.h b/video/out/gpu/video.h index 0ef4618790..5a974f9ee0 100644 --- a/video/out/gpu/video.h +++ b/video/out/gpu/video.h @@ -171,6 +171,7 @@ struct gl_video_opts { float unsharp; int tex_pad_x, tex_pad_y; struct mp_icc_opts *icc_opts; + bool shader_cache; int early_flush; char *shader_cache_dir; char *hwdec_interop; diff --git a/video/out/vo_gpu_next.c b/video/out/vo_gpu_next.c index fbee007cc8..8416f4f2f7 100644 --- a/video/out/vo_gpu_next.c +++ b/video/out/vo_gpu_next.c @@ -1348,10 +1348,15 @@ static void wait_events(struct vo *vo, int64_t until_time_us) static char *get_cache_file(struct priv *p) { struct gl_video_opts *opts = p->opts_cache->opts; - if (!opts->shader_cache_dir || !opts->shader_cache_dir[0]) + if (!opts->shader_cache) return NULL; - char *dir = mp_get_user_path(NULL, p->global, opts->shader_cache_dir); + char *dir = opts->shader_cache_dir; + if (dir && dir[0]) { + dir = mp_get_user_path(NULL, p->global, dir); + } else { + dir = mp_find_user_file(NULL, p->global, "cache", ""); + } char *file = mp_path_join(NULL, dir, "libplacebo.cache"); mp_mkdirp(dir); talloc_free(dir); @@ -1575,7 +1580,7 @@ static const struct pl_hook *load_hook(struct priv *p, const char *path) static stream_t *icc_open_cache(struct priv *p, uint64_t sig, int flags) { const struct gl_video_opts *opts = p->opts_cache->opts; - if (!opts->icc_opts->cache_dir || !opts->icc_opts->cache_dir[0]) + if (!opts->icc_opts->cache) return NULL; char cache_name[16+1]; @@ -1585,7 +1590,12 @@ static stream_t *icc_open_cache(struct priv *p, uint64_t sig, int flags) } cache_name[16] = '\0'; - char *cache_dir = mp_get_user_path(NULL, p->global, opts->icc_opts->cache_dir); + char *cache_dir = opts->icc_opts->cache_dir; + if (cache_dir && cache_dir[0]) { + cache_dir = mp_get_user_path(NULL, p->global, cache_dir); + } else { + cache_dir = mp_find_user_file(NULL, p->global, "cache", ""); + } char *path = mp_path_join(NULL, cache_dir, cache_name); stream_t *stream = NULL;