diff --git a/include/chroma.h b/include/chroma.h index eee298a..6c8ed6e 100644 --- a/include/chroma.h +++ b/include/chroma.h @@ -99,6 +99,7 @@ typedef struct { GLuint ebo; bool gl_resources_initialized; bool texture_uploaded; + bool vbo_dirty; // track VBO needs update } chroma_output_t; // Config mapping structure @@ -119,6 +120,12 @@ typedef struct { // Global scaling and filtering settings (used as defaults) chroma_scale_mode_t default_scale_mode; chroma_filter_quality_t default_filter_quality; + + // Image downsampling settings + bool enable_downsampling; // enable automatic downsampling + int max_output_width; // maximum expected output width + int max_output_height; // maximum expected output height + float min_scale_factor; // minimum scale factor (don't scale below this) } chroma_config_t; // Main application state @@ -205,7 +212,8 @@ void chroma_layer_surface_closed(void *data, // Image loading void chroma_image_init_stb(void); -int chroma_image_load(chroma_image_t *image, const char *path); +int chroma_image_load(chroma_image_t *image, const char *path, + const chroma_config_t *config); void chroma_image_free(chroma_image_t *image); chroma_image_t *chroma_image_find_by_path(chroma_state_t *state, const char *path); @@ -224,7 +232,7 @@ const char *chroma_config_get_image_for_output(chroma_config_t *config, int chroma_config_get_mapping_for_output( chroma_config_t *config, const char *output_name, chroma_scale_mode_t *scale_mode, chroma_filter_quality_t *filter_quality); -int chroma_config_create_sample(const char *config_file); + void chroma_config_print(const chroma_config_t *config); // Main loop and events diff --git a/src/config.c b/src/config.c index 6dde3b1..619af3a 100644 --- a/src/config.c +++ b/src/config.c @@ -184,6 +184,12 @@ static void init_default_config(chroma_config_t *config) { config->default_scale_mode = CHROMA_SCALE_FILL; config->default_filter_quality = CHROMA_FILTER_LINEAR; + // Set default downsampling settings + config->enable_downsampling = true; // enable by default, performance etc. + config->max_output_width = 3840; // 4K width + config->max_output_height = 2160; // 4K height + config->min_scale_factor = 0.25f; // don't scale below 25% + // Set default image path (can be overridden) const char *home = getenv("HOME"); if (home) { @@ -276,6 +282,34 @@ static int parse_config_line(chroma_config_t *config, char *line, "Filter quality configuration: key='%s', value='%s', parsed=%s", key, value, filter_quality_to_string(config->default_filter_quality)); + } else if (strcasecmp(key, "enable_downsampling") == 0) { + config->enable_downsampling = parse_bool(value); + chroma_log("DEBUG", "Set downsampling: %s", + config->enable_downsampling ? "enabled" : "disabled"); + } else if (strcasecmp(key, "max_output_width") == 0) { + int width = atoi(value); + if (width > 0 && width <= 16384) { // Reasonable limits + config->max_output_width = width; + chroma_log("DEBUG", "Set max output width: %d", width); + } else { + chroma_log("WARN", "Invalid max_output_width: %s (using 3840)", value); + } + } else if (strcasecmp(key, "max_output_height") == 0) { + int height = atoi(value); + if (height > 0 && height <= 16384) { // Reasonable limits + config->max_output_height = height; + chroma_log("DEBUG", "Set max output height: %d", height); + } else { + chroma_log("WARN", "Invalid max_output_height: %s (using 2160)", value); + } + } else if (strcasecmp(key, "min_scale_factor") == 0) { + float factor = atof(value); + if (factor > 0.0f && factor <= 1.0f) { // Valid range + config->min_scale_factor = factor; + chroma_log("DEBUG", "Set minimum scale factor: %.2f", factor); + } else { + chroma_log("WARN", "Invalid min_scale_factor: %s (using 0.25)", value); + } } else if (strncasecmp(key, "output.", 7) == 0) { // Output-specific mapping: e.g., output.DP-1=/path/to/image.jpg const char *output_name = key + 7; @@ -515,39 +549,7 @@ int chroma_config_get_mapping_for_output( return CHROMA_OK; } -// Create a sample configuration file -int chroma_config_create_sample(const char *config_file) { - if (!config_file) { - return CHROMA_ERROR_INIT; - } - FILE *file = fopen(config_file, "w"); - if (!file) { - chroma_log("ERROR", "Failed to create sample config file %s: %s", - config_file, strerror(errno)); - return CHROMA_ERROR_CONFIG; - } - - fprintf(file, "# Chroma Wallpaper Daemon Configuration\n"); - fprintf(file, "# Lines starting with # are comments\n\n"); - - fprintf(file, "# Default wallpaper for outputs without specific mapping\n"); - fprintf(file, "default_image = ~/.config/chroma/default.jpg\n\n"); - - fprintf(file, "# Output-specific wallpapers\n"); - fprintf(file, "# Format: output.OUTPUT_NAME = /path/to/image.jpg\n"); - fprintf(file, "# You can find output names using: wlr-randr\n"); - fprintf(file, "\n"); - fprintf(file, "# Examples:\n"); - fprintf(file, "# output.DP-1 = ~/.config/chroma/monitor1.jpg\n"); - fprintf(file, "# output.DP-2 = ~/.config/chroma/monitor2.png\n"); - fprintf(file, "# output.HDMI-A-1 = ~/.config/chroma/hdmi.jpg\n"); - - fclose(file); - - chroma_log("INFO", "Created sample configuration file: %s", config_file); - return CHROMA_OK; -} // Print current configuration for debugging void chroma_config_print(const chroma_config_t *config) { @@ -562,6 +564,13 @@ void chroma_config_print(const chroma_config_t *config) { scale_mode_to_string(config->default_scale_mode)); chroma_log("INFO", "Default filter quality: %s", filter_quality_to_string(config->default_filter_quality)); + chroma_log("INFO", "Downsampling: %s", + config->enable_downsampling ? "enabled" : "disabled"); + if (config->enable_downsampling) { + chroma_log("INFO", "Max output size: %dx%d", config->max_output_width, + config->max_output_height); + chroma_log("INFO", "Min scale factor: %.2f", config->min_scale_factor); + } chroma_log("INFO", "Output mappings: %d", config->mapping_count); for (int i = 0; i < config->mapping_count; i++) {