diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index ca2fdabaf..a66cae767 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -305,7 +305,6 @@ 4BB73EC21B587A5100552FC2 /* Clock_SignalUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB73EC11B587A5100552FC2 /* Clock_SignalUITests.swift */; }; 4BBF99141C8FBA6F0075DAFB /* CRTInputBufferBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF99081C8FBA6F0075DAFB /* CRTInputBufferBuilder.cpp */; }; 4BBF99151C8FBA6F0075DAFB /* CRTOpenGL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF990A1C8FBA6F0075DAFB /* CRTOpenGL.cpp */; }; - 4BBF99161C8FBA6F0075DAFB /* CRTRunBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF990C1C8FBA6F0075DAFB /* CRTRunBuilder.cpp */; }; 4BBF99171C8FBA6F0075DAFB /* Shader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF99101C8FBA6F0075DAFB /* Shader.cpp */; }; 4BBF99181C8FBA6F0075DAFB /* TextureTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF99121C8FBA6F0075DAFB /* TextureTarget.cpp */; }; 4BC76E691C98E31700E6EF73 /* FIRFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC76E671C98E31700E6EF73 /* FIRFilter.cpp */; }; @@ -660,8 +659,6 @@ 4BBF99091C8FBA6F0075DAFB /* CRTInputBufferBuilder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CRTInputBufferBuilder.hpp; sourceTree = ""; }; 4BBF990A1C8FBA6F0075DAFB /* CRTOpenGL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CRTOpenGL.cpp; sourceTree = ""; }; 4BBF990B1C8FBA6F0075DAFB /* CRTOpenGL.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CRTOpenGL.hpp; sourceTree = ""; }; - 4BBF990C1C8FBA6F0075DAFB /* CRTRunBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CRTRunBuilder.cpp; sourceTree = ""; }; - 4BBF990D1C8FBA6F0075DAFB /* CRTRunBuilder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CRTRunBuilder.hpp; sourceTree = ""; }; 4BBF990E1C8FBA6F0075DAFB /* Flywheel.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Flywheel.hpp; sourceTree = ""; }; 4BBF990F1C8FBA6F0075DAFB /* OpenGL.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = OpenGL.hpp; sourceTree = ""; }; 4BBF99101C8FBA6F0075DAFB /* Shader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Shader.cpp; sourceTree = ""; }; @@ -1210,8 +1207,6 @@ 4BBF99091C8FBA6F0075DAFB /* CRTInputBufferBuilder.hpp */, 4BBF990A1C8FBA6F0075DAFB /* CRTOpenGL.cpp */, 4BBF990B1C8FBA6F0075DAFB /* CRTOpenGL.hpp */, - 4BBF990C1C8FBA6F0075DAFB /* CRTRunBuilder.cpp */, - 4BBF990D1C8FBA6F0075DAFB /* CRTRunBuilder.hpp */, 4BBF990E1C8FBA6F0075DAFB /* Flywheel.hpp */, 4BBF990F1C8FBA6F0075DAFB /* OpenGL.hpp */, 4BBF99101C8FBA6F0075DAFB /* Shader.cpp */, @@ -1653,7 +1648,6 @@ 4B0CCC451C62D0B3001CAC5F /* CRT.cpp in Sources */, 4B55CE591C3B7D360093A61B /* ElectronDocument.swift in Sources */, 4B55CE4B1C3B3B0C0093A61B /* CSAtari2600.mm in Sources */, - 4BBF99161C8FBA6F0075DAFB /* CRTRunBuilder.cpp in Sources */, 4B55CE581C3B7D360093A61B /* Atari2600Document.swift in Sources */, 4B0EBFB81C487F2F00A11F35 /* AudioQueue.m in Sources */, 4BBF99181C8FBA6F0075DAFB /* TextureTarget.cpp in Sources */, diff --git a/Outputs/CRT/CRT.cpp b/Outputs/CRT/CRT.cpp index c01587273..db6e745f7 100644 --- a/Outputs/CRT/CRT.cpp +++ b/Outputs/CRT/CRT.cpp @@ -10,6 +10,7 @@ #include "CRTOpenGL.hpp" #include #include +#include using namespace Outputs::CRT; @@ -149,14 +150,14 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi // set the type, initial raster position and type of this run output_position_x(0) = output_position_x(1) = output_position_x(2) = (uint16_t)_horizontal_flywheel->get_current_output_position(); 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_timestamp(0) = output_timestamp(1) = output_timestamp(2) = _openGL_output_builder->get_current_field_time(); +// output_timestamp(0) = output_timestamp(1) = output_timestamp(2) = _openGL_output_builder->get_current_field_time(); output_tex_x(0) = output_tex_x(1) = output_tex_x(2) = tex_x; // these things are constants across the line so just throw them out now output_tex_y(0) = output_tex_y(1) = output_tex_y(2) = output_tex_y(3) = output_tex_y(4) = output_tex_y(5) = tex_y; output_lateral(0) = output_lateral(1) = output_lateral(3) = 0; output_lateral(2) = output_lateral(4) = output_lateral(5) = 1; - output_frame_id(0) = output_frame_id(1) = output_frame_id(2) = output_frame_id(3) = output_frame_id(4) = output_frame_id(5) = (uint8_t)_openGL_output_builder->get_current_field(); +// output_frame_id(0) = output_frame_id(1) = output_frame_id(2) = output_frame_id(3) = output_frame_id(4) = output_frame_id(5) = (uint8_t)_openGL_output_builder->get_current_field(); } else { @@ -175,7 +176,7 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi // decrement the number of cycles left to run for and increment the // horizontal counter appropriately number_of_cycles -= next_run_length; - _openGL_output_builder->add_to_field_time(next_run_length); +// _openGL_output_builder->add_to_field_time(next_run_length); // either charge or deplete the vertical retrace capacitor (making sure it stops at 0) if(vsync_charging) @@ -197,7 +198,7 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi // store the final raster position output_position_x(3) = output_position_x(4) = output_position_x(5) = (uint16_t)_horizontal_flywheel->get_current_output_position(); output_position_y(3) = output_position_y(4) = output_position_y(5) = (uint16_t)(_vertical_flywheel->get_current_output_position() / _vertical_flywheel_output_divider); - output_timestamp(3) = output_timestamp(4) = output_timestamp(5) = _openGL_output_builder->get_current_field_time(); +// output_timestamp(3) = output_timestamp(4) = output_timestamp(5) = _openGL_output_builder->get_current_field_time(); output_tex_x(3) = output_tex_x(4) = output_tex_x(5) = tex_x; _openGL_output_builder->complete_output_run(6); @@ -227,13 +228,13 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi output_position_x(0) = output_position_x(1) = output_position_x(2) = (uint16_t)_horizontal_flywheel->get_current_output_position(); 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_timestamp(0) = output_timestamp(1) = output_timestamp(2) = _openGL_output_builder->get_current_field_time(); +// output_timestamp(0) = output_timestamp(1) = output_timestamp(2) = _openGL_output_builder->get_current_field_time(); 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; - output_frame_id(0) = output_frame_id(1) = output_frame_id(2) = (uint8_t)_openGL_output_builder->get_current_field(); +// output_frame_id(0) = output_frame_id(1) = output_frame_id(2) = (uint8_t)_openGL_output_builder->get_current_field(); _openGL_output_builder->complete_output_run(3); _is_writing_composite_run ^= true; @@ -258,7 +259,7 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi } } - _openGL_output_builder->increment_field(); +// _openGL_output_builder->increment_field(); } } } diff --git a/Outputs/CRT/Internals/CRTOpenGL.cpp b/Outputs/CRT/Internals/CRTOpenGL.cpp index 5ebbc25d5..0400f8da6 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.cpp +++ b/Outputs/CRT/Internals/CRTOpenGL.cpp @@ -36,8 +36,14 @@ static const GLenum formatForDepth(size_t depth) } } -static int getCircularRanges(GLsizei start, GLsizei end, GLsizei buffer_length, GLsizei *ranges) +static int getCircularRanges(GLsizei start, GLsizei end, GLsizei buffer_length, GLsizei granularity, GLsizei *ranges) { + GLsizei startOffset = start%granularity; + if(startOffset) + { + start -= startOffset; + } + GLsizei length = end - start; if(!length) return 0; if(length > buffer_length) @@ -74,7 +80,6 @@ namespace { } OpenGLOutputBuilder::OpenGLOutputBuilder(unsigned int buffer_depth) : - _run_write_pointer(0), _output_mutex(new std::mutex), _visible_area(Rect(0, 0, 1, 1)), _composite_src_output_y(0), @@ -85,18 +90,14 @@ OpenGLOutputBuilder::OpenGLOutputBuilder(unsigned int buffer_depth) : _source_buffer_data(nullptr), _input_texture_data(nullptr), _output_buffer_data_pointer(0), + _drawn_output_buffer_data_pointer(0), _source_buffer_data_pointer(0), _drawn_source_buffer_data_pointer(0) { - _run_builders = new CRTRunBuilder *[NumberOfFields]; - for(int builder = 0; builder < NumberOfFields; builder++) - { - _run_builders[builder] = new CRTRunBuilder(); - } _buffer_builder = std::unique_ptr(new CRTInputBufferBuilder(buffer_depth)); glBlendFunc(GL_SRC_ALPHA, GL_CONSTANT_ALPHA); - glBlendColor(1.0f, 1.0f, 1.0f, 0.33f); + glBlendColor(1.0f, 1.0f, 1.0f, 0.5f); // Create intermediate textures and bind to slots 0, 1 and 2 glActiveTexture(composite_texture_unit); @@ -156,12 +157,6 @@ OpenGLOutputBuilder::OpenGLOutputBuilder(unsigned int buffer_depth) : OpenGLOutputBuilder::~OpenGLOutputBuilder() { - for(int builder = 0; builder < NumberOfFields; builder++) - { - delete _run_builders[builder]; - } - delete[] _run_builders; - glUnmapBuffer(GL_ARRAY_BUFFER); glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); glDeleteTextures(1, &textureName); @@ -203,11 +198,7 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out // release the mapping, giving up on trying to draw if data has been lost glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer); - if(glUnmapBuffer(GL_ARRAY_BUFFER) == GL_FALSE) - { - for(int c = 0; c < NumberOfFields; c++) - _run_builders[c]->reset(); - } + glUnmapBuffer(GL_ARRAY_BUFFER); glBindBuffer(GL_ARRAY_BUFFER, source_array_buffer); glUnmapBuffer(GL_ARRAY_BUFFER); glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); @@ -242,8 +233,8 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out { // determine how many lines are newly reclaimed; they'll need to be cleared GLsizei clearing_zones[4], drawing_zones[4]; - int number_of_clearing_zones = getCircularRanges(_cleared_composite_output_y+1, _composite_src_output_y+1, IntermediateBufferHeight, clearing_zones); - int number_of_drawing_zones = getCircularRanges(_drawn_source_buffer_data_pointer, _source_buffer_data_pointer, SourceVertexBufferDataSize, drawing_zones); + int number_of_clearing_zones = getCircularRanges(_cleared_composite_output_y+1, _composite_src_output_y+1, IntermediateBufferHeight, 1, clearing_zones); + int number_of_drawing_zones = getCircularRanges(_drawn_source_buffer_data_pointer, _source_buffer_data_pointer, SourceVertexBufferDataSize, 2*SourceVertexSize, drawing_zones); _composite_src_output_y %= IntermediateBufferHeight; _cleared_composite_output_y = _composite_src_output_y; @@ -324,23 +315,17 @@ void OpenGLOutputBuilder::perform_output_stage(unsigned int output_width, unsign if(shader) { // clear the buffer - glClear(GL_COLOR_BUFFER_BIT); +// glClear(GL_COLOR_BUFFER_BIT); - // draw all sitting frames - unsigned int run = (unsigned int)_run_write_pointer; - GLint total_age = 0; - float timestampBases[4]; - size_t start = 0, count = 0; - for(int c = 0; c < NumberOfFields; c++) - { - total_age += _run_builders[run]->duration; - timestampBases[run] = (float)total_age; - count += _run_builders[run]->amount_of_data; - start = _run_builders[run]->start; - run = (run - 1 + NumberOfFields) % NumberOfFields; - } + // draw all pending lines + GLsizei drawing_zones[4]; + int number_of_drawing_zones = getCircularRanges(_drawn_output_buffer_data_pointer, _output_buffer_data_pointer, OutputVertexBufferDataSize, 6*OutputVertexSize, drawing_zones); - if(count > 0) + _output_buffer_data_pointer %= SourceVertexBufferDataSize; + _output_buffer_data_pointer -= (_output_buffer_data_pointer%(6*OutputVertexSize)); + _drawn_output_buffer_data_pointer = _output_buffer_data_pointer; + + if(number_of_drawing_zones > 0) { glEnable(GL_BLEND); @@ -352,18 +337,9 @@ void OpenGLOutputBuilder::perform_output_stage(unsigned int output_width, unsign push_size_uniforms(output_width, output_height); // draw - glUniform4fv(timestampBaseUniform, 1, timestampBases); - - GLsizei primitive_count = (GLsizei)(count / OutputVertexSize); - GLsizei max_count = (GLsizei)((OutputVertexBufferDataSize - start) / OutputVertexSize); - if(primitive_count < max_count) + for(int c = 0; c < number_of_drawing_zones; c++) { - glDrawArrays(GL_TRIANGLE_STRIP, (GLint)(start / OutputVertexSize), primitive_count); - } - else - { - glDrawArrays(GL_TRIANGLE_STRIP, (GLint)(start / OutputVertexSize), max_count); - glDrawArrays(GL_TRIANGLE_STRIP, 0, primitive_count - max_count); + glDrawArrays(GL_TRIANGLE_STRIP, drawing_zones[c*2] / OutputVertexSize, drawing_zones[c*2 + 1] / OutputVertexSize); } } } @@ -673,7 +649,7 @@ char *OpenGLOutputBuilder::get_output_vertex_shader(const char *header) "iSrcCoordinatesVarying = srcCoordinates;" "srcCoordinatesVarying = vec2(srcCoordinates.x / textureSize.x, (srcCoordinates.y + 0.5) / textureSize.y);" "float age = (timestampBase[int(lateralAndTimestampBaseOffset.y)] - timestamp) / ticksPerFrame;" - "alpha = 1.0;"//15.0*exp(-age*3.0);" + "alpha = 0.5;"//15.0*exp(-age*3.0);" "vec2 floatingPosition = (position / positionConversion) + lateralAndTimestampBaseOffset.x * scanNormal;" "vec2 mappedPosition = (floatingPosition - boundsOrigin) / boundsSize;" @@ -884,12 +860,6 @@ void OpenGLOutputBuilder::set_output_device(OutputDevice output_device) if(_output_device != output_device) { _output_device = output_device; - - for(int builder = 0; builder < NumberOfFields; builder++) - { - _run_builders[builder]->reset(); - } - _composite_src_output_y = 0; } } diff --git a/Outputs/CRT/Internals/CRTOpenGL.hpp b/Outputs/CRT/Internals/CRTOpenGL.hpp index fc5144770..8d8d00ee8 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.hpp +++ b/Outputs/CRT/Internals/CRTOpenGL.hpp @@ -15,7 +15,6 @@ #include "TextureTarget.hpp" #include "Shader.hpp" #include "CRTInputBufferBuilder.hpp" -#include "CRTRunBuilder.hpp" #include @@ -58,8 +57,6 @@ class OpenGLOutputBuilder { // the run and input data buffers std::unique_ptr _buffer_builder; - CRTRunBuilder **_run_builders; - int _run_write_pointer; std::shared_ptr _output_mutex; // transient buffers indicating composite data not yet decoded @@ -132,13 +129,12 @@ class OpenGLOutputBuilder { inline uint8_t *get_next_output_run() { _output_mutex->lock(); - return &_output_buffer_data[_output_buffer_data_pointer]; + return &_output_buffer_data[_output_buffer_data_pointer % OutputVertexBufferDataSize]; } inline void complete_output_run(GLsizei vertices_written) { - _run_builders[_run_write_pointer]->amount_of_data += (size_t)(vertices_written * OutputVertexSize); - _output_buffer_data_pointer = (_output_buffer_data_pointer + vertices_written * OutputVertexSize) % OutputVertexBufferDataSize; + _output_buffer_data_pointer += vertices_written * OutputVertexSize; _output_mutex->unlock(); } @@ -147,16 +143,6 @@ class OpenGLOutputBuilder { return _output_device; } - inline uint32_t get_current_field_time() - { - return _run_builders[_run_write_pointer]->duration; - } - - inline void add_to_field_time(uint32_t amount) - { - _run_builders[_run_write_pointer]->duration += amount; - } - inline uint16_t get_composite_output_y() { return _composite_src_output_y % IntermediateBufferHeight; @@ -167,20 +153,6 @@ class OpenGLOutputBuilder { _composite_src_output_y++; } - inline void increment_field() - { - _output_mutex->lock(); - _run_write_pointer = (_run_write_pointer + 1)%NumberOfFields; - _run_builders[_run_write_pointer]->start = (size_t)_output_buffer_data_pointer; - _run_builders[_run_write_pointer]->reset(); - _output_mutex->unlock(); - } - - inline int get_current_field() - { - return _run_write_pointer; - } - inline uint8_t *allocate_write_area(size_t required_length) { _output_mutex->lock(); @@ -217,12 +189,13 @@ class OpenGLOutputBuilder { GLsync _input_texture_sync; GLsizeiptr _input_texture_array_size; - uint8_t *_output_buffer_data; - GLsizei _output_buffer_data_pointer; - uint8_t *_source_buffer_data; GLsizei _source_buffer_data_pointer; GLsizei _drawn_source_buffer_data_pointer; + + uint8_t *_output_buffer_data; + GLsizei _output_buffer_data_pointer; + GLsizei _drawn_output_buffer_data_pointer; }; } diff --git a/Outputs/CRT/Internals/CRTRunBuilder.cpp b/Outputs/CRT/Internals/CRTRunBuilder.cpp deleted file mode 100644 index 5191a1c84..000000000 --- a/Outputs/CRT/Internals/CRTRunBuilder.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// -// CRTFrameBuilder.cpp -// Clock Signal -// -// Created by Thomas Harte on 04/02/2016. -// Copyright © 2016 Thomas Harte. All rights reserved. -// - -#include "CRT.hpp" -#include "CRTOpenGL.hpp" - -using namespace Outputs::CRT; diff --git a/Outputs/CRT/Internals/CRTRunBuilder.hpp b/Outputs/CRT/Internals/CRTRunBuilder.hpp deleted file mode 100644 index 137f4ed85..000000000 --- a/Outputs/CRT/Internals/CRTRunBuilder.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// -// CRTRunBuilder.h -// Clock Signal -// -// Created by Thomas Harte on 08/03/2016. -// Copyright © 2016 Thomas Harte. All rights reserved. -// - -#ifndef CRTRunBuilder_h -#define CRTRunBuilder_h - -#import - -namespace Outputs { -namespace CRT { - -struct CRTRunBuilder { - CRTRunBuilder() : start(0) { reset(); } - - // Resets the run builder. - inline void reset() - { - duration = 0; - amount_of_uploaded_data = 0; - amount_of_data = 0; - } - - // Container for total length in cycles of all contained runs. - uint32_t duration; - size_t start; - - // Storage for the length of run data uploaded so far; reset to zero by reset but otherwise - // entrusted to the CRT to update. - size_t amount_of_uploaded_data; - size_t amount_of_data; -}; - -} -} - -#endif /* CRTRunBuilder_h */