Cocoa Port: Increment/decrement the number of display views in need of CPU filtering, instead of looping through all outputs to determine it. Prevents a possible deadlock when changing CPU-based pixel scalers.

- Also do some additional code cleanup.
This commit is contained in:
rogerman 2017-02-10 11:28:35 -08:00
parent 241f50ee7a
commit ff2e6cb220
7 changed files with 74 additions and 35 deletions

View File

@ -354,17 +354,20 @@ void ClientDisplayView::SetPixelScaler(const VideoFilterTypeID filterID)
const size_t newDstBufferWidth = (this->_vf[NDSDisplayID_Main]->GetSrcWidth() + this->_vf[NDSDisplayID_Touch]->GetSrcWidth()) * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide; const size_t newDstBufferWidth = (this->_vf[NDSDisplayID_Main]->GetSrcWidth() + this->_vf[NDSDisplayID_Touch]->GetSrcWidth()) * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide;
const size_t newDstBufferHeight = (this->_vf[NDSDisplayID_Main]->GetSrcHeight() + this->_vf[NDSDisplayID_Touch]->GetSrcHeight()) * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide; const size_t newDstBufferHeight = (this->_vf[NDSDisplayID_Main]->GetSrcHeight() + this->_vf[NDSDisplayID_Touch]->GetSrcHeight()) * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide;
uint32_t *oldMasterBuffer = NULL;
if ( (oldDstBufferWidth != newDstBufferWidth) || (oldDstBufferHeight != newDstBufferHeight) ) if ( (oldDstBufferWidth != newDstBufferWidth) || (oldDstBufferHeight != newDstBufferHeight) )
{ {
uint32_t *oldMasterBuffer = this->_vfMasterDstBuffer; oldMasterBuffer = this->_vfMasterDstBuffer;
this->_ResizeCPUPixelScaler(newFilterID); this->_ResizeCPUPixelScaler(newFilterID);
free_aligned(oldMasterBuffer);
} }
this->_vf[NDSDisplayID_Main]->ChangeFilterByID(newFilterID); this->_vf[NDSDisplayID_Main]->ChangeFilterByID(newFilterID);
this->_vf[NDSDisplayID_Touch]->ChangeFilterByID(newFilterID); this->_vf[NDSDisplayID_Touch]->ChangeFilterByID(newFilterID);
this->_pixelScaler = newFilterID; this->_pixelScaler = newFilterID;
free_aligned(oldMasterBuffer);
} }
VideoFilter* ClientDisplayView::GetPixelScalerObject(const NDSDisplayID displayID) VideoFilter* ClientDisplayView::GetPixelScalerObject(const NDSDisplayID displayID)

View File

@ -38,14 +38,17 @@ class GPUEventHandlerOSX;
pthread_rwlock_t *_rwlockFramebuffer[2]; pthread_rwlock_t *_rwlockFramebuffer[2];
pthread_mutex_t *_mutexOutputList; pthread_mutex_t *_mutexOutputList;
NSMutableArray *_cdsOutputList; NSMutableArray *_cdsOutputList;
volatile int32_t numberViewsUsingCPUFiltering;
} }
@property (assign, nonatomic) GPUClientFetchObject *GPUFetchObject; @property (assign, nonatomic) GPUClientFetchObject *GPUFetchObject;
@property (readonly, nonatomic) int32_t numberViewsUsingCPUFiltering;
- (const NDSDisplayInfo &) fetchDisplayInfoForIndex:(const u8)bufferIndex; - (const NDSDisplayInfo &) fetchDisplayInfoForIndex:(const u8)bufferIndex;
- (pthread_rwlock_t *) rwlockFramebufferAtIndex:(const u8)bufferIndex; - (pthread_rwlock_t *) rwlockFramebufferAtIndex:(const u8)bufferIndex;
- (void) setOutputList:(NSMutableArray *)theOutputList mutex:(pthread_mutex_t *)theMutex; - (void) setOutputList:(NSMutableArray *)theOutputList mutex:(pthread_mutex_t *)theMutex;
- (BOOL) isCPUFilteringNeeded; - (void) incrementViewsUsingCPUFiltering;
- (void) decrementViewsUsingCPUFiltering;
- (void) handleFetchFromBufferIndexAndPushVideo:(NSData *)indexData; - (void) handleFetchFromBufferIndexAndPushVideo:(NSData *)indexData;
- (void) pushVideoDataToAllDisplayViews; - (void) pushVideoDataToAllDisplayViews;
- (void) finishAllDisplayViewsAtIndex:(const u8)bufferIndex; - (void) finishAllDisplayViewsAtIndex:(const u8)bufferIndex;

