Cocoa Port: Fix a crash and a potential deadlock that may occur when responding to host display changes. (Regression from commit 4957d7b.)

This commit is contained in:
rogerman 2017-10-03 23:49:18 -07:00
parent addb17b660
commit 6ca2dbe6d0
4 changed files with 32 additions and 47 deletions

View File

@ -44,7 +44,7 @@ typedef std::map<CGDirectDisplayID, int64_t> DisplayLinkFlushTimeLimitMap;
GPUClientFetchObject *GPUFetchObject; GPUClientFetchObject *GPUFetchObject;
pthread_rwlock_t *_rwlockFramebuffer[2]; pthread_rwlock_t *_rwlockFramebuffer[2];
pthread_mutex_t *_mutexOutputList; pthread_mutex_t *_mutexOutputList;
pthread_mutex_t _mutexFlushVideo; pthread_mutex_t _mutexDisplayLinkLists;
NSMutableArray *_cdsOutputList; NSMutableArray *_cdsOutputList;
volatile int32_t numberViewsUsingDirectToCPUFiltering; volatile int32_t numberViewsUsingDirectToCPUFiltering;
@ -70,7 +70,6 @@ typedef std::map<CGDirectDisplayID, int64_t> DisplayLinkFlushTimeLimitMap;
- (void) finishAllDisplayViewsAtIndex:(const u8)bufferIndex; - (void) finishAllDisplayViewsAtIndex:(const u8)bufferIndex;
- (void) flushAllDisplaysOnDisplayLink:(CVDisplayLinkRef)displayLink timeStamp:(const CVTimeStamp *)timeStamp; - (void) flushAllDisplaysOnDisplayLink:(CVDisplayLinkRef)displayLink timeStamp:(const CVTimeStamp *)timeStamp;
- (BOOL) isDisplayLinkRunningUsingID:(CGDirectDisplayID)displayID;
- (void) displayLinkStartUsingID:(CGDirectDisplayID)displayID; - (void) displayLinkStartUsingID:(CGDirectDisplayID)displayID;
- (void) displayLinkListUpdate; - (void) displayLinkListUpdate;

View File

