From a697a2e4f6c60afa05fc53ee5f9415473dd3cd88 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 22 Nov 2018 17:20:31 -0500 Subject: [PATCH] =?UTF-8?q?Attempts=20to=20complete=20all=20input=20proces?= =?UTF-8?q?sing=20=E2=80=94=20an=20RGB,=20S-Video=20or=20composite=20input?= =?UTF-8?q?=20buffer=20is=20now=20produced.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... for all input data types. --- .../xcschemes/Clock Signal.xcscheme | 1 + Outputs/CRT/CRT.cpp | 2 +- Outputs/OpenGL/ScanTarget.cpp | 17 ++- Outputs/OpenGL/ScanTargetGLSLFragments.cpp | 114 +++++++++--------- Outputs/ScanTarget.hpp | 2 +- 5 files changed, 79 insertions(+), 57 deletions(-) diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme index f46055641..f9049689f 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme +++ b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme @@ -78,6 +78,7 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" stopOnEveryThreadSanitizerIssue = "YES" + stopOnEveryUBSanitizerIssue = "YES" debugServiceExtension = "internal" allowLocationSimulation = "NO"> get_current_output_position() / vertical_flywheel_output_divider_)); // Prepare for the next line. - if(next_horizontal_sync_event == Flywheel::SyncEvent::EndRetrace) { + if(next_horizontal_sync_event == Flywheel::SyncEvent::StartRetrace) { is_alernate_line_ ^= phase_alternates_; colour_burst_amplitude_ = 0; } diff --git a/Outputs/OpenGL/ScanTarget.cpp b/Outputs/OpenGL/ScanTarget.cpp index 028a1cf83..ac06d9bfe 100644 --- a/Outputs/OpenGL/ScanTarget.cpp +++ b/Outputs/OpenGL/ScanTarget.cpp @@ -157,6 +157,21 @@ void ScanTarget::set_modals(Modals modals) { set_uniforms(Outputs::Display::OpenGL::ScanTarget::ShaderType::Line, *input_shader_); input_shader_->set_uniform("textureName", GLint(SourceData1BppTextureUnit - GL_TEXTURE0)); + switch(modals.composite_colour_space) { + case ColourSpace::YIQ: { + const GLfloat rgbToYIQ[] = {0.299f, 0.596f, 0.211f, 0.587f, -0.274f, -0.523f, 0.114f, -0.322f, 0.312f}; + const GLfloat yiqToRGB[] = {1.0f, 1.0f, 1.0f, 0.956f, -0.272f, -1.106f, 0.621f, -0.647f, 1.703f}; + input_shader_->set_uniform_matrix("lumaChromaToRGB", 3, false, yiqToRGB); + input_shader_->set_uniform_matrix("rgbToLumaChroma", 3, false, rgbToYIQ); + } break; + + case ColourSpace::YUV: { + const GLfloat rgbToYUV[] = {0.299f, -0.14713f, 0.615f, 0.587f, -0.28886f, -0.51499f, 0.114f, 0.436f, -0.10001f}; + const GLfloat yuvToRGB[] = {1.0f, 1.0f, 1.0f, 0.0f, -0.39465f, 2.03211f, 1.13983f, -0.58060f, 0.0f}; + input_shader_->set_uniform_matrix("lumaChromaToRGB", 3, false, yuvToRGB); + input_shader_->set_uniform_matrix("rgbToLumaChroma", 3, false, rgbToYUV); + } break; + } output_shader_->set_uniform("textureName", GLint(UnprocessedLineBufferTextureUnit - GL_TEXTURE0)); output_shader_->set_uniform("origin", modals.visible_area.origin.x, modals.visible_area.origin.y); @@ -521,7 +536,7 @@ void ScanTarget::draw(bool synchronous, int output_width, int output_height) { // If this is start-of-frame, clear any untouched pixels and flush the stencil buffer if(line_metadata_buffer_[start_line].is_first_in_frame) { if(stencil_is_valid_ && line_metadata_buffer_[start_line].previous_frame_was_complete) { - full_display_rectangle_.draw(1.0, 0.0, 0.0f); + full_display_rectangle_.draw(0.0f, 0.0f, 0.0f); } stencil_is_valid_ = true; glClear(GL_STENCIL_BUFFER_BIT); diff --git a/Outputs/OpenGL/ScanTargetGLSLFragments.cpp b/Outputs/OpenGL/ScanTargetGLSLFragments.cpp index 1d2d4cf57..3dc89173e 100644 --- a/Outputs/OpenGL/ScanTargetGLSLFragments.cpp +++ b/Outputs/OpenGL/ScanTargetGLSLFragments.cpp @@ -17,9 +17,11 @@ std::string ScanTarget::glsl_globals(ShaderType type) { "#version 150\n" "uniform vec2 scale;" - "uniform float rowHeight;" + "uniform mat3 lumaChromaToRGB;" "uniform mat3 rgbToLumaChroma;" + + "uniform float rowHeight;" "uniform float processingWidth;" "in vec2 startPoint;" @@ -32,6 +34,7 @@ std::string ScanTarget::glsl_globals(ShaderType type) { "in float dataY;" "in float lineY;" + "in float compositeAmplitude;" "uniform usampler2D textureName;"; @@ -59,12 +62,16 @@ std::string ScanTarget::glsl_default_vertex_shader(ShaderType type) { case ShaderType::Scan: return "out vec2 textureCoordinate;" + "out float compositeAngle;" + "out float compositeAmplitudeOut;" "void main(void) {" "float lateral = float(gl_VertexID & 1);" "float longitudinal = float((gl_VertexID & 2) >> 1);" "textureCoordinate = vec2(mix(startDataX, endDataX, lateral), dataY) / textureSize(textureName, 0);" + "compositeAngle = (mix(startCompositeAngle, endCompositeAngle, lateral) / 32.0) * 3.141592654;" + "compositeAmplitudeOut = compositeAmplitude / 255.0;" "vec2 eyePosition = vec2(mix(startPoint.x, endPoint.x, lateral) * processingWidth, lineY + longitudinal) / vec2(scale.x, 2048.0);" "gl_Position = vec4(eyePosition*2 - vec2(1.0), 0.0, 1.0);" @@ -126,6 +133,12 @@ void ScanTarget::enable_vertex_attributes(ShaderType type, Shader &target) { sizeof(Scan), reinterpret_cast(offsetof(Scan, line)), 1); + target.enable_vertex_attribute_with_pointer( + "compositeAmplitude", + 1, GL_UNSIGNED_BYTE, GL_FALSE, + sizeof(Scan), + reinterpret_cast(offsetof(Scan, scan.composite_amplitude)), + 1); break; case ShaderType::Line: @@ -155,85 +168,78 @@ std::unique_ptr ScanTarget::input_shader(InputDataType input_data_type, "#version 150\n" "out vec4 fragColour;" - "in vec2 textureCoordinate;"; + "in vec2 textureCoordinate;" + "in float compositeAngle;" + "in float compositeAmplitudeOut;" + "uniform mat3 lumaChromaToRGB;" + "uniform mat3 rgbToLumaChroma;" + "uniform usampler2D textureName;" + + "void main(void) {"; + + DisplayType computed_display_type; switch(input_data_type) { case InputDataType::Luminance1: - fragment_shader += - "uniform usampler2D textureName;" - "void main(void) {"; - - switch(display_type) { - case DisplayType::RGB: - fragment_shader += "fragColour = vec4(texture(textureName, textureCoordinate).rrr, 1.0);"; - break; - default: - fragment_shader += "fragColour = vec4(texture(textureName, textureCoordinate).r, 0.0, 0.0, 1.0);"; - break; - } - - fragment_shader += "}"; + computed_display_type = DisplayType::CompositeMonochrome; + fragment_shader += "fragColour = vec4(vec3(texture(textureName, textureCoordinate).r), 1.0);"; break; case InputDataType::Luminance8: + computed_display_type = DisplayType::CompositeMonochrome; + fragment_shader += "fragColour = vec4(vec3(texture(textureName, textureCoordinate).r / 255.0), 1.0);"; break; -// SVideo, -// CompositeColour, -// CompositeMonochrome - case InputDataType::Phase8Luminance8: - return nullptr; -// fragment_shader += -// "uniform sampler2D textureName;" -// "void main(void) {"; -// -// switch(display_type) { -// default: return nullptr; -// -// case OutputType::SVideo: -// break; -//// CompositeColour, -//// CompositeMonochrome -// } -// -// fragment_shader += "}"; -// break; - - // TODO: write encoding functions for RGB -> composite/s-video for the RGB inputs. + computed_display_type = DisplayType::SVideo; + fragment_shader += "fragColour = vec4(texture(textureName, textureCoordinate).rg / vec2(255.0), 0.0, 1.0);"; + break; case InputDataType::Red1Green1Blue1: + computed_display_type = DisplayType::RGB; fragment_shader += - "uniform usampler2D textureName;" - "void main(void) {" - "uint textureValue = texture(textureName, textureCoordinate).r;" - "fragColour = vec4(uvec3(textureValue) & uvec3(4u, 2u, 1u), 1.0);" - "}"; + "uint textureValue = texture(textureName, textureCoordinate).r;" + "fragColour = vec4(uvec3(textureValue) & uvec3(4u, 2u, 1u), 1.0);"; break; case InputDataType::Red2Green2Blue2: + computed_display_type = DisplayType::RGB; fragment_shader += - "uniform usampler2D textureName;" - "void main(void) {" - "uint textureValue = texture(textureName, textureCoordinate).r;" - "fragColour = vec4(vec3(float((textureValue >> 4) & 3u), float((textureValue >> 2) & 3u), float(textureValue & 3u)) / 3.0, 1.0);" - "}"; + "uint textureValue = texture(textureName, textureCoordinate).r;" + "fragColour = vec4(vec3(float((textureValue >> 4) & 3u), float((textureValue >> 2) & 3u), float(textureValue & 3u)) / 3.0, 1.0);"; break; case InputDataType::Red4Green4Blue4: + computed_display_type = DisplayType::RGB; + fragment_shader += + "uvec2 textureValue = texture(textureName, textureCoordinate).rg;" + "fragColour = vec4(float(textureValue.r) / 15.0, float(textureValue.g & 240u) / 240.0, float(textureValue.g & 15u) / 15.0, 1.0);"; break; case InputDataType::Red8Green8Blue8: - fragment_shader += - "uniform usampler2D textureName;" - "void main(void) {" - "fragColour = vec4(texture(textureName, textureCoordinate).rgb / vec3(255.0), 1.0);" - "}"; + computed_display_type = DisplayType::RGB; + fragment_shader += "fragColour = vec4(texture(textureName, textureCoordinate).rgb / vec3(255.0), 1.0);"; break; } + if(computed_display_type != display_type) { + // If the input type is RGB but the output type isn't then + // there'll definitely be an RGB to SVideo step. + if(computed_display_type == DisplayType::RGB) { + fragment_shader += + "vec3 composite_colour = rgbToLumaChroma * vec3(fragColour);" + "vec2 quadrature = vec2(cos(compositeAngle), sin(compositeAngle));" + "fragColour = vec4(composite_colour.r, 0.5 + dot(quadrature, composite_colour.gb)*0.5, 0.0, 1.0);"; + } + + // If the output type isn't SVideo, add an SVideo to composite step. + if(computed_display_type != DisplayType::SVideo) { + fragment_shader += "fragColour = vec4(vec3(mix(fragColour.r,fragColour.g, compositeAmplitudeOut)), 1.0);"; + } + } + return std::unique_ptr(new Shader( glsl_globals(ShaderType::Scan) + glsl_default_vertex_shader(ShaderType::Scan), - fragment_shader + fragment_shader + "}" )); } diff --git a/Outputs/ScanTarget.hpp b/Outputs/ScanTarget.hpp index 5521d50ae..c06f3dcf5 100644 --- a/Outputs/ScanTarget.hpp +++ b/Outputs/ScanTarget.hpp @@ -124,7 +124,7 @@ struct ScanTarget { InputDataType input_data_type; /// Describes the type of display that the data is being shown on. - DisplayType display_type = DisplayType::RGB; + DisplayType display_type = DisplayType::CompositeMonochrome; /// If being fed composite data, this defines the colour space in use. ColourSpace composite_colour_space;