View File

@ -153,13 +153,21 @@ public:
GPU->SetEventHandler(gpuEvent); GPU->SetEventHandler(gpuEvent);
GPU->SetWillAutoResolveToCustomBuffer(false); GPU->SetWillAutoResolveToCustomBuffer(false);
fetchObject = NULL;
#ifdef ENABLE_APPLE_METAL #ifdef ENABLE_APPLE_METAL
if (IsOSXVersionSupported(10, 11, 0)) if (IsOSXVersionSupported(10, 11, 0))
{ {
fetchObject = new MacMetalFetchObject; fetchObject = new MacMetalFetchObject;
if (fetchObject->GetClientData() == nil)
{
delete fetchObject;
fetchObject = NULL;
}
} }
else
#endif #endif
if (fetchObject == NULL)
{ {
fetchObject = new MacOGLClientFetchObject; fetchObject = new MacOGLClientFetchObject;
} }
@ -852,6 +860,7 @@ public:
@implementation MacClientSharedObject @implementation MacClientSharedObject
@synthesize GPUFetchObject; @synthesize GPUFetchObject;
@synthesize numberViewsUsingCPUFiltering;
- (id)init - (id)init
{ {
@ -870,6 +879,7 @@ public:
GPUFetchObject = nil; GPUFetchObject = nil;
_mutexOutputList = NULL; _mutexOutputList = NULL;
_cdsOutputList = nil; _cdsOutputList = nil;
numberViewsUsingCPUFiltering = 0;
return self; return self;
} }
@ -952,36 +962,14 @@ public:
_mutexOutputList = theMutex; _mutexOutputList = theMutex;
} }
- (BOOL) isCPUFilteringNeeded - (void) incrementViewsUsingCPUFiltering
{ {
bool useCPUFilterPipeline = NO; OSAtomicIncrement32(&numberViewsUsingCPUFiltering);
pthread_mutex_t *currentMutex = _mutexOutputList; }
if (currentMutex != NULL) - (void) decrementViewsUsingCPUFiltering
{ {
pthread_mutex_lock(currentMutex); OSAtomicDecrement32(&numberViewsUsingCPUFiltering);
}
for (CocoaDSOutput *cdsOutput in _cdsOutputList)
{
if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]])
{
ClientDisplay3DView *cdv = [(CocoaDSDisplay *)cdsOutput clientDisplayView];
if (!cdv->WillFilterOnGPU() && (cdv->GetPixelScaler() != VideoFilterTypeID_None))
{
useCPUFilterPipeline = YES;
break;
}
}
}
if (currentMutex != NULL)
{
pthread_mutex_unlock(currentMutex);
}
return useCPUFilterPipeline;
} }
- (void) pushVideoDataToAllDisplayViews - (void) pushVideoDataToAllDisplayViews

View File

@ -140,7 +140,8 @@ struct NDSFrameInfo;
OSSpinLock spinlockPixelScaler; OSSpinLock spinlockPixelScaler;
} }
@property (readonly) BOOL canFilterOnGPU; @property (readonly, nonatomic) BOOL canFilterOnGPU;
@property (readonly, nonatomic) BOOL willFilterOnGPU;
@property (assign) BOOL isHUDVisible; @property (assign) BOOL isHUDVisible;
@property (assign) BOOL isHUDVideoFPSVisible; @property (assign) BOOL isHUDVideoFPSVisible;
@property (assign) BOOL isHUDRender3DFPSVisible; @property (assign) BOOL isHUDRender3DFPSVisible;

View File