@ -876,7 +876,7 @@ public:
pthread_rwlock_init(_rwlockFramebuffer[0], NULL); pthread_rwlock_init(_rwlockFramebuffer[0], NULL);
pthread_rwlock_init(_rwlockFramebuffer[1], NULL); pthread_rwlock_init(_rwlockFramebuffer[1], NULL);
pthread_mutex_init(&_mutexFlushVideo, NULL); pthread_mutex_init(&_mutexDisplayLinkLists, NULL);
GPUFetchObject = nil; GPUFetchObject = nil;
_mutexOutputList = NULL; _mutexOutputList = NULL;
@ -911,24 +911,27 @@ public:
pthread_cond_destroy(&_condSignalFetch); pthread_cond_destroy(&_condSignalFetch);
pthread_mutex_destroy(&_mutexFetchExecute); pthread_mutex_destroy(&_mutexFetchExecute);
pthread_mutex_lock(&_mutexFlushVideo); pthread_mutex_lock(&_mutexDisplayLinkLists);
for (DisplayLinksActiveMap::iterator it = _displayLinksActiveList.begin(); it != _displayLinksActiveList.end(); ++it) while (_displayLinksActiveList.size() > 0)
{ {
DisplayLinksActiveMap::iterator it = _displayLinksActiveList.begin();
CGDirectDisplayID displayID = it->first; CGDirectDisplayID displayID = it->first;
CVDisplayLinkRef displayLinkRef = it->second; CVDisplayLinkRef displayLinkRef = it->second;
if (CVDisplayLinkIsRunning(displayLinkRef)) if (CVDisplayLinkIsRunning(displayLinkRef))
{ {
CVDisplayLinkStop(displayLinkRef); CVDisplayLinkStop(displayLinkRef);
CVDisplayLinkRelease(displayLinkRef);
} }
CVDisplayLinkRelease(displayLinkRef);
_displayLinksActiveList.erase(displayID); _displayLinksActiveList.erase(displayID);
_displayLinkFlushTimeList.erase(displayID); _displayLinkFlushTimeList.erase(displayID);
} }
pthread_mutex_unlock(&_mutexFlushVideo); pthread_mutex_unlock(&_mutexDisplayLinkLists);
pthread_mutex_destroy(&_mutexFlushVideo); pthread_mutex_destroy(&_mutexDisplayLinkLists);
pthread_mutex_t *currentMutex = _mutexOutputList; pthread_mutex_t *currentMutex = _mutexOutputList;
@ -1066,8 +1069,6 @@ public:
pthread_mutex_unlock(currentMutex); pthread_mutex_unlock(currentMutex);
} }
pthread_mutex_lock(&_mutexFlushVideo);
if (didFlushOccur) if (didFlushOccur)
{ {
// Set the new time limit to 8 seconds after the current time. // Set the new time limit to 8 seconds after the current time.
@ -1077,45 +1078,25 @@ public:
{ {
CVDisplayLinkStop(displayLink); CVDisplayLinkStop(displayLink);
} }
pthread_mutex_unlock(&_mutexFlushVideo);
}
- (BOOL) isDisplayLinkRunningUsingID:(CGDirectDisplayID)displayID
{
CVDisplayLinkRef displayLink = NULL;
pthread_mutex_lock(&_mutexFlushVideo);
if (_displayLinksActiveList.find(displayID) != _displayLinksActiveList.end())
{
displayLink = _displayLinksActiveList[displayID];
}
const BOOL isRunning = ( (displayLink != NULL) && CVDisplayLinkIsRunning(displayLink) ) ? YES : NO;
pthread_mutex_unlock(&_mutexFlushVideo);
return isRunning;
} }
- (void) displayLinkStartUsingID:(CGDirectDisplayID)displayID - (void) displayLinkStartUsingID:(CGDirectDisplayID)displayID
{ {
CVDisplayLinkRef displayLink = NULL; CVDisplayLinkRef displayLink = NULL;
pthread_mutex_lock(&_mutexFlushVideo); pthread_mutex_lock(&_mutexDisplayLinkLists);
if (_displayLinksActiveList.find(displayID) != _displayLinksActiveList.end()) if (_displayLinksActiveList.find(displayID) != _displayLinksActiveList.end())
{ {
displayLink = _displayLinksActiveList[displayID]; displayLink = _displayLinksActiveList[displayID];
} }
if (displayLink != NULL) if ( (displayLink != NULL) && !CVDisplayLinkIsRunning(displayLink) )
{ {
CVDisplayLinkStart(displayLink); CVDisplayLinkStart(displayLink);
} }
pthread_mutex_unlock(&_mutexFlushVideo); pthread_mutex_unlock(&_mutexDisplayLinkLists);
} }
- (void) displayLinkListUpdate - (void) displayLinkListUpdate
@ -1124,7 +1105,7 @@ public:
NSArray *screenList = [NSScreen screens]; NSArray *screenList = [NSScreen screens];
std::set<CGDirectDisplayID> screenActiveDisplayIDsList; std::set<CGDirectDisplayID> screenActiveDisplayIDsList;
pthread_mutex_lock(&_mutexFlushVideo); pthread_mutex_lock(&_mutexDisplayLinkLists);
// Add new CGDirectDisplayIDs for new screens // Add new CGDirectDisplayIDs for new screens
for (size_t i = 0; i < [screenList count]; i++) for (size_t i = 0; i < [screenList count]; i++)
@ -1152,7 +1133,7 @@ public:
} }
// Remove old CGDirectDisplayIDs for screens that no longer exist // Remove old CGDirectDisplayIDs for screens that no longer exist
for (DisplayLinksActiveMap::iterator it = _displayLinksActiveList.begin(); it != _displayLinksActiveList.end(); ++it) for (DisplayLinksActiveMap::iterator it = _displayLinksActiveList.begin(); it != _displayLinksActiveList.end(); )
{ {
CGDirectDisplayID displayID = it->first; CGDirectDisplayID displayID = it->first;
CVDisplayLinkRef displayLinkRef = it->second; CVDisplayLinkRef displayLinkRef = it->second;
@ -1162,15 +1143,28 @@ public:
if (CVDisplayLinkIsRunning(displayLinkRef)) if (CVDisplayLinkIsRunning(displayLinkRef))
{ {
CVDisplayLinkStop(displayLinkRef); CVDisplayLinkStop(displayLinkRef);
CVDisplayLinkRelease(displayLinkRef);
} }
CVDisplayLinkRelease(displayLinkRef);
_displayLinksActiveList.erase(displayID); _displayLinksActiveList.erase(displayID);
_displayLinkFlushTimeList.erase(displayID); _displayLinkFlushTimeList.erase(displayID);
if (_displayLinksActiveList.empty())
{
break;
}
else
{
it = _displayLinksActiveList.begin();
continue;
}
} }
++it;
} }
pthread_mutex_unlock(&_mutexFlushVideo); pthread_mutex_unlock(&_mutexDisplayLinkLists);
} }
- (void) signalFetchAtIndex:(uint8_t)index - (void) signalFetchAtIndex:(uint8_t)index

View File

@ -2200,11 +2200,7 @@ void MacMetalDisplayView::SetAllowViewFlushes(bool allowFlushes)
{ {
CGDirectDisplayID displayID = (CGDirectDisplayID)this->GetDisplayViewID(); CGDirectDisplayID displayID = (CGDirectDisplayID)this->GetDisplayViewID();
MacClientSharedObject *sharedData = ((MacMetalDisplayPresenter *)this->_presenter)->GetSharedData(); MacClientSharedObject *sharedData = ((MacMetalDisplayPresenter *)this->_presenter)->GetSharedData();
[sharedData displayLinkStartUsingID:displayID];
if (![sharedData isDisplayLinkRunningUsingID:displayID])
{
[sharedData displayLinkStartUsingID:displayID];
}
} }
void MacMetalDisplayView::FlushView() void MacMetalDisplayView::FlushView()

View File

@ -485,11 +485,7 @@ void MacOGLDisplayView::SetAllowViewFlushes(bool allowFlushes)
{ {
CGDirectDisplayID displayID = (CGDirectDisplayID)this->GetDisplayViewID(); CGDirectDisplayID displayID = (CGDirectDisplayID)this->GetDisplayViewID();
MacClientSharedObject *sharedData = ((MacOGLDisplayPresenter *)this->_presenter)->GetSharedData(); MacClientSharedObject *sharedData = ((MacOGLDisplayPresenter *)this->_presenter)->GetSharedData();
[sharedData displayLinkStartUsingID:displayID];
if (![sharedData isDisplayLinkRunningUsingID:displayID])
{
[sharedData displayLinkStartUsingID:displayID];
}
} }
void MacOGLDisplayView::SetUseVerticalSync(const bool useVerticalSync) void MacOGLDisplayView::SetUseVerticalSync(const bool useVerticalSync)