Cocoa Port: Huge refactor to ClientDisplayView, now supporting the use of shared fetch objects and shared client objects in order to lower memory usage and CPU/GPU usage when many display views are running at the same time.

- OpenGL display views now use a shared fetch object to fetch the emulated GPU framebuffers and store them in shared textures within a shared context. In conjunction with the new double-buffering support from the last commit, this eliminates the copying between the framebuffers and each display view.
- OpenGL display views now use shared HQnx LUT textures, rather than having to initialize and maintain a copy of the LUT textures for each display view.
- OpenGL display views no longer perform any rendering while their associated NSView is hidden, improving the performance of creating new display views.
- OpenGL display views can now DMA directly from pinned-memory both custom-sized framebuffers and CPU-pixel-scaled native-sized framebuffers at the same time.
This commit is contained in:
rogerman 2017-02-01 15:56:54 -08:00
parent 08b8a1a62c
commit aff2d07146
15 changed files with 1057 additions and 756 deletions

View File

@ -21,6 +21,8 @@
ClientDisplayView::ClientDisplayView()
{
_fetchObject = NULL;
ClientDisplayViewProperties defaultProperty;
defaultProperty.normalWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH;
defaultProperty.normalHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2.0;
@ -80,6 +82,7 @@ void ClientDisplayView::__InstanceInit(const ClientDisplayViewProperties &props)
memset(&_emuFrameInfo, 0, sizeof(_emuFrameInfo));
_hudString = "\x01"; // Char value 0x01 will represent the "text box" character, which will always be first in the string.
_hudNeedsUpdate = true;
_allowViewUpdates = true;
FT_Error error = FT_Init_FreeType(&_ftLibrary);
if (error)
@ -481,14 +484,24 @@ void ClientDisplayView::ClearHUDNeedsUpdate()
}
// NDS GPU Interface
void ClientDisplayView::_FetchNativeDisplayByID(const NDSDisplayID displayID)
const GPUClientFetchObject& ClientDisplayView::GetFetchObject() const
{
// Do nothing. This is implementation dependent.
return *this->_fetchObject;
}
void ClientDisplayView::_FetchCustomDisplayByID(const NDSDisplayID displayID)
void ClientDisplayView::SetFetchObject(GPUClientFetchObject *fetchObject)
{
// Do nothing. This is implementation dependent.
this->_fetchObject = fetchObject;
}
bool ClientDisplayView::GetAllowViewUpdates() const
{
return this->_allowViewUpdates;
}
void ClientDisplayView::SetAllowViewUpdates(const bool allowUpdates)
{
this->_allowViewUpdates = allowUpdates;
}
void ClientDisplayView::_LoadNativeDisplayByID(const NDSDisplayID displayID)
@ -501,38 +514,10 @@ void ClientDisplayView::_LoadCustomDisplayByID(const NDSDisplayID displayID)
// Do nothing. This is implementation dependent.
}
void ClientDisplayView::FetchDisplays()
{
const bool loadMainScreen = this->_emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Main] && ((this->_renderProperty.mode == ClientDisplayMode_Main) || (this->_renderProperty.mode == ClientDisplayMode_Dual));
const bool loadTouchScreen = this->_emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Touch] && ((this->_renderProperty.mode == ClientDisplayMode_Touch) || (this->_renderProperty.mode == ClientDisplayMode_Dual));
if (loadMainScreen)
{
if (!this->_emuDisplayInfo.didPerformCustomRender[NDSDisplayID_Main])
{
this->_FetchNativeDisplayByID(NDSDisplayID_Main);
}
else
{
this->_FetchCustomDisplayByID(NDSDisplayID_Main);
}
}
if (loadTouchScreen)
{
if (!this->_emuDisplayInfo.didPerformCustomRender[NDSDisplayID_Touch])
{
this->_FetchNativeDisplayByID(NDSDisplayID_Touch);
}
else
{
this->_FetchCustomDisplayByID(NDSDisplayID_Touch);
}
}
}
void ClientDisplayView::LoadDisplays()
{
this->_emuDisplayInfo = this->_fetchObject->GetFetchDisplayInfoForBufferIndex(this->_fetchObject->GetLastFetchIndex());
const bool loadMainScreen = this->_emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Main] && ((this->_renderProperty.mode == ClientDisplayMode_Main) || (this->_renderProperty.mode == ClientDisplayMode_Dual));
const bool loadTouchScreen = this->_emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Touch] && ((this->_renderProperty.mode == ClientDisplayMode_Touch) || (this->_renderProperty.mode == ClientDisplayMode_Dual));
@ -987,16 +972,6 @@ void ClientDisplay3DView::SetSourceDeposterize(bool useDeposterize)
this->_useDeposterize = (this->_canFilterOnGPU) ? useDeposterize : false;
}
void ClientDisplay3DView::SetVideoBuffers(const uint32_t colorFormat,
const void *videoBufferHead,
const void *nativeBuffer0,
const void *nativeBuffer1,
const void *customBuffer0, const size_t customWidth0, const size_t customHeight0,
const void *customBuffer1, const size_t customWidth1, const size_t customHeight1)
{
// Do nothing. This is implementation dependent.
}
void ClientDisplay3DView::SetHUDVertices(float viewportWidth, float viewportHeight, float *vtxBufferPtr)
{
const char *cString = this->_hudString.c_str();

View File

@ -114,6 +114,7 @@ protected:
ClientDisplayViewProperties _renderProperty;
ClientDisplayViewProperties _stagedProperty;
InitialTouchPressMap *_initialTouchInMajorDisplay;
GPUClientFetchObject *_fetchObject;
bool _useDeposterize;
VideoFilterTypeID _pixelScaler;
@ -135,6 +136,7 @@ protected:
NDSFrameInfo _emuFrameInfo;
std::string _hudString;
bool _hudNeedsUpdate;
bool _allowViewUpdates;
FT_Library _ftLibrary;
const char *_lastFontFilePath;
@ -151,8 +153,6 @@ protected:
virtual void _UpdateClientSize();
virtual void _UpdateViewScale();
virtual void _FetchNativeDisplayByID(const NDSDisplayID displayID);
virtual void _FetchCustomDisplayByID(const NDSDisplayID displayID);
virtual void _LoadNativeDisplayByID(const NDSDisplayID displayID);
virtual void _LoadCustomDisplayByID(const NDSDisplayID displayID);
@ -218,11 +218,16 @@ public:
void ClearHUDNeedsUpdate();
// Client view interface
virtual void FetchDisplays();
const GPUClientFetchObject& GetFetchObject() const;
void SetFetchObject(GPUClientFetchObject *fetchObject);
bool GetAllowViewUpdates() const;
void SetAllowViewUpdates(const bool allowUpdates);
virtual void LoadDisplays();
virtual void ProcessDisplays();
virtual void UpdateView();
virtual void FrameFinish() = 0;
virtual void FinishFrameAtIndex(const u8 bufferIndex) = 0;
// Emulator interface
const NDSDisplayInfo& GetEmuDisplayInfo() const;
@ -269,13 +274,6 @@ public:
virtual void SetSourceDeposterize(const bool useDeposterize);
virtual void SetVideoBuffers(const uint32_t colorFormat,
const void *videoBufferHead,
const void *nativeBuffer0,
const void *nativeBuffer1,
const void *customBuffer0, const size_t customWidth0, const size_t customHeight0,
const void *customBuffer1, const size_t customWidth1, const size_t customHeight1);
void SetHUDVertices(float viewportWidth, float viewportHeight, float *vtxBufferPtr);
void SetHUDTextureCoordinates(float *texCoordBufferPtr);
void SetScreenVertices(float *vtxBufferPtr);

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,7 @@
#include <set>
#include <string>
#include <pthread.h>
#include "../../filter/videofilter.h"
#include "ClientDisplayView.h"
@ -217,8 +218,6 @@ protected:
GLint _uniformFinalOutputScalar;
GLint _uniformFinalOutputViewSize;
void UploadHQnxLUTs();
void UploadVerticesOGL();
void UploadTexCoordsOGL();
void UploadTransformationOGL();
@ -270,7 +269,7 @@ public:
virtual void SetVisibility(const bool visibleState);
virtual void RenderOGL() = 0;
virtual void FinishOGL() {};
virtual void FinishOGL(const u8 bufferIndex) {};
};
class OGLHUDLayer : public OGLVideoLayer
@ -301,33 +300,19 @@ class OGLDisplayLayer : public OGLVideoLayer
protected:
bool _useShader150;
ShaderSupportTier _shaderSupport;
GLboolean _useClientStorage;
OGLShaderProgram *_finalOutputProgram;
OGLFilter *_filterDeposterize[2];
OGLFilter *_shaderFilter[2];
GLint _displayTexFilter[2];
GLuint _texVideoInputDataNativeID[2];
GLuint _texVideoInputDataCustomID[2];
GLuint _texVideoOutputID[2];
GLenum _videoColorFormat;
const void *_videoSrcBufferHead;
void *_videoSrcNativeBuffer[2];
void *_videoSrcCustomBuffer[2];
size_t _videoSrcBufferSize;
uint32_t *_vfMasterDstBuffer;
size_t _vfMasterDstBufferSize;
VideoFilter *_vf[2];
GLuint _texCPUFilterDstID[2];
GLuint _texLQ2xLUT;
GLuint _texHQ2xLUT;
GLuint _texHQ3xLUT;
GLuint _texHQ4xLUT;
GLuint _vaoMainStatesID;
GLuint _vboVertexID;
GLuint _vboTexCoordID;
@ -336,9 +321,6 @@ protected:
GLint _uniformFinalOutputScalar;
GLint _uniformFinalOutputViewSize;
void _UploadHQnxLUTs();
void _DetermineTextureStorageHints(GLint &videoSrcTexStorageHint, GLint &cpuFilterTexStorageHint);
void _ResizeCPUPixelScalerOGL(const size_t srcWidthMain, const size_t srcHeightMain, const size_t srcWidthTouch, const size_t srcHeightTouch, const size_t scaleMultiply, const size_t scaleDivide);
void _UpdateRotationScaleOGL();
@ -351,30 +333,60 @@ public:
OGLDisplayLayer(OGLVideoOutput *oglVO);
virtual ~OGLDisplayLayer();
void SetVideoBuffers(const uint32_t colorFormat,
const void *videoBufferHead,
const void *nativeBuffer0,
const void *nativeBuffer1,
const void *customBuffer0, const size_t customWidth0, const size_t customHeight0,
const void *customBuffer1, const size_t customWidth1, const size_t customHeight1);
void SetNeedsUpdateRotationScale();
void SetFiltersPreferGPUOGL();
bool CanUseShaderBasedFilters();
OutputFilterTypeID SetOutputFilterOGL(const OutputFilterTypeID filterID);
bool SetGPUPixelScalerOGL(const VideoFilterTypeID filterID);
void SetCPUPixelScalerOGL(const VideoFilterTypeID filterID);
void CopyNativeDisplayByID_OGL(const NDSDisplayID displayID);
void CopyCustomDisplayByID_OGL(const NDSDisplayID displayID);
void LoadNativeDisplayByID_OGL(const NDSDisplayID displayID);
void LoadCustomDisplayByID_OGL(const NDSDisplayID displayID);
void ProcessOGL();
virtual void RenderOGL();
virtual void FinishOGL();
virtual void FinishOGL(const u8 bufferIndex);
};
class OGLClientFetchObject : public GPUClientFetchObject
{
protected:
OGLContextInfo *_contextInfo;
GLenum _fetchColorFormatOGL;
GLuint _texDisplayFetchNative[2][2];
GLuint _texDisplayFetchCustom[2][2];
GLuint _texLQ2xLUT;
GLuint _texHQ2xLUT;
GLuint _texHQ3xLUT;
GLuint _texHQ4xLUT;
bool _useCPUFilterPipeline;
uint32_t *_srcNativeCloneMaster;
uint32_t *_srcNativeClone[2][2];
pthread_rwlock_t _srcCloneRWLock[2][2];
virtual void _FetchNativeDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex);
virtual void _FetchCustomDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex);
public:
OGLClientFetchObject();
virtual ~OGLClientFetchObject();
OGLContextInfo* GetContextInfo() const;
uint32_t* GetSrcClone(const NDSDisplayID displayID, const u8 bufferIndex) const;
GLuint GetTexNative(const NDSDisplayID displayID, const u8 bufferIndex) const;
GLuint GetTexCustom(const NDSDisplayID displayID, const u8 bufferIndex) const;
// For lack of a better place, we're putting the HQnx LUTs in the fetch object because
// we know that it will be shared for all display views.
GLuint GetTexLQ2xLUT() const;
GLuint GetTexHQ2xLUT() const;
GLuint GetTexHQ3xLUT() const;
GLuint GetTexHQ4xLUT() const;
void CopyFromSrcClone(uint32_t *dstBufferPtr, const NDSDisplayID displayID, const u8 bufferIndex);
virtual void Init();
virtual void SetFetchBuffers(const NDSDisplayInfo &currentDisplayInfo);
};
class OGLVideoOutput : public ClientDisplay3DView
@ -394,10 +406,7 @@ protected:
virtual void _UpdateClientSize();
virtual void _UpdateViewScale();
virtual void _FetchNativeDisplayByID(const NDSDisplayID displayID);
virtual void _FetchCustomDisplayByID(const NDSDisplayID displayID);
virtual void _LoadNativeDisplayByID(const NDSDisplayID displayID);
virtual void _LoadCustomDisplayByID(const NDSDisplayID displayID);
public:
OGLVideoOutput();
@ -421,17 +430,12 @@ public:
virtual void SetFiltersPreferGPU(const bool preferGPU);
virtual void SetVideoBuffers(const uint32_t colorFormat,
const void *videoBufferHead,
const void *nativeBuffer0,
const void *nativeBuffer1,
const void *customBuffer0, const size_t customWidth0, const size_t customHeight0,
const void *customBuffer1, const size_t customWidth1, const size_t customHeight1);
// Client view interface
virtual void ProcessDisplays();
virtual void FrameFinish();
virtual void FinishFrameAtIndex(const u8 bufferIndex);
virtual void RenderViewOGL();
virtual void LockDisplayTextures();
virtual void UnlockDisplayTextures();
};
extern void (*glBindVertexArrayDESMUME)(GLuint id);

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2013-2015 DeSmuME team
Copyright (C) 2013-2017 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
@ -19,9 +19,39 @@
#include <pthread.h>
#include <libkern/OSAtomic.h>
#import "cocoa_util.h"
#include "../../GPU.h"
#ifdef BOOL
#undef BOOL
#endif
#if defined(MAC_OS_X_VERSION_10_11) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11)
//#define ENABLE_APPLE_METAL
#endif
class GPUEventHandlerOSX;
@interface MacClientSharedObject : CocoaDSThread
{
GPUClientFetchObject *GPUFetchObject;
pthread_rwlock_t *_rwlockFramebuffer[2];
pthread_mutex_t *_mutexOutputList;
NSMutableArray *_cdsOutputList;
}
@property (assign, nonatomic) GPUClientFetchObject *GPUFetchObject;
- (const NDSDisplayInfo &) fetchDisplayInfoForIndex:(const u8)bufferIndex;
- (pthread_rwlock_t *) rwlockFramebufferAtIndex:(const u8)bufferIndex;
- (void) setOutputList:(NSMutableArray *)theOutputList mutex:(pthread_mutex_t *)theMutex;
- (BOOL) isCPUFilteringNeeded;
- (void) handleFetchFromBufferIndexAndPushVideo:(NSData *)indexData;
- (void) pushVideoDataToAllDisplayViews;
- (void) finishAllDisplayViewsAtIndex:(const u8)bufferIndex;
@end
@interface CocoaDSGPU : NSObject
{
UInt32 gpuStateFlags;
@ -32,6 +62,7 @@ class GPUEventHandlerOSX;
OSSpinLock spinlockGpuState;
GPUEventHandlerOSX *gpuEvent;
GPUClientFetchObject *fetchObject;
}
@property (assign) UInt32 gpuStateFlags;
@ -39,6 +70,8 @@ class GPUEventHandlerOSX;
@property (assign) NSUInteger gpuScale;
@property (assign) NSUInteger gpuColorFormat;
@property (readonly) pthread_rwlock_t *gpuFrameRWLock;
@property (readonly, nonatomic) GPUClientFetchObject *fetchObject;
@property (readonly, nonatomic) MacClientSharedObject *sharedData;
@property (assign) BOOL layerMainGPU;
@property (assign) BOOL layerMainBG0;

