openMSX
RenderSettings.cc
Go to the documentation of this file.
1#include "RenderSettings.hh"
2
4#include "CommandException.hh"
5#include "Version.hh"
6
7#include "stl.hh"
8#include "unreachable.hh"
9
10#include "build-info.hh"
11
12#include <algorithm>
13#include <iostream>
14#include <cmath>
15
16using namespace gl;
17
18namespace openmsx {
19
20EnumSetting<RenderSettings::ScaleAlgorithm>::Map RenderSettings::getScalerMap()
21{
22 using enum ScaleAlgorithm;
23 EnumSetting<ScaleAlgorithm>::Map scalerMap = {
24 {"simple", SIMPLE},
25 {"ScaleNx", SCALE},
26 {"hq", HQ},
27 {"hqlite", HQLITE},
28 {"RGBtriplet", RGBTRIPLET},
29 {"TV", TV}
30 };
31 return scalerMap;
32}
33
34EnumSetting<RenderSettings::RendererID>::Map RenderSettings::getRendererMap()
35{
36 EnumSetting<RendererID>::Map rendererMap = {
37 {"none", RendererID::DUMMY},// TODO: only register when in CliComm mode
38 {"SDLGL-PP", RendererID::SDLGL_PP}
39 };
40 return rendererMap;
41}
42
44 : accuracySetting(commandController,
45 "accuracy", "rendering accuracy", Accuracy::PIXEL,
47 {"screen", Accuracy::SCREEN},
48 {"line", Accuracy::LINE},
49 {"pixel", Accuracy::PIXEL}})
50
51 , deinterlaceSetting(commandController,
52 "deinterlace", "deinterlacing on/off", true)
53
54 , deflickerSetting(commandController,
55 "deflicker", "deflicker on/off", false)
56
57 , maxFrameSkipSetting(commandController,
58 "maxframeskip", "set the max amount of frameskip", 3, 0, 100)
59
60 , minFrameSkipSetting(commandController,
61 "minframeskip", "set the min amount of frameskip", 0, 0, 100)
62
63 , fullScreenSetting(commandController,
64 "fullscreen", "full screen display on/off", false)
65
66 , gammaSetting(commandController, "gamma",
67 "amount of gamma correction: low is dark, high is bright",
68 1.1, 0.1, 5.0)
69
70 , brightnessSetting(commandController, "brightness",
71 "brightness video setting: "
72 "0 is normal, lower is darker, higher is brighter",
73 0.0, -100.0, 100.0)
74 , contrastSetting(commandController, "contrast",
75 "contrast video setting: "
76 "0 is normal, lower is less contrast, higher is more contrast",
77 0.0, -100.0, 100.0)
78
79 , colorMatrixSetting(commandController,
80 "color_matrix",
81 "3x3 matrix to transform MSX RGB to host RGB, see manual for details",
82 "{ 1 0 0 } { 0 1 0 } { 0 0 1 }")
83
84 , glowSetting(commandController,
85 "glow", "amount of afterglow effect: 0 = none, 100 = lots",
86 0, 0, 100)
87
88 , noiseSetting(commandController,
89 "noise", "amount of noise to add to the frame",
90 0.0, 0.0, 100.0)
91
92 , rendererSetting(commandController,
93 "renderer", "rendering back-end used to display the MSX screen",
94 RendererID::SDLGL_PP, getRendererMap(), Setting::DONT_SAVE)
95
96 , horizontalBlurSetting(commandController,
97 "blur", "amount of horizontal blur effect: 0 = none, 100 = full",
98 50, 0, 100)
99
100 , scaleAlgorithmSetting(
101 commandController, "scale_algorithm", "scale algorithm",
102 ScaleAlgorithm::SIMPLE, getScalerMap())
103
104 , scaleFactorSetting(commandController,
105 "scale_factor", "scale factor",
107
108 , scanlineAlphaSetting(commandController,
109 "scanline", "amount of scanline effect: 0 = none, 100 = full",
110 20, 0, 100)
111
112 , limitSpritesSetting(commandController,
113 "limitsprites", "limit number of sprites per line "
114 "(on for realism, off to reduce sprite flashing)", true)
115
116 , disableSpritesSetting(commandController,
117 "disablesprites", "disable sprite rendering",
118 false, Setting::DONT_SAVE)
119
120 , cmdTimingSetting(commandController,
121 "cmdtiming", "VDP command timing", false,
122 EnumSetting<bool>::Map{{"real", false}, {"broken", true}},
123 Setting::DONT_SAVE)
124
125 , tooFastAccessSetting(commandController,
126 "too_fast_vram_access",
127 "Should too fast VDP VRAM access be correctly emulated.\n"
128 "Possible values are:\n"
129 " real -> too fast accesses are dropped\n"
130 " ignore -> access speed is ignored, all accesses are executed",
131 false,
132 EnumSetting<bool>::Map{{"real", false }, {"ignore", true}},
133 Setting::DONT_SAVE)
134
135 , displayDeformSetting(
136 commandController,
137 "display_deform", "Display deform", DisplayDeform::NORMAL,
138 EnumSetting<DisplayDeform>::Map{
139 {"normal", DisplayDeform::NORMAL},
140 {"3d", DisplayDeform::_3D}})
141
142 , vSyncSetting(commandController,
143 "vsync", "Synchronize page flip with the host screen vertical sync:\n"
144 " on -> flip on host vsync: avoids tearing\n"
145 " off -> immediate flip: might be more fluent when host framerate"
146 " (typically 60Hz) differs from MSX framerate (50 or 60Hz).\n",
147 true)
148
149 // Many android devices are relatively low powered. Therefore use
150 // no stretch (value 320) as default for Android because it gives
151 // better performance
152 , horizontalStretchSetting(commandController,
153 "horizontal_stretch",
154 "Amount of horizontal stretch: this many MSX pixels will be "
155 "stretched over the complete width of the output screen.\n"
156 " 320 = no stretch (large borders)\n"
157 " 288 = a bit more than all border pixels\n"
158 " 284 = all border pixels\n"
159 " 280 = a bit less than all border pixels\n"
160 " 272 = realistic\n"
161 " 256 = max stretch (no border visible at all)\n"
162 " good values are 272 or 280\n",
163 PLATFORM_ANDROID ? 320.0 : 280.0, 256.0, 320.0)
164
165 , pointerHideDelaySetting(commandController,
166 "pointer_hide_delay",
167 "number of seconds after which the mouse pointer is hidden in the openMSX "
168 "window; negative = no hiding, 0 = immediately",
169 2.0, -1.0, 60.0)
170
171 , interleaveBlackFrameSetting(commandController,
172 "interleave_black_frame",
173 "Insert a black frame in between each normal MSX frame. "
174 "Useful on (100Hz+) lightboost enabled monitors to reduce "
175 "motion blur and double frame artifacts.",
176 false)
177{
178 brightnessSetting.attach(*this);
179 contrastSetting .attach(*this);
180 updateBrightnessAndContrast();
181
182 auto& interp = commandController.getInterpreter();
183 colorMatrixSetting.setChecker([this, &interp](const TclObject& newValue) {
184 try {
185 parseColorMatrix(interp, newValue);
186 } catch (CommandException& e) {
187 throw CommandException(
188 "Invalid color matrix: ", e.getMessage());
189 }
190 });
191 try {
192 parseColorMatrix(interp, colorMatrixSetting.getValue());
193 } catch (MSXException& e) {
194 std::cerr << e.getMessage() << '\n';
195 cmIdentity = true;
196 }
197
198 rendererSetting.setEnum(RendererID::DUMMY); // always start hidden
199}
200
201RenderSettings::~RenderSettings()
202{
203 brightnessSetting.detach(*this);
204 contrastSetting .detach(*this);
205}
206
207void RenderSettings::update(const Setting& setting) noexcept
208{
209 if (&setting == &brightnessSetting) {
210 updateBrightnessAndContrast();
211 } else if (&setting == &contrastSetting) {
212 updateBrightnessAndContrast();
213 } else {
215 }
216}
217
218void RenderSettings::updateBrightnessAndContrast()
219{
220 float contrastValue = getContrast();
221 contrast = (contrastValue >= 0.0f) ? (1.0f + contrastValue * (1.0f / 25.0f))
222 : (1.0f + contrastValue * (1.0f / 125.0f));
223 brightness = (getBrightness() * (1.0f / 100.0f) - 0.5f) * contrast + 0.5f;
224}
225
226static float conv2(float x, float gamma)
227{
228 return ::powf(std::clamp(x, 0.0f, 1.0f), gamma);
229}
230
231float RenderSettings::transformComponent(float c) const
232{
233 float c2 = c * contrast + brightness;
234 return conv2(c2, 1.0f / getGamma());
235}
236
237vec3 RenderSettings::transformRGB(vec3 rgb) const
238{
239 auto [r, g, b] = colorMatrix * (rgb * contrast + vec3(brightness));
240 float gamma = 1.0f / getGamma();
241 return {conv2(r, gamma),
242 conv2(g, gamma),
243 conv2(b, gamma)};
244}
245
246void RenderSettings::parseColorMatrix(Interpreter& interp, const TclObject& value)
247{
248 if (value.getListLength(interp) != 3) {
249 throw CommandException("must have 3 rows");
250 }
251 bool identity = true;
252 for (auto i : xrange(3)) {
253 TclObject row = value.getListIndex(interp, i);
254 if (row.getListLength(interp) != 3) {
255 throw CommandException("each row must have 3 elements");
256 }
257 for (auto j : xrange(3)) {
258 TclObject element = row.getListIndex(interp, j);
259 float val = element.getFloat(interp);
260 colorMatrix[j][i] = val;
261 identity &= (val == (i == j ? 1.0f : 0.0f));
262 }
263 }
264 cmIdentity = identity;
265}
266
267} // namespace openmsx
BaseSetting * setting
int g
#define MIN_SCALE_FACTOR
Definition build-info.hh:18
#define PLATFORM_ANDROID
Definition build-info.hh:17
#define MAX_SCALE_FACTOR
Definition build-info.hh:19
EnumSettingBase::Map Map
Accuracy
Render accuracy: granularity of the rendered area.
RenderSettings(CommandController &commandController)
ScaleAlgorithm
Scaler algorithm.
unsigned getListLength(Interpreter &interp) const
Definition TclObject.cc:155
TclObject getListIndex(Interpreter &interp, unsigned index) const
Definition TclObject.cc:173
constexpr double e
Definition Math.hh:21
Definition gl_mat.hh:23
vecN< 3, float > vec3
Definition gl_vec.hh:179
This file implemented 3 utility functions:
Definition Autofire.cc:11
#define UNREACHABLE
constexpr auto xrange(T e)
Definition xrange.hh:132