diff --git a/Outputs/CRT/CRT.cpp b/Outputs/CRT/CRT.cpp index 1b6c32084..029dd3b52 100644 --- a/Outputs/CRT/CRT.cpp +++ b/Outputs/CRT/CRT.cpp @@ -99,7 +99,6 @@ Flywheel::SyncEvent CRT::get_next_horizontal_sync_event(bool hsync_is_requested, #define output_position_y(v) (*(uint16_t *)&next_run[OutputVertexSize*v + OutputVertexOffsetOfPosition + 2]) #define output_tex_x(v) (*(uint16_t *)&next_run[OutputVertexSize*v + OutputVertexOffsetOfTexCoord + 0]) #define output_tex_y(v) (*(uint16_t *)&next_run[OutputVertexSize*v + OutputVertexOffsetOfTexCoord + 2]) -#define output_lateral(v) next_run[OutputVertexSize*v + OutputVertexOffsetOfLateral] #define source_input_position_x(v) (*(uint16_t *)&next_run[SourceVertexSize*v + SourceVertexOffsetOfInputPosition + 0]) #define source_input_position_y(v) (*(uint16_t *)&next_run[SourceVertexSize*v + SourceVertexOffsetOfInputPosition + 2]) @@ -195,9 +194,6 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi output_position_y(0) = output_position_y(1) = output_position_y(2) = (uint16_t)(_vertical_flywheel->get_current_output_position() / _vertical_flywheel_output_divider); output_tex_x(0) = output_tex_x(1) = output_tex_x(2) = (uint16_t)_horizontal_flywheel->get_current_output_position(); output_tex_y(0) = output_tex_y(1) = output_tex_y(2) = _openGL_output_builder->get_composite_output_y(); - output_lateral(0) = 0; - output_lateral(1) = _is_writing_composite_run ? 1 : 0; - output_lateral(2) = 1; _openGL_output_builder->complete_output_run(3); _is_writing_composite_run ^= true; diff --git a/Outputs/CRT/Internals/CRTConstants.hpp b/Outputs/CRT/Internals/CRTConstants.hpp index 63cfe99ed..b6edb5013 100644 --- a/Outputs/CRT/Internals/CRTConstants.hpp +++ b/Outputs/CRT/Internals/CRTConstants.hpp @@ -19,9 +19,8 @@ namespace CRT { // or is one of the intermediate buffers that we've used to convert from composite towards RGB. const GLsizei OutputVertexOffsetOfPosition = 0; const GLsizei OutputVertexOffsetOfTexCoord = 4; -const GLsizei OutputVertexOffsetOfLateral = 8; -const GLsizei OutputVertexSize = 12; +const GLsizei OutputVertexSize = 8; // Input vertices, used only in composite mode, map from the input buffer to temporary buffer locations; such // remapping occurs to ensure a continous stream of data for each scan, giving correct out-of-bounds behaviour @@ -41,7 +40,7 @@ const GLsizei IntermediateBufferWidth = 2048; const GLsizei IntermediateBufferHeight = 2048; // Some internal buffer sizes -const GLsizeiptr OutputVertexBufferDataSize = 89856; // a multiple of 6 * OutputVertexSize +const GLsizeiptr OutputVertexBufferDataSize = 59904; // a multiple of 6 * OutputVertexSize const GLsizeiptr SourceVertexBufferDataSize = 87360; // a multiple of 2 * SourceVertexSize } diff --git a/Outputs/CRT/Internals/CRTOpenGL.cpp b/Outputs/CRT/Internals/CRTOpenGL.cpp index 55adaa3a4..f804dce9d 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.cpp +++ b/Outputs/CRT/Internals/CRTOpenGL.cpp @@ -137,6 +137,17 @@ OpenGLOutputBuilder::OpenGLOutputBuilder(unsigned int buffer_depth) : glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer); glBufferData(GL_ARRAY_BUFFER, OutputVertexBufferDataSize, NULL, GL_STREAM_DRAW); + // create and populate a buffer for the lateral attributes + glGenBuffers(1, &lateral_array_buffer); + glBindBuffer(GL_ARRAY_BUFFER, lateral_array_buffer); + size_t number_of_vertices = OutputVertexBufferDataSize/OutputVertexSize; + uint8_t lateral_pattern[] = {0, 0, 1, 0, 1, 1}; + uint8_t *laterals = new uint8_t[number_of_vertices]; + for(size_t c = 0; c < number_of_vertices; c++) + laterals[c] = lateral_pattern[c%6]; + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)number_of_vertices, laterals, GL_STATIC_DRAW); + delete[] laterals; + // map that buffer too, for any CRT activity that may occur before the first draw _output_buffer_data = (uint8_t *)glMapBufferRange(GL_ARRAY_BUFFER, 0, OutputVertexBufferDataSize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); @@ -160,6 +171,7 @@ OpenGLOutputBuilder::~OpenGLOutputBuilder() glDeleteBuffers(1, &_input_texture_array); glDeleteBuffers(1, &output_array_buffer); glDeleteBuffers(1, &source_array_buffer); + glDeleteBuffers(1, &lateral_array_buffer); glDeleteVertexArrays(1, &output_vertex_array); free(_composite_shader); @@ -168,6 +180,9 @@ OpenGLOutputBuilder::~OpenGLOutputBuilder() void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int output_height, bool only_if_dirty) { + // lock down any further work on the current frame + _output_mutex->lock(); + // establish essentials if(!output_shader_program) { @@ -190,9 +205,6 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out defaultFramebuffer = 0; } - // lock down any further work on the current frame - _output_mutex->lock(); - // release the mapping, giving up on trying to draw if data has been lost glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer); glUnmapBuffer(GL_ARRAY_BUFFER); @@ -466,19 +478,21 @@ void OpenGLOutputBuilder::prepare_output_vertex_array() { GLint positionAttribute = output_shader_program->get_attrib_location("position"); GLint textureCoordinatesAttribute = output_shader_program->get_attrib_location("srcCoordinates"); - GLint lateralAttribute = output_shader_program->get_attrib_location("lateral"); glBindVertexArray(output_vertex_array); glEnableVertexAttribArray((GLuint)positionAttribute); glEnableVertexAttribArray((GLuint)textureCoordinatesAttribute); - glEnableVertexAttribArray((GLuint)lateralAttribute); const GLsizei vertexStride = OutputVertexSize; glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer); glVertexAttribPointer((GLuint)positionAttribute, 2, GL_UNSIGNED_SHORT, GL_FALSE, vertexStride, (void *)OutputVertexOffsetOfPosition); glVertexAttribPointer((GLuint)textureCoordinatesAttribute, 2, GL_UNSIGNED_SHORT, GL_FALSE, vertexStride, (void *)OutputVertexOffsetOfTexCoord); - glVertexAttribPointer((GLuint)lateralAttribute, 1, GL_UNSIGNED_BYTE, GL_FALSE, vertexStride, (void *)OutputVertexOffsetOfLateral); + + GLint lateralAttribute = output_shader_program->get_attrib_location("lateral"); + glEnableVertexAttribArray((GLuint)lateralAttribute); + glBindBuffer(GL_ARRAY_BUFFER, lateral_array_buffer); + glVertexAttribPointer((GLuint)lateralAttribute, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, (void *)0); } } @@ -497,6 +511,7 @@ void OpenGLOutputBuilder::set_output_device(OutputDevice output_device) void OpenGLOutputBuilder::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) { + _output_mutex->lock(); _input_frequency = input_frequency; _cycles_per_line = cycles_per_line; _height_of_display = height_of_display; @@ -505,13 +520,13 @@ void OpenGLOutputBuilder::set_timing(unsigned int input_frequency, unsigned int _vertical_period_divider = vertical_period_divider; set_timing_uniforms(); + _output_mutex->unlock(); } #pragma mark - Internal Configuration void OpenGLOutputBuilder::set_colour_space_uniforms() { - _output_mutex->lock(); GLfloat rgbToYUV[] = {0.299f, -0.14713f, 0.615f, 0.587f, -0.28886f, -0.51499f, 0.114f, 0.436f, -0.10001f}; GLfloat yuvToRGB[] = {1.0f, 1.0f, 1.0f, 0.0f, -0.39465f, 2.03211f, 1.13983f, -0.58060f, 0.0f}; @@ -535,13 +550,10 @@ void OpenGLOutputBuilder::set_colour_space_uniforms() if(composite_input_shader_program) composite_input_shader_program->set_colour_conversion_matrices(fromRGB, toRGB); if(composite_chrominance_filter_shader_program) composite_chrominance_filter_shader_program->set_colour_conversion_matrices(fromRGB, toRGB); - _output_mutex->unlock(); } void OpenGLOutputBuilder::set_timing_uniforms() { - _output_mutex->lock(); - OpenGL::IntermediateShader *intermediate_shaders[] = { composite_input_shader_program.get(), composite_separation_filter_program.get(), @@ -563,6 +575,4 @@ void OpenGLOutputBuilder::set_timing_uniforms() if(composite_y_filter_shader_program) composite_y_filter_shader_program->set_filter_coefficients(_cycles_per_line, colour_subcarrier_frequency * 0.66f); if(composite_chrominance_filter_shader_program) composite_chrominance_filter_shader_program->set_filter_coefficients(_cycles_per_line, colour_subcarrier_frequency * 0.5f); if(rgb_filter_shader_program) rgb_filter_shader_program->set_filter_coefficients(_cycles_per_line, (float)_input_frequency * 0.5f); - - _output_mutex->unlock(); } diff --git a/Outputs/CRT/Internals/CRTOpenGL.hpp b/Outputs/CRT/Internals/CRTOpenGL.hpp index 5015d2486..a8abfb24f 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.hpp +++ b/Outputs/CRT/Internals/CRTOpenGL.hpp @@ -73,7 +73,7 @@ class OpenGLOutputBuilder { std::unique_ptr framebuffer; // the current pixel output - GLuint output_array_buffer, output_vertex_array; + GLuint output_array_buffer, lateral_array_buffer, output_vertex_array; GLuint source_array_buffer, source_vertex_array; unsigned int _last_output_width, _last_output_height; @@ -91,10 +91,12 @@ class OpenGLOutputBuilder { inline void set_colour_format(ColourSpace colour_space, unsigned int colour_cycle_numerator, unsigned int colour_cycle_denominator) { + _output_mutex->lock(); _colour_space = colour_space; _colour_cycle_numerator = colour_cycle_numerator; _colour_cycle_denominator = colour_cycle_denominator; set_colour_space_uniforms(); + _output_mutex->unlock(); } inline void set_visible_area(Rect visible_area)