diff --git a/desmume/src/GPU.cpp b/desmume/src/GPU.cpp index 5be104c0a..65f24fa9d 100644 --- a/desmume/src/GPU.cpp +++ b/desmume/src/GPU.cpp @@ -723,7 +723,7 @@ void GPUEngineBase::_RenderLine_Clear(const u16 clearColor, const u16 l, u16 *ds } template -void GPUEngineBase::RenderLine(const u16 l, bool isFrameSkipRequested) +void GPUEngineBase::RenderLine(const u16 l) { } @@ -2710,7 +2710,7 @@ void GPUEngineA::SetCustomFramebufferSize(size_t w, size_t h) } template -void GPUEngineA::RenderLine(const u16 l, bool isFrameSkipRequested) +void GPUEngineA::RenderLine(const u16 l) { const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); const size_t dstLineWidth = (ISCUSTOMRENDERINGNEEDED) ? dispInfo.customWidth : GPU_FRAMEBUFFER_NATIVE_WIDTH; @@ -3808,6 +3808,9 @@ void GPUEngineB::_RenderLine_Layer(const u16 l, u16 *dstColorLine, const size_t GPUSubsystem::GPUSubsystem() { + _defaultEventHandler = new GPUEventHandlerDefault; + _event = _defaultEventHandler; + gfx3d_init(); _engineMain = GPUEngineA::Allocate(); @@ -3867,6 +3870,8 @@ GPUSubsystem::~GPUSubsystem() _engineSub->FinalizeAndDeallocate(); gfx3d_deinit(); + + delete _defaultEventHandler; } GPUSubsystem* GPUSubsystem::Allocate() @@ -3880,6 +3885,16 @@ void GPUSubsystem::FinalizeAndDeallocate() free_aligned(this); } +void GPUSubsystem::SetEventHandler(GPUEventHandler *eventHandler) +{ + this->_event = eventHandler; +} + +GPUEventHandler* GPUSubsystem::GetEventHandler() +{ + return this->_event; +} + void GPUSubsystem::Reset() { if (this->_customVRAM == NULL || this->_customVRAM == NULL || this->_customFramebuffer == NULL) @@ -4184,6 +4199,7 @@ void GPUSubsystem::RenderLine(const u16 l, bool isFrameSkipRequested) if (l == 0) { CurrentRenderer->RenderFinish(); + this->_event->DidFrameBegin(); this->UpdateVRAM3DUsageProperties(); // Clear displays to black if they are turned off by the user. @@ -4215,11 +4231,11 @@ void GPUSubsystem::RenderLine(const u16 l, bool isFrameSkipRequested) { if (this->_engineMain->isCustomRenderingNeeded) { - this->_engineMain->RenderLine(l, isFrameSkipRequested); + this->_engineMain->RenderLine(l); } else { - this->_engineMain->RenderLine(l, isFrameSkipRequested); + this->_engineMain->RenderLine(l); } } @@ -4249,16 +4265,17 @@ void GPUSubsystem::RenderLine(const u16 l, bool isFrameSkipRequested) { this->_engineSub->ApplyMasterBrightness(); } - } - - if (this->_willAutoResolveToCustomBuffer) - { - this->_engineMain->ResolveToCustomFramebuffer(); - this->_engineSub->ResolveToCustomFramebuffer(); + + if (this->_willAutoResolveToCustomBuffer) + { + this->_engineMain->ResolveToCustomFramebuffer(); + this->_engineSub->ResolveToCustomFramebuffer(); + } } this->_engineMain->FramebufferPostprocess(); this->_engineSub->FramebufferPostprocess(); + this->_event->DidFrameEnd(isFrameSkipRequested); } } diff --git a/desmume/src/GPU.h b/desmume/src/GPU.h index 85558e8c8..70282d0fe 100644 --- a/desmume/src/GPU.h +++ b/desmume/src/GPU.h @@ -1229,7 +1229,7 @@ public: template void ParseAllRegisters(); - template void RenderLine(const u16 l, bool isFrameSkipRequested); + template void RenderLine(const u16 l); void FramebufferPostprocess(); bool isCustomRenderingNeeded; @@ -1337,7 +1337,7 @@ public: template void _LineLarge8bpp(u16 *dstColorLine, const u16 lineIndex); - template void RenderLine(const u16 l, bool isFrameSkipRequested); + template void RenderLine(const u16 l); void FramebufferPostprocess(); }; @@ -1376,12 +1376,36 @@ public: void SetEngineByID(const GPUEngineID theID); }; +class GPUEventHandler +{ +public: + virtual void DidFrameBegin() = 0; + virtual void DidFrameEnd(bool isFrameSkipped) = 0; + virtual void DidRender3DBegin() = 0; + virtual void DidRender3DEnd() = 0; +}; + +// All of the default event handler methods should do nothing. +// If a subclass doesn't need to override every method, then it might be easier +// if you subclass GPUEventHandlerDefault instead of GPUEventHandler. +class GPUEventHandlerDefault : public GPUEventHandler +{ +public: + virtual void DidFrameBegin() {}; + virtual void DidFrameEnd(bool isFrameSkipped) {}; + virtual void DidRender3DBegin() {}; + virtual void DidRender3DEnd() {}; +}; + class GPUSubsystem { private: GPUSubsystem(); ~GPUSubsystem(); + GPUEventHandlerDefault *_defaultEventHandler; + GPUEventHandler *_event; + GPUEngineA *_engineMain; GPUEngineB *_engineSub; NDSDisplay *_displayMain; @@ -1401,6 +1425,9 @@ public: static GPUSubsystem* Allocate(); void FinalizeAndDeallocate(); + void SetEventHandler(GPUEventHandler *eventHandler); + GPUEventHandler* GetEventHandler(); + void Reset(); VRAM3DUsageProperties& GetVRAM3DUsageProperties(); const NDSDisplayInfo& GetDisplayInfo(); // Frontends need to call this whenever they need to read the video buffers from the emulator core diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index 75c4f1050..69017f0dc 100644 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -2720,11 +2720,13 @@ Render3DError OpenGLRenderer_1_2::RenderFinish() { if (!this->_pixelReadNeedsFinish) { + GPU->GetEventHandler()->DidRender3DEnd(); return OGLERROR_NOERR; } if(!BEGINGL()) { + GPU->GetEventHandler()->DidRender3DEnd(); return OGLERROR_BEGINGL_FAILED; } @@ -2747,6 +2749,7 @@ Render3DError OpenGLRenderer_1_2::RenderFinish() this->FlushFramebuffer(GPU->GetEngineMain()->Get3DFramebufferRGBA6665(), GPU->GetEngineMain()->Get3DFramebufferRGBA5551()); this->_pixelReadNeedsFinish = false; + GPU->GetEventHandler()->DidRender3DEnd(); return OGLERROR_NOERR; } @@ -3287,11 +3290,13 @@ Render3DError OpenGLRenderer_1_5::RenderFinish() { if (!this->_pixelReadNeedsFinish) { + GPU->GetEventHandler()->DidRender3DEnd(); return OGLERROR_NOERR; } if(!BEGINGL()) { + GPU->GetEventHandler()->DidRender3DEnd(); return OGLERROR_BEGINGL_FAILED; } @@ -3314,6 +3319,7 @@ Render3DError OpenGLRenderer_1_5::RenderFinish() this->FlushFramebuffer(GPU->GetEngineMain()->Get3DFramebufferRGBA6665(), GPU->GetEngineMain()->Get3DFramebufferRGBA5551()); this->_pixelReadNeedsFinish = false; + GPU->GetEventHandler()->DidRender3DEnd(); return OGLERROR_NOERR; } @@ -4077,11 +4083,13 @@ Render3DError OpenGLRenderer_2_1::RenderFinish() { if (!this->_pixelReadNeedsFinish) { + GPU->GetEventHandler()->DidRender3DEnd(); return OGLERROR_NOERR; } if(!BEGINGL()) { + GPU->GetEventHandler()->DidRender3DEnd(); return OGLERROR_BEGINGL_FAILED; } @@ -4097,5 +4105,6 @@ Render3DError OpenGLRenderer_2_1::RenderFinish() this->FlushFramebuffer(GPU->GetEngineMain()->Get3DFramebufferRGBA6665(), GPU->GetEngineMain()->Get3DFramebufferRGBA5551()); this->_pixelReadNeedsFinish = false; + GPU->GetEventHandler()->DidRender3DEnd(); return OGLERROR_NOERR; } diff --git a/desmume/src/cocoa/cocoa_GPU.h b/desmume/src/cocoa/cocoa_GPU.h index 97f47990b..9c68b3ea4 100644 --- a/desmume/src/cocoa/cocoa_GPU.h +++ b/desmume/src/cocoa/cocoa_GPU.h @@ -19,6 +19,9 @@ #include #include + +class GPUEventHandlerOSX; + @interface CocoaDSGPU : NSObject { UInt32 gpuStateFlags; @@ -26,13 +29,14 @@ BOOL isCPUCoreCountAuto; OSSpinLock spinlockGpuState; - pthread_rwlock_t *rwlockProducer; + GPUEventHandlerOSX *gpuEvent; } @property (assign) UInt32 gpuStateFlags; @property (assign) NSSize gpuDimensions; @property (assign) NSUInteger gpuScale; -@property (assign) pthread_rwlock_t *rwlockProducer; +@property (readonly) pthread_rwlock_t *gpuFrameRWLock; +@property (assign) NSMutableArray *outputList; @property (assign) BOOL layerMainGPU; @property (assign) BOOL layerMainBG0; diff --git a/desmume/src/cocoa/cocoa_GPU.mm b/desmume/src/cocoa/cocoa_GPU.mm index e9b051bb7..65822df19 100644 --- a/desmume/src/cocoa/cocoa_GPU.mm +++ b/desmume/src/cocoa/cocoa_GPU.mm @@ -16,6 +16,7 @@ */ #import "cocoa_GPU.h" +#import "cocoa_output.h" #import "cocoa_globals.h" #include "utilities.h" @@ -40,12 +41,41 @@ GPU3DInterface *core3DList[] = { NULL }; +class GPUEventHandlerOSX : public GPUEventHandlerDefault +{ +private: + pthread_rwlock_t _rwlockFrame; + pthread_mutex_t _mutex3DRender; + NSMutableArray *_cdsOutputList; + bool _isRender3DLockHeld; + +public: + GPUEventHandlerOSX(); + ~GPUEventHandlerOSX(); + + void FramebufferLockWrite(); + void FramebufferLockRead(); + void FramebufferUnlock(); + void Render3DLock(); + void Render3DUnlock(); + + pthread_rwlock_t* GetFrameRWLock(); + NSMutableArray* GetOutputList(); + void SetOutputList(NSMutableArray *outputList); + + virtual void DidFrameBegin(); + virtual void DidFrameEnd(bool isFrameSkipped); + virtual void DidRender3DBegin(); + virtual void DidRender3DEnd(); +}; + @implementation CocoaDSGPU @dynamic gpuStateFlags; @dynamic gpuDimensions; @dynamic gpuScale; -@synthesize rwlockProducer; +@dynamic gpuFrameRWLock; +@dynamic outputList; @dynamic layerMainGPU; @dynamic layerMainBG0; @@ -81,7 +111,6 @@ GPU3DInterface *core3DList[] = { } spinlockGpuState = OS_SPINLOCK_INIT; - rwlockProducer = NULL; _gpuScale = 1; gpuStateFlags = GPUSTATE_MAIN_GPU_MASK | @@ -104,6 +133,8 @@ GPU3DInterface *core3DList[] = { &OSXOpenGLRendererEnd, &OSXOpenGLRendererFramebufferDidResize); + gpuEvent = new GPUEventHandlerOSX; + GPU->SetEventHandler(gpuEvent); GPU->SetWillAutoResolveToCustomBuffer(false); return self; @@ -114,6 +145,8 @@ GPU3DInterface *core3DList[] = { NDS_3D_ChangeCore(CORE3DLIST_NULL); DestroyOpenGLRenderer(); + delete gpuEvent; + [super dealloc]; } @@ -149,16 +182,20 @@ GPU3DInterface *core3DList[] = { - (void) setGpuDimensions:(NSSize)theDimensions { - pthread_rwlock_wrlock(self.rwlockProducer); + gpuEvent->FramebufferLockWrite(); + gpuEvent->Render3DLock(); GPU->SetCustomFramebufferSize(theDimensions.width, theDimensions.height); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); + gpuEvent->FramebufferUnlock(); } - (NSSize) gpuDimensions { - pthread_rwlock_rdlock(self.rwlockProducer); + gpuEvent->FramebufferLockRead(); + gpuEvent->Render3DLock(); const NSSize dimensions = NSMakeSize(GPU->GetCustomFramebufferWidth(), GPU->GetCustomFramebufferHeight()); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); + gpuEvent->FramebufferUnlock(); return dimensions; } @@ -174,98 +211,113 @@ GPU3DInterface *core3DList[] = { return (NSUInteger)_gpuScale; } +- (pthread_rwlock_t *) gpuFrameRWLock +{ + return gpuEvent->GetFrameRWLock(); +} + +- (void) setOutputList:(NSMutableArray *)outputList +{ + gpuEvent->SetOutputList(outputList); +} + +- (NSMutableArray *) outputList +{ + return gpuEvent->GetOutputList(); +} + - (void) setRender3DRenderingEngine:(NSInteger)methodID { - pthread_rwlock_wrlock(self.rwlockProducer); + gpuEvent->Render3DLock(); NDS_3D_ChangeCore(methodID); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); } - (NSInteger) render3DRenderingEngine { - pthread_rwlock_rdlock(self.rwlockProducer); + gpuEvent->Render3DLock(); const NSInteger methodID = (NSInteger)cur3DCore; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); return methodID; } - (void) setRender3DHighPrecisionColorInterpolation:(BOOL)state { - pthread_rwlock_wrlock(self.rwlockProducer); + gpuEvent->Render3DLock(); CommonSettings.GFX3D_HighResolutionInterpolateColor = state ? true : false; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); } - (BOOL) render3DHighPrecisionColorInterpolation { - pthread_rwlock_rdlock(self.rwlockProducer); + gpuEvent->Render3DLock(); const BOOL state = CommonSettings.GFX3D_HighResolutionInterpolateColor ? YES : NO; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); return state; } - (void) setRender3DEdgeMarking:(BOOL)state { - pthread_rwlock_wrlock(self.rwlockProducer); + gpuEvent->Render3DLock(); CommonSettings.GFX3D_EdgeMark = state ? true : false; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); } - (BOOL) render3DEdgeMarking { - pthread_rwlock_rdlock(self.rwlockProducer); + gpuEvent->Render3DLock(); const BOOL state = CommonSettings.GFX3D_EdgeMark ? YES : NO; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); return state; } - (void) setRender3DFog:(BOOL)state { - pthread_rwlock_wrlock(self.rwlockProducer); + gpuEvent->Render3DLock(); CommonSettings.GFX3D_Fog = state ? true : false; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); } - (BOOL) render3DFog { - pthread_rwlock_rdlock(self.rwlockProducer); + gpuEvent->Render3DLock(); const BOOL state = CommonSettings.GFX3D_Fog ? YES : NO; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); return state; } - (void) setRender3DTextures:(BOOL)state { - pthread_rwlock_wrlock(self.rwlockProducer); + gpuEvent->Render3DLock(); CommonSettings.GFX3D_Texture = state ? true : false; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); } - (BOOL) render3DTextures { - pthread_rwlock_rdlock(self.rwlockProducer); + gpuEvent->Render3DLock(); const BOOL state = CommonSettings.GFX3D_Texture ? YES : NO; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); return state; } - (void) setRender3DDepthComparisonThreshold:(NSUInteger)threshold { - pthread_rwlock_wrlock(self.rwlockProducer); + gpuEvent->Render3DLock(); CommonSettings.GFX3D_Zelda_Shadow_Depth_Hack = threshold; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); } - (NSUInteger) render3DDepthComparisonThreshold { - pthread_rwlock_rdlock(self.rwlockProducer); + gpuEvent->Render3DLock(); const NSUInteger threshold = (NSUInteger)CommonSettings.GFX3D_Zelda_Shadow_Depth_Hack; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); return threshold; } @@ -302,7 +354,7 @@ GPU3DInterface *core3DList[] = { const NSInteger renderingEngineID = [self render3DRenderingEngine]; - pthread_rwlock_wrlock(self.rwlockProducer); + gpuEvent->Render3DLock(); CommonSettings.num_cores = numberCores; @@ -311,71 +363,71 @@ GPU3DInterface *core3DList[] = { NDS_3D_ChangeCore(renderingEngineID); } - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); } - (NSUInteger) render3DThreads { - pthread_rwlock_rdlock(self.rwlockProducer); + gpuEvent->Render3DLock(); const NSUInteger numberThreads = isCPUCoreCountAuto ? 0 : (NSUInteger)CommonSettings.num_cores; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); return numberThreads; } - (void) setRender3DLineHack:(BOOL)state { - pthread_rwlock_wrlock(self.rwlockProducer); + gpuEvent->Render3DLock(); CommonSettings.GFX3D_LineHack = state ? true : false; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); } - (BOOL) render3DLineHack { - pthread_rwlock_rdlock(self.rwlockProducer); + gpuEvent->Render3DLock(); const BOOL state = CommonSettings.GFX3D_LineHack ? YES : NO; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); return state; } - (void) setRender3DMultisample:(BOOL)state { - pthread_rwlock_wrlock(self.rwlockProducer); + gpuEvent->Render3DLock(); CommonSettings.GFX3D_Renderer_Multisample = state ? true : false; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); } - (BOOL) render3DMultisample { - pthread_rwlock_rdlock(self.rwlockProducer); + gpuEvent->Render3DLock(); const BOOL state = CommonSettings.GFX3D_Renderer_Multisample ? YES : NO; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); return state; } - (void) setRender3DFragmentSamplingHack:(BOOL)state { - pthread_rwlock_wrlock(self.rwlockProducer); + gpuEvent->Render3DLock(); CommonSettings.GFX3D_TXTHack = state ? true : false; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); } - (BOOL) render3DFragmentSamplingHack { - pthread_rwlock_rdlock(self.rwlockProducer); + gpuEvent->Render3DLock(); const BOOL state = CommonSettings.GFX3D_TXTHack ? YES : NO; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); return state; } - (void) setLayerMainGPU:(BOOL)gpuState { - pthread_rwlock_wrlock(self.rwlockProducer); + gpuEvent->FramebufferLockWrite(); GPU->GetEngineMain()->SetEnableState((gpuState) ? true : false); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferUnlock(); OSSpinLockLock(&spinlockGpuState); gpuStateFlags = (gpuState) ? (gpuStateFlags | GPUSTATE_MAIN_GPU_MASK) : (gpuStateFlags & ~GPUSTATE_MAIN_GPU_MASK); @@ -384,18 +436,18 @@ GPU3DInterface *core3DList[] = { - (BOOL) layerMainGPU { - pthread_rwlock_rdlock(self.rwlockProducer); + gpuEvent->FramebufferLockRead(); const BOOL gpuState = GPU->GetEngineMain()->GetEnableState() ? YES : NO; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferUnlock(); return gpuState; } - (void) setLayerMainBG0:(BOOL)layerState { - pthread_rwlock_wrlock(self.rwlockProducer); - GPU->GetEngineMain()->SetLayerEnableState(0, (layerState) ? true : false); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockWrite(); + GPU->GetEngineMain()->SetLayerEnableState(GPULayerID_BG0, (layerState) ? true : false); + gpuEvent->FramebufferUnlock(); OSSpinLockLock(&spinlockGpuState); gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_MAIN_BG0_MASK) : (gpuStateFlags & ~GPUSTATE_MAIN_BG0_MASK); @@ -404,18 +456,18 @@ GPU3DInterface *core3DList[] = { - (BOOL) layerMainBG0 { - pthread_rwlock_rdlock(self.rwlockProducer); - const BOOL layerState = GPU->GetEngineMain()->GetLayerEnableState(0); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockRead(); + const BOOL layerState = GPU->GetEngineMain()->GetLayerEnableState(GPULayerID_BG0); + gpuEvent->FramebufferUnlock(); return layerState; } - (void) setLayerMainBG1:(BOOL)layerState { - pthread_rwlock_wrlock(self.rwlockProducer); - GPU->GetEngineMain()->SetLayerEnableState(1, (layerState) ? true : false); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockWrite(); + GPU->GetEngineMain()->SetLayerEnableState(GPULayerID_BG1, (layerState) ? true : false); + gpuEvent->FramebufferUnlock(); OSSpinLockLock(&spinlockGpuState); gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_MAIN_BG1_MASK) : (gpuStateFlags & ~GPUSTATE_MAIN_BG1_MASK); @@ -424,18 +476,18 @@ GPU3DInterface *core3DList[] = { - (BOOL) layerMainBG1 { - pthread_rwlock_rdlock(self.rwlockProducer); - const BOOL layerState = GPU->GetEngineMain()->GetLayerEnableState(1); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockRead(); + const BOOL layerState = GPU->GetEngineMain()->GetLayerEnableState(GPULayerID_BG1); + gpuEvent->FramebufferUnlock(); return layerState; } - (void) setLayerMainBG2:(BOOL)layerState { - pthread_rwlock_wrlock(self.rwlockProducer); - GPU->GetEngineMain()->SetLayerEnableState(2, (layerState) ? true : false); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockWrite(); + GPU->GetEngineMain()->SetLayerEnableState(GPULayerID_BG2, (layerState) ? true : false); + gpuEvent->FramebufferUnlock(); OSSpinLockLock(&spinlockGpuState); gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_MAIN_BG2_MASK) : (gpuStateFlags & ~GPUSTATE_MAIN_BG2_MASK); @@ -444,18 +496,18 @@ GPU3DInterface *core3DList[] = { - (BOOL) layerMainBG2 { - pthread_rwlock_rdlock(self.rwlockProducer); - const BOOL layerState = GPU->GetEngineMain()->GetLayerEnableState(2); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockRead(); + const BOOL layerState = GPU->GetEngineMain()->GetLayerEnableState(GPULayerID_BG2); + gpuEvent->FramebufferUnlock(); return layerState; } - (void) setLayerMainBG3:(BOOL)layerState { - pthread_rwlock_wrlock(self.rwlockProducer); - GPU->GetEngineMain()->SetLayerEnableState(3, (layerState) ? true : false); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockWrite(); + GPU->GetEngineMain()->SetLayerEnableState(GPULayerID_BG3, (layerState) ? true : false); + gpuEvent->FramebufferUnlock(); OSSpinLockLock(&spinlockGpuState); gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_MAIN_BG3_MASK) : (gpuStateFlags & ~GPUSTATE_MAIN_BG3_MASK); @@ -464,18 +516,18 @@ GPU3DInterface *core3DList[] = { - (BOOL) layerMainBG3 { - pthread_rwlock_rdlock(self.rwlockProducer); - const BOOL layerState = GPU->GetEngineMain()->GetLayerEnableState(3); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockRead(); + const BOOL layerState = GPU->GetEngineMain()->GetLayerEnableState(GPULayerID_BG3); + gpuEvent->FramebufferUnlock(); return layerState; } - (void) setLayerMainOBJ:(BOOL)layerState { - pthread_rwlock_wrlock(self.rwlockProducer); - GPU->GetEngineMain()->SetLayerEnableState(4, (layerState) ? true : false); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockWrite(); + GPU->GetEngineMain()->SetLayerEnableState(GPULayerID_OBJ, (layerState) ? true : false); + gpuEvent->FramebufferUnlock(); OSSpinLockLock(&spinlockGpuState); gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_MAIN_OBJ_MASK) : (gpuStateFlags & ~GPUSTATE_MAIN_OBJ_MASK); @@ -484,18 +536,18 @@ GPU3DInterface *core3DList[] = { - (BOOL) layerMainOBJ { - pthread_rwlock_rdlock(self.rwlockProducer); - const BOOL layerState = GPU->GetEngineMain()->GetLayerEnableState(4); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockRead(); + const BOOL layerState = GPU->GetEngineMain()->GetLayerEnableState(GPULayerID_OBJ); + gpuEvent->FramebufferUnlock(); return layerState; } - (void) setLayerSubGPU:(BOOL)gpuState { - pthread_rwlock_wrlock(self.rwlockProducer); + gpuEvent->FramebufferLockWrite(); GPU->GetEngineSub()->SetEnableState((gpuState) ? true : false); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferUnlock(); OSSpinLockLock(&spinlockGpuState); gpuStateFlags = (gpuState) ? (gpuStateFlags | GPUSTATE_SUB_GPU_MASK) : (gpuStateFlags & ~GPUSTATE_SUB_GPU_MASK); @@ -504,18 +556,18 @@ GPU3DInterface *core3DList[] = { - (BOOL) layerSubGPU { - pthread_rwlock_rdlock(self.rwlockProducer); + gpuEvent->FramebufferLockRead(); const BOOL gpuState = GPU->GetEngineSub()->GetEnableState() ? YES : NO; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferUnlock(); return gpuState; } - (void) setLayerSubBG0:(BOOL)layerState { - pthread_rwlock_wrlock(self.rwlockProducer); - GPU->GetEngineSub()->SetLayerEnableState(0, (layerState) ? true : false); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockWrite(); + GPU->GetEngineSub()->SetLayerEnableState(GPULayerID_BG0, (layerState) ? true : false); + gpuEvent->FramebufferUnlock(); OSSpinLockLock(&spinlockGpuState); gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_SUB_BG0_MASK) : (gpuStateFlags & ~GPUSTATE_SUB_BG0_MASK); @@ -524,18 +576,18 @@ GPU3DInterface *core3DList[] = { - (BOOL) layerSubBG0 { - pthread_rwlock_rdlock(self.rwlockProducer); - const BOOL layerState = GPU->GetEngineSub()->GetLayerEnableState(0); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockRead(); + const BOOL layerState = GPU->GetEngineSub()->GetLayerEnableState(GPULayerID_BG0); + gpuEvent->FramebufferUnlock(); return layerState; } - (void) setLayerSubBG1:(BOOL)layerState { - pthread_rwlock_wrlock(self.rwlockProducer); - GPU->GetEngineSub()->SetLayerEnableState(1, (layerState) ? true : false); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockWrite(); + GPU->GetEngineSub()->SetLayerEnableState(GPULayerID_BG1, (layerState) ? true : false); + gpuEvent->FramebufferUnlock(); OSSpinLockLock(&spinlockGpuState); gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_SUB_BG1_MASK) : (gpuStateFlags & ~GPUSTATE_SUB_BG1_MASK); @@ -544,18 +596,18 @@ GPU3DInterface *core3DList[] = { - (BOOL) layerSubBG1 { - pthread_rwlock_rdlock(self.rwlockProducer); - const BOOL layerState = GPU->GetEngineSub()->GetLayerEnableState(1); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockRead(); + const BOOL layerState = GPU->GetEngineSub()->GetLayerEnableState(GPULayerID_BG1); + gpuEvent->FramebufferUnlock(); return layerState; } - (void) setLayerSubBG2:(BOOL)layerState { - pthread_rwlock_wrlock(self.rwlockProducer); - GPU->GetEngineSub()->SetLayerEnableState(2, (layerState) ? true : false); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockWrite(); + GPU->GetEngineSub()->SetLayerEnableState(GPULayerID_BG2, (layerState) ? true : false); + gpuEvent->FramebufferUnlock(); OSSpinLockLock(&spinlockGpuState); gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_SUB_BG2_MASK) : (gpuStateFlags & ~GPUSTATE_SUB_BG2_MASK); @@ -564,18 +616,18 @@ GPU3DInterface *core3DList[] = { - (BOOL) layerSubBG2 { - pthread_rwlock_rdlock(self.rwlockProducer); - const BOOL layerState = GPU->GetEngineSub()->GetLayerEnableState(2); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockRead(); + const BOOL layerState = GPU->GetEngineSub()->GetLayerEnableState(GPULayerID_BG2); + gpuEvent->FramebufferUnlock(); return layerState; } - (void) setLayerSubBG3:(BOOL)layerState { - pthread_rwlock_wrlock(self.rwlockProducer); - GPU->GetEngineSub()->SetLayerEnableState(3, (layerState) ? true : false); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockWrite(); + GPU->GetEngineSub()->SetLayerEnableState(GPULayerID_BG3, (layerState) ? true : false); + gpuEvent->FramebufferUnlock(); OSSpinLockLock(&spinlockGpuState); gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_SUB_BG3_MASK) : (gpuStateFlags & ~GPUSTATE_SUB_BG3_MASK); @@ -584,18 +636,18 @@ GPU3DInterface *core3DList[] = { - (BOOL) layerSubBG3 { - pthread_rwlock_rdlock(self.rwlockProducer); - const BOOL layerState = GPU->GetEngineSub()->GetLayerEnableState(3); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockRead(); + const BOOL layerState = GPU->GetEngineSub()->GetLayerEnableState(GPULayerID_BG3); + gpuEvent->FramebufferUnlock(); return layerState; } - (void) setLayerSubOBJ:(BOOL)layerState { - pthread_rwlock_wrlock(self.rwlockProducer); - GPU->GetEngineSub()->SetLayerEnableState(4, (layerState) ? true : false); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockWrite(); + GPU->GetEngineSub()->SetLayerEnableState(GPULayerID_OBJ, (layerState) ? true : false); + gpuEvent->FramebufferUnlock(); OSSpinLockLock(&spinlockGpuState); gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_SUB_OBJ_MASK) : (gpuStateFlags & ~GPUSTATE_SUB_OBJ_MASK); @@ -604,9 +656,9 @@ GPU3DInterface *core3DList[] = { - (BOOL) layerSubOBJ { - pthread_rwlock_rdlock(self.rwlockProducer); - const BOOL layerState = GPU->GetEngineSub()->GetLayerEnableState(4); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferLockRead(); + const BOOL layerState = GPU->GetEngineSub()->GetLayerEnableState(GPULayerID_OBJ); + gpuEvent->FramebufferUnlock(); return layerState; } @@ -620,31 +672,120 @@ GPU3DInterface *core3DList[] = { { NSString *theString = @"Uninitialized"; - pthread_rwlock_rdlock(self.rwlockProducer); + gpuEvent->Render3DLock(); if(gpu3D == NULL) { - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); return theString; } const char *theName = gpu3D->name; theString = [NSString stringWithCString:theName encoding:NSUTF8StringEncoding]; - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->Render3DUnlock(); return theString; } - (void) clearWithColor:(const uint16_t)colorBGRA5551 { - pthread_rwlock_wrlock(self.rwlockProducer); + gpuEvent->FramebufferLockWrite(); GPU->ClearWithColor(colorBGRA5551); - pthread_rwlock_unlock(self.rwlockProducer); + gpuEvent->FramebufferUnlock(); } @end +GPUEventHandlerOSX::GPUEventHandlerOSX() +{ + _isRender3DLockHeld = false; + pthread_rwlock_init(&_rwlockFrame, NULL); + pthread_mutex_init(&_mutex3DRender, NULL); +} + +GPUEventHandlerOSX::~GPUEventHandlerOSX() +{ + pthread_rwlock_destroy(&this->_rwlockFrame); + pthread_mutex_destroy(&this->_mutex3DRender); +} + +void GPUEventHandlerOSX::DidFrameBegin() +{ + this->FramebufferLockWrite(); +} + +void GPUEventHandlerOSX::DidFrameEnd(bool isFrameSkipped) +{ + this->FramebufferUnlock(); + + if (!isFrameSkipped) + { + for (CocoaDSOutput *cdsOutput in this->_cdsOutputList) + { + if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]]) + { + [cdsOutput doCoreEmuFrame]; + } + } + } +} + +void GPUEventHandlerOSX::DidRender3DBegin() +{ + this->_isRender3DLockHeld = true; + this->Render3DLock(); +} + +void GPUEventHandlerOSX::DidRender3DEnd() +{ + if (this->_isRender3DLockHeld) + { + this->Render3DUnlock(); + this->_isRender3DLockHeld = false; + } +} + +void GPUEventHandlerOSX::FramebufferLockWrite() +{ + pthread_rwlock_wrlock(&this->_rwlockFrame); +} + +void GPUEventHandlerOSX::FramebufferLockRead() +{ + pthread_rwlock_rdlock(&this->_rwlockFrame); +} + +void GPUEventHandlerOSX::FramebufferUnlock() +{ + pthread_rwlock_unlock(&this->_rwlockFrame); +} + +void GPUEventHandlerOSX::Render3DLock() +{ + pthread_mutex_lock(&this->_mutex3DRender); +} + +void GPUEventHandlerOSX::Render3DUnlock() +{ + pthread_mutex_unlock(&this->_mutex3DRender); +} + +pthread_rwlock_t* GPUEventHandlerOSX::GetFrameRWLock() +{ + return &this->_rwlockFrame; +} + +NSMutableArray* GPUEventHandlerOSX::GetOutputList() +{ + return this->_cdsOutputList; +} + +void GPUEventHandlerOSX::SetOutputList(NSMutableArray *outputList) +{ + this->_cdsOutputList = outputList; +} + CGLContextObj OSXOpenGLRendererContext = NULL; CGLPBufferObj OSXOpenGLRendererPBuffer = NULL; diff --git a/desmume/src/cocoa/cocoa_core.mm b/desmume/src/cocoa/cocoa_core.mm index bf402eb88..a8848f093 100644 --- a/desmume/src/cocoa/cocoa_core.mm +++ b/desmume/src/cocoa/cocoa_core.mm @@ -213,7 +213,7 @@ volatile bool execute = true; sp.sched_priority = sched_get_priority_max(thePolicy); pthread_setschedparam(coreThread, thePolicy, &sp); - [cdsGPU setRwlockProducer:self.rwlockCoreExecute]; + [cdsGPU setOutputList:cdsOutputList]; OSXDriver *newDriver = new OSXDriver; newDriver->SetCoreThreadMutexLock(&threadParam.mutexThreadExecute); @@ -950,7 +950,16 @@ volatile bool execute = true; - (void) addOutput:(CocoaDSOutput *)theOutput { pthread_mutex_lock(&threadParam.mutexOutputList); - [theOutput setRwlockProducer:[self rwlockCoreExecute]]; + + if ([theOutput isKindOfClass:[CocoaDSDisplay class]]) + { + [theOutput setRwlockProducer:[[self cdsGPU] gpuFrameRWLock]]; + } + else + { + [theOutput setRwlockProducer:[self rwlockCoreExecute]]; + } + [[self cdsOutputList] addObject:theOutput]; pthread_mutex_unlock(&threadParam.mutexOutputList); } @@ -1145,12 +1154,10 @@ static void* RunCoreThread(void *arg) { for(CocoaDSOutput *cdsOutput in cdsOutputList) { - if (param->framesToSkip > 0 && [cdsOutput isKindOfClass:[CocoaDSDisplay class]]) + if (![cdsOutput isKindOfClass:[CocoaDSDisplay class]]) { - continue; + [cdsOutput doCoreEmuFrame]; } - - [cdsOutput doCoreEmuFrame]; } break; } @@ -1159,7 +1166,10 @@ static void* RunCoreThread(void *arg) { for(CocoaDSOutput *cdsOutput in cdsOutputList) { - [cdsOutput doCoreEmuFrame]; + if (![cdsOutput isKindOfClass:[CocoaDSDisplay class]]) + { + [cdsOutput doCoreEmuFrame]; + } } break; } @@ -1168,7 +1178,7 @@ static void* RunCoreThread(void *arg) { for(CocoaDSOutput *cdsOutput in cdsOutputList) { - if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]] && (param->framesToSkip == 0 || frameNum >= param->frameJumpTarget)) + if (![cdsOutput isKindOfClass:[CocoaDSDisplay class]]) { [cdsOutput doCoreEmuFrame]; } diff --git a/desmume/src/gfx3d.cpp b/desmume/src/gfx3d.cpp index efcaa7469..749a68daa 100644 --- a/desmume/src/gfx3d.cpp +++ b/desmume/src/gfx3d.cpp @@ -559,7 +559,6 @@ void gfx3d_init() makeTables(); Render3D_Init(); - gfx3d_reset(); } void gfx3d_deinit() diff --git a/desmume/src/rasterize.cpp b/desmume/src/rasterize.cpp index 175b276b3..e721a93ea 100644 --- a/desmume/src/rasterize.cpp +++ b/desmume/src/rasterize.cpp @@ -1933,6 +1933,7 @@ Render3DError SoftRasterizerRenderer::Render(const GFX3D &engine) { Render3DError error = RENDER3DERROR_NOERR; + GPU->GetEventHandler()->DidRender3DBegin(); error = this->BeginRender(engine); if (error != RENDER3DERROR_NOERR) { @@ -1970,6 +1971,7 @@ Render3DError SoftRasterizerRenderer::RenderFinish() { if (!this->_renderGeometryNeedsFinish) { + GPU->GetEventHandler()->DidRender3DEnd(); return RENDER3DERROR_NOERR; } @@ -2005,6 +2007,7 @@ Render3DError SoftRasterizerRenderer::RenderFinish() this->FlushFramebuffer(GPU->GetEngineMain()->Get3DFramebufferRGBA6665(), GPU->GetEngineMain()->Get3DFramebufferRGBA5551()); + GPU->GetEventHandler()->DidRender3DEnd(); return RENDER3DERROR_NOERR; } diff --git a/desmume/src/render3D.cpp b/desmume/src/render3D.cpp index f184f6568..2805c97f4 100644 --- a/desmume/src/render3D.cpp +++ b/desmume/src/render3D.cpp @@ -437,6 +437,7 @@ Render3DError Render3D::Render(const GFX3D &engine) { Render3DError error = RENDER3DERROR_NOERR; + GPU->GetEventHandler()->DidRender3DBegin(); error = this->BeginRender(engine); if (error != RENDER3DERROR_NOERR) { @@ -465,6 +466,7 @@ Render3DError Render3D::Render(const GFX3D &engine) Render3DError Render3D::RenderFinish() { + GPU->GetEventHandler()->DidRender3DEnd(); return RENDER3DERROR_NOERR; }