diff --git a/Outputs/OpenGL/ScanTarget.cpp b/Outputs/OpenGL/ScanTarget.cpp index 58670922d..9e4231ff2 100644 --- a/Outputs/OpenGL/ScanTarget.cpp +++ b/Outputs/OpenGL/ScanTarget.cpp @@ -148,19 +148,6 @@ void ScanTarget::set_modals(Modals modals) { // Establish an input shader. input_shader_ = input_shader(modals_.input_data_type, OutputType::RGB); -// input_shader_ = reset(new Shader( -// glsl_globals(ShaderType::Scan) + glsl_default_vertex_shader(ShaderType::Scan), -// "#version 150\n" -// -// "out vec4 fragColour;" -// "in vec2 textureCoordinate;" -// -// "uniform usampler2D textureName;" -// -// "void main(void) {" -// "fragColour = vec4(vec3(texture(textureName, textureCoordinate).rgb), 1.0);" -// "}" -// )); glBindVertexArray(scan_vertex_array_); glBindBuffer(GL_ARRAY_BUFFER, scan_buffer_name_); @@ -170,7 +157,10 @@ 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)); + output_shader_->set_uniform("textureName", GLint(UnprocessedLineBufferTextureUnit - GL_TEXTURE0)); + output_shader_->set_uniform("origin", modals.visible_area.origin.x, modals.visible_area.origin.y); + output_shader_->set_uniform("size", modals.visible_area.size.width, modals.visible_area.size.height); } void Outputs::Display::OpenGL::ScanTarget::set_uniforms(ShaderType type, Shader &target) { @@ -278,8 +268,10 @@ void ScanTarget::end_data(size_t actual_length) { void ScanTarget::submit() { if(allocation_has_failed_) { - // Reset all pointers to where they were. + // Reset all pointers to where they were; this also means + // the stencil won't be properly populated. write_pointers_ = submit_pointers_.load(); + frame_was_complete_ = false; } else { // Advance submit pointer. submit_pointers_.store(write_pointers_); @@ -304,6 +296,7 @@ void ScanTarget::announce(Event event, uint16_t x, uint16_t y) { // Store metadata if concluding a previous line. if(active_line_) { line_metadata_buffer_[size_t(write_pointers_.line)].is_first_in_frame = is_first_in_frame_; + line_metadata_buffer_[size_t(write_pointers_.line)].previous_frame_was_complete = frame_was_complete_; is_first_in_frame_ = false; } @@ -329,6 +322,7 @@ void ScanTarget::announce(Event event, uint16_t x, uint16_t y) { } break; case ScanTarget::Event::EndVerticalRetrace: is_first_in_frame_ = true; + frame_was_complete_ = true; break; } @@ -526,8 +520,8 @@ 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_) { - full_display_rectangle_.draw(0.0, 0.0, 0.0); + if(stencil_is_valid_ && line_metadata_buffer_[start_line].previous_frame_was_complete) { + full_display_rectangle_.draw(1.0, 0.0, 0.0f); } stencil_is_valid_ = true; glClear(GL_STENCIL_BUFFER_BIT); diff --git a/Outputs/OpenGL/ScanTarget.hpp b/Outputs/OpenGL/ScanTarget.hpp index e3c8e14f4..537736f6b 100644 --- a/Outputs/OpenGL/ScanTarget.hpp +++ b/Outputs/OpenGL/ScanTarget.hpp @@ -94,6 +94,7 @@ class ScanTarget: public Outputs::Display::ScanTarget { }; struct LineMetadata { bool is_first_in_frame; + bool previous_frame_was_complete; }; std::array line_buffer_; std::array line_metadata_buffer_; @@ -113,6 +114,7 @@ class ScanTarget: public Outputs::Display::ScanTarget { Line *active_line_ = nullptr; int provided_scans_ = 0; bool is_first_in_frame_ = true; + bool frame_was_complete_ = true; // OpenGL storage handles for buffer data. GLuint scan_buffer_name_ = 0, scan_vertex_array_ = 0; diff --git a/Outputs/OpenGL/ScanTargetGLSLFragments.cpp b/Outputs/OpenGL/ScanTargetGLSLFragments.cpp index 7cadc4107..74db82bfd 100644 --- a/Outputs/OpenGL/ScanTargetGLSLFragments.cpp +++ b/Outputs/OpenGL/ScanTargetGLSLFragments.cpp @@ -31,7 +31,9 @@ std::string ScanTarget::glsl_globals(ShaderType type) { "in float endCompositeAngle;" "in float dataY;" - "in float lineY;"; + "in float lineY;" + + "uniform usampler2D textureName;"; case ShaderType::Line: return @@ -44,7 +46,11 @@ std::string ScanTarget::glsl_globals(ShaderType type) { "in vec2 startPoint;" "in vec2 endPoint;" - "in float lineY;"; + "in float lineY;" + + "uniform sampler2D textureName;" + "uniform vec2 origin;" + "uniform vec2 size;"; } } @@ -53,7 +59,6 @@ std::string ScanTarget::glsl_default_vertex_shader(ShaderType type) { case ShaderType::Scan: return "out vec2 textureCoordinate;" - "uniform usampler2D textureName;" "void main(void) {" "float lateral = float(gl_VertexID & 1);" @@ -68,7 +73,6 @@ std::string ScanTarget::glsl_default_vertex_shader(ShaderType type) { case ShaderType::Line: return "out vec2 textureCoordinate;" - "uniform sampler2D textureName;" "void main(void) {" "float lateral = float(gl_VertexID & 1);" @@ -78,7 +82,7 @@ std::string ScanTarget::glsl_default_vertex_shader(ShaderType type) { "vec2 centrePoint = mix(startPoint, endPoint, lateral) / scale;" "vec2 height = normalize(endPoint - startPoint).yx * (longitudinal - 0.5) * rowHeight;" - "vec2 eyePosition = vec2(-1.0, 1.0) + vec2(2.0, -2.0) * (centrePoint + height);" + "vec2 eyePosition = vec2(-1.0, 1.0) + vec2(2.0, -2.0) * (((centrePoint + height) - origin) / size);" "gl_Position = vec4(eyePosition, 0.0, 1.0);" "}"; }