1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-06 01:28:57 +00:00

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.

This commit is contained in:
Thomas Harte 2016-05-08 18:50:30 -04:00
parent 8ca3dfc9c5
commit dd469fe83a
4 changed files with 38 additions and 32 deletions

View File

@ -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

View File

@ -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

View File

@ -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
}
}

View File

@ -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