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

Merge pull request #184 from TomHarte/DeferredVideo

Reduces CRTC counter sizes to match real hardware; introduces a CRT gamma transform
This commit is contained in:
Thomas Harte 2017-08-10 16:00:39 -04:00 committed by GitHub
commit 5d374ebb18
9 changed files with 58 additions and 3 deletions

View File

@ -104,7 +104,7 @@ template <class T> class CRTC6845 {
bus_state_.row_address = 0;
bool is_at_end_of_frame = line_counter_ == registers_[4];
line_counter_++;
line_counter_ = (line_counter_ + 1) & 0x7f;
// check for end of visible lines
if(line_counter_ == registers_[6]) {
@ -131,7 +131,7 @@ template <class T> class CRTC6845 {
line_counter_ = 0;
}
} else {
bus_state_.row_address++;
bus_state_.row_address = (bus_state_.row_address + 1) & 0x1f;
}
bus_state_.refresh_address = line_address_;
}
@ -141,6 +141,7 @@ template <class T> class CRTC6845 {
}
bus_state_.display_enable = character_is_visible_ && line_is_visible_;
bus_state_.refresh_address &= 0x3fff;
bus_handler_.perform_bus_cycle(bus_state_);
}
}
@ -168,6 +169,11 @@ template <class T> class CRTC6845 {
registers_[selected_register_] = value & masks[selected_register_];
}
void trigger_light_pen() {
registers_[17] = bus_state_.refresh_address & 0xff;
registers_[16] = bus_state_.refresh_address >> 8;
}
private:
Personality personality_;
T &bus_handler_;

View File

@ -291,6 +291,7 @@ class CRTCBusHandler {
"return vec3(float((sample >> 4) & 3u), float((sample >> 2) & 3u), float(sample & 3u)) / 2.0;"
"}");
crt_->set_visible_area(Outputs::CRT::Rect(0.075f, 0.05f, 0.9f, 0.9f));
crt_->set_output_device(Outputs::CRT::Monitor);
}
/// Destructs the CRT.

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.