1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-01-12 15:31:09 +00:00

Introduces S-Video as a video signal type at the interface level.

This commit is contained in:
Thomas Harte 2018-03-30 10:25:41 -04:00
parent 389979923e
commit 33281b9d89
13 changed files with 56 additions and 35 deletions

View File

@ -96,7 +96,7 @@ TMS9918::TMS9918(Personality p) {
"{"
"return texture(sampler, coordinate).rgb / vec3(255.0);"
"}");
crt_->set_output_device(Outputs::CRT::OutputDevice::Monitor);
crt_->set_video_signal(Outputs::CRT::VideoSignal::RGB);
crt_->set_visible_area(Outputs::CRT::Rect(0.055f, 0.025f, 0.9f, 0.9f));
crt_->set_input_gamma(2.8f);

View File

@ -317,7 +317,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::OutputDevice::Monitor);
crt_->set_video_signal(Outputs::CRT::VideoSignal::RGB);
}
/// Destructs the CRT.

View File

@ -25,7 +25,7 @@ namespace {
TIA::TIA(bool create_crt) {
if(create_crt) {
crt_.reset(new Outputs::CRT::CRT(cycles_per_line * 2 - 1, 1, Outputs::CRT::DisplayType::NTSC60, 1));
crt_->set_output_device(Outputs::CRT::OutputDevice::Television);
crt_->set_video_signal(Outputs::CRT::VideoSignal::Composite);
set_output_mode(OutputMode::NTSC);
}

View File

@ -135,7 +135,7 @@ class ConcreteMachine:
void setup_output(float aspect_ratio) override {
vdp_.reset(new TI::TMS9918(TI::TMS9918::TMS9918A));
get_crt()->set_output_device(Outputs::CRT::OutputDevice::Television);
get_crt()->set_video_signal(Outputs::CRT::VideoSignal::Composite);
}
void close_output() override {

View File

@ -454,7 +454,7 @@ class ConcreteMachine:
Configurable::Display display;
if(Configurable::get_display(selections_by_option, display)) {
get_crt()->set_output_device((display == Configurable::Display::RGB) ? Outputs::CRT::OutputDevice::Monitor : Outputs::CRT::OutputDevice::Television);
get_crt()->set_video_signal((display == Configurable::Display::RGB) ? Outputs::CRT::VideoSignal::RGB : Outputs::CRT::VideoSignal::Composite);
}
}

View File

@ -562,7 +562,7 @@ class ConcreteMachine:
Configurable::Display display;
if(Configurable::get_display(selections_by_option, display)) {
get_crt()->set_output_device((display == Configurable::Display::RGB) ? Outputs::CRT::OutputDevice::Monitor : Outputs::CRT::OutputDevice::Television);
get_crt()->set_video_signal((display == Configurable::Display::RGB) ? Outputs::CRT::VideoSignal::RGB : Outputs::CRT::VideoSignal::Composite);
}
}

View File

@ -263,7 +263,7 @@ class ConcreteMachine:
use_fast_tape_hack_ = activate;
}
void set_output_device(Outputs::CRT::OutputDevice output_device) {
void set_output_device(Outputs::CRT::VideoSignal output_device) {
video_output_->set_output_device(output_device);
}
@ -392,7 +392,7 @@ class ConcreteMachine:
video_output_.reset(new VideoOutput(ram_));
if(!colour_rom_.empty()) video_output_->set_colour_rom(colour_rom_);
set_output_device(Outputs::CRT::OutputDevice::Monitor);
set_output_device(Outputs::CRT::VideoSignal::RGB);
}
void close_output() override final {
@ -465,7 +465,7 @@ class ConcreteMachine:
Configurable::Display display;
if(Configurable::get_display(selections_by_option, display)) {
set_output_device((display == Configurable::Display::RGB) ? Outputs::CRT::OutputDevice::Monitor : Outputs::CRT::OutputDevice::Television);
set_output_device((display == Configurable::Display::RGB) ? Outputs::CRT::VideoSignal::RGB : Outputs::CRT::VideoSignal::Composite);
}
}

