1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-11 04:28:58 +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 { - (void)setupOutputWithAspectRatio:(float)aspectRatio {
self.machine->setup_output(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 { - (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) { switch(displayType) {
case DisplayType::PAL50: 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_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; break;
case DisplayType::NTSC60: 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_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; 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) : CRT::CRT(unsigned int common_output_divisor, unsigned int buffer_depth) :
is_receiving_sync_(false), is_receiving_sync_(false),
common_output_divisor_(common_output_divisor), common_output_divisor_(common_output_divisor),

View File

@ -97,6 +97,9 @@ class CRT {
unsigned int cycles_per_line_; unsigned int cycles_per_line_;
float input_gamma_, output_gamma_;
void update_gamma();
public: public:
/*! Constructs the CRT with a specified clock rate, height and colour subcarrier frequency. /*! 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, 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); 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 /*! Tells the CRT that the next call to draw_frame will occur on a different OpenGL context than
the previous. the previous.

View File

@ -89,6 +89,7 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out
set_timing_uniforms(); set_timing_uniforms();
set_colour_space_uniforms(); set_colour_space_uniforms();
set_gamma();
} }
if(fence_ != nullptr) { 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); 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 { float OpenGLOutputBuilder::get_composite_output_width() const {
return ((float)colour_cycle_numerator_ * 4.0f) / (float)(colour_cycle_denominator_ * IntermediateBufferWidth); 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_numerator_;
unsigned int colour_cycle_denominator_; unsigned int colour_cycle_denominator_;
OutputDevice output_device_; OutputDevice output_device_;
float gamma_;
// timing information to allow reasoning about input information // timing information to allow reasoning about input information
unsigned int input_frequency_; unsigned int input_frequency_;
@ -89,6 +90,7 @@ class OpenGLOutputBuilder {
void set_timing_uniforms(); void set_timing_uniforms();
void set_colour_space_uniforms(); void set_colour_space_uniforms();
void set_gamma();
void establish_OpenGL_state(); void establish_OpenGL_state();
void reset_all_OpenGL_state(); void reset_all_OpenGL_state();
@ -118,6 +120,11 @@ class OpenGLOutputBuilder {
visible_area_ = visible_area; visible_area_ = visible_area;
} }
inline void set_gamma(float gamma) {
gamma_ = gamma;
set_gamma();
}
inline std::unique_lock<std::mutex> get_output_lock() { inline std::unique_lock<std::mutex> get_output_lock() {
return std::unique_lock<std::mutex>(output_mutex_); 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;" "out vec4 fragColour;"
"uniform %s texID;" "uniform %s texID;"
"uniform float gamma;"
"\n%s\n" "\n%s\n"
"void main(void)" "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); 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); 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) { void OutputShader::set_input_width_scaler(float input_scaler) {
set_uniform("inputScaler", 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_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 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. space, 0.5 means use half, etc.