1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-06 01:28:57 +00:00

Built in gamma conversion for all machines, assuming an output of 2.8 for PAL, 2.2 for NTSC.

This commit is contained in:
Thomas Harte 2017-08-10 15:17:08 -04:00
parent a5593bec79
commit ad8c8166bc
7 changed files with 49 additions and 1 deletions

View File

@ -116,6 +116,9 @@ struct MachineDelegate: CRTMachine::Machine::Delegate {
- (void)setupOutputWithAspectRatio:(float)aspectRatio {
self.machine->setup_output(aspectRatio);
// Since OS X v10.6, Macs have had a gamma of 2.2.
self.machine->get_crt()->set_output_gamma(2.2f);
}
- (void)drawViewForPixelSize:(CGSize)pixelSize onlyIfDirty:(BOOL)onlyIfDirty {

View File

@ -56,10 +56,12 @@ void CRT::set_new_display_type(unsigned int cycles_per_line, DisplayType display
switch(displayType) {
case DisplayType::PAL50:
set_new_timing(cycles_per_line, 312, ColourSpace::YUV, 709379, 2500, 5, true); // i.e. 283.7516; 2.5 lines = vertical sync
set_input_gamma(2.8f);
break;
case DisplayType::NTSC60:
set_new_timing(cycles_per_line, 262, ColourSpace::YIQ, 455, 2, 6, false); // i.e. 227.5, 3 lines = vertical sync
set_input_gamma(2.2f);
break;
}
}
@ -72,6 +74,21 @@ void CRT::set_composite_function_type(CompositeSourceType type, float offset_of_
}
}
void CRT::set_input_gamma(float gamma) {
input_gamma_ = gamma;
update_gamma();
}
void CRT::set_output_gamma(float gamma) {
output_gamma_ = gamma;
update_gamma();
}
void CRT::update_gamma() {
float gamma_ratio = output_gamma_ / input_gamma_;
openGL_output_builder_.set_gamma(gamma_ratio);
}
CRT::CRT(unsigned int common_output_divisor, unsigned int buffer_depth) :
is_receiving_sync_(false),
common_output_divisor_(common_output_divisor),

View File

@ -97,6 +97,9 @@ class CRT {
unsigned int cycles_per_line_;
float input_gamma_, output_gamma_;
void update_gamma();
public:
/*! Constructs the CRT with a specified clock rate, height and colour subcarrier frequency.
The requested number of buffers, each with the requested number of bytes per pixel,
@ -238,6 +241,12 @@ class CRT {
openGL_output_builder_.draw_frame(output_width, output_height, only_if_dirty);
}
/*! Sets the gamma exponent for the simulated screen. */
void set_input_gamma(float gamma);
/*! Sets the gamma exponent for the real, tangible screen on which content will be drawn. */
void set_output_gamma(float gamma);
/*! Tells the CRT that the next call to draw_frame will occur on a different OpenGL context than
the previous.

View File

@ -89,6 +89,7 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out
set_timing_uniforms();
set_colour_space_uniforms();
set_gamma();
}
if(fence_ != nullptr) {
@ -375,6 +376,10 @@ void OpenGLOutputBuilder::set_colour_space_uniforms() {
if(composite_chrominance_filter_shader_program_) composite_chrominance_filter_shader_program_->set_colour_conversion_matrices(fromRGB, toRGB);
}
void OpenGLOutputBuilder::set_gamma() {
if(output_shader_program_) output_shader_program_->set_gamma_ratio(gamma_);
}
float OpenGLOutputBuilder::get_composite_output_width() const {
return ((float)colour_cycle_numerator_ * 4.0f) / (float)(colour_cycle_denominator_ * IntermediateBufferWidth);
}

View File

@ -34,6 +34,7 @@ class OpenGLOutputBuilder {
unsigned int colour_cycle_numerator_;
unsigned int colour_cycle_denominator_;
OutputDevice output_device_;
float gamma_;
// timing information to allow reasoning about input information
unsigned int input_frequency_;
@ -89,6 +90,7 @@ class OpenGLOutputBuilder {
void set_timing_uniforms();
void set_colour_space_uniforms();
void set_gamma();
void establish_OpenGL_state();
void reset_all_OpenGL_state();
@ -118,6 +120,11 @@ class OpenGLOutputBuilder {
visible_area_ = visible_area;
}
inline void set_gamma(float gamma) {
gamma_ = gamma;
set_gamma();
}
inline std::unique_lock<std::mutex> get_output_lock() {
return std::unique_lock<std::mutex>(output_mutex_);
}

View File

@ -74,12 +74,13 @@ std::unique_ptr<OutputShader> OutputShader::make_shader(const char *fragment_met
"out vec4 fragColour;"
"uniform %s texID;"
"uniform float gamma;"
"\n%s\n"
"void main(void)"
"{"
"fragColour = vec4(%s, 0.5);"//*cos(lateralVarying)
"fragColour = vec4(pow(%s, vec3(gamma)), 0.5);"//*cos(lateralVarying)
"}",
sampler_type, fragment_methods, colour_expression);
@ -116,6 +117,10 @@ void OutputShader::set_timing(unsigned int height_of_display, unsigned int cycle
set_uniform("positionConversion", (GLfloat)horizontal_scan_period, (GLfloat)vertical_scan_period / (GLfloat)vertical_period_divider);
}
void OutputShader::set_gamma_ratio(float ratio) {
set_uniform("gamma", ratio);
}
void OutputShader::set_input_width_scaler(float input_scaler) {
set_uniform("inputScaler", input_scaler);
}

View File

@ -63,6 +63,8 @@ public:
*/
void set_origin_is_double_height(bool is_double_height);
void set_gamma_ratio(float ratio);
/*!
Sets the proportion of the input area that should be considered the whole width 1.0 means use all available
space, 0.5 means use half, etc.