@ -733,6 +733,7 @@
@implementation CocoaDSDisplayVideo @implementation CocoaDSDisplayVideo
@dynamic canFilterOnGPU; @dynamic canFilterOnGPU;
@dynamic willFilterOnGPU;
@dynamic isHUDVisible; @dynamic isHUDVisible;
@dynamic isHUDVideoFPSVisible; @dynamic isHUDVideoFPSVisible;
@dynamic isHUDRender3DFPSVisible; @dynamic isHUDRender3DFPSVisible;
@ -774,6 +775,11 @@
return (_cdv->CanFilterOnGPU()) ? YES : NO; return (_cdv->CanFilterOnGPU()) ? YES : NO;
} }
- (BOOL) willFilterOnGPU
{
return (_cdv->WillFilterOnGPU()) ? YES : NO;
}
- (void) setIsHUDVisible:(BOOL)theState - (void) setIsHUDVisible:(BOOL)theState
{ {
OSSpinLockLock(&spinlockIsHUDVisible); OSSpinLockLock(&spinlockIsHUDVisible);

View File

@ -1751,7 +1751,26 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
- (void) setVideoFiltersPreferGPU:(BOOL)theState - (void) setVideoFiltersPreferGPU:(BOOL)theState
{ {
const BOOL oldState = (![[self cdsVideoOutput] willFilterOnGPU] && ([[self cdsVideoOutput] pixelScaler] != VideoFilterTypeID_None));
[[self cdsVideoOutput] setVideoFiltersPreferGPU:theState]; [[self cdsVideoOutput] setVideoFiltersPreferGPU:theState];
const BOOL newState = (![[self cdsVideoOutput] willFilterOnGPU] && ([[self cdsVideoOutput] pixelScaler] != VideoFilterTypeID_None));
if (oldState != newState)
{
DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate];
CocoaDSCore *cdsCore = (CocoaDSCore *)[[[windowController emuControl] cdsCoreController] content];
CocoaDSGPU *cdsGPU = [cdsCore cdsGPU];
MacClientSharedObject *macSharedData = [cdsGPU sharedData];
if (newState)
{
[macSharedData incrementViewsUsingCPUFiltering];
}
else
{
[macSharedData decrementViewsUsingCPUFiltering];
}
}
} }
- (BOOL) videoFiltersPreferGPU - (BOOL) videoFiltersPreferGPU
@ -1781,7 +1800,26 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
- (void) setPixelScaler:(NSInteger)filterID - (void) setPixelScaler:(NSInteger)filterID
{ {
const BOOL oldState = (![[self cdsVideoOutput] willFilterOnGPU] && ([[self cdsVideoOutput] pixelScaler] != VideoFilterTypeID_None));
[[self cdsVideoOutput] setPixelScaler:filterID]; [[self cdsVideoOutput] setPixelScaler:filterID];
const BOOL newState = (![[self cdsVideoOutput] willFilterOnGPU] && ([[self cdsVideoOutput] pixelScaler] != VideoFilterTypeID_None));
if (oldState != newState)
{
DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate];
CocoaDSCore *cdsCore = (CocoaDSCore *)[[[windowController emuControl] cdsCoreController] content];
CocoaDSGPU *cdsGPU = [cdsCore cdsGPU];
MacClientSharedObject *macSharedData = [cdsGPU sharedData];
if (newState)
{
[macSharedData incrementViewsUsingCPUFiltering];
}
else
{
[macSharedData decrementViewsUsingCPUFiltering];
}
}
} }
- (NSInteger) pixelScaler - (NSInteger) pixelScaler

View File

@ -199,7 +199,7 @@ void MacOGLClientFetchObject::SetFetchBuffers(const NDSDisplayInfo &currentDispl
void MacOGLClientFetchObject::FetchFromBufferIndex(const u8 index) void MacOGLClientFetchObject::FetchFromBufferIndex(const u8 index)
{ {
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_clientData; MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_clientData;
this->_useCPUFilterPipeline = ([sharedViewObject isCPUFilteringNeeded]) ? true : false; this->_useCPUFilterPipeline = ([sharedViewObject numberViewsUsingCPUFiltering] > 0);
pthread_rwlock_rdlock([sharedViewObject rwlockFramebufferAtIndex:index]); pthread_rwlock_rdlock([sharedViewObject rwlockFramebufferAtIndex:index]);