diff options
| author | Ryan Houdek <Sonicadvance1@gmail.com> | 2014-08-13 02:41:15 -0500 |
|---|---|---|
| committer | Ryan Houdek <Sonicadvance1@gmail.com> | 2014-08-13 02:41:15 -0500 |
| commit | f2a1dd91fe7b94580534b4299803ef9e6cb60d04 (patch) | |
| tree | 8f94445a0ae3a33f8520a207053b0f789abfcf71 /Source/Core/VideoCommon/PostProcessing.cpp | |
| parent | e4e44909d5ffa60abf81d4685a156654c463bbf9 (diff) | |
| parent | 287758f15d07cb6e0c19d861d8134124361d2d30 (diff) | |
Merge pull request #693 from Sonicadvance1/PP-shaders-improvement
Improved system for post processing shaders.
Diffstat (limited to 'Source/Core/VideoCommon/PostProcessing.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/PostProcessing.cpp | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/Source/Core/VideoCommon/PostProcessing.cpp b/Source/Core/VideoCommon/PostProcessing.cpp new file mode 100644 index 0000000000..019001da15 --- /dev/null +++ b/Source/Core/VideoCommon/PostProcessing.cpp @@ -0,0 +1,304 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include <string> + +#include "Common/CommonPaths.h" +#include "Common/FileUtil.h" +#include "Common/IniFile.h" +#include "Common/StringUtil.h" + +#include "VideoCommon/PostProcessing.h" +#include "VideoCommon/VideoConfig.h" + + +PostProcessingShaderImplementation::PostProcessingShaderImplementation() +{ + m_timer.Start(); +} + +PostProcessingShaderImplementation::~PostProcessingShaderImplementation() +{ + m_timer.Stop(); +} + +std::string PostProcessingShaderConfiguration::LoadShader(std::string shader) +{ + // Load the shader from the configuration if there isn't one sent to us. + if (shader == "") + shader = g_ActiveConfig.sPostProcessingShader; + m_current_shader = shader; + + // loading shader code + std::string code; + std::string path = File::GetUserPath(D_SHADERS_IDX) + shader + ".glsl"; + + if (!File::Exists(path)) + { + // Fallback to shared user dir + path = File::GetSysDirectory() + SHADERS_DIR DIR_SEP + shader + ".glsl"; + } + + if (!File::ReadFileToString(path, code)) + { + ERROR_LOG(VIDEO, "Post-processing shader not found: %s", path.c_str()); + return ""; + } + + LoadOptions(code); + LoadOptionsConfiguration(); + + return code; +} + +void PostProcessingShaderConfiguration::LoadOptions(const std::string& code) +{ + const std::string config_start_delimiter = "[configuration]"; + const std::string config_end_delimiter = "[/configuration]"; + size_t configuration_start = code.find(config_start_delimiter); + size_t configuration_end = code.find(config_end_delimiter); + + m_options.clear(); + m_any_options_dirty = true; + + if (configuration_start == std::string::npos || + configuration_end == std::string::npos) + { + // Issue loading configuration or there isn't one. + return; + } + + std::string configuration_string = code.substr(configuration_start + config_start_delimiter.size(), + configuration_end - configuration_start - config_start_delimiter.size()); + + std::istringstream in(configuration_string); + + struct GLSLStringOption + { + std::string m_type; + std::vector<std::pair<std::string, std::string>> m_options; + }; + + std::vector<GLSLStringOption> option_strings; + GLSLStringOption* current_strings = nullptr; + while (!in.eof()) + { + std::string line; + + if (std::getline(in, line)) + { +#ifndef _WIN32 + // Check for CRLF eol and convert it to LF + if (!line.empty() && line.at(line.size()-1) == '\r') + { + line.erase(line.size()-1); + } +#endif + + if (line.size() > 0) + { + if (line[0] == '[') + { + size_t endpos = line.find("]"); + + if (endpos != std::string::npos) + { + // New section! + std::string sub = line.substr(1, endpos - 1); + option_strings.push_back({ sub }); + current_strings = &option_strings.back(); + } + } + else + { + if (current_strings) + { + std::string key, value; + IniFile::ParseLine(line, &key, &value); + + if (!(key == "" && value == "")) + current_strings->m_options.push_back(std::make_pair(key, value)); + } + } + } + } + } + + for (const auto& it : option_strings) + { + ConfigurationOption option; + option.m_dirty = true; + + if (it.m_type == "OptionBool") + option.m_type = ConfigurationOption::OptionType::OPTION_BOOL; + else if (it.m_type == "OptionRangeFloat") + option.m_type = ConfigurationOption::OptionType::OPTION_FLOAT; + else if (it.m_type == "OptionRangeInteger") + option.m_type = ConfigurationOption::OptionType::OPTION_INTEGER; + + for (const auto& string_option : it.m_options) + { + if (string_option.first == "GUIName") + { + option.m_gui_name = string_option.second; + } + else if (string_option.first == "OptionName") + { + option.m_option_name = string_option.second; + } + else if (string_option.first == "DependentOption") + { + option.m_dependent_option = string_option.second; + } + else if (string_option.first == "MinValue" || + string_option.first == "MaxValue" || + string_option.first == "DefaultValue" || + string_option.first == "StepAmount") + { + std::vector<s32>* output_integer = nullptr; + std::vector<float>* output_float = nullptr; + + if (string_option.first == "MinValue") + { + output_integer = &option.m_integer_min_values; + output_float = &option.m_float_min_values; + } + else if (string_option.first == "MaxValue") + { + output_integer = &option.m_integer_max_values; + output_float = &option.m_float_max_values; + } + else if (string_option.first == "DefaultValue") + { + output_integer = &option.m_integer_values; + output_float = &option.m_float_values; + } + else if (string_option.first == "StepAmount") + { + output_integer = &option.m_integer_step_values; + output_float = &option.m_float_step_values; + } + + if (option.m_type == ConfigurationOption::OptionType::OPTION_BOOL) + { + TryParse(string_option.second, &option.m_bool_value); + } + else if (option.m_type == ConfigurationOption::OptionType::OPTION_INTEGER) + { + TryParseVector(string_option.second, output_integer); + if (output_integer->size() > 4) + output_integer->erase(output_integer->begin() + 4, output_integer->end()); + } + else if (option.m_type == ConfigurationOption::OptionType::OPTION_FLOAT) + { + TryParseVector(string_option.second, output_float); + if (output_float->size() > 4) + output_float->erase(output_float->begin() + 4, output_float->end()); + } + } + } + m_options[option.m_option_name] = option; + } +} + +void PostProcessingShaderConfiguration::LoadOptionsConfiguration() +{ + IniFile ini; + ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX)); + std::string section = m_current_shader + "-options"; + + for (auto& it : m_options) + { + switch (it.second.m_type) + { + case ConfigurationOption::OptionType::OPTION_BOOL: + ini.GetOrCreateSection(section)->Get(it.second.m_option_name, &it.second.m_bool_value, it.second.m_bool_value); + break; + case ConfigurationOption::OptionType::OPTION_INTEGER: + { + std::string value; + ini.GetOrCreateSection(section)->Get(it.second.m_option_name, &value); + if (value != "") + TryParseVector(value, &it.second.m_integer_values); + } + break; + case ConfigurationOption::OptionType::OPTION_FLOAT: + { + std::string value; + ini.GetOrCreateSection(section)->Get(it.second.m_option_name, &value); + if (value != "") + TryParseVector(value, &it.second.m_float_values); + } + break; + } + } +} + +void PostProcessingShaderConfiguration::SaveOptionsConfiguration() +{ + IniFile ini; + ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX)); + std::string section = m_current_shader + "-options"; + + for (auto& it : m_options) + { + switch (it.second.m_type) + { + case ConfigurationOption::OptionType::OPTION_BOOL: + { + ini.GetOrCreateSection(section)->Set(it.second.m_option_name, it.second.m_bool_value); + } + break; + case ConfigurationOption::OptionType::OPTION_INTEGER: + { + std::string value = ""; + for (size_t i = 0; i < it.second.m_integer_values.size(); ++i) + value += StringFromFormat("%d%s", it.second.m_integer_values[i], i == (it.second.m_integer_values.size() - 1) ? "": ", "); + ini.GetOrCreateSection(section)->Set(it.second.m_option_name, value); + } + break; + case ConfigurationOption::OptionType::OPTION_FLOAT: + { + std::string value = ""; + for (size_t i = 0; i < it.second.m_float_values.size(); ++i) + value += StringFromFormat("%f%s", it.second.m_float_values[i], i == (it.second.m_float_values.size() - 1) ? "": ", "); + ini.GetOrCreateSection(section)->Set(it.second.m_option_name, value); + } + break; + } + } + ini.Save(File::GetUserPath(F_DOLPHINCONFIG_IDX)); +} + +void PostProcessingShaderConfiguration::ReloadShader() +{ + m_current_shader = ""; +} + +void PostProcessingShaderConfiguration::SetOptionf(std::string option, int index, float value) +{ + auto it = m_options.find(option); + + it->second.m_float_values[index] = value; + it->second.m_dirty = true; + m_any_options_dirty = true; +} + +void PostProcessingShaderConfiguration::SetOptioni(std::string option, int index, s32 value) +{ + auto it = m_options.find(option); + + it->second.m_integer_values[index] = value; + it->second.m_dirty = true; + m_any_options_dirty = true; +} + +void PostProcessingShaderConfiguration::SetOptionb(std::string option, bool value) +{ + auto it = m_options.find(option); + + it->second.m_bool_value = value; + it->second.m_dirty = true; + m_any_options_dirty = true; +} |
