From 8232ed765e468da77c0c9c18035b344d24ab546e Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 20 Apr 2016 20:44:25 -0400 Subject: [PATCH] Eliminated use of zero-alpha runs to clear new lines in the intermediate buffer in favour of a scissored glClear. It's just an easier way to scale the current approach to three intermediate buffers. --- Outputs/CRT/CRT.cpp | 10 ----- Outputs/CRT/Internals/CRTOpenGL.cpp | 61 +++++++++++++++++++++++++---- Outputs/CRT/Internals/CRTOpenGL.hpp | 6 +-- 3 files changed, 56 insertions(+), 21 deletions(-) diff --git a/Outputs/CRT/CRT.cpp b/Outputs/CRT/CRT.cpp index 50ef7a3a1..91567e77c 100644 --- a/Outputs/CRT/CRT.cpp +++ b/Outputs/CRT/CRT.cpp @@ -106,7 +106,6 @@ Flywheel::SyncEvent CRT::get_next_horizontal_sync_event(bool hsync_is_requested, #define source_output_position_y(v) (*(uint16_t *)&next_run[SourceVertexSize*v + SourceVertexOffsetOfOutputPosition + 2]) #define source_phase(v) next_run[SourceVertexSize*v + SourceVertexOffsetOfPhaseAmplitudeAndAlpha + 0] #define source_amplitude(v) next_run[SourceVertexSize*v + SourceVertexOffsetOfPhaseAmplitudeAndAlpha + 1] -#define source_alpha(v) next_run[SourceVertexSize*v + SourceVertexOffsetOfPhaseAmplitudeAndAlpha + 2] #define source_phase_time(v) (*(uint16_t *)&next_run[SourceVertexSize*v + SourceVertexOffsetOfPhaseTime]) void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divider, bool hsync_requested, bool vsync_requested, const bool vsync_charging, const Scan::Type type, uint16_t tex_x, uint16_t tex_y) @@ -165,7 +164,6 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi source_phase(0) = source_phase(1) = _colour_burst_phase; source_amplitude(0) = source_amplitude(1) = _colour_burst_amplitude; source_phase_time(0) = source_phase_time(1) = _colour_burst_time; - source_alpha(0) = source_alpha(1) = 255; } } @@ -244,14 +242,6 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi if(next_run_length == time_until_horizontal_sync_event && next_horizontal_sync_event == Flywheel::SyncEvent::StartRetrace) { _openGL_output_builder->increment_composite_output_y(); - - // store a run to clear the new line - next_run = _openGL_output_builder->get_next_source_run(); - source_output_position_x(0) = 0; - source_output_position_x(1) = IntermediateBufferWidth; - source_output_position_y(0) = source_output_position_y(1) = _openGL_output_builder->get_composite_output_y(); - source_alpha(0) = source_alpha(1) = 0; - _openGL_output_builder->complete_source_run(); } } diff --git a/Outputs/CRT/Internals/CRTOpenGL.cpp b/Outputs/CRT/Internals/CRTOpenGL.cpp index f887a0456..a9ea0d8b0 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.cpp +++ b/Outputs/CRT/Internals/CRTOpenGL.cpp @@ -206,12 +206,59 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out // decide how much to draw if(_drawn_source_buffer_data_pointer != _source_buffer_data_pointer) { + // determine how many lines are newly reclaimed; they'll need to be cleared + uint16_t clearing_zones[4]; + int number_of_clearing_zones = 0; + + if(_composite_src_output_y != _cleared_composite_output_y) + { + uint16_t lines_to_clear = _composite_src_output_y - _cleared_composite_output_y; + if(lines_to_clear > IntermediateBufferHeight) + { + number_of_clearing_zones = 1; + clearing_zones[0] = 0; + clearing_zones[1] = IntermediateBufferHeight; + } + else + { + clearing_zones[0] = (_cleared_composite_output_y+1)%IntermediateBufferHeight; + if(clearing_zones[0]+lines_to_clear < IntermediateBufferHeight) + { + clearing_zones[1] = lines_to_clear; + number_of_clearing_zones = 1; + } + else + { + clearing_zones[1] = IntermediateBufferHeight - clearing_zones[0]; + clearing_zones[2] = 0; + clearing_zones[3] = lines_to_clear - clearing_zones[1]; + number_of_clearing_zones = 2; + } + } + + _composite_src_output_y %= IntermediateBufferHeight; + _cleared_composite_output_y = _composite_src_output_y; + } + + // all drawing will be from the source vertex array and without blending + glBindVertexArray(source_vertex_array); + glDisable(GL_BLEND); + + // switch to the initial texture + compositeTexture->bind_framebuffer(); composite_input_shader_program->bind(); - compositeTexture->bind_framebuffer(); - glBindVertexArray(source_vertex_array); - - glDisable(GL_BLEND); + // clear as desired + if(number_of_clearing_zones) + { + glEnable(GL_SCISSOR_TEST); + for(int c = 0; c < number_of_clearing_zones; c++) + { + glScissor(0, clearing_zones[c*2], IntermediateBufferWidth, clearing_zones[c*2 + 1]); + glClear(GL_COLOR_BUFFER_BIT); + } + glDisable(GL_SCISSOR_TEST); + } size_t new_data_size = _source_buffer_data_pointer - _drawn_source_buffer_data_pointer; size_t new_data_start = _drawn_source_buffer_data_pointer; @@ -231,6 +278,7 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out glDrawArrays(GL_LINES, 0, (GLsizei)((new_data_size - first_data_length) / SourceVertexSize)); } + // switch back to screen output glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer); glViewport(0, 0, (GLsizei)output_width, (GLsizei)output_height); } @@ -358,7 +406,6 @@ char *OpenGLOutputBuilder::get_input_vertex_shader() "out vec2 inputPositionVarying;" "out vec2 iInputPositionVarying;" "out float phaseVarying;" - "out float alphaVarying;" "void main(void)" "{" @@ -367,7 +414,6 @@ char *OpenGLOutputBuilder::get_input_vertex_shader() "inputPositionVarying = (inputPosition + vec2(0.0, 0.5)) / vec2(textureSize);" "phaseVarying = (phaseCyclesPerTick * phaseTime + phaseAmplitudeAndAlpha.x) * 2.0 * 3.141592654;" - "alphaVarying = phaseAmplitudeAndAlpha.z;" "vec2 eyePosition = 2.0*(outputPosition / outputTextureSize) - vec2(1.0) + vec2(0.5)/textureSize;" "gl_Position = vec4(eyePosition, 0.0, 1.0);" @@ -390,7 +436,6 @@ char *OpenGLOutputBuilder::get_input_fragment_shader() "in vec2 inputPositionVarying;" "in vec2 iInputPositionVarying;" "in float phaseVarying;" - "in float alphaVarying;" "out vec4 fragColour;" @@ -400,7 +445,7 @@ char *OpenGLOutputBuilder::get_input_fragment_shader() "void main(void)" "{" - "fragColour = vec4(rgb_sample(texID, inputPositionVarying, iInputPositionVarying) * alphaVarying, 1.0);" // composite + "fragColour = vec4(rgb_sample(texID, inputPositionVarying, iInputPositionVarying), 1.0);" "}" , composite_shader); return result; diff --git a/Outputs/CRT/Internals/CRTOpenGL.hpp b/Outputs/CRT/Internals/CRTOpenGL.hpp index 26307df82..6da878397 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.hpp +++ b/Outputs/CRT/Internals/CRTOpenGL.hpp @@ -60,7 +60,7 @@ class OpenGLOutputBuilder { std::shared_ptr _output_mutex; // transient buffers indicating composite data not yet decoded - uint16_t _composite_src_output_y; + uint16_t _composite_src_output_y, _cleared_composite_output_y; char *get_output_vertex_shader(const char *header); char *get_rgb_output_vertex_shader(); @@ -150,12 +150,12 @@ class OpenGLOutputBuilder { inline uint16_t get_composite_output_y() { - return _composite_src_output_y; + return _composite_src_output_y % IntermediateBufferHeight; } inline void increment_composite_output_y() { - _composite_src_output_y = (_composite_src_output_y + 1) % IntermediateBufferHeight; + _composite_src_output_y++; } inline void increment_field()