View File

@ -41,13 +41,13 @@ VideoOutput::VideoOutput(uint8_t *memory) :
);
crt_->set_composite_function_type(Outputs::CRT::CRT::CompositeSourceType::DiscreteFourSamplesPerCycle, 0.0f);
set_output_device(Outputs::CRT::OutputDevice::Television);
set_output_device(Outputs::CRT::VideoSignal::Composite);
crt_->set_visible_area(crt_->get_rect_for_area(53, 224, 16 * 6, 40 * 6, 4.0f / 3.0f));
}
void VideoOutput::set_output_device(Outputs::CRT::OutputDevice output_device) {
void VideoOutput::set_output_device(Outputs::CRT::VideoSignal output_device) {
output_device_ = output_device;
crt_->set_output_device(output_device);
crt_->set_video_signal(output_device);
}
void VideoOutput::set_colour_rom(const std::vector<uint8_t> &rom) {
@ -129,7 +129,7 @@ void VideoOutput::run_for(const Cycles cycles) {
if(control_byte & 0x60) {
if(pixel_target_) {
uint16_t colours[2];
if(output_device_ == Outputs::CRT::OutputDevice::Monitor) {
if(output_device_ == Outputs::CRT::VideoSignal::RGB) {
colours[0] = static_cast<uint8_t>(paper_ ^ inverse_mask);
colours[1] = static_cast<uint8_t>(ink_ ^ inverse_mask);
} else {
@ -183,7 +183,7 @@ void VideoOutput::run_for(const Cycles cycles) {
pixel_target_[0] = pixel_target_[1] =
pixel_target_[2] = pixel_target_[3] =
pixel_target_[4] = pixel_target_[5] =
(output_device_ == Outputs::CRT::OutputDevice::Monitor) ? paper_ ^ inverse_mask : colour_forms_[paper_ ^ inverse_mask];
(output_device_ == Outputs::CRT::VideoSignal::RGB) ? paper_ ^ inverse_mask : colour_forms_[paper_ ^ inverse_mask];
}
}
if(pixel_target_) pixel_target_ += 6;

View File

@ -20,7 +20,7 @@ class VideoOutput {
Outputs::CRT::CRT *get_crt();
void run_for(const Cycles cycles);
void set_colour_rom(const std::vector<uint8_t> &rom);
void set_output_device(Outputs::CRT::OutputDevice output_device);
void set_output_device(Outputs::CRT::VideoSignal output_device);
private:
uint8_t *ram_;
@ -33,7 +33,7 @@ class VideoOutput {
// Output target and device
uint16_t *pixel_target_;
uint16_t colour_forms_[8];
Outputs::CRT::OutputDevice output_device_;
Outputs::CRT::VideoSignal output_device_;
// Registers
uint8_t ink_, paper_;

View File

@ -306,10 +306,27 @@ class CRT {
*/
void set_composite_function_type(CompositeSourceType type, float offset_of_first_sample = 0.0f);
/*! Sets a function that will map from whatever data the machine provided to an s-video signal.
If the output mode is composite then a default mapping from RGB to the display's
output mode will be applied.
@param shader A GLSL fragment including a function with the signature
`vec2 svideo_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase)`
that evaluates to the s-video signal level, luminance as the first component and chrominance
as the second, as a function of a source buffer, sampling location and colour
carrier phase.
*/
inline void set_svideo_sampling_function(const std::string &shader) {
enqueue_openGL_function([shader, this] {
openGL_output_builder_.set_svideo_sampling_function(shader);
});
}
/*! Sets a function that will map from whatever data the machine provided to an RGB signal.
If the output mode is composite then a default mapping from RGB to the display's composite
format will be applied.
If the output mode is composite or svideo then a default mapping from RGB to the display's
output mode will be applied.
@param shader A GLSL fragent including a function with the signature
`vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)` that evaluates to an RGB colour
@ -329,9 +346,9 @@ class CRT {
openGL_output_builder_.texture_builder.set_bookender(std::move(bookender));
}
inline void set_output_device(OutputDevice output_device) {
enqueue_openGL_function([output_device, this] {
openGL_output_builder_.set_output_device(output_device);
inline void set_video_signal(VideoSignal video_signal) {
enqueue_openGL_function([video_signal, this] {
openGL_output_builder_.set_video_signal(video_signal);
});
}

View File

@ -36,9 +36,10 @@ enum class ColourSpace {
YUV
};
enum class OutputDevice {
Monitor,
Television
enum class VideoSignal {
RGB,
SVideo,
Composite
};
}

View File

@ -72,7 +72,7 @@ OpenGLOutputBuilder::~OpenGLOutputBuilder() {
}
bool OpenGLOutputBuilder::get_is_television_output() {
return output_device_ == OutputDevice::Television || !rgb_input_shader_program_;
return video_signal_ == VideoSignal::Composite || !rgb_input_shader_program_;
}
void OpenGLOutputBuilder::set_target_framebuffer(GLint target_framebuffer) {
@ -363,9 +363,9 @@ void OpenGLOutputBuilder::prepare_output_vertex_array() {
// MARK: - Public Configuration
void OpenGLOutputBuilder::set_output_device(OutputDevice output_device) {
if(output_device_ != output_device) {
output_device_ = output_device;
void OpenGLOutputBuilder::set_video_signal(VideoSignal video_signal) {
if(video_signal_ != video_signal) {
video_signal_ = video_signal;
composite_src_output_y_ = 0;
last_output_width_ = 0;
last_output_height_ = 0;

View File

@ -33,7 +33,7 @@ class OpenGLOutputBuilder {
ColourSpace colour_space_;
unsigned int colour_cycle_numerator_;
unsigned int colour_cycle_denominator_;
OutputDevice output_device_;
VideoSignal video_signal_;
float gamma_;
// timing information to allow reasoning about input information
@ -73,6 +73,8 @@ class OpenGLOutputBuilder {
std::unique_ptr<OpenGL::IntermediateShader> composite_separation_filter_program_;
std::unique_ptr<OpenGL::IntermediateShader> composite_chrominance_filter_shader_program_;
std::unique_ptr<OpenGL::IntermediateShader> svideo_input_shader_program_;
std::unique_ptr<OpenGL::IntermediateShader> rgb_input_shader_program_;
std::unique_ptr<OpenGL::IntermediateShader> rgb_filter_shader_program_;
@ -130,8 +132,8 @@ class OpenGLOutputBuilder {
return std::unique_lock<std::mutex>(output_mutex_);
}
inline OutputDevice get_output_device() {
return output_device_;
inline VideoSignal get_output_device() {
return video_signal_;
}
inline uint16_t get_composite_output_y() {
@ -147,12 +149,13 @@ class OpenGLOutputBuilder {
composite_src_output_y_++;
}
void set_target_framebuffer(GLint target_framebuffer);
void set_target_framebuffer(GLint);
void draw_frame(unsigned int output_width, unsigned int output_height, bool only_if_dirty);
void set_openGL_context_will_change(bool should_delete_resources);
void set_composite_sampling_function(const std::string &shader);
void set_rgb_sampling_function(const std::string &shader);
void set_output_device(OutputDevice output_device);
void set_composite_sampling_function(const std::string &);
void set_svideo_sampling_function(const std::string &);
void set_rgb_sampling_function(const std::string &);
void set_video_signal(VideoSignal);
void set_timing(unsigned int input_frequency, unsigned int cycles_per_line, unsigned int height_of_display, unsigned int horizontal_scan_period, unsigned int vertical_scan_period, unsigned int vertical_period_divider);
};