From dd469fe83a645164b9135b82dd7539eff71d5e3d Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 8 May 2016 18:50:30 -0400 Subject: [PATCH] Switched back to normal frame drawing logic and cleaned up the circular range stuff a little, to make it clear that no errors lie there. --- .../Documents/MachineDocument.swift | 8 +-- .../Mac/Clock Signal/Views/CSOpenGLView.m | 2 +- Outputs/CRT/Internals/CRTConstants.hpp | 4 +- Outputs/CRT/Internals/CRTOpenGL.cpp | 56 +++++++++++-------- 4 files changed, 38 insertions(+), 32 deletions(-) diff --git a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift index 41eb71ebf..db28c4456 100644 --- a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift +++ b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift @@ -36,16 +36,12 @@ 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 && frameSkip < 500 { +// if (frameSkip % 1) == 0 && frameSkip < 50000 { // 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.m b/OSBindings/Mac/Clock Signal/Views/CSOpenGLView.m index 8e41cc50e..90444e057 100644 --- a/OSBindings/Mac/Clock Signal/Views/CSOpenGLView.m +++ b/OSBindings/Mac/Clock Signal/Views/CSOpenGLView.m @@ -134,7 +134,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/Internals/CRTConstants.hpp b/Outputs/CRT/Internals/CRTConstants.hpp index 9180d3c32..1b83ce9b2 100644 --- a/Outputs/CRT/Internals/CRTConstants.hpp +++ b/Outputs/CRT/Internals/CRTConstants.hpp @@ -40,8 +40,8 @@ const GLsizei IntermediateBufferWidth = 2048; const GLsizei IntermediateBufferHeight = 512; // Some internal buffer sizes -const GLsizeiptr OutputVertexBufferDataSize = 6 * 8 * 312 * 10; // a multiple of 6 * OutputVertexSize -const GLsizeiptr SourceVertexBufferDataSize = 2 * 16 * 312 * 10; // a multiple of 2 * SourceVertexSize +const GLsizeiptr OutputVertexBufferDataSize = 6 * 8 * 312; // a multiple of 6 * OutputVertexSize +const GLsizeiptr SourceVertexBufferDataSize = 2 * 16 * 312; // a multiple of 2 * SourceVertexSize } } diff --git a/Outputs/CRT/Internals/CRTOpenGL.cpp b/Outputs/CRT/Internals/CRTOpenGL.cpp index cfac44ba2..5e2652ac6 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.cpp +++ b/Outputs/CRT/Internals/CRTOpenGL.cpp @@ -37,7 +37,11 @@ static const GLenum formatForDepth(size_t depth) } } -static int getCircularRanges(GLsizei start, GLsizei end, GLsizei buffer_length, GLsizei granularity, GLsizei *ranges) +struct Range { + GLsizei location, length; +}; + +static int getCircularRanges(GLsizei start, GLsizei end, GLsizei buffer_length, GLsizei granularity, Range *ranges) { start -= start%granularity; end -= end%granularity; @@ -46,28 +50,36 @@ static int getCircularRanges(GLsizei start, GLsizei end, GLsizei buffer_length, if(!length) return 0; if(length >= buffer_length) { - ranges[0] = 0; - ranges[1] = buffer_length; + ranges[0].location = 0; + ranges[0].length = buffer_length; return 1; } else { - ranges[0] = start % buffer_length; - if(ranges[0]+length <= buffer_length) + ranges[0].location = start % buffer_length; + if(ranges[0].location + length <= buffer_length) { - ranges[1] = length; + ranges[0].length = length; return 1; } else { - ranges[1] = buffer_length - ranges[0]; - ranges[2] = 0; - ranges[3] = length - ranges[1]; + ranges[0].length = buffer_length - ranges[0].location; + ranges[1].location = 0; + ranges[1].length = length - ranges[0].length; return 2; } } } +static inline void drawArrayRanges(GLenum mode, GLsizei vertex_size, int number_of_ranges, Range *ranges) +{ + for(int c = 0; c < number_of_ranges; c++) + { + glDrawArrays(mode, ranges[c].location / vertex_size, ranges[c].length / vertex_size); + } +} + using namespace Outputs::CRT; namespace { @@ -180,8 +192,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], source_drawing_zones[4]; - GLsizei output_drawing_zones[4]; + Range clearing_zones[2], source_drawing_zones[2]; + Range output_drawing_zones[2]; 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); @@ -195,11 +207,13 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out _drawn_source_buffer_data_pointer = _source_buffer_data_pointer; _drawn_output_buffer_data_pointer = _output_buffer_data_pointer; + glFinish(); + // release the mapping, giving up on trying to draw if data has been lost glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer); for(int c = 0; c < number_of_output_drawing_zones; c++) { - glFlushMappedBufferRange(GL_ARRAY_BUFFER, output_drawing_zones[c*2], output_drawing_zones[c*2 + 1]); + glFlushMappedBufferRange(GL_ARRAY_BUFFER, output_drawing_zones[c].location, output_drawing_zones[c].length); } glUnmapBuffer(GL_ARRAY_BUFFER); @@ -207,7 +221,7 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out glBindBuffer(GL_ARRAY_BUFFER, source_array_buffer); for(int c = 0; c < number_of_source_drawing_zones; c++) { - glFlushMappedBufferRange(GL_ARRAY_BUFFER, source_drawing_zones[c*2], source_drawing_zones[c*2 + 1]); + glFlushMappedBufferRange(GL_ARRAY_BUFFER, source_drawing_zones[c].location, source_drawing_zones[c].length); } glUnmapBuffer(GL_ARRAY_BUFFER); @@ -284,26 +298,25 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out glClearColor(active_pipeline->clear_colour[0], active_pipeline->clear_colour[1], active_pipeline->clear_colour[2], 1.0); for(int c = 0; c < number_of_clearing_zones; c++) { - glScissor(0, clearing_zones[c*2], IntermediateBufferWidth, clearing_zones[c*2 + 1]); + glScissor(0, clearing_zones[c].location, IntermediateBufferWidth, clearing_zones[c].length); glClear(GL_COLOR_BUFFER_BIT); } glDisable(GL_SCISSOR_TEST); } // draw as desired - for(int c = 0; c < number_of_source_drawing_zones; c++) - { - glDrawArrays(GL_LINES, source_drawing_zones[c*2] / SourceVertexSize, source_drawing_zones[c*2 + 1] / SourceVertexSize); - } + drawArrayRanges(GL_LINES, SourceVertexSize, number_of_source_drawing_zones, source_drawing_zones); active_pipeline++; } + + // TODO: determine why the finish below is required +// glFinish(); } // transfer to framebuffer framebuffer->bind_framebuffer(); - if(number_of_output_drawing_zones) { glEnable(GL_BLEND); @@ -321,10 +334,7 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out output_shader_program->bind(); // draw - for(int c = 0; c < number_of_output_drawing_zones; c++) - { - glDrawArrays(GL_TRIANGLE_STRIP, output_drawing_zones[c*2] / OutputVertexSize, output_drawing_zones[c*2 + 1] / OutputVertexSize); - } + drawArrayRanges(GL_TRIANGLE_STRIP, OutputVertexSize, number_of_output_drawing_zones, output_drawing_zones); } // copy framebuffer to the intended place