mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 23:52:26 +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:
commit
5d374ebb18
@ -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_;
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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),
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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_);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user