View File

@ -21,7 +21,6 @@
#include "utilities.h"
#include "../../NDSSystem.h"
#include "../../GPU.h"
#include "../../rasterize.h"
#ifdef MAC_OS_X_VERSION_10_7
@ -31,8 +30,12 @@
#endif
#include <OpenGL/OpenGL.h>
#include "userinterface/MacOGLDisplayView.h"
#include "userinterface/MacMetalDisplayView.h"
#ifdef BOOL
#undef BOOL
#endif
GPU3DInterface *core3DList[] = {
&gpu3DNull,
@ -44,28 +47,26 @@ GPU3DInterface *core3DList[] = {
class GPUEventHandlerOSX : public GPUEventHandlerDefault
{
private:
GPUClientFetchObject *_fetchObject;
pthread_rwlock_t _rwlockFrame;
pthread_mutex_t _mutex3DRender;
pthread_mutex_t *_mutexOutputList;
NSMutableArray *_cdsOutputList;
bool _render3DNeedsFinish;
public:
GPUEventHandlerOSX();
~GPUEventHandlerOSX();
GPUClientFetchObject* GetFetchObject() const;
void SetFetchObject(GPUClientFetchObject *fetchObject);
void FramebufferLockWrite();
void FramebufferLockRead();
void FramebufferUnlock();
void Render3DLock();
void Render3DUnlock();
void FrameFinish();
void SetVideoBuffers();
pthread_rwlock_t* GetFrameRWLock();
NSMutableArray* GetOutputList();
void SetOutputList(NSMutableArray *outputList, pthread_mutex_t *theMutex);
bool GetRender3DNeedsFinish();
virtual void DidFrameBegin(bool isFrameSkipRequested, const u8 targetBufferIndex, const size_t line);
@ -81,6 +82,8 @@ public:
@dynamic gpuScale;
@dynamic gpuColorFormat;
@dynamic gpuFrameRWLock;
@synthesize fetchObject;
@dynamic sharedData;
@dynamic layerMainGPU;
@dynamic layerMainBG0;
@ -147,6 +150,20 @@ public:
GPU->SetEventHandler(gpuEvent);
GPU->SetWillAutoResolveToCustomBuffer(false);
#ifdef ENABLE_APPLE_METAL
if (IsOSXVersionSupported(10, 11, 0))
{
fetchObject = new MacMetalFetchObject;
}
else
#endif
{
fetchObject = new MacOGLClientFetchObject;
}
fetchObject->Init();
gpuEvent->SetFetchObject(fetchObject);
return self;
}
@ -154,11 +171,22 @@ public:
{
DestroyOpenGLRenderer();
delete fetchObject;
delete gpuEvent;
[super dealloc];
}
- (GPUClientFetchObject *) fetchObject
{
return fetchObject;
}
- (MacClientSharedObject *) sharedData
{
return (MacClientSharedObject *)fetchObject->GetClientData();
}
- (void) setGpuStateFlags:(UInt32)flags
{
OSSpinLockLock(&spinlockGpuState);
@ -191,13 +219,15 @@ public:
- (void) setGpuDimensions:(NSSize)theDimensions
{
gpuEvent->FrameFinish();
[[self sharedData] finishAllDisplayViewsAtIndex:0];
[[self sharedData] finishAllDisplayViewsAtIndex:1];
gpuEvent->Render3DLock();
gpuEvent->FramebufferLockWrite();
GPU->SetCustomFramebufferSize(theDimensions.width, theDimensions.height);
fetchObject->SetFetchBuffers(GPU->GetDisplayInfo());
gpuEvent->SetVideoBuffers();
gpuEvent->FramebufferUnlock();
gpuEvent->Render3DUnlock();
}
@ -226,13 +256,15 @@ public:
- (void) setGpuColorFormat:(NSUInteger)colorFormat
{
gpuEvent->FrameFinish();
[[self sharedData] finishAllDisplayViewsAtIndex:0];
[[self sharedData] finishAllDisplayViewsAtIndex:1];
gpuEvent->Render3DLock();
gpuEvent->FramebufferLockWrite();
GPU->SetColorFormat((NDSColorFormat)colorFormat);
fetchObject->SetFetchBuffers(GPU->GetDisplayInfo());
gpuEvent->SetVideoBuffers();
gpuEvent->FramebufferUnlock();
gpuEvent->Render3DUnlock();
}
@ -255,7 +287,7 @@ public:
- (void) setOutputList:(NSMutableArray *)theOutputList mutexPtr:(pthread_mutex_t *)theMutex
{
gpuEvent->SetOutputList(theOutputList, theMutex);
[(MacClientSharedObject *)fetchObject->GetClientData() setOutputList:theOutputList mutex:theMutex];
}
- (void) setRender3DRenderingEngine:(NSInteger)methodID
@ -814,10 +846,196 @@ public:
@end
@implementation MacClientSharedObject
@synthesize GPUFetchObject;
- (id)init
{
self = [super init];
if (self == nil)
{
return self;
}
_rwlockFramebuffer[0] = (pthread_rwlock_t *)malloc(sizeof(pthread_rwlock_t));
_rwlockFramebuffer[1] = (pthread_rwlock_t *)malloc(sizeof(pthread_rwlock_t));
pthread_rwlock_init(_rwlockFramebuffer[0], NULL);
pthread_rwlock_init(_rwlockFramebuffer[1], NULL);
GPUFetchObject = nil;
_mutexOutputList = NULL;
_cdsOutputList = nil;
return self;
}
- (void)dealloc
{
pthread_mutex_t *currentMutex = _mutexOutputList;
if (currentMutex != NULL)
{
pthread_mutex_lock(currentMutex);
}
[_cdsOutputList release];
if (currentMutex != NULL)
{
pthread_mutex_unlock(currentMutex);
}
pthread_rwlock_destroy(_rwlockFramebuffer[0]);
pthread_rwlock_destroy(_rwlockFramebuffer[1]);
[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];
GPUFetchObject->FetchFromBufferIndex(index);
[self pushVideoDataToAllDisplayViews];
}
- (const NDSDisplayInfo &) fetchDisplayInfoForIndex:(const u8)bufferIndex
{
return GPUFetchObject->GetFetchDisplayInfoForBufferIndex(bufferIndex);
}
- (pthread_rwlock_t *) rwlockFramebufferAtIndex:(const u8)bufferIndex
{
return _rwlockFramebuffer[bufferIndex];
}
- (void) setOutputList:(NSMutableArray *)theOutputList mutex:(pthread_mutex_t *)theMutex
{
pthread_mutex_t *currentMutex = _mutexOutputList;
if (currentMutex != NULL)
{
pthread_mutex_lock(currentMutex);
}
[_cdsOutputList release];
_cdsOutputList = theOutputList;
[_cdsOutputList retain];
if (currentMutex != NULL)
{
pthread_mutex_unlock(currentMutex);
}
_mutexOutputList = theMutex;
}
- (BOOL) isCPUFilteringNeeded
{
bool useCPUFilterPipeline = NO;
pthread_mutex_t *currentMutex = _mutexOutputList;
if (currentMutex != NULL)
{
pthread_mutex_lock(currentMutex);
}
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
{
pthread_mutex_t *currentMutex = _mutexOutputList;
if (currentMutex != NULL)
{
pthread_mutex_lock(currentMutex);
}
for (CocoaDSOutput *cdsOutput in _cdsOutputList)
{
if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]])
{
[CocoaDSUtil messageSendOneWay:[cdsOutput receivePort] msgID:MESSAGE_RECEIVE_GPU_FRAME];
}
}
if (currentMutex != NULL)
{
pthread_mutex_unlock(currentMutex);
}
}
- (void) finishAllDisplayViewsAtIndex:(const u8)bufferIndex
{
pthread_mutex_t *currentMutex = _mutexOutputList;
if (currentMutex != NULL)
{
pthread_mutex_lock(currentMutex);
}
for (CocoaDSOutput *cdsOutput in _cdsOutputList)
{
if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]])
{
ClientDisplay3DView *cdv = [(CocoaDSDisplay *)cdsOutput clientDisplayView];
cdv->FinishFrameAtIndex(bufferIndex);
}
}
if (currentMutex != NULL)
{
pthread_mutex_unlock(currentMutex);
}
}
@end
#pragma mark -
GPUEventHandlerOSX::GPUEventHandlerOSX()
{
_fetchObject = nil;
_render3DNeedsFinish = false;
_mutexOutputList = NULL;
pthread_rwlock_init(&_rwlockFrame, NULL);
pthread_mutex_init(&_mutex3DRender, NULL);
}
@ -833,37 +1051,46 @@ GPUEventHandlerOSX::~GPUEventHandlerOSX()
pthread_mutex_destroy(&this->_mutex3DRender);
}
GPUClientFetchObject* GPUEventHandlerOSX::GetFetchObject() const
{
return this->_fetchObject;
}
void GPUEventHandlerOSX::SetFetchObject(GPUClientFetchObject *fetchObject)
{
this->_fetchObject = fetchObject;
}
void GPUEventHandlerOSX::DidFrameBegin(bool isFrameSkipRequested, const u8 targetBufferIndex, const size_t line)
{
this->FramebufferLockWrite();
#if !defined(PORT_VERSION_OPENEMU)
if (!isFrameSkipRequested)
{
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_fetchObject->GetClientData();
pthread_rwlock_wrlock([sharedViewObject rwlockFramebufferAtIndex:targetBufferIndex]);
}
#endif
}
void GPUEventHandlerOSX::DidFrameEnd(bool isFrameSkipped, const NDSDisplayInfo &latestDisplayInfo)
{
#if !defined(PORT_VERSION_OPENEMU)
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_fetchObject->GetClientData();
if (!isFrameSkipped)
{
this->_fetchObject->SetFetchDisplayInfo(latestDisplayInfo);
pthread_rwlock_unlock([sharedViewObject rwlockFramebufferAtIndex:latestDisplayInfo.bufferIndex]);
}
#endif
this->FramebufferUnlock();
#if !defined(PORT_VERSION_OPENEMU)
if (!isFrameSkipped)
{
if (this->_mutexOutputList != NULL)
{
pthread_mutex_lock(this->_mutexOutputList);
}
NSMutableArray *outputList = this->_cdsOutputList;
for (CocoaDSOutput *cdsOutput in outputList)
{
if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]])
{
[(CocoaDSDisplay *)cdsOutput doReceiveGPUFrame];
}
}
if (this->_mutexOutputList != NULL)
{
pthread_mutex_unlock(this->_mutexOutputList);
}
[CocoaDSUtil messageSendOneWayWithInteger:[sharedViewObject receivePort] msgID:MESSAGE_FETCH_AND_PUSH_VIDEO integerValue:latestDisplayInfo.bufferIndex];
}
#endif
}
@ -905,56 +1132,6 @@ void GPUEventHandlerOSX::Render3DUnlock()
pthread_mutex_unlock(&this->_mutex3DRender);
}
void GPUEventHandlerOSX::FrameFinish()
{
#if !defined(PORT_VERSION_OPENEMU)
if (this->_mutexOutputList != NULL)
{
pthread_mutex_lock(this->_mutexOutputList);
}
NSMutableArray *outputList = this->_cdsOutputList;
for (CocoaDSOutput *cdsOutput in outputList)
{
if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]])
{
[(CocoaDSDisplay *)cdsOutput finishFrame];
}
}
if (this->_mutexOutputList != NULL)
{
pthread_mutex_unlock(this->_mutexOutputList);
}
#endif
}
void GPUEventHandlerOSX::SetVideoBuffers()
{
#if !defined(PORT_VERSION_OPENEMU)
if (this->_mutexOutputList != NULL)
{
pthread_mutex_lock(this->_mutexOutputList);
}
NSMutableArray *outputList = this->_cdsOutputList;
for (CocoaDSOutput *cdsOutput in outputList)
{
if ([cdsOutput isKindOfClass:[CocoaDSDisplayVideo class]])
{
[(CocoaDSDisplayVideo *)cdsOutput resetVideoBuffers];
}
}
if (this->_mutexOutputList != NULL)
{
pthread_mutex_unlock(this->_mutexOutputList);
}
#endif
}
bool GPUEventHandlerOSX::GetRender3DNeedsFinish()
{
return this->_render3DNeedsFinish;
@ -965,16 +1142,7 @@ pthread_rwlock_t* GPUEventHandlerOSX::GetFrameRWLock()
return &this->_rwlockFrame;
}
NSMutableArray* GPUEventHandlerOSX::GetOutputList()
{
return this->_cdsOutputList;
}
void GPUEventHandlerOSX::SetOutputList(NSMutableArray *outputList, pthread_mutex_t *theMutex)
{
this->_cdsOutputList = outputList;
this->_mutexOutputList = theMutex;
}
#pragma mark -
CGLContextObj OSXOpenGLRendererContext = NULL;

View File

@ -404,6 +404,7 @@ enum
MESSAGE_SET_EMULATION_FLAGS,
// Video Messages
MESSAGE_FETCH_AND_PUSH_VIDEO,
MESSAGE_RECEIVE_GPU_FRAME,
MESSAGE_CHANGE_VIEW_PROPERTIES,
MESSAGE_REDRAW_VIEW,

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2011 Roger Manuel
Copyright (C) 2011-2016 DeSmuME team
Copyright (C) 2011-2017 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
@ -118,13 +118,11 @@ struct NDSFrameInfo;
- (void) commitViewProperties:(const ClientDisplayViewProperties &)viewProps;
- (void) doReceiveGPUFrame;
- (void) handleReceiveGPUFrame;
- (void) handleChangeViewProperties;
- (void) handleRequestScreenshot:(NSData *)fileURLStringData fileTypeData:(NSData *)fileTypeData;
- (void) handleCopyToPasteboard;
- (void) finishFrame;
- (void) takeFrameCount;
- (void) setCPULoadAvgARM9:(uint32_t)loadAvgARM9 ARM7:(uint32_t)loadAvgARM7;
- (NSImage *) image;
@ -133,11 +131,7 @@ struct NDSFrameInfo;
@end
@interface CocoaDSDisplayVideo : CocoaDSDisplay
{
void *_videoBuffer;
void *_nativeBuffer[2];
void *_customBuffer[2];
{
OSSpinLock spinlockIsHUDVisible;
OSSpinLock spinlockUseVerticalSync;
OSSpinLock spinlockVideoFiltersPreferGPU;
@ -165,7 +159,6 @@ struct NDSFrameInfo;
- (void) handleReprocessRedraw;
- (void) handleRedraw;
- (void) resetVideoBuffers;
- (void) setScaleFactor:(float)theScaleFactor;
@end

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2011 Roger Manuel
Copyright (C) 2011-2016 DeSmuME team
Copyright (C) 2011-2017 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
@ -561,11 +561,6 @@
return size;
}
- (void) doReceiveGPUFrame
{
[CocoaDSUtil messageSendOneWay:self.receivePort msgID:MESSAGE_RECEIVE_GPU_FRAME];
}
- (void)handlePortMessage:(NSPortMessage *)portMessage
{
NSInteger message = (NSInteger)[portMessage msgid];
@ -642,11 +637,6 @@
[pboard setData:[screenshot TIFFRepresentationUsingCompression:NSTIFFCompressionLZW factor:1.0f] forType:NSTIFFPboardType];
}
- (void) finishFrame
{
_cdv->FrameFinish();
}
- (void) takeFrameCount
{
OSSpinLockLock(&spinlockReceivedFrameIndex);
@ -764,12 +754,6 @@
return self;
}
_videoBuffer = NULL;
_nativeBuffer[NDSDisplayID_Main] = NULL;
_nativeBuffer[NDSDisplayID_Touch] = NULL;
_customBuffer[NDSDisplayID_Main] = NULL;
_customBuffer[NDSDisplayID_Touch] = NULL;
spinlockIsHUDVisible = OS_SPINLOCK_INIT;
spinlockUseVerticalSync = OS_SPINLOCK_INIT;
spinlockVideoFiltersPreferGPU = OS_SPINLOCK_INIT;
@ -782,12 +766,6 @@
- (void)dealloc
{
free_aligned(_videoBuffer);
_nativeBuffer[NDSDisplayID_Main] = NULL;
_nativeBuffer[NDSDisplayID_Touch] = NULL;
_customBuffer[NDSDisplayID_Main] = NULL;
_customBuffer[NDSDisplayID_Touch] = NULL;
[super dealloc];
}
@ -1038,15 +1016,6 @@
- (void) handleReceiveGPUFrame
{
[super handleReceiveGPUFrame];
[self finishFrame];
pthread_rwlock_rdlock(self.rwlockProducer);
const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo();
_cdv->SetEmuDisplayInfo(dispInfo);
_cdv->FetchDisplays();
pthread_rwlock_unlock(self.rwlockProducer);
_cdv->LoadDisplays();
_cdv->ProcessDisplays();
@ -1054,13 +1023,20 @@
- (void) handleReloadReprocessRedraw
{
[self handleReceiveGPUFrame];
GPUClientFetchObject &fetchObjMutable = (GPUClientFetchObject &)_cdv->GetFetchObject();
const u8 bufferIndex = fetchObjMutable.GetLastFetchIndex();
fetchObjMutable.FetchFromBufferIndex(bufferIndex);
_cdv->LoadDisplays();
_cdv->ProcessDisplays();
[self handleEmuFrameProcessed];
}
- (void) handleReprocessRedraw
{
[self handleEmuFrameProcessed];
{
_cdv->ProcessDisplays();
_cdv->UpdateView();
}
- (void) handleRedraw
@ -1068,33 +1044,6 @@
_cdv->UpdateView();
}
- (void) resetVideoBuffers
{
const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo();
void *oldVideoBuffer = _videoBuffer;
uint8_t *newVideoBuffer = (uint8_t *)malloc_alignedCacheLine( ((GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT) + (dispInfo.customWidth * dispInfo.customHeight)) * 2 * dispInfo.pixelBytes );
_cdv->SetVideoBuffers(dispInfo.colorFormat,
newVideoBuffer,
newVideoBuffer,
newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * dispInfo.pixelBytes),
newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * dispInfo.pixelBytes),
dispInfo.customWidth,
dispInfo.customHeight,
newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * dispInfo.pixelBytes) + (dispInfo.customWidth * dispInfo.customHeight * dispInfo.pixelBytes),
dispInfo.customWidth,
dispInfo.customHeight);
_videoBuffer = newVideoBuffer;
_nativeBuffer[NDSDisplayID_Main] = newVideoBuffer;
_nativeBuffer[NDSDisplayID_Touch] = newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * dispInfo.pixelBytes);
_customBuffer[NDSDisplayID_Main] = newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * dispInfo.pixelBytes);
_customBuffer[NDSDisplayID_Touch] = newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * dispInfo.pixelBytes) + (dispInfo.customWidth * dispInfo.customHeight * dispInfo.pixelBytes);
free_aligned(oldVideoBuffer);
}
- (void) setScaleFactor:(float)theScaleFactor
{
OSSpinLockLock(&spinlockIsHUDVisible);

View File

@ -47,6 +47,7 @@ class OGLVideoOutput;
@property (retain) CocoaDSDisplayVideo *cdsVideoOutput;
@property (readonly, nonatomic) ClientDisplay3DView *clientDisplay3DView;
@property (readonly) BOOL canUseShaderBasedFilters;
@property (assign, nonatomic) BOOL allowViewUpdates;
@property (assign) BOOL isHUDVisible;
@property (assign) BOOL isHUDVideoFPSVisible;
@property (assign) BOOL isHUDRender3DFPSVisible;
@ -60,7 +61,7 @@ class OGLVideoOutput;
@property (assign) NSInteger outputFilter;
@property (assign) NSInteger pixelScaler;
- (void) reassignLocalCALayer;
- (void) setupLayer;
- (BOOL) handleKeyPress:(NSEvent *)theEvent keyPressed:(BOOL)keyPressed;
- (BOOL) handleMouseButton:(NSEvent *)theEvent buttonPressed:(BOOL)buttonPressed;

View File

@ -20,6 +20,7 @@
#import "InputManager.h"
#import "cocoa_core.h"
#import "cocoa_GPU.h"
#import "cocoa_file.h"
#import "cocoa_input.h"
#import "cocoa_globals.h"
@ -28,9 +29,7 @@
#include "MacOGLDisplayView.h"
//#define ENABLE_APPLE_METAL
#if defined(MAC_OS_X_VERSION_10_11) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11) && defined(ENABLE_APPLE_METAL)
#ifdef ENABLE_APPLE_METAL
#include "MacMetalDisplayView.h"
#endif
@ -356,7 +355,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
- (void) setVideoOutputFilter:(NSInteger)filterID
{
[[self view] setOutputFilter:filterID];
[CocoaDSUtil messageSendOneWay:[[self cdsVideoOutput] receivePort] msgID:MESSAGE_REPROCESS_AND_REDRAW];
[CocoaDSUtil messageSendOneWay:[[self cdsVideoOutput] receivePort] msgID:MESSAGE_REDRAW_VIEW];
}
- (NSInteger) videoOutputFilter
@ -668,6 +667,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
// Show the full screen window.
[self setWindow:newFullScreenWindow];
[newFullScreenWindow makeKeyAndOrderFront:self];
[newFullScreenWindow makeMainWindow];
[newFullScreenWindow display];
[self setAssignedScreen:targetScreen];
@ -697,6 +697,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
[[masterWindow contentView] addSubview:view];
[masterWindow setInitialFirstResponder:view];
[masterWindow makeKeyAndOrderFront:self];
[masterWindow makeMainWindow];
[masterWindow display];
}
@ -1272,7 +1273,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
[[emuControl windowList] addObject:self];
[emuControl updateAllWindowTitles];
[view reassignLocalCALayer];
[view setupLayer];
[view setInputManager:[emuControl inputManager]];
// Set up the scaling factor if this is a Retina window
@ -1305,7 +1306,6 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
cdv->LoadHUDFont();
}
[newDisplayOutput resetVideoBuffers];
[self setCdsVideoOutput:newDisplayOutput];
[view setCdsVideoOutput:newDisplayOutput];
@ -1600,6 +1600,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
@synthesize cdsVideoOutput;
@dynamic clientDisplay3DView;
@dynamic canUseShaderBasedFilters;
@dynamic allowViewUpdates;
@dynamic isHUDVisible;
@dynamic isHUDVideoFPSVisible;
@dynamic isHUDRender3DFPSVisible;
@ -1625,45 +1626,6 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
cdsVideoOutput = nil;
localLayer = nil;
localOGLContext = nil;
#if defined(MAC_OS_X_VERSION_10_11) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11) && defined(ENABLE_APPLE_METAL)
if (IsOSXVersionSupported(10, 11, 0))
{
localLayer = [[DisplayViewMetalLayer alloc] init];
if ([(DisplayViewMetalLayer *)localLayer device] == nil)
{
[localLayer release];
localLayer = nil;
}
}
#endif
if (localLayer == nil)
{
localLayer = [[DisplayViewOpenGLLayer alloc] init];
MacOGLDisplayView *macOGLCDV = (MacOGLDisplayView *)[(id<DisplayViewCALayer>)localLayer clientDisplay3DView];
// For macOS 10.8 Mountain Lion and later, we can use the CAOpenGLLayer directly. But for
// earlier versions of macOS, using the CALayer directly will cause too many strange issues,
// so we'll just keep using the old-school NSOpenGLContext for these older macOS versions.
if (IsOSXVersionSupported(10, 8, 0))
{
macOGLCDV->SetRenderToCALayer(true);
}
else
{
#if defined(MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
if ([self respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)])
{
[self setWantsBestResolutionOpenGLSurface:YES];
}
#endif
localOGLContext = macOGLCDV->GetNSContext();
[localOGLContext retain];
macOGLCDV->SetRenderToCALayer(false);
}
}
return self;
}
@ -1697,6 +1659,16 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
return [[self cdsVideoOutput] canFilterOnGPU];
}
- (BOOL) allowViewUpdates
{
return ([self clientDisplay3DView]->GetAllowViewUpdates()) ? YES : NO;
}
- (void) setAllowViewUpdates:(BOOL)allowUpdates
{
[self clientDisplay3DView]->SetAllowViewUpdates((allowUpdates) ? true : false);
}
- (void) setIsHUDVisible:(BOOL)theState
{
[[self cdsVideoOutput] setIsHUDVisible:theState];
@ -1818,8 +1790,59 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
}
#pragma mark Class Methods
- (void) reassignLocalCALayer
- (void) setupLayer
{
DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate];
CocoaDSCore *cdsCore = (CocoaDSCore *)[[[windowController emuControl] cdsCoreController] content];
CocoaDSGPU *cdsGPU = [cdsCore cdsGPU];
#ifdef ENABLE_APPLE_METAL
MacClientSharedObject *macSharedData = [cdsGPU sharedData];
if ((macSharedData != nil) && [macSharedData isKindOfClass:[MetalDisplayViewSharedData class]])
{
localLayer = [[DisplayViewMetalLayer alloc] init];
[(DisplayViewMetalLayer *)localLayer setSharedData:(MetalDisplayViewSharedData *)macSharedData];
MacMetalDisplayView *cdv = (MacMetalDisplayView *)[(id<DisplayViewCALayer>)localLayer clientDisplay3DView];
cdv->SetFetchObject([cdsGPU fetchObject]);
cdv->Init();
if ([(DisplayViewMetalLayer *)localLayer device] == nil)
{
[localLayer release];
localLayer = nil;
}
}
#endif
if (localLayer == nil)
{
localLayer = [[DisplayViewOpenGLLayer alloc] init];
MacOGLDisplayView *macOGLCDV = (MacOGLDisplayView *)[(id<DisplayViewCALayer>)localLayer clientDisplay3DView];
macOGLCDV->SetFetchObject([cdsGPU fetchObject]);
macOGLCDV->Init();
// For macOS 10.8 Mountain Lion and later, we can use the CAOpenGLLayer directly. But for
// earlier versions of macOS, using the CALayer directly will cause too many strange issues,
// so we'll just keep using the old-school NSOpenGLContext for these older macOS versions.
if (IsOSXVersionSupported(10, 8, 0))
{
macOGLCDV->SetRenderToCALayer(true);
}
else
{
#if defined(MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
if ([self respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)])
{
[self setWantsBestResolutionOpenGLSurface:YES];
}
#endif
localOGLContext = macOGLCDV->GetNSContext();
[localOGLContext retain];
macOGLCDV->SetRenderToCALayer(false);
}
}
if (localOGLContext != nil)
{
// If localOGLContext isn't nil, then we will not assign the local layer
@ -1978,14 +2001,12 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
- (void)updateLayer
{
ClientDisplay3DView *cdv = [(id<DisplayViewCALayer>)localLayer clientDisplay3DView];
cdv->UpdateView();
[self clientDisplay3DView]->UpdateView();
}
- (void)drawRect:(NSRect)dirtyRect
{
ClientDisplay3DView *cdv = [(id<DisplayViewCALayer>)localLayer clientDisplay3DView];
cdv->UpdateView();
[self clientDisplay3DView]->UpdateView();
}
- (void)setFrame:(NSRect)rect
@ -2023,7 +2044,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
{
[localLayer setBounds:CGRectMake(0.0f, 0.0f, props.clientWidth, props.clientHeight)];
}
#if defined(MAC_OS_X_VERSION_10_11) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11) && defined(ENABLE_APPLE_METAL)
#ifdef ENABLE_APPLE_METAL
else if ([[self layer] isKindOfClass:[CAMetalLayer class]])
{
[(CAMetalLayer *)localLayer setDrawableSize:CGSizeMake(props.clientWidth, props.clientHeight)];

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2013-2015 DeSmuME Team
Copyright (C) 2013-2017 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
@ -347,8 +347,9 @@
{
DisplayWindowController *newWindowController = [[DisplayWindowController alloc] initWithWindowNibName:@"DisplayWindow" emuControlDelegate:self];
[CocoaDSUtil messageSendOneWay:[[newWindowController cdsVideoOutput] receivePort] msgID:MESSAGE_RELOAD_REPROCESS_REDRAW];
[newWindowController window]; // Just reference the window to force the nib to load.
[[newWindowController view] setAllowViewUpdates:YES];
[[newWindowController cdsVideoOutput] handleReloadReprocessRedraw];
[[newWindowController window] makeKeyAndOrderFront:self];
[[newWindowController window] makeMainWindow];
}

View File

@ -22,6 +22,7 @@
#import <OpenGL/OpenGL.h>
#import "DisplayViewCALayer.h"
#import "../cocoa_GPU.h"
#ifdef MAC_OS_X_VERSION_10_7
#include "../OGLDisplayOutput_3_2.h"
@ -29,7 +30,9 @@
#include "../OGLDisplayOutput.h"
#endif
#ifdef BOOL
#undef BOOL
#endif
class MacOGLDisplayView;
@ -39,6 +42,24 @@ class MacOGLDisplayView;
}
@end
class MacOGLClientFetchObject : public OGLClientFetchObject
{
protected:
NSOpenGLContext *_nsContext;
CGLContextObj _context;
public:
void operator delete(void *ptr);
MacOGLClientFetchObject();
NSOpenGLContext* GetNSContext() const;
CGLContextObj GetContext() const;
virtual void Init();
virtual void SetFetchBuffers(const NDSDisplayInfo &currentDisplayInfo);
virtual void FetchFromBufferIndex(const u8 index);
};
class MacOGLDisplayView : public OGLVideoOutput, public DisplayViewCALayerInterface
{
protected:
@ -64,13 +85,6 @@ public:
virtual void LoadHUDFont();
virtual void SetVideoBuffers(const uint32_t colorFormat,
const void *videoBufferHead,
const void *nativeBuffer0,
const void *nativeBuffer1,
const void *customBuffer0, const size_t customWidth0, const size_t customHeight0,
const void *customBuffer1, const size_t customWidth1, const size_t customHeight1);
virtual void SetUseVerticalSync(const bool useVerticalSync);
virtual void SetScaleFactor(const double scaleFactor);
@ -83,7 +97,9 @@ public:
virtual void LoadDisplays();
virtual void ProcessDisplays();
virtual void UpdateView();
virtual void FrameFinish();
virtual void FinishFrameAtIndex(const u8 bufferIndex);
virtual void LockDisplayTextures();
virtual void UnlockDisplayTextures();
};
#endif // _MAC_OGLDISPLAYOUTPUT_H_

View File

@ -18,6 +18,7 @@
#include "MacOGLDisplayView.h"
#include "../utilities.h"
@implementation DisplayViewOpenGLLayer
- (id)init
@ -30,7 +31,6 @@
_cdv = new MacOGLDisplayView();
_cdv->SetFrontendLayer(self);
_cdv->Init();
[self setBounds:CGRectMake(0.0f, 0.0f, (float)GPU_FRAMEBUFFER_NATIVE_WIDTH, (float)GPU_FRAMEBUFFER_NATIVE_HEIGHT)];
[self setAsynchronous:NO];
@ -82,6 +82,137 @@
@end
#pragma mark -
void MacOGLClientFetchObject::operator delete(void *ptr)
{
MacOGLClientFetchObject *fetchObjectPtr = (MacOGLClientFetchObject *)ptr;
[(MacClientSharedObject *)(fetchObjectPtr->GetClientData()) release];
CGLContextObj context = fetchObjectPtr->GetContext();
OGLContextInfo *contextInfo = fetchObjectPtr->GetContextInfo();
if (context != NULL)
{
CGLContextObj prevContext = CGLGetCurrentContext();
CGLSetCurrentContext(context);
::operator delete(ptr);
CGLSetCurrentContext(prevContext);
delete contextInfo;
[fetchObjectPtr->GetNSContext() release];
}
}
MacOGLClientFetchObject::MacOGLClientFetchObject()
{
// Initialize the OpenGL context.
//
// We create an NSOpenGLContext and extract the CGLContextObj from it because
// [NSOpenGLContext CGLContextObj] is available on macOS 10.5 Leopard, but
// [NSOpenGLContext initWithCGLContextObj:] is only available on macOS 10.6
// Snow Leopard.
bool useContext_3_2 = false;
NSOpenGLPixelFormatAttribute attributes[] = {
NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute)24,
NSOpenGLPFAAlphaSize, (NSOpenGLPixelFormatAttribute)8,
NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)0,
NSOpenGLPFAStencilSize, (NSOpenGLPixelFormatAttribute)0,
(NSOpenGLPixelFormatAttribute)0, (NSOpenGLPixelFormatAttribute)0,
(NSOpenGLPixelFormatAttribute)0
};
#ifdef _OGLDISPLAYOUTPUT_3_2_H_
// If we can support a 3.2 Core Profile context, then request that in our
// pixel format attributes.
useContext_3_2 = IsOSXVersionSupported(10, 7, 0);
if (useContext_3_2)
{
attributes[8] = NSOpenGLPFAOpenGLProfile;
attributes[9] = (NSOpenGLPixelFormatAttribute)NSOpenGLProfileVersion3_2Core;
}
#endif
NSOpenGLPixelFormat *nsPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
if (nsPixelFormat == nil)
{
// If we can't get a 3.2 Core Profile context, then switch to using a
// legacy context instead.
useContext_3_2 = false;
attributes[9] = (NSOpenGLPixelFormatAttribute)0;
attributes[10] = (NSOpenGLPixelFormatAttribute)0;
nsPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
}
_nsContext = [[NSOpenGLContext alloc] initWithFormat:nsPixelFormat shareContext:nil];
_context = (CGLContextObj)[_nsContext CGLContextObj];
[nsPixelFormat release];
CGLContextObj prevContext = CGLGetCurrentContext();
CGLSetCurrentContext(_context);
#ifdef _OGLDISPLAYOUTPUT_3_2_H_
if (useContext_3_2)
{
_contextInfo = new OGLContextInfo_3_2;
}
else
#endif
{
_contextInfo = new OGLContextInfo_Legacy;
}
CGLSetCurrentContext(prevContext);
_clientData = [[MacClientSharedObject alloc] init];
}
NSOpenGLContext* MacOGLClientFetchObject::GetNSContext() const
{
return this->_nsContext;
}
CGLContextObj MacOGLClientFetchObject::GetContext() const
{
return this->_context;
}
void MacOGLClientFetchObject::Init()
{
[(MacClientSharedObject *)this->_clientData setGPUFetchObject:this];
CGLContextObj prevContext = CGLGetCurrentContext();
CGLSetCurrentContext(_context);
this->OGLClientFetchObject::Init();
CGLSetCurrentContext(prevContext);
}
void MacOGLClientFetchObject::SetFetchBuffers(const NDSDisplayInfo &currentDisplayInfo)
{
CGLLockContext(this->_context);
CGLSetCurrentContext(this->_context);
this->OGLClientFetchObject::SetFetchBuffers(currentDisplayInfo);
CGLUnlockContext(this->_context);
}
void MacOGLClientFetchObject::FetchFromBufferIndex(const u8 index)
{
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_clientData;
this->_useCPUFilterPipeline = ([sharedViewObject isCPUFilteringNeeded]) ? true : false;
pthread_rwlock_rdlock([sharedViewObject rwlockFramebufferAtIndex:index]);
CGLLockContext(this->_context);
CGLSetCurrentContext(this->_context);
this->GPUClientFetchObject::FetchFromBufferIndex(index);
CGLUnlockContext(this->_context);
pthread_rwlock_unlock([sharedViewObject rwlockFramebufferAtIndex:index]);
}
#pragma mark -
void MacOGLDisplayView::operator delete(void *ptr)
{
CGLContextObj context = ((MacOGLDisplayView *)ptr)->GetContext();
@ -141,33 +272,37 @@ MacOGLDisplayView::MacOGLDisplayView()
_nsPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
}
_nsContext = [[NSOpenGLContext alloc] initWithFormat:_nsPixelFormat shareContext:nil];
_context = (CGLContextObj)[_nsContext CGLContextObj];
_pixelFormat = (CGLPixelFormatObj)[_nsPixelFormat CGLPixelFormatObj];
CGLContextObj prevContext = CGLGetCurrentContext();
CGLSetCurrentContext(_context);
#ifdef _OGLDISPLAYOUTPUT_3_2_H_
if (useContext_3_2)
{
_contextInfo = new OGLContextInfo_3_2;
}
else
#endif
{
_contextInfo = new OGLContextInfo_Legacy;
}
CGLSetCurrentContext(prevContext);
_nsContext = nil;
_context = nil;
_willRenderToCALayer = false;
_allowViewUpdates = false;
}
void MacOGLDisplayView::Init()
{
this->_nsContext = [[NSOpenGLContext alloc] initWithFormat:this->_nsPixelFormat
shareContext:((MacOGLClientFetchObject *)this->_fetchObject)->GetNSContext()];
this->_context = (CGLContextObj)[this->_nsContext CGLContextObj];
CGLContextObj prevContext = CGLGetCurrentContext();
CGLSetCurrentContext(this->_context);
#ifdef _OGLDISPLAYOUTPUT_3_2_H_
GLint profileVersion = 0;
CGLDescribePixelFormat(this->_pixelFormat, 0, kCGLPFAOpenGLProfile, &profileVersion);
if (profileVersion == kCGLOGLPVersion_3_2_Core)
{
this->_contextInfo = new OGLContextInfo_3_2;
}
else
#endif
{
this->_contextInfo = new OGLContextInfo_Legacy;
}
this->OGLVideoOutput::Init();
CGLSetCurrentContext(prevContext);
}
@ -210,26 +345,6 @@ void MacOGLDisplayView::LoadHUDFont()
CGLUnlockContext(this->_context);
}
void MacOGLDisplayView::SetVideoBuffers(const uint32_t colorFormat,
const void *videoBufferHead,
const void *nativeBuffer0,
const void *nativeBuffer1,
const void *customBuffer0, const size_t customWidth0, const size_t customHeight0,
const void *customBuffer1, const size_t customWidth1, const size_t customHeight1)
{
CGLLockContext(this->_context);
CGLSetCurrentContext(this->_context);
this->OGLVideoOutput::SetVideoBuffers(colorFormat,
videoBufferHead,
nativeBuffer0,
nativeBuffer1,
customBuffer0, customWidth0, customHeight0,
customBuffer1, customWidth1, customHeight1);
CGLUnlockContext(this->_context);
}
void MacOGLDisplayView::SetUseVerticalSync(const bool useVerticalSync)
{
const GLint swapInt = (useVerticalSync) ? 1 : 0;
@ -292,6 +407,11 @@ void MacOGLDisplayView::ProcessDisplays()
void MacOGLDisplayView::UpdateView()
{
if (!this->_allowViewUpdates)
{
return;
}
if (this->_willRenderToCALayer)
{
this->CALayerDisplay();
@ -306,10 +426,28 @@ void MacOGLDisplayView::UpdateView()
}
}
void MacOGLDisplayView::FrameFinish()
void MacOGLDisplayView::FinishFrameAtIndex(const u8 bufferIndex)
{
CGLLockContext(this->_context);
CGLSetCurrentContext(this->_context);
this->OGLVideoOutput::FrameFinish();
this->OGLVideoOutput::FinishFrameAtIndex(bufferIndex);
CGLUnlockContext(this->_context);
}
void MacOGLDisplayView::LockDisplayTextures()
{
const GPUClientFetchObject &fetchObj = this->GetFetchObject();
const u8 bufferIndex = this->_emuDisplayInfo.bufferIndex;
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData();
pthread_rwlock_rdlock([sharedViewObject rwlockFramebufferAtIndex:bufferIndex]);
}
void MacOGLDisplayView::UnlockDisplayTextures()
{
const GPUClientFetchObject &fetchObj = this->GetFetchObject();
const u8 bufferIndex = this->_emuDisplayInfo.bufferIndex;
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData();
pthread_rwlock_unlock([sharedViewObject rwlockFramebufferAtIndex:bufferIndex]);
}

View File

@ -28,6 +28,7 @@
#import "inputPrefsView.h"
#import "cocoa_core.h"
#import "cocoa_GPU.h"
#import "cocoa_file.h"
#import "cocoa_firmware.h"
#import "cocoa_globals.h"
@ -178,6 +179,14 @@
// Init the DS emulation core.
CocoaDSCore *newCore = [[[CocoaDSCore alloc] init] autorelease];
MacClientSharedObject *sharedViewObject = [[newCore cdsGPU] sharedData];
[NSThread detachNewThreadSelector:@selector(runThread:) toTarget:sharedViewObject withObject:nil];
// Wait until the SPU is finished starting up.
while ([sharedViewObject thread] == nil)
{
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
}
// Init the DS controller.
CocoaDSController *newController = [[[CocoaDSController alloc] init] autorelease];
@ -683,6 +692,9 @@
// If this is the last window in the list, make this window key and main.
// Otherwise, just order the window to the front so that the windows will
// stack in a deterministic order.
[[windowController view] setAllowViewUpdates:YES];
[[windowController cdsVideoOutput] handleReloadReprocessRedraw];
if (windowProperties == [windowPropertiesList lastObject])
{
[[windowController window] makeKeyAndOrderFront:self];
@ -693,9 +705,6 @@
[[windowController window] orderFront:self];
}
// Draw the display view now so that we guarantee that its drawn at least once.
[CocoaDSUtil messageSendOneWay:[[windowController cdsVideoOutput] receivePort] msgID:MESSAGE_RELOAD_REPROCESS_REDRAW];
// If this window is set to full screen mode, its associated screen index must
// exist. If not, this window will not enter full screen mode. This is necessary,
// since the user's screen configuration could change in between app launches,
@ -704,8 +713,6 @@
([[NSScreen screens] indexOfObject:[[windowController window] screen]] == screenIndex))
{
[windowController toggleFullScreenDisplay:self];
[[windowController window] makeKeyAndOrderFront:self];
[[windowController window] makeMainWindow];
}
}
}