diff --git a/OSBindings/Mac/Clock Signal/Documents/ElectronDocument.swift b/OSBindings/Mac/Clock Signal/Documents/ElectronDocument.swift index 43cb38475..4568d6982 100644 --- a/OSBindings/Mac/Clock Signal/Documents/ElectronDocument.swift +++ b/OSBindings/Mac/Clock Signal/Documents/ElectronDocument.swift @@ -61,8 +61,8 @@ class ElectronDocument: MachineDocument { electron.runForNumberOfCycles(numberOfCycles) } - override func openGLViewDrawView(view: CSCathodeRayView) { - electron.drawViewForPixelSize(view.backingSize) + override func openGLView(view: CSCathodeRayView, drawViewOnlyIfDirty onlyIfDirty: Bool) { + electron.drawViewForPixelSize(view.backingSize, onlyIfDirty: onlyIfDirty) } // MARK: CSOpenGLViewResponderDelegate diff --git a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift index 126eb2a9d..e1f14f833 100644 --- a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift +++ b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift @@ -46,7 +46,7 @@ class MachineDocument: NSDocument, CSCathodeRayViewDelegate, CSCathodeRayViewRes lastCycleCount = cycleCount } - func openGLViewDrawView(view: CSCathodeRayView) {} + func openGLView(view: CSCathodeRayView, drawViewOnlyIfDirty onlyIfDirty: Bool) {} func runForNumberOfCycles(numberOfCycles: Int32) {} // MARK: CSOpenGLViewResponderDelegate diff --git a/OSBindings/Mac/Clock Signal/Views/CSCathodeRayView.h b/OSBindings/Mac/Clock Signal/Views/CSCathodeRayView.h index abecc655b..a463953d5 100644 --- a/OSBindings/Mac/Clock Signal/Views/CSCathodeRayView.h +++ b/OSBindings/Mac/Clock Signal/Views/CSCathodeRayView.h @@ -13,7 +13,7 @@ @protocol CSCathodeRayViewDelegate - (void)openGLView:(nonnull CSCathodeRayView *)view didUpdateToTime:(CVTimeStamp)time; -- (void)openGLViewDrawView:(nonnull CSCathodeRayView *)view; +- (void)openGLView:(nonnull CSCathodeRayView *)view drawViewOnlyIfDirty:(BOOL)onlyIfDirty; @end @protocol CSCathodeRayViewResponderDelegate diff --git a/OSBindings/Mac/Clock Signal/Views/CSCathodeRayView.m b/OSBindings/Mac/Clock Signal/Views/CSCathodeRayView.m index 069f10dd0..1dc801978 100644 --- a/OSBindings/Mac/Clock Signal/Views/CSCathodeRayView.m +++ b/OSBindings/Mac/Clock Signal/Views/CSCathodeRayView.m @@ -76,6 +76,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt { CSCathodeRayView *view = (__bridge CSCathodeRayView *)displayLinkContext; [view.delegate openGLView:view didUpdateToTime:*now]; + [view drawViewOnlyIfDirty:YES]; return kCVReturnSuccess; } @@ -291,15 +292,15 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt - (void)drawRect:(NSRect)dirtyRect { - [self drawView]; + [self drawViewOnlyIfDirty:NO]; } -- (void)drawView +- (void)drawViewOnlyIfDirty:(BOOL)onlyIfDirty { [self.openGLContext makeCurrentContext]; CGLLockContext([[self openGLContext] CGLContextObj]); - [self.delegate openGLViewDrawView:self]; + [self.delegate openGLView:self drawViewOnlyIfDirty:onlyIfDirty]; CGLFlushDrawable([[self openGLContext] CGLContextObj]); CGLUnlockContext([[self openGLContext] CGLContextObj]); diff --git a/OSBindings/Mac/Clock Signal/Wrappers/CSElectron.h b/OSBindings/Mac/Clock Signal/Wrappers/CSElectron.h index a58cf49cc..7902fee52 100644 --- a/OSBindings/Mac/Clock Signal/Wrappers/CSElectron.h +++ b/OSBindings/Mac/Clock Signal/Wrappers/CSElectron.h @@ -18,6 +18,6 @@ - (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed; -- (void)drawViewForPixelSize:(CGSize)pixelSize; +- (void)drawViewForPixelSize:(CGSize)pixelSize onlyIfDirty:(BOOL)onlyIfDirty; @end diff --git a/OSBindings/Mac/Clock Signal/Wrappers/CSElectron.mm b/OSBindings/Mac/Clock Signal/Wrappers/CSElectron.mm index 11957973b..a48cde887 100644 --- a/OSBindings/Mac/Clock Signal/Wrappers/CSElectron.mm +++ b/OSBindings/Mac/Clock Signal/Wrappers/CSElectron.mm @@ -32,8 +32,8 @@ _electron.set_rom((Electron::ROMSlot)slot, rom.length, (const uint8_t *)rom.bytes); } -- (void)drawViewForPixelSize:(CGSize)pixelSize { - _electron.get_crt()->draw_frame((int)pixelSize.width, (int)pixelSize.height, false); +- (void)drawViewForPixelSize:(CGSize)pixelSize onlyIfDirty:(BOOL)onlyIfDirty { + _electron.get_crt()->draw_frame((int)pixelSize.width, (int)pixelSize.height, onlyIfDirty ? true : false); } - (BOOL)openUEFAtURL:(NSURL *)URL { diff --git a/Outputs/CRT/CRTOpenGL.cpp b/Outputs/CRT/CRTOpenGL.cpp index 5c815a904..83ed3a0b9 100644 --- a/Outputs/CRT/CRTOpenGL.cpp +++ b/Outputs/CRT/CRTOpenGL.cpp @@ -37,7 +37,7 @@ static GLenum formatForDepth(unsigned int depth) { switch(depth) { - default: return -1; + default: return GL_FALSE; case 1: return GL_RED; case 2: return GL_RG; case 3: return GL_RGB; @@ -64,50 +64,44 @@ void CRT::draw_frame(int output_width, int output_height, bool only_if_dirty) { _current_frame_mutex->lock(); - if(!_current_frame) + if(!_current_frame || !only_if_dirty) { glClear(GL_COLOR_BUFFER_BIT); } - else + + if(_current_frame && _current_frame != _last_drawn_frame) { - if(_current_frame != _last_drawn_frame) + if(!_openGL_state) { - if(!_openGL_state) - { - _openGL_state = new OpenGLState; - - glGenTextures(1, &_openGL_state->textureName); - glBindTexture(GL_TEXTURE_2D, _openGL_state->textureName); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - glGenVertexArrays(1, &_openGL_state->vertexArray); - glBindVertexArray(_openGL_state->vertexArray); - glGenBuffers(1, &_openGL_state->arrayBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _openGL_state->arrayBuffer); - } - - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(_current_frame->number_of_vertices * _current_frame->size_per_vertex), _current_frame->vertices, GL_DYNAMIC_DRAW); + _openGL_state = new OpenGLState; + glGenTextures(1, &_openGL_state->textureName); glBindTexture(GL_TEXTURE_2D, _openGL_state->textureName); - if(_openGL_state->textureSize.width != _current_frame->size.width || _openGL_state->textureSize.height != _current_frame->size.height) - { - GLenum format = formatForDepth(_current_frame->buffers[0].depth); - glTexImage2D(GL_TEXTURE_2D, 0, (GLint)format, _current_frame->size.width, _current_frame->size.height, 0, format, GL_UNSIGNED_BYTE, _current_frame->buffers[0].data); - _openGL_state->textureSize = _current_frame->size; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - if(_openGL_state->textureSizeUniform >= 0) glUniform2f(_openGL_state->textureSizeUniform, _current_frame->size.width, _current_frame->size.height); - } - else - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _current_frame->dirty_size.width, _current_frame->dirty_size.height, formatForDepth(_current_frame->buffers[0].depth), GL_UNSIGNED_BYTE, _current_frame->buffers[0].data); + glGenVertexArrays(1, &_openGL_state->vertexArray); + glBindVertexArray(_openGL_state->vertexArray); + glGenBuffers(1, &_openGL_state->arrayBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _openGL_state->arrayBuffer); } - } - if(_current_frame != _last_drawn_frame || only_if_dirty) - { - glClear(GL_COLOR_BUFFER_BIT); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(_current_frame->number_of_vertices * _current_frame->size_per_vertex), _current_frame->vertices, GL_DYNAMIC_DRAW); + + glBindTexture(GL_TEXTURE_2D, _openGL_state->textureName); + if(_openGL_state->textureSize.width != _current_frame->size.width || _openGL_state->textureSize.height != _current_frame->size.height) + { + GLenum format = formatForDepth(_current_frame->buffers[0].depth); + glTexImage2D(GL_TEXTURE_2D, 0, (GLint)format, _current_frame->size.width, _current_frame->size.height, 0, format, GL_UNSIGNED_BYTE, _current_frame->buffers[0].data); + _openGL_state->textureSize = _current_frame->size; + + if(_openGL_state->textureSizeUniform >= 0) glUniform2f(_openGL_state->textureSizeUniform, _current_frame->size.width, _current_frame->size.height); + } + else + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _current_frame->dirty_size.width, _current_frame->dirty_size.height, formatForDepth(_current_frame->buffers[0].depth), GL_UNSIGNED_BYTE, _current_frame->buffers[0].data); + glDrawArrays(GL_TRIANGLES, 0, (GLsizei)_current_frame->number_of_vertices); }