mirror of
https://github.com/TomHarte/CLK.git
synced 2024-07-30 23:29:08 +00:00
At last a genuine bug fixed: was nudging the wrong amount in intermediate shaders.
This commit is contained in:
parent
1142c86811
commit
9485ef2c8c
@ -77,6 +77,11 @@ class Atari2600Document: MachineDocument {
|
|||||||
atari2600.setState(true, forDigitalInput: input)
|
atari2600.setState(true, forDigitalInput: input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if event.keyCode == 49 {
|
||||||
|
self.runForNumberOfCycles(Int32(self.intendedCyclesPerSecond / 60))
|
||||||
|
self.openGLView.drawViewOnlyIfDirty(true)
|
||||||
|
}
|
||||||
|
|
||||||
if event.keyCode == 36 {
|
if event.keyCode == 36 {
|
||||||
atari2600.setResetLineEnabled(true)
|
atari2600.setResetLineEnabled(true)
|
||||||
}
|
}
|
||||||
|
@ -36,12 +36,16 @@ class MachineDocument: NSDocument, CSOpenGLViewDelegate, CSOpenGLViewResponderDe
|
|||||||
private var cycleCountError: Int64 = 0
|
private var cycleCountError: Int64 = 0
|
||||||
private var lastTime: CVTimeStamp?
|
private var lastTime: CVTimeStamp?
|
||||||
private var skippedFrames = 0
|
private var skippedFrames = 0
|
||||||
// private var frameSkip = 0
|
private var frameSkip = 0
|
||||||
final func openGLView(view: CSOpenGLView, didUpdateToTime time: CVTimeStamp, didSkipPreviousUpdate : Bool, frequency : Double) {
|
final func openGLView(view: CSOpenGLView, didUpdateToTime time: CVTimeStamp, didSkipPreviousUpdate : Bool, frequency : Double) {
|
||||||
// frameSkip = frameSkip + 1
|
// frameSkip = frameSkip + 1
|
||||||
// let modFrameSkip = frameSkip % 10
|
// let modFrameSkip = frameSkip % 10
|
||||||
// if modFrameSkip == 0 {
|
// if modFrameSkip == 0 && frameSkip < 500 {
|
||||||
// runForNumberOfCycles(Int32(intendedCyclesPerSecond / 60))
|
// runForNumberOfCycles(Int32(intendedCyclesPerSecond / 60))
|
||||||
|
// view.drawViewOnlyIfDirty(true)
|
||||||
|
// view.performWithGLContext({ () -> Void in
|
||||||
|
// self.openGLView(view, drawViewOnlyIfDirty: true)
|
||||||
|
// })
|
||||||
// }
|
// }
|
||||||
if let lastTime = lastTime {
|
if let lastTime = lastTime {
|
||||||
// perform (time passed in seconds) * (intended cycles per second), converting and
|
// perform (time passed in seconds) * (intended cycles per second), converting and
|
||||||
|
@ -75,4 +75,6 @@
|
|||||||
|
|
||||||
- (void)performWithGLContext:(nonnull dispatch_block_t)action;
|
- (void)performWithGLContext:(nonnull dispatch_block_t)action;
|
||||||
|
|
||||||
|
- (void)drawViewOnlyIfDirty:(BOOL)onlyIfDirty;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -60,6 +60,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
|
|||||||
BOOL didSkip = _hasSkipped;
|
BOOL didSkip = _hasSkipped;
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
||||||
[self.delegate openGLView:self didUpdateToTime:time didSkipPreviousUpdate:didSkip frequency:frequency];
|
[self.delegate openGLView:self didUpdateToTime:time didSkipPreviousUpdate:didSkip frequency:frequency];
|
||||||
|
[self drawViewOnlyIfDirty:YES];
|
||||||
OSAtomicTestAndClear(processingMask, &_updateIsOngoing);
|
OSAtomicTestAndClear(processingMask, &_updateIsOngoing);
|
||||||
});
|
});
|
||||||
_hasSkipped = NO;
|
_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
|
// 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
|
// 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.
|
// the above interrupting the below or vice versa.
|
||||||
if(!OSAtomicTestAndSet(drawingMask, &_updateIsOngoing))
|
// if(!OSAtomicTestAndSet(drawingMask, &_updateIsOngoing))
|
||||||
{
|
// {
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
||||||
[self drawViewOnlyIfDirty:YES];
|
// [self drawViewOnlyIfDirty:YES];
|
||||||
OSAtomicTestAndClear(drawingMask, &_updateIsOngoing);
|
// OSAtomicTestAndClear(drawingMask, &_updateIsOngoing);
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)invalidate
|
- (void)invalidate
|
||||||
@ -134,7 +135,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
|
|||||||
|
|
||||||
- (void)drawRect:(NSRect)dirtyRect
|
- (void)drawRect:(NSRect)dirtyRect
|
||||||
{
|
{
|
||||||
[self drawViewOnlyIfDirty:NO];
|
// [self drawViewOnlyIfDirty:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)drawViewOnlyIfDirty:(BOOL)onlyIfDirty
|
- (void)drawViewOnlyIfDirty:(BOOL)onlyIfDirty
|
||||||
|
@ -141,7 +141,6 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
|
|||||||
// [0/1] 3
|
// [0/1] 3
|
||||||
if(next_run)
|
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_x(0) = tex_x;
|
||||||
source_input_position_y(0) = source_input_position_y(1) = tex_y;
|
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();
|
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();
|
uint8_t *next_run = _openGL_output_builder->get_next_output_run();
|
||||||
if(next_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_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_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_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 this is vertical retrace then adcance a field
|
||||||
if(next_run_length == time_until_vertical_sync_event && next_vertical_sync_event == Flywheel::SyncEvent::EndRetrace)
|
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
|
// TODO: eliminate the below; it's to aid with debug, aligning the top of the
|
||||||
// input buffer with the top of the incoming frame.
|
// input buffer with the top of the incoming frame.
|
||||||
_openGL_output_builder->release_source_buffer_write_pointer();
|
_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))
|
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 {
|
Scan scan {
|
||||||
.type = Scan::Type::Data,
|
.type = Scan::Type::Data,
|
||||||
.number_of_cycles = number_of_cycles,
|
.number_of_cycles = number_of_cycles,
|
||||||
|
@ -33,11 +33,11 @@ const GLsizei SourceVertexSize = 16;
|
|||||||
|
|
||||||
// These constants hold the size of the rolling buffer to which the CPU writes
|
// These constants hold the size of the rolling buffer to which the CPU writes
|
||||||
const GLsizei InputBufferBuilderWidth = 2048;
|
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
|
// This is the size of the intermediate buffers used during composite to RGB conversion
|
||||||
const GLsizei IntermediateBufferWidth = 2048;
|
const GLsizei IntermediateBufferWidth = 2048;
|
||||||
const GLsizei IntermediateBufferHeight = 2048;
|
const GLsizei IntermediateBufferHeight = 512;
|
||||||
|
|
||||||
// Some internal buffer sizes
|
// Some internal buffer sizes
|
||||||
const GLsizeiptr OutputVertexBufferDataSize = 44928; // a multiple of 6 * OutputVertexSize
|
const GLsizeiptr OutputVertexBufferDataSize = 44928; // a multiple of 6 * OutputVertexSize
|
||||||
|
@ -42,7 +42,7 @@ void CRTInputBufferBuilder::allocate_write_area(size_t required_length)
|
|||||||
|
|
||||||
_write_x_position = _next_write_x_position + 1;
|
_write_x_position = _next_write_x_position + 1;
|
||||||
_write_y_position = _next_write_y_position;
|
_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;
|
_write_target_pointer = (_write_y_position * InputBufferBuilderWidth) + _write_x_position;
|
||||||
_next_write_x_position += required_length + 2;
|
_next_write_x_position += required_length + 2;
|
||||||
}
|
}
|
||||||
@ -53,6 +53,7 @@ void CRTInputBufferBuilder::release_write_pointer()
|
|||||||
if(_should_reset)
|
if(_should_reset)
|
||||||
{
|
{
|
||||||
_next_write_x_position = _next_write_y_position = 0;
|
_next_write_x_position = _next_write_y_position = 0;
|
||||||
|
// printf("#Reset!#\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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_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_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);
|
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();
|
uint16_t completed_texture_y = _buffer_builder->get_and_finalise_current_line();
|
||||||
|
|
||||||
_composite_src_output_y %= IntermediateBufferHeight;
|
_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)
|
if(number_of_output_drawing_zones)
|
||||||
{
|
{
|
||||||
// glClearColor(0.5, 0.5, 0.5, 1.0);
|
|
||||||
// glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
|
|
||||||
// Ensure we're back on the output framebuffer, drawing from the output array buffer
|
// 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, 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
|
// 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);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
framebuffer->draw((float)output_width / (float)output_height);
|
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
|
// drawing commands having been issued, reclaim the array buffer pointer
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer);
|
glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer);
|
||||||
|
@ -57,7 +57,7 @@ class OpenGLOutputBuilder {
|
|||||||
|
|
||||||
// the run and input data buffers
|
// the run and input data buffers
|
||||||
std::unique_ptr<CRTInputBufferBuilder> _buffer_builder;
|
std::unique_ptr<CRTInputBufferBuilder> _buffer_builder;
|
||||||
std::shared_ptr<std::mutex> _output_mutex;
|
std::unique_ptr<std::mutex> _output_mutex;
|
||||||
|
|
||||||
// transient buffers indicating composite data not yet decoded
|
// transient buffers indicating composite data not yet decoded
|
||||||
uint16_t _composite_src_output_y, _cleared_composite_output_y;
|
uint16_t _composite_src_output_y, _cleared_composite_output_y;
|
||||||
|
@ -78,7 +78,7 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_shader(const char *
|
|||||||
"phaseAndAmplitudeVarying.x = (phaseCyclesPerTick * (extendedOutputPosition.x - phaseTime) + phaseAndAmplitude.x) * 2.0 * 3.141592654;"
|
"phaseAndAmplitudeVarying.x = (phaseCyclesPerTick * (extendedOutputPosition.x - phaseTime) + phaseAndAmplitude.x) * 2.0 * 3.141592654;"
|
||||||
"phaseAndAmplitudeVarying.y = 0.33;" // TODO: reinstate connection with phaseAndAmplitude
|
"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);"
|
"gl_Position = vec4(eyePosition, 0.0, 1.0);"
|
||||||
"}", sampler_type, input_variable);
|
"}", sampler_type, input_variable);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user