diff --git a/desmume/src/frontend/cocoa/cocoa_GPU.h b/desmume/src/frontend/cocoa/cocoa_GPU.h index a86c3db45..6f47ddef0 100644 --- a/desmume/src/frontend/cocoa/cocoa_GPU.h +++ b/desmume/src/frontend/cocoa/cocoa_GPU.h @@ -39,7 +39,7 @@ class GPUEventHandlerOSX; typedef std::map DisplayLinksActiveMap; typedef std::map DisplayLinkFlushTimeLimitMap; -@interface MacClientSharedObject : CocoaDSThread +@interface MacClientSharedObject : NSObject { GPUClientFetchObject *GPUFetchObject; pthread_rwlock_t *_rwlockFramebuffer[2]; @@ -50,6 +50,13 @@ typedef std::map DisplayLinkFlushTimeLimitMap; DisplayLinksActiveMap _displayLinksActiveList; DisplayLinkFlushTimeLimitMap _displayLinkFlushTimeList; + + OSSpinLock spinlockFetchSignal; + BOOL _isFetchSignalled; + uint8_t _fetchIndex; + pthread_t _threadFetch; + pthread_cond_t _condSignalFetch; + pthread_mutex_t _mutexFetchExecute; } @property (assign, nonatomic) GPUClientFetchObject *GPUFetchObject; @@ -69,6 +76,9 @@ typedef std::map DisplayLinkFlushTimeLimitMap; - (void) displayLinkStartUsingID:(CGDirectDisplayID)displayID; - (void) displayLinkListUpdate; +- (void) signalFetchAtIndex:(uint8_t)index; +- (void) runFetchLoop; + @end @interface CocoaDSGPU : NSObject @@ -131,6 +141,8 @@ extern "C" { #endif +static void* RunFetchThread(void *arg); + CVReturn MacDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *inNow, const CVTimeStamp *inOutputTime, diff --git a/desmume/src/frontend/cocoa/cocoa_GPU.mm b/desmume/src/frontend/cocoa/cocoa_GPU.mm index f4e206835..a99ceacbc 100644 --- a/desmume/src/frontend/cocoa/cocoa_GPU.mm +++ b/desmume/src/frontend/cocoa/cocoa_GPU.mm @@ -887,6 +887,13 @@ public: _displayLinkFlushTimeList.clear(); [self displayLinkListUpdate]; + spinlockFetchSignal = OS_SPINLOCK_INIT; + _isFetchSignalled = NO; + _fetchIndex = 0; + pthread_cond_init(&_condSignalFetch, NULL); + pthread_create(&_threadFetch, NULL, &RunFetchThread, self); + pthread_mutex_init(&_mutexFetchExecute, NULL); + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(respondToScreenChange:) name:@"NSApplicationDidChangeScreenParametersNotification" @@ -897,6 +904,13 @@ public: - (void)dealloc { + pthread_cancel(_threadFetch); + pthread_join(_threadFetch, NULL); + _threadFetch = NULL; + + pthread_cond_destroy(&_condSignalFetch); + pthread_mutex_destroy(&_mutexFetchExecute); + pthread_mutex_lock(&_mutexFlushVideo); for (DisplayLinksActiveMap::iterator it = _displayLinksActiveList.begin(); it != _displayLinksActiveList.end(); ++it) @@ -914,6 +928,7 @@ public: } pthread_mutex_unlock(&_mutexFlushVideo); + pthread_mutex_destroy(&_mutexFlushVideo); pthread_mutex_t *currentMutex = _mutexOutputList; @@ -931,28 +946,10 @@ public: pthread_rwlock_destroy(_rwlockFramebuffer[0]); pthread_rwlock_destroy(_rwlockFramebuffer[1]); - pthread_mutex_destroy(&_mutexFlushVideo); [super dealloc]; } -- (void)handlePortMessage:(NSPortMessage *)portMessage -{ - NSInteger message = (NSInteger)[portMessage msgid]; - NSArray *messageComponents = [portMessage components]; - - switch (message) - { - case MESSAGE_FETCH_AND_PUSH_VIDEO: - [self handleFetchFromBufferIndexAndPushVideo:[messageComponents objectAtIndex:0]]; - break; - - default: - [super handlePortMessage:portMessage]; - break; - } -} - - (void) handleFetchFromBufferIndexAndPushVideo:(NSData *)indexData { const NSInteger index = *(NSInteger *)[indexData bytes]; @@ -1013,7 +1010,7 @@ public: for (CocoaDSOutput *cdsOutput in _cdsOutputList) { - if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]]) + if ([cdsOutput isKindOfClass:[CocoaDSDisplayVideo class]]) { [CocoaDSUtil messageSendOneWay:[cdsOutput receivePort] msgID:MESSAGE_RECEIVE_GPU_FRAME]; } @@ -1036,9 +1033,9 @@ public: for (CocoaDSOutput *cdsOutput in _cdsOutputList) { - if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]]) + if ([cdsOutput isKindOfClass:[CocoaDSDisplayVideo class]]) { - ClientDisplay3DView *cdv = [(CocoaDSDisplay *)cdsOutput clientDisplayView]; + ClientDisplay3DView *cdv = [(CocoaDSDisplayVideo *)cdsOutput clientDisplayView]; cdv->FinishFrameAtIndex(bufferIndex); } } @@ -1189,6 +1186,36 @@ public: pthread_mutex_unlock(&_mutexFlushVideo); } +- (void) signalFetchAtIndex:(uint8_t)index +{ + pthread_mutex_lock(&_mutexFetchExecute); + + _fetchIndex = index; + _isFetchSignalled = YES; + pthread_cond_signal(&_condSignalFetch); + + pthread_mutex_unlock(&_mutexFetchExecute); +} + +- (void) runFetchLoop +{ + do + { + pthread_mutex_lock(&_mutexFetchExecute); + + while (!_isFetchSignalled) + { + pthread_cond_wait(&_condSignalFetch, &_mutexFetchExecute); + } + _isFetchSignalled = NO; + + GPUFetchObject->FetchFromBufferIndex(_fetchIndex); + [self pushVideoDataToAllDisplayViews]; + + pthread_mutex_unlock(&_mutexFetchExecute); + } while(true); +} + - (void) respondToScreenChange:(NSNotification *)aNotification { [self displayLinkListUpdate]; @@ -1256,7 +1283,7 @@ void GPUEventHandlerOSX::DidFrameEnd(bool isFrameSkipped, const NDSDisplayInfo & #if !defined(PORT_VERSION_OPENEMU) if (!isFrameSkipped) { - [CocoaDSUtil messageSendOneWayWithInteger:[sharedViewObject receivePort] msgID:MESSAGE_FETCH_AND_PUSH_VIDEO integerValue:latestDisplayInfo.bufferIndex]; + [sharedViewObject signalFetchAtIndex:latestDisplayInfo.bufferIndex]; } #endif } @@ -1317,6 +1344,14 @@ CGLContextObj OSXOpenGLRendererContext = NULL; CGLPBufferObj OSXOpenGLRendererPBuffer = NULL; #pragma GCC diagnostic pop +static void* RunFetchThread(void *arg) +{ + MacClientSharedObject *sharedData = (MacClientSharedObject *)arg; + [sharedData runFetchLoop]; + + return NULL; +} + CVReturn MacDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *inNow, const CVTimeStamp *inOutputTime, diff --git a/desmume/src/frontend/cocoa/cocoa_core.mm b/desmume/src/frontend/cocoa/cocoa_core.mm index 96518c5f3..973fda2ad 100644 --- a/desmume/src/frontend/cocoa/cocoa_core.mm +++ b/desmume/src/frontend/cocoa/cocoa_core.mm @@ -35,6 +35,7 @@ #include "../../gdbstub.h" #include "../../slot1.h" #include "../../slot2.h" +#include "../../SPU.h" #undef BOOL // Need to include assert.h this way so that GDB stub will work @@ -1031,6 +1032,7 @@ static void* RunCoreThread(void *arg) // Execute the frame and increment the frame counter. pthread_rwlock_wrlock(¶m->rwlockCoreExecute); NDS_exec(); + SPU_Emulate_user(); execControl->FetchOutputPostNDSExec(); pthread_rwlock_unlock(¶m->rwlockCoreExecute); @@ -1069,7 +1071,7 @@ static void* RunCoreThread(void *arg) [(CocoaDSDisplay *)cdsOutput setNDSFrameInfo:ndsFrameInfo]; } - if ( ![cdsOutput isKindOfClass:[CocoaDSDisplay class]] || (framesToSkip == 0) ) + if ( ![cdsOutput isKindOfClass:[CocoaDSSpeaker class]] && (![cdsOutput isKindOfClass:[CocoaDSDisplay class]] || (framesToSkip == 0)) ) { [cdsOutput doCoreEmuFrame]; } diff --git a/desmume/src/frontend/cocoa/cocoa_output.h b/desmume/src/frontend/cocoa/cocoa_output.h index b2eb1062d..a7e7961cf 100644 --- a/desmume/src/frontend/cocoa/cocoa_output.h +++ b/desmume/src/frontend/cocoa/cocoa_output.h @@ -96,10 +96,6 @@ @interface CocoaDSDisplay : CocoaDSOutput { - ClientDisplay3DView *_cdv; - ClientDisplayViewProperties _intermediateViewProps; - NSSize displaySize; - uint32_t _receivedFrameIndex; uint32_t _currentReceivedFrameIndex; uint32_t _receivedFrameCount; @@ -108,28 +104,21 @@ OSSpinLock spinlockReceivedFrameIndex; OSSpinLock spinlockNDSFrameInfo; - OSSpinLock spinlockViewProperties; } -@property (assign, nonatomic) ClientDisplay3DView *clientDisplayView; -@property (readonly) NSSize displaySize; - -- (void) commitViewProperties:(const ClientDisplayViewProperties &)viewProps; - - (void) handleReceiveGPUFrame; -- (void) handleChangeViewProperties; -- (void) handleRequestScreenshot:(NSData *)fileURLStringData fileTypeData:(NSData *)fileTypeData; -- (void) handleCopyToPasteboard; - (void) takeFrameCount; - (void) setNDSFrameInfo:(const NDSFrameInfo &)ndsFrameInfo; -- (NSImage *) image; -- (NSBitmapImageRep *) bitmapImageRep; @end @interface CocoaDSDisplayVideo : CocoaDSDisplay -{ +{ + ClientDisplay3DView *_cdv; + ClientDisplayViewProperties _intermediateViewProps; + + OSSpinLock spinlockViewProperties; OSSpinLock spinlockIsHUDVisible; OSSpinLock spinlockUseVerticalSync; OSSpinLock spinlockVideoFiltersPreferGPU; @@ -140,6 +129,7 @@ OSSpinLock spinlockDisplayID; } +@property (assign, nonatomic) ClientDisplay3DView *clientDisplayView; @property (readonly, nonatomic) BOOL canFilterOnGPU; @property (readonly, nonatomic) BOOL willFilterOnGPU; @property (assign) BOOL isHUDVisible; @@ -168,12 +158,19 @@ @property (assign) NSInteger outputFilter; @property (assign) NSInteger pixelScaler; +- (void) commitViewProperties:(const ClientDisplayViewProperties &)viewProps; + +- (void) handleChangeViewProperties; - (void) handleReceiveGPUFrame; - (void) handleReloadReprocessRedraw; - (void) handleReprocessRedraw; - (void) handleRedraw; +- (void) handleCopyToPasteboard; +- (void) handleRequestScreenshot:(NSData *)fileURLStringData fileTypeData:(NSData *)fileTypeData; - (void) setScaleFactor:(float)theScaleFactor; - (void) hudUpdate; +- (NSImage *) image; +- (NSBitmapImageRep *) bitmapImageRep; @end diff --git a/desmume/src/frontend/cocoa/cocoa_output.mm b/desmume/src/frontend/cocoa/cocoa_output.mm index 870da4f39..8383b86ba 100644 --- a/desmume/src/frontend/cocoa/cocoa_output.mm +++ b/desmume/src/frontend/cocoa/cocoa_output.mm @@ -501,9 +501,6 @@ @implementation CocoaDSDisplay -@dynamic clientDisplayView; -@dynamic displaySize; - - (id)init { self = [super init]; @@ -514,9 +511,7 @@ spinlockReceivedFrameIndex = OS_SPINLOCK_INIT; spinlockNDSFrameInfo = OS_SPINLOCK_INIT; - spinlockViewProperties = OS_SPINLOCK_INIT; - _cdv = NULL; _ndsFrameInfo.clear(); _receivedFrameIndex = 0; @@ -531,56 +526,15 @@ [super dealloc]; } -- (void) setClientDisplayView:(ClientDisplay3DView *)clientDisplayView -{ - _cdv = clientDisplayView; -} - -- (ClientDisplay3DView *) clientDisplayView -{ - return _cdv; -} - -- (void) commitViewProperties:(const ClientDisplayViewProperties &)viewProps -{ - OSSpinLockLock(&spinlockViewProperties); - _intermediateViewProps = viewProps; - OSSpinLockUnlock(&spinlockViewProperties); - - [self handleChangeViewProperties]; -} - -- (NSSize) displaySize -{ - pthread_rwlock_rdlock(self.rwlockProducer); - NSSize size = NSMakeSize((CGFloat)GPU->GetCustomFramebufferWidth(), (_cdv->GetMode() == ClientDisplayMode_Dual) ? (CGFloat)(GPU->GetCustomFramebufferHeight() * 2): (CGFloat)GPU->GetCustomFramebufferHeight()); - pthread_rwlock_unlock(self.rwlockProducer); - - return size; -} - - (void)handlePortMessage:(NSPortMessage *)portMessage { NSInteger message = (NSInteger)[portMessage msgid]; - NSArray *messageComponents = [portMessage components]; switch (message) { case MESSAGE_RECEIVE_GPU_FRAME: [self handleReceiveGPUFrame]; break; - - case MESSAGE_CHANGE_VIEW_PROPERTIES: - [self handleChangeViewProperties]; - break; - - case MESSAGE_REQUEST_SCREENSHOT: - [self handleRequestScreenshot:[messageComponents objectAtIndex:0] fileTypeData:[messageComponents objectAtIndex:1]]; - break; - - case MESSAGE_COPY_TO_PASTEBOARD: - [self handleCopyToPasteboard]; - break; default: [super handlePortMessage:portMessage]; @@ -595,46 +549,6 @@ OSSpinLockUnlock(&spinlockReceivedFrameIndex); } -- (void) handleChangeViewProperties -{ - OSSpinLockLock(&spinlockViewProperties); - _cdv->CommitViewProperties(_intermediateViewProps); - OSSpinLockUnlock(&spinlockViewProperties); - - _cdv->SetupViewProperties(); -} - -- (void) handleRequestScreenshot:(NSData *)fileURLStringData fileTypeData:(NSData *)fileTypeData -{ - NSString *fileURLString = [[NSString alloc] initWithData:fileURLStringData encoding:NSUTF8StringEncoding]; - NSURL *fileURL = [NSURL URLWithString:fileURLString]; - NSBitmapImageFileType fileType = *(NSBitmapImageFileType *)[fileTypeData bytes]; - - NSDictionary *userInfo = [[NSDictionary alloc] initWithObjectsAndKeys: - fileURL, @"fileURL", - [NSNumber numberWithInteger:(NSInteger)fileType], @"fileType", - [self image], @"screenshotImage", - nil]; - - [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:@"org.desmume.DeSmuME.requestScreenshotDidFinish" object:self userInfo:userInfo]; - [userInfo release]; - - [fileURLString release]; -} - -- (void) handleCopyToPasteboard -{ - NSImage *screenshot = [self image]; - if (screenshot == nil) - { - return; - } - - NSPasteboard *pboard = [NSPasteboard generalPasteboard]; - [pboard declareTypes:[NSArray arrayWithObjects:NSTIFFPboardType, nil] owner:self]; - [pboard setData:[screenshot TIFFRepresentationUsingCompression:NSTIFFCompressionLZW factor:1.0f] forType:NSTIFFPboardType]; -} - - (void) takeFrameCount { OSSpinLockLock(&spinlockReceivedFrameIndex); @@ -650,88 +564,11 @@ OSSpinLockUnlock(&spinlockNDSFrameInfo); } -- (NSImage *) image -{ - NSImage *newImage = [[NSImage alloc] initWithSize:[self displaySize]]; - if (newImage == nil) - { - return newImage; - } - - // Render the frame in an NSBitmapImageRep - NSBitmapImageRep *newImageRep = [self bitmapImageRep]; - if (newImageRep == nil) - { - [newImage release]; - newImage = nil; - return newImage; - } - - // Attach the rendered frame to the NSImageRep - [newImage addRepresentation:newImageRep]; - - return [newImage autorelease]; -} - -- (NSBitmapImageRep *) bitmapImageRep -{ - GPUClientFetchObject &fetchObjMutable = (GPUClientFetchObject &)_cdv->GetFetchObject(); - NDSDisplayInfo &displayInfoMutable = (NDSDisplayInfo &)fetchObjMutable.GetFetchDisplayInfoForBufferIndex(fetchObjMutable.GetLastFetchIndex()); - - NSUInteger w = (NSUInteger)displayInfoMutable.customWidth; - NSUInteger h = (_cdv->GetMode() == ClientDisplayMode_Dual) ? (NSUInteger)(displayInfoMutable.customHeight * 2) : (NSUInteger)displayInfoMutable.customHeight; - - NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL - pixelsWide:w - pixelsHigh:h - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSCalibratedRGBColorSpace - bytesPerRow:w * 4 - bitsPerPixel:32]; - - if(imageRep == nil) - { - return imageRep; - } - - void *displayBuffer = displayInfoMutable.masterCustomBuffer; - uint32_t *bitmapData = (uint32_t *)[imageRep bitmapData]; - - pthread_rwlock_wrlock(self.rwlockProducer); - - GPU->PostprocessDisplay(NDSDisplayID_Main, displayInfoMutable); - GPU->PostprocessDisplay(NDSDisplayID_Touch, displayInfoMutable); - GPU->ResolveDisplayToCustomFramebuffer(NDSDisplayID_Main, displayInfoMutable); - GPU->ResolveDisplayToCustomFramebuffer(NDSDisplayID_Touch, displayInfoMutable); - - if (displayInfoMutable.pixelBytes == 2) - { - ColorspaceConvertBuffer555To8888Opaque((u16 *)displayBuffer, bitmapData, (w * h)); - } - else if (displayInfoMutable.pixelBytes == 4) - { - memcpy(bitmapData, displayBuffer, w * h * sizeof(uint32_t)); - } - - pthread_rwlock_unlock(self.rwlockProducer); - -#ifdef MSB_FIRST - for (size_t i = 0; i < w * h; i++) - { - bitmapData[i] = LE_TO_LOCAL_32(bitmapData[i]); - } -#endif - - return [imageRep autorelease]; -} - @end @implementation CocoaDSDisplayVideo +@dynamic clientDisplayView; @dynamic canFilterOnGPU; @dynamic willFilterOnGPU; @dynamic isHUDVisible; @@ -768,6 +605,9 @@ return self; } + _cdv = NULL; + + spinlockViewProperties = OS_SPINLOCK_INIT; spinlockIsHUDVisible = OS_SPINLOCK_INIT; spinlockUseVerticalSync = OS_SPINLOCK_INIT; spinlockVideoFiltersPreferGPU = OS_SPINLOCK_INIT; @@ -785,6 +625,25 @@ [super dealloc]; } +- (void) setClientDisplayView:(ClientDisplay3DView *)clientDisplayView +{ + _cdv = clientDisplayView; +} + +- (ClientDisplay3DView *) clientDisplayView +{ + return _cdv; +} + +- (void) commitViewProperties:(const ClientDisplayViewProperties &)viewProps +{ + OSSpinLockLock(&spinlockViewProperties); + _intermediateViewProps = viewProps; + OSSpinLockUnlock(&spinlockViewProperties); + + [self handleChangeViewProperties]; +} + - (BOOL) canFilterOnGPU { return (_cdv->CanFilterOnGPU()) ? YES : NO; @@ -1198,9 +1057,14 @@ - (void)handlePortMessage:(NSPortMessage *)portMessage { NSInteger message = (NSInteger)[portMessage msgid]; + NSArray *messageComponents = [portMessage components]; switch (message) { + case MESSAGE_CHANGE_VIEW_PROPERTIES: + [self handleChangeViewProperties]; + break; + case MESSAGE_RELOAD_REPROCESS_REDRAW: [self handleReloadReprocessRedraw]; break; @@ -1213,6 +1077,14 @@ [self handleRedraw]; break; + case MESSAGE_COPY_TO_PASTEBOARD: + [self handleCopyToPasteboard]; + break; + + case MESSAGE_REQUEST_SCREENSHOT: + [self handleRequestScreenshot:[messageComponents objectAtIndex:0] fileTypeData:[messageComponents objectAtIndex:1]]; + break; + default: [super handlePortMessage:portMessage]; break; @@ -1226,6 +1098,15 @@ _cdv->HandleEmulatorFrameEndEvent(); } +- (void) handleChangeViewProperties +{ + OSSpinLockLock(&spinlockViewProperties); + _cdv->CommitViewProperties(_intermediateViewProps); + OSSpinLockUnlock(&spinlockViewProperties); + + _cdv->SetupViewProperties(); +} + - (void) handleReceiveGPUFrame { [super handleReceiveGPUFrame]; @@ -1257,6 +1138,37 @@ _cdv->UpdateView(); } +- (void) handleCopyToPasteboard +{ + NSImage *screenshot = [self image]; + if (screenshot == nil) + { + return; + } + + NSPasteboard *pboard = [NSPasteboard generalPasteboard]; + [pboard declareTypes:[NSArray arrayWithObjects:NSTIFFPboardType, nil] owner:self]; + [pboard setData:[screenshot TIFFRepresentationUsingCompression:NSTIFFCompressionLZW factor:1.0f] forType:NSTIFFPboardType]; +} + +- (void) handleRequestScreenshot:(NSData *)fileURLStringData fileTypeData:(NSData *)fileTypeData +{ + NSString *fileURLString = [[NSString alloc] initWithData:fileURLStringData encoding:NSUTF8StringEncoding]; + NSURL *fileURL = [NSURL URLWithString:fileURLString]; + NSBitmapImageFileType fileType = *(NSBitmapImageFileType *)[fileTypeData bytes]; + + NSDictionary *userInfo = [[NSDictionary alloc] initWithObjectsAndKeys: + fileURL, @"fileURL", + [NSNumber numberWithInteger:(NSInteger)fileType], @"fileType", + [self image], @"screenshotImage", + nil]; + + [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:@"org.desmume.DeSmuME.requestScreenshotDidFinish" object:self userInfo:userInfo]; + [userInfo release]; + + [fileURLString release]; +} + - (void) setScaleFactor:(float)theScaleFactor { OSSpinLockLock(&spinlockIsHUDVisible); @@ -1276,4 +1188,86 @@ OSSpinLockUnlock(&spinlockNDSFrameInfo); } +- (NSImage *) image +{ + pthread_rwlock_rdlock(self.rwlockProducer); + NSSize displaySize = NSMakeSize((CGFloat)GPU->GetCustomFramebufferWidth(), (_cdv->GetMode() == ClientDisplayMode_Dual) ? (CGFloat)(GPU->GetCustomFramebufferHeight() * 2): (CGFloat)GPU->GetCustomFramebufferHeight()); + pthread_rwlock_unlock(self.rwlockProducer); + + NSImage *newImage = [[NSImage alloc] initWithSize:displaySize]; + if (newImage == nil) + { + return newImage; + } + + // Render the frame in an NSBitmapImageRep + NSBitmapImageRep *newImageRep = [self bitmapImageRep]; + if (newImageRep == nil) + { + [newImage release]; + newImage = nil; + return newImage; + } + + // Attach the rendered frame to the NSImageRep + [newImage addRepresentation:newImageRep]; + + return [newImage autorelease]; +} + +- (NSBitmapImageRep *) bitmapImageRep +{ + GPUClientFetchObject &fetchObjMutable = (GPUClientFetchObject &)_cdv->GetFetchObject(); + NDSDisplayInfo &displayInfoMutable = (NDSDisplayInfo &)fetchObjMutable.GetFetchDisplayInfoForBufferIndex(fetchObjMutable.GetLastFetchIndex()); + + NSUInteger w = (NSUInteger)displayInfoMutable.customWidth; + NSUInteger h = (_cdv->GetMode() == ClientDisplayMode_Dual) ? (NSUInteger)(displayInfoMutable.customHeight * 2) : (NSUInteger)displayInfoMutable.customHeight; + + NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL + pixelsWide:w + pixelsHigh:h + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSCalibratedRGBColorSpace + bytesPerRow:w * 4 + bitsPerPixel:32]; + + if (imageRep == nil) + { + return imageRep; + } + + void *displayBuffer = displayInfoMutable.masterCustomBuffer; + uint32_t *bitmapData = (uint32_t *)[imageRep bitmapData]; + + pthread_rwlock_wrlock(self.rwlockProducer); + + GPU->PostprocessDisplay(NDSDisplayID_Main, displayInfoMutable); + GPU->PostprocessDisplay(NDSDisplayID_Touch, displayInfoMutable); + GPU->ResolveDisplayToCustomFramebuffer(NDSDisplayID_Main, displayInfoMutable); + GPU->ResolveDisplayToCustomFramebuffer(NDSDisplayID_Touch, displayInfoMutable); + + if (displayInfoMutable.pixelBytes == 2) + { + ColorspaceConvertBuffer555To8888Opaque((u16 *)displayBuffer, bitmapData, (w * h)); + } + else if (displayInfoMutable.pixelBytes == 4) + { + memcpy(bitmapData, displayBuffer, w * h * sizeof(uint32_t)); + } + + pthread_rwlock_unlock(self.rwlockProducer); + +#ifdef MSB_FIRST + for (size_t i = 0; i < w * h; i++) + { + bitmapData[i] = LE_TO_LOCAL_32(bitmapData[i]); + } +#endif + + return [imageRep autorelease]; +} + @end diff --git a/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm b/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm index fbe146b0a..c23864468 100644 --- a/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm +++ b/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm @@ -1323,7 +1323,7 @@ static std::unordered_map _screenMap; // // Set up the video output thread. CocoaDSDisplayVideo *newDisplayOutput = [[[CocoaDSDisplayVideo alloc] init] autorelease]; - [newDisplayOutput setClientDisplayView:[view clientDisplay3DView]]; + [newDisplayOutput setClientDisplayView:[newView clientDisplay3DView]]; ClientDisplayView *cdv = [newDisplayOutput clientDisplayView]; NSString *fontPath = [[NSBundle mainBundle] pathForResource:@"SourceSansPro-Bold" ofType:@"otf"]; diff --git a/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm b/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm index 7c3351768..c655804ce 100644 --- a/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm +++ b/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm @@ -810,32 +810,32 @@ { const float vol = [self currentVolumeValue]; [self setCurrentVolumeValue:vol]; - [CocoaDSUtil messageSendOneWayWithFloat:[cdsSpeaker receivePort] msgID:MESSAGE_SET_VOLUME floatValue:vol]; + [[self cdsSpeaker] setVolume:vol]; } - (IBAction) changeAudioEngine:(id)sender { - [CocoaDSUtil messageSendOneWayWithInteger:[cdsSpeaker receivePort] msgID:MESSAGE_SET_AUDIO_PROCESS_METHOD integerValue:[CocoaDSUtil getIBActionSenderTag:sender]]; + [[self cdsSpeaker] setAudioOutputEngine:[CocoaDSUtil getIBActionSenderTag:sender]]; } - (IBAction) changeSpuAdvancedLogic:(id)sender { - [CocoaDSUtil messageSendOneWayWithBool:[cdsSpeaker receivePort] msgID:MESSAGE_SET_SPU_ADVANCED_LOGIC boolValue:[CocoaDSUtil getIBActionSenderButtonStateBool:sender]]; + [[self cdsSpeaker] setSpuAdvancedLogic:[CocoaDSUtil getIBActionSenderButtonStateBool:sender]]; } - (IBAction) changeSpuInterpolationMode:(id)sender { - [CocoaDSUtil messageSendOneWayWithInteger:[cdsSpeaker receivePort] msgID:MESSAGE_SET_SPU_INTERPOLATION_MODE integerValue:[CocoaDSUtil getIBActionSenderTag:sender]]; + [[self cdsSpeaker] setSpuInterpolationMode:[CocoaDSUtil getIBActionSenderTag:sender]]; } - (IBAction) changeSpuSyncMode:(id)sender { - [CocoaDSUtil messageSendOneWayWithInteger:[cdsSpeaker receivePort] msgID:MESSAGE_SET_SPU_SYNC_MODE integerValue:[CocoaDSUtil getIBActionSenderTag:sender]]; + [[self cdsSpeaker] setSpuSyncMode:[CocoaDSUtil getIBActionSenderTag:sender]]; } - (IBAction) changeSpuSyncMethod:(id)sender { - [CocoaDSUtil messageSendOneWayWithInteger:[cdsSpeaker receivePort] msgID:MESSAGE_SET_SPU_SYNC_METHOD integerValue:[CocoaDSUtil getIBActionSenderTag:sender]]; + [[self cdsSpeaker] setSpuSyncMethod:[CocoaDSUtil getIBActionSenderTag:sender]]; } - (IBAction) toggleAllDisplays:(id)sender @@ -1533,7 +1533,7 @@ } [self setCurrentVolumeValue:vol]; - [CocoaDSUtil messageSendOneWayWithFloat:[cdsSpeaker receivePort] msgID:MESSAGE_SET_VOLUME floatValue:vol]; + [[self cdsSpeaker] setVolume:vol]; } - (void) cmdToggleGPUState:(NSValue *)cmdAttrValue diff --git a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm index d0c2e9733..db45560c9 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm +++ b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm @@ -1127,7 +1127,7 @@ { const VideoFilterAttributes vfAttr = VideoFilter::GetAttributesByID(filterID); - id cb = [[sharedData commandQueue] commandBufferWithUnretainedReferences]; + id cb = [self newCommandBuffer]; id dummyEncoder = [cb blitCommandEncoder]; [dummyEncoder endEncoding]; [cb commit]; @@ -1145,7 +1145,7 @@ options:MTLResourceStorageModeManaged deallocator:nil]]; - cb = [[sharedData commandQueue] commandBufferWithUnretainedReferences]; + cb = [self newCommandBuffer]; dummyEncoder = [cb blitCommandEncoder]; [dummyEncoder endEncoding]; [cb commit]; @@ -1285,7 +1285,7 @@ VideoFilter *vfMain = _cdv->GetPixelScalerObject(NDSDisplayID_Main); VideoFilter *vfTouch = _cdv->GetPixelScalerObject(NDSDisplayID_Touch); - id cb = [[sharedData commandQueue] commandBufferWithUnretainedReferences]; + id cb = [self newCommandBuffer]; id cce = [cb computeCommandEncoder]; // Run the video source filters and the pixel scalers @@ -1591,7 +1591,7 @@ // Now that everything is set up, go ahead and draw everything. id layerDrawable = [self nextDrawable]; [colorAttachment0Desc setTexture:[layerDrawable texture]]; - id cb = [[sharedData commandQueue] commandBufferWithUnretainedReferences]; + id cb = [self newCommandBuffer]; id ce = [cb renderCommandEncoderWithDescriptor:_outputRenderPassDesc]; if (_needEncodeViewport) @@ -1804,7 +1804,10 @@ void MacMetalFetchObject::FetchFromBufferIndex(const u8 index) MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_clientData; this->_useDirectToCPUFilterPipeline = ([sharedViewObject numberViewsUsingDirectToCPUFiltering] > 0); - [(MetalDisplayViewSharedData *)this->_clientData fetchFromBufferIndex:index]; + @autoreleasepool + { + [(MetalDisplayViewSharedData *)this->_clientData fetchFromBufferIndex:index]; + } } void MacMetalFetchObject::_FetchNativeDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex) diff --git a/desmume/src/frontend/cocoa/userinterface/appDelegate.mm b/desmume/src/frontend/cocoa/userinterface/appDelegate.mm index f706c3706..2f751d227 100644 --- a/desmume/src/frontend/cocoa/userinterface/appDelegate.mm +++ b/desmume/src/frontend/cocoa/userinterface/appDelegate.mm @@ -183,13 +183,6 @@ // Init the DS emulation core. CocoaDSCore *newCore = [[[CocoaDSCore alloc] init] autorelease]; - MacClientSharedObject *sharedViewObject = [[newCore cdsGPU] sharedData]; - - [NSThread detachNewThreadSelector:@selector(runThread:) toTarget:sharedViewObject withObject:nil]; - while ([sharedViewObject thread] == nil) - { - [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]]; - } // Init the DS controller. [[newCore cdsController] setDelegate:emuControl]; @@ -205,13 +198,6 @@ [slot2WindowDelegate setHidManager:[inputManager hidManager]]; [slot2WindowDelegate setAutoSelectedDeviceText:[[slot2WindowDelegate deviceManager] autoSelectedDeviceName]]; - // Start up the threads for our outputs. - [NSThread detachNewThreadSelector:@selector(runThread:) toTarget:newSpeaker withObject:nil]; - while ([newSpeaker thread] == nil) - { - [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]]; - } - // Set up all the object controllers. [cdsCoreController setContent:newCore]; [romInfoPanelController setContent:[CocoaDSRom romNotLoadedBindings]];