diff --git a/desmume/src/frontend/cocoa/ClientDisplayView.cpp b/desmume/src/frontend/cocoa/ClientDisplayView.cpp index 5885f2853..497de7762 100644 --- a/desmume/src/frontend/cocoa/ClientDisplayView.cpp +++ b/desmume/src/frontend/cocoa/ClientDisplayView.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 DeSmuME team + Copyright (C) 2017-2018 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1290,12 +1290,23 @@ void ClientDisplayViewInterface::SetAllowViewFlushes(bool allowFlushes) this->_allowViewFlushes = allowFlushes; } -void ClientDisplayViewInterface::FlushView() +void ClientDisplayViewInterface::FlushView(void *userData) { // Do nothing. This is implementation dependent. this->_viewNeedsFlush = false; } +void ClientDisplayViewInterface::FinalizeFlush(void *userData) +{ + // Do nothing. This is implementation dependent. +} + +void ClientDisplayViewInterface::FlushAndFinalizeImmediate() +{ + this->FlushView(NULL); + this->FinalizeFlush(NULL); +} + // Touch screen input handling void ClientDisplayViewInterface::GetNDSPoint(const ClientDisplayPresenterProperties &props, const double logicalClientWidth, const double logicalClientHeight, diff --git a/desmume/src/frontend/cocoa/ClientDisplayView.h b/desmume/src/frontend/cocoa/ClientDisplayView.h index 4a26fb1df..36f6fc68e 100644 --- a/desmume/src/frontend/cocoa/ClientDisplayView.h +++ b/desmume/src/frontend/cocoa/ClientDisplayView.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 DeSmuME team + Copyright (C) 2017-2018 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -355,7 +355,9 @@ public: bool GetAllowViewFlushes() const; virtual void SetAllowViewFlushes(bool allowFlushes); - virtual void FlushView(); + virtual void FlushView(void *userData); + virtual void FinalizeFlush(void *userData); + virtual void FlushAndFinalizeImmediate(); // Touch screen input handling void GetNDSPoint(const ClientDisplayPresenterProperties &props, diff --git a/desmume/src/frontend/cocoa/cocoa_GPU.h b/desmume/src/frontend/cocoa/cocoa_GPU.h index d420863fe..b70c7a88e 100644 --- a/desmume/src/frontend/cocoa/cocoa_GPU.h +++ b/desmume/src/frontend/cocoa/cocoa_GPU.h @@ -23,6 +23,7 @@ #include #include #include +#include #import "cocoa_util.h" #include "../../GPU.h" @@ -57,6 +58,7 @@ enum ClientDisplayBufferState }; class GPUEventHandlerOSX; +class ClientDisplay3DView; #ifdef ENABLE_SHARED_FETCH_OBJECT @@ -102,7 +104,10 @@ typedef std::map DisplayLinkFlushTimeLimitMap; - (void) incrementViewsUsingDirectToCPUFiltering; - (void) decrementViewsUsingDirectToCPUFiltering; - (void) pushVideoDataToAllDisplayViews; + - (void) flushAllDisplaysOnDisplayLink:(CVDisplayLinkRef)displayLink timeStamp:(const CVTimeStamp *)timeStamp; +- (void) flushMultipleViews:(const std::vector &)cdvFlushList; +- (void) finalizeFlushMultipleViews:(const std::vector &)cdvFlushList; - (void) displayLinkStartUsingID:(CGDirectDisplayID)displayID; - (void) displayLinkListUpdate; diff --git a/desmume/src/frontend/cocoa/cocoa_GPU.mm b/desmume/src/frontend/cocoa/cocoa_GPU.mm index a8a3373ec..3f29b0475 100644 --- a/desmume/src/frontend/cocoa/cocoa_GPU.mm +++ b/desmume/src/frontend/cocoa/cocoa_GPU.mm @@ -24,16 +24,16 @@ #include "../../rasterize.h" #ifdef MAC_OS_X_VERSION_10_7 -#include "../../OGLRender_3_2.h" + #include "../../OGLRender_3_2.h" #else -#include "../../OGLRender.h" + #include "../../OGLRender.h" #endif #include #import "userinterface/MacOGLDisplayView.h" #ifdef ENABLE_APPLE_METAL -#import "userinterface/MacMetalDisplayView.h" + #import "userinterface/MacMetalDisplayView.h" #endif #ifdef BOOL @@ -1219,6 +1219,8 @@ public: CGDirectDisplayID displayID = CVDisplayLinkGetCurrentCGDisplay(displayLink); bool didFlushOccur = false; + std::vector cdvFlushList; + if (currentRWLock != NULL) { pthread_rwlock_rdlock(currentRWLock); @@ -1234,13 +1236,21 @@ public: if (cdv->GetViewNeedsFlush()) { - cdv->FlushView(); - didFlushOccur = true; + cdvFlushList.push_back(cdv); } } } } + const size_t listSize = cdvFlushList.size(); + + if (listSize > 0) + { + [self flushMultipleViews:cdvFlushList]; + [self finalizeFlushMultipleViews:cdvFlushList]; + didFlushOccur = true; + } + if (currentRWLock != NULL) { pthread_rwlock_unlock(currentRWLock); @@ -1257,6 +1267,28 @@ public: } } +- (void) flushMultipleViews:(const std::vector &)cdvFlushList +{ + const size_t listSize = cdvFlushList.size(); + + for (size_t i = 0; i < listSize; i++) + { + ClientDisplay3DView *cdv = (ClientDisplay3DView *)cdvFlushList[i]; + cdv->FlushView(NULL); + } +} + +- (void) finalizeFlushMultipleViews:(const std::vector &)cdvFlushList +{ + const size_t listSize = cdvFlushList.size(); + + for (size_t i = 0; i < listSize; i++) + { + ClientDisplay3DView *cdv = (ClientDisplay3DView *)cdvFlushList[i]; + cdv->FinalizeFlush(NULL); + } +} + - (void) displayLinkStartUsingID:(CGDirectDisplayID)displayID { CVDisplayLinkRef displayLink = NULL; diff --git a/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm b/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm index c0d226927..9b6b2c9e0 100644 --- a/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm +++ b/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm @@ -2128,7 +2128,7 @@ static std::unordered_map _screenMap; // // If localOGLContext isn't nil, then we will not assign the local layer // directly to the view, since the OpenGL context will already be what // is assigned. - cdv->FlushView(); + cdv->FlushAndFinalizeImmediate(); return; } @@ -2144,7 +2144,7 @@ static std::unordered_map _screenMap; // if (isMetalLayer) { - cdv->FlushView(); + cdv->FlushAndFinalizeImmediate(); } else { @@ -2226,12 +2226,12 @@ static std::unordered_map _screenMap; // - (void)updateLayer { - [self clientDisplayView]->FlushView(); + [self clientDisplayView]->FlushAndFinalizeImmediate(); } - (void)drawRect:(NSRect)dirtyRect { - [self clientDisplayView]->FlushView(); + [self clientDisplayView]->FlushAndFinalizeImmediate(); } - (void)setFrame:(NSRect)rect diff --git a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.h b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.h index c082462bf..0bfb3faaf 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.h +++ b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.h @@ -168,6 +168,9 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties; - (void) fetchNativeDisplayByID:(const NDSDisplayID)displayID bufferIndex:(const u8)bufferIndex blitCommandEncoder:(id)bce; - (void) fetchCustomDisplayByID:(const NDSDisplayID)displayID bufferIndex:(const u8)bufferIndex blitCommandEncoder:(id)bce; +- (void) flushMultipleViews:(const std::vector &)cdvFlushList;; +- (void) finalizeFlushMultipleViews:(const std::vector &)cdvFlushList; + @end @interface MacMetalDisplayPresenterObject : NSObject @@ -261,13 +264,17 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties; MacDisplayLayeredView *_cdv; MacMetalDisplayPresenterObject *presenterObject; dispatch_semaphore_t _semDrawable; + id layerDrawable; } @property (readonly, nonatomic) MacMetalDisplayPresenterObject *presenterObject; +@property (retain) id layerDrawable; - (id) initWithDisplayPresenterObject:(MacMetalDisplayPresenterObject *)thePresenterObject; - (void) setupLayer; -- (void) renderToDrawable; +- (void) renderToDrawableUsingCommandBuffer:(id)cb; +- (void) presentDrawableWithCommandBuffer:(id)cb; +- (void) renderAndPresentDrawableImmediate; @end @@ -360,7 +367,9 @@ public: virtual void SetAllowViewFlushes(bool allowFlushes); // Client view interface - virtual void FlushView(); + virtual void FlushView(void *userData); + virtual void FinalizeFlush(void *userData); + virtual void FlushAndFinalizeImmediate(); }; #pragma mark - diff --git a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm index df844f5a9..ce64ca16d 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm +++ b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm @@ -150,7 +150,7 @@ idxBufferPtr[j+5] = k+0; } - id cb = [_fetchCommandQueue commandBufferWithUnretainedReferences];; + id cb = [_fetchCommandQueue commandBufferWithUnretainedReferences]; id bce = [cb blitCommandEncoder]; [bce copyFromBuffer:tempHUDIndexBuffer @@ -383,8 +383,11 @@ #ifdef MAC_OS_X_VERSION_10_13 if (_isSharedBufferTextureSupported) { - _texDisplayFetchNative[NDSDisplayID_Main][i] = [_bufDisplayFetchNative[NDSDisplayID_Main][i] newTextureWithDescriptor:newTexDisplayNativeDesc offset:0 bytesPerRow:_nativeLineSize]; - _texDisplayFetchNative[NDSDisplayID_Touch][i] = [_bufDisplayFetchNative[NDSDisplayID_Touch][i] newTextureWithDescriptor:newTexDisplayNativeDesc offset:0 bytesPerRow:_nativeLineSize]; + if (@available(macOS 10_13, *)) + { + _texDisplayFetchNative[NDSDisplayID_Main][i] = [_bufDisplayFetchNative[NDSDisplayID_Main][i] newTextureWithDescriptor:newTexDisplayNativeDesc offset:0 bytesPerRow:_nativeLineSize]; + _texDisplayFetchNative[NDSDisplayID_Touch][i] = [_bufDisplayFetchNative[NDSDisplayID_Touch][i] newTextureWithDescriptor:newTexDisplayNativeDesc offset:0 bytesPerRow:_nativeLineSize]; + } } else #endif @@ -409,8 +412,11 @@ #ifdef MAC_OS_X_VERSION_10_13 if (_isSharedBufferTextureSupported) { - _texDisplayFetchCustom[NDSDisplayID_Main][i] = [_bufDisplayFetchCustom[NDSDisplayID_Main][i] newTextureWithDescriptor:newTexDisplayCustomDesc offset:0 bytesPerRow:_customLineSize]; - _texDisplayFetchCustom[NDSDisplayID_Touch][i] = [_bufDisplayFetchCustom[NDSDisplayID_Touch][i] newTextureWithDescriptor:newTexDisplayCustomDesc offset:0 bytesPerRow:_customLineSize]; + if (@available(macOS 10_13, *)) + { + _texDisplayFetchCustom[NDSDisplayID_Main][i] = [_bufDisplayFetchCustom[NDSDisplayID_Main][i] newTextureWithDescriptor:newTexDisplayCustomDesc offset:0 bytesPerRow:_customLineSize]; + _texDisplayFetchCustom[NDSDisplayID_Touch][i] = [_bufDisplayFetchCustom[NDSDisplayID_Touch][i] newTextureWithDescriptor:newTexDisplayCustomDesc offset:0 bytesPerRow:_customLineSize]; + } } else #endif @@ -731,6 +737,34 @@ } } +- (void) flushMultipleViews:(const std::vector &)cdvFlushList +{ + const size_t listSize = cdvFlushList.size(); + id cb = [commandQueue commandBufferWithUnretainedReferences]; + + for (size_t i = 0; i < listSize; i++) + { + ClientDisplay3DView *cdv = (ClientDisplay3DView *)cdvFlushList[i]; + cdv->FlushView(cb); + } + + [cb commit]; +} + +- (void) finalizeFlushMultipleViews:(const std::vector &)cdvFlushList +{ + const size_t listSize = cdvFlushList.size(); + id cb = [commandQueue commandBufferWithUnretainedReferences]; + + for (size_t i = 0; i < listSize; i++) + { + ClientDisplay3DView *cdv = (ClientDisplay3DView *)cdvFlushList[i]; + cdv->FinalizeFlush(cb); + } + + [cb commit]; +} + @end @implementation MacMetalDisplayPresenterObject @@ -2142,6 +2176,7 @@ @synthesize _cdv; @synthesize presenterObject; +@synthesize layerDrawable; - (id) initWithDisplayPresenterObject:(MacMetalDisplayPresenterObject *)thePresenterObject { @@ -2153,6 +2188,7 @@ _cdv = NULL; _semDrawable = dispatch_semaphore_create(3); + layerDrawable = nil; presenterObject = thePresenterObject; if (thePresenterObject != nil) @@ -2168,6 +2204,7 @@ - (void)dealloc { + [self setLayerDrawable:nil]; dispatch_release(_semDrawable); [super dealloc]; @@ -2182,46 +2219,37 @@ } } -- (void) renderToDrawable +- (void) renderToDrawableUsingCommandBuffer:(id)cb { @autoreleasepool { // Now that everything is set up, go ahead and draw everything. dispatch_semaphore_wait(_semDrawable, DISPATCH_TIME_FOREVER); - id layerDrawable = [[self nextDrawable] retain]; + id drawable = [self nextDrawable]; - if (layerDrawable != nil) + if (drawable != nil) { - [[presenterObject colorAttachment0Desc] setTexture:[layerDrawable texture]]; - id cbRender = [presenterObject newCommandBuffer]; - id cbPresent = [presenterObject newCommandBuffer]; + [[presenterObject colorAttachment0Desc] setTexture:[drawable texture]]; const MetalTexturePair texProcess = [presenterObject texPairProcess]; const MetalRenderFrameInfo mrfi = [presenterObject renderFrameInfo]; - [presenterObject renderForCommandBuffer:cbRender + [presenterObject renderForCommandBuffer:cb outputPipelineState:[presenterObject outputDrawablePipeline] hudPipelineState:[[presenterObject sharedData] hudPipeline] texDisplays:texProcess mrfi:mrfi doYFlip:NO]; - [cbRender addScheduledHandler:^(id block) { + [cb addScheduledHandler:^(id block) { [presenterObject setRenderBufferState:ClientDisplayBufferState_Reading index:mrfi.renderIndex]; }]; - [cbRender addCompletedHandler:^(id block) { + [cb addCompletedHandler:^(id block) { [presenterObject renderFinishAtIndex:mrfi.renderIndex]; }]; - [cbPresent presentDrawable:layerDrawable]; - [cbPresent addCompletedHandler:^(id block) { - [layerDrawable release]; - dispatch_semaphore_signal(_semDrawable); - }]; - - [cbRender commit]; - [cbPresent commit]; + [self setLayerDrawable:drawable]; } else { @@ -2230,6 +2258,32 @@ } } +- (void) presentDrawableWithCommandBuffer:(id)cb +{ + id drawable = [self layerDrawable]; + if (drawable == nil) + { + return; + } + + [cb presentDrawable:drawable]; + [cb addCompletedHandler:^(id block) { + [self setLayerDrawable:nil]; + dispatch_semaphore_signal(_semDrawable); + }]; +} + +- (void) renderAndPresentDrawableImmediate +{ + id cb = [presenterObject newCommandBuffer]; + _cdv->FlushView(cb); + [cb commit]; + + cb = [presenterObject newCommandBuffer]; + _cdv->FinalizeFlush(cb); + [cb commit]; +} + @end #pragma mark - @@ -2575,13 +2629,23 @@ void MacMetalDisplayView::SetAllowViewFlushes(bool allowFlushes) [sharedData displayLinkStartUsingID:displayID]; } -void MacMetalDisplayView::FlushView() +void MacMetalDisplayView::FlushView(void *userData) { OSSpinLockLock(&this->_spinlockViewNeedsFlush); this->_viewNeedsFlush = false; OSSpinLockUnlock(&this->_spinlockViewNeedsFlush); - [(DisplayViewMetalLayer *)this->_caLayer renderToDrawable]; + [(DisplayViewMetalLayer *)this->_caLayer renderToDrawableUsingCommandBuffer:(id)userData]; +} + +void MacMetalDisplayView::FinalizeFlush(void *userData) +{ + [(DisplayViewMetalLayer *)this->_caLayer presentDrawableWithCommandBuffer:(id)userData]; +} + +void MacMetalDisplayView::FlushAndFinalizeImmediate() +{ + [(DisplayViewMetalLayer *)this->_caLayer renderAndPresentDrawableImmediate]; } #pragma mark - diff --git a/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.h b/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.h index 4b06c9f0a..67ee00c81 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.h +++ b/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.h @@ -133,7 +133,8 @@ public: virtual void SetUseVerticalSync(const bool useVerticalSync); // Client view interface - virtual void FlushView(); + virtual void FlushView(void *userData); + virtual void FinalizeFlush(void *userData); }; #endif // _MAC_OGLDISPLAYOUTPUT_H_ diff --git a/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.mm b/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.mm index e489444c6..419e11cab 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.mm +++ b/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.mm @@ -538,7 +538,7 @@ void MacOGLDisplayView::SetUseVerticalSync(const bool useVerticalSync) CGLUnlockContext(context); } -void MacOGLDisplayView::FlushView() +void MacOGLDisplayView::FlushView(void *userData) { OSSpinLockLock(&this->_spinlockViewNeedsFlush); this->_viewNeedsFlush = false; @@ -549,6 +549,15 @@ void MacOGLDisplayView::FlushView() CGLLockContext(context); CGLSetCurrentContext(context); ((MacOGLDisplayPresenter *)this->_presenter)->RenderFrameOGL(false); + CGLUnlockContext(context); +} + +void MacOGLDisplayView::FinalizeFlush(void *userData) +{ + CGLContextObj context = ((MacOGLDisplayPresenter *)this->_presenter)->GetContext(); + + CGLLockContext(context); + CGLSetCurrentContext(context); CGLFlushDrawable(context); CGLUnlockContext(context); }