diff --git a/OSBindings/Mac/Clock Signal/Documents/Atari2600Document.swift b/OSBindings/Mac/Clock Signal/Documents/Atari2600Document.swift index 6c586c360..071a44db1 100644 --- a/OSBindings/Mac/Clock Signal/Documents/Atari2600Document.swift +++ b/OSBindings/Mac/Clock Signal/Documents/Atari2600Document.swift @@ -77,6 +77,11 @@ class Atari2600Document: MachineDocument { atari2600.setState(true, forDigitalInput: input) } + if event.keyCode == 49 { + self.runForNumberOfCycles(Int32(self.intendedCyclesPerSecond / 60)) + self.openGLView.drawViewOnlyIfDirty(true) + } + if event.keyCode == 36 { atari2600.setResetLineEnabled(true) } diff --git a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift index 19c905c68..41eb71ebf 100644 --- a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift +++ b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift @@ -36,12 +36,16 @@ class MachineDocument: NSDocument, CSOpenGLViewDelegate, CSOpenGLViewResponderDe private var cycleCountError: Int64 = 0 private var lastTime: CVTimeStamp? private var skippedFrames = 0 -// private var frameSkip = 0 + private var frameSkip = 0 final func openGLView(view: CSOpenGLView, didUpdateToTime time: CVTimeStamp, didSkipPreviousUpdate : Bool, frequency : Double) { // frameSkip = frameSkip + 1 // let modFrameSkip = frameSkip % 10 -// if modFrameSkip == 0 { +// if modFrameSkip == 0 && frameSkip < 500 { // runForNumberOfCycles(Int32(intendedCyclesPerSecond / 60)) +// view.drawViewOnlyIfDirty(true) +// view.performWithGLContext({ () -> Void in +// self.openGLView(view, drawViewOnlyIfDirty: true) +// }) // } if let lastTime = lastTime { // perform (time passed in seconds) * (intended cycles per second), converting and diff --git a/OSBindings/Mac/Clock Signal/Views/CSOpenGLView.h b/OSBindings/Mac/Clock Signal/Views/CSOpenGLView.h index f5c821fe8..dad53987d 100644 --- a/OSBindings/Mac/Clock Signal/Views/CSOpenGLView.h +++ b/OSBindings/Mac/Clock Signal/Views/CSOpenGLView.h @@ -75,4 +75,6 @@ - (void)performWithGLContext:(nonnull dispatch_block_t)action; +- (void)drawViewOnlyIfDirty:(BOOL)onlyIfDirty; + @end diff --git a/OSBindings/Mac/Clock Signal/Views/CSOpenGLView.m b/OSBindings/Mac/Clock Signal/Views/CSOpenGLView.m index 8e41cc50e..e6bf76dfd 100644 --- a/OSBindings/Mac/Clock Signal/Views/CSOpenGLView.m +++ b/OSBindings/Mac/Clock Signal/Views/CSOpenGLView.m @@ -60,6 +60,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt BOOL didSkip = _hasSkipped; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ [self.delegate openGLView:self didUpdateToTime:time didSkipPreviousUpdate:didSkip frequency:frequency]; + [self drawViewOnlyIfDirty:YES]; OSAtomicTestAndClear(processingMask, &_updateIsOngoing); }); _hasSkipped = NO; @@ -68,13 +69,13 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt // Draw the display only if a previous draw is not still ongoing. -drawViewOnlyIfDirty: is guaranteed // to be safe to call concurrently with -openGLView:updateToTime: so there's no need to worry about // the above interrupting the below or vice versa. - if(!OSAtomicTestAndSet(drawingMask, &_updateIsOngoing)) - { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ - [self drawViewOnlyIfDirty:YES]; - OSAtomicTestAndClear(drawingMask, &_updateIsOngoing); - }); - } +// if(!OSAtomicTestAndSet(drawingMask, &_updateIsOngoing)) +// { +// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ +// [self drawViewOnlyIfDirty:YES]; +// OSAtomicTestAndClear(drawingMask, &_updateIsOngoing); +// }); +// } } - (void)invalidate @@ -134,7 +135,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt - (void)drawRect:(NSRect)dirtyRect { - [self drawViewOnlyIfDirty:NO]; +// [self drawViewOnlyIfDirty:NO]; } - (void)drawViewOnlyIfDirty:(BOOL)onlyIfDirty diff --git a/Outputs/CRT/CRT.cpp b/Outputs/CRT/CRT.cpp index 0f1680df1..2c5969047 100644 --- a/Outputs/CRT/CRT.cpp +++ b/Outputs/CRT/CRT.cpp @@ -141,7 +141,6 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi // [0/1] 3 if(next_run) { -// printf("%d -> %d", tex_y, _openGL_output_builder->get_composite_output_y()); source_input_position_x(0) = tex_x; source_input_position_y(0) = source_input_position_y(1) = tex_y; source_output_position_x(0) = (uint16_t)_horizontal_flywheel->get_current_output_position(); @@ -194,7 +193,6 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi uint8_t *next_run = _openGL_output_builder->get_next_output_run(); if(next_run) { -// printf("{%d -> %0.2f}", _openGL_output_builder->get_composite_output_y(), (float)_vertical_flywheel->get_current_output_position() / (float)_vertical_flywheel->get_scan_period()); 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_tex_x(0) = output_tex_x(1) = output_tex_x(2) = (uint16_t)_horizontal_flywheel->get_current_output_position(); @@ -215,7 +213,6 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi // if this is vertical retrace then adcance a field if(next_run_length == time_until_vertical_sync_event && next_vertical_sync_event == Flywheel::SyncEvent::EndRetrace) { -// printf("\n!%d!\n", _openGL_output_builder->get_composite_output_y()); // TODO: eliminate the below; it's to aid with debug, aligning the top of the // input buffer with the top of the incoming frame. _openGL_output_builder->release_source_buffer_write_pointer(); @@ -326,7 +323,6 @@ void CRT::output_data(unsigned int number_of_cycles, unsigned int source_divider { if(_openGL_output_builder->reduce_previous_allocation_to(number_of_cycles / source_divider)) { -// printf("[%d with %d]", (_vertical_flywheel->get_current_time() * 262) / _vertical_flywheel->get_scan_period(), _openGL_output_builder->get_last_write_y_posititon()); Scan scan { .type = Scan::Type::Data, .number_of_cycles = number_of_cycles, diff --git a/Outputs/CRT/Internals/CRTConstants.hpp b/Outputs/CRT/Internals/CRTConstants.hpp index f2764d9b0..da9484fd9 100644 --- a/Outputs/CRT/Internals/CRTConstants.hpp +++ b/Outputs/CRT/Internals/CRTConstants.hpp @@ -33,11 +33,11 @@ const GLsizei SourceVertexSize = 16; // These constants hold the size of the rolling buffer to which the CPU writes const GLsizei InputBufferBuilderWidth = 2048; -const GLsizei InputBufferBuilderHeight = 1024; // 1024 +const GLsizei InputBufferBuilderHeight = 512; // This is the size of the intermediate buffers used during composite to RGB conversion const GLsizei IntermediateBufferWidth = 2048; -const GLsizei IntermediateBufferHeight = 2048; +const GLsizei IntermediateBufferHeight = 512; // Some internal buffer sizes const GLsizeiptr OutputVertexBufferDataSize = 44928; // a multiple of 6 * OutputVertexSize diff --git a/Outputs/CRT/Internals/CRTInputBufferBuilder.cpp b/Outputs/CRT/Internals/CRTInputBufferBuilder.cpp index 605423033..920375437 100644 --- a/Outputs/CRT/Internals/CRTInputBufferBuilder.cpp +++ b/Outputs/CRT/Internals/CRTInputBufferBuilder.cpp @@ -42,7 +42,7 @@ void CRTInputBufferBuilder::allocate_write_area(size_t required_length) _write_x_position = _next_write_x_position + 1; _write_y_position = _next_write_y_position; -// printf("#%d,%d#", _write_x_position, _write_y_position); +// printf("#%d,%d#\n", _write_x_position, _write_y_position); _write_target_pointer = (_write_y_position * InputBufferBuilderWidth) + _write_x_position; _next_write_x_position += required_length + 2; } @@ -53,6 +53,7 @@ void CRTInputBufferBuilder::release_write_pointer() if(_should_reset) { _next_write_x_position = _next_write_y_position = 0; +// printf("#Reset!#\n"); } } diff --git a/Outputs/CRT/Internals/CRTOpenGL.cpp b/Outputs/CRT/Internals/CRTOpenGL.cpp index 90b9ecaad..ed6a20478 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.cpp +++ b/Outputs/CRT/Internals/CRTOpenGL.cpp @@ -185,15 +185,6 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out int number_of_clearing_zones = getCircularRanges(_cleared_composite_output_y, _composite_src_output_y, IntermediateBufferHeight, 1, clearing_zones); int number_of_source_drawing_zones = getCircularRanges(_drawn_source_buffer_data_pointer, _source_buffer_data_pointer, SourceVertexBufferDataSize, 2*SourceVertexSize, source_drawing_zones); int number_of_output_drawing_zones = getCircularRanges(_drawn_output_buffer_data_pointer, _output_buffer_data_pointer, OutputVertexBufferDataSize, 6*OutputVertexSize, output_drawing_zones); - -// for(int c = 0; c < number_of_output_drawing_zones; c++) -// { -// printf("\n(%d->%d)\n", output_drawing_zones[c*2], output_drawing_zones[c*2] + output_drawing_zones[c*2 + 1]); -// } - -// if(number_of_output_drawing_zones) -// printf("\n\n"); - uint16_t completed_texture_y = _buffer_builder->get_and_finalise_current_line(); _composite_src_output_y %= IntermediateBufferHeight; @@ -315,8 +306,6 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out if(number_of_output_drawing_zones) { -// glClearColor(0.5, 0.5, 0.5, 1.0); -// glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_BLEND); // Ensure we're back on the output framebuffer, drawing from the output array buffer @@ -336,7 +325,6 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out { glDrawArrays(GL_TRIANGLE_STRIP, output_drawing_zones[c*2] / OutputVertexSize, output_drawing_zones[c*2 + 1] / OutputVertexSize); } -// glDrawArrays(GL_TRIANGLE_STRIP, 0, OutputVertexBufferDataSize / OutputVertexSize); } // copy framebuffer to the intended place @@ -346,7 +334,6 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out glClear(GL_COLOR_BUFFER_BIT); framebuffer->draw((float)output_width / (float)output_height); -// filteredYTexture->draw((float)output_width / (float)output_height); // drawing commands having been issued, reclaim the array buffer pointer glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer); diff --git a/Outputs/CRT/Internals/CRTOpenGL.hpp b/Outputs/CRT/Internals/CRTOpenGL.hpp index 13c3daa20..dcea80003 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.hpp +++ b/Outputs/CRT/Internals/CRTOpenGL.hpp @@ -57,7 +57,7 @@ class OpenGLOutputBuilder { // the run and input data buffers std::unique_ptr _buffer_builder; - std::shared_ptr _output_mutex; + std::unique_ptr _output_mutex; // transient buffers indicating composite data not yet decoded uint16_t _composite_src_output_y, _cleared_composite_output_y; diff --git a/Outputs/CRT/Internals/Shaders/IntermediateShader.cpp b/Outputs/CRT/Internals/Shaders/IntermediateShader.cpp index 003b3e19f..4bdbb0b9b 100644 --- a/Outputs/CRT/Internals/Shaders/IntermediateShader.cpp +++ b/Outputs/CRT/Internals/Shaders/IntermediateShader.cpp @@ -78,7 +78,7 @@ std::unique_ptr IntermediateShader::make_shader(const char * "phaseAndAmplitudeVarying.x = (phaseCyclesPerTick * (extendedOutputPosition.x - phaseTime) + phaseAndAmplitude.x) * 2.0 * 3.141592654;" "phaseAndAmplitudeVarying.y = 0.33;" // TODO: reinstate connection with phaseAndAmplitude - "vec2 eyePosition = 2.0*(extendedOutputPosition / outputTextureSize) - vec2(1.0) + vec2(0.5)/textureSize;" + "vec2 eyePosition = 2.0*(extendedOutputPosition / outputTextureSize) - vec2(1.0) + vec2(0.5)/outputTextureSize;" "gl_Position = vec4(eyePosition, 0.0, 1.0);" "}", sampler_type, input_variable);