From ebc39eae64887d5285a2a86690385bd697cde8d1 Mon Sep 17 00:00:00 2001 From: rogerman Date: Wed, 27 Apr 2022 17:02:04 -0700 Subject: [PATCH] Cocoa Port: Major code refactor to the video display system with the purpose of breaking up multipurpose classes of homogenous data into more focused classes. - Also removes unnecessary Objective-C code and converts it into C++. Objective-C has its place, but not at this level of function. --- desmume/src/GPU.cpp | 15 +- desmume/src/GPU.h | 2 + .../src/frontend/cocoa/OGLDisplayOutput.cpp | 186 +++-- desmume/src/frontend/cocoa/OGLDisplayOutput.h | 34 +- desmume/src/frontend/cocoa/cocoa_GPU.h | 201 +++-- desmume/src/frontend/cocoa/cocoa_GPU.mm | 735 +++++++++--------- desmume/src/frontend/cocoa/cocoa_core.mm | 4 +- desmume/src/frontend/cocoa/cocoa_globals.h | 21 + .../userinterface/DisplayWindowController.mm | 34 +- .../userinterface/EmuControllerDelegate.mm | 6 +- .../cocoa/userinterface/MacAVCaptureTool.mm | 30 +- .../cocoa/userinterface/MacBaseCaptureTool.h | 10 +- .../cocoa/userinterface/MacBaseCaptureTool.mm | 5 +- .../cocoa/userinterface/MacMetalDisplayView.h | 4 +- .../userinterface/MacMetalDisplayView.mm | 22 +- .../cocoa/userinterface/MacOGLDisplayView.h | 36 +- .../cocoa/userinterface/MacOGLDisplayView.mm | 167 ++-- .../userinterface/MacScreenshotCaptureTool.mm | 28 +- 18 files changed, 850 insertions(+), 690 deletions(-) diff --git a/desmume/src/GPU.cpp b/desmume/src/GPU.cpp index c75c5afb9..020f2be0c 100644 --- a/desmume/src/GPU.cpp +++ b/desmume/src/GPU.cpp @@ -5908,10 +5908,7 @@ void GPUEventHandlerDefault::DidFrameBegin(const size_t line, const bool isFrame GPUClientFetchObject::GPUClientFetchObject() { - for (size_t i = 0; i < MAX_FRAMEBUFFER_PAGES; i++) - { - memset(&_fetchDisplayInfo[i], 0, sizeof(NDSDisplayInfo)); - } + _id = 0; memset(_name, 0, sizeof(_name)); strncpy(_name, "Generic Video", sizeof(_name) - 1); @@ -5921,6 +5918,11 @@ GPUClientFetchObject::GPUClientFetchObject() _clientData = NULL; _lastFetchIndex = 0; + + for (size_t i = 0; i < MAX_FRAMEBUFFER_PAGES; i++) + { + memset(&_fetchDisplayInfo[i], 0, sizeof(NDSDisplayInfo)); + } } void GPUClientFetchObject::Init() @@ -6003,6 +6005,11 @@ void GPUClientFetchObject::SetFetchDisplayInfo(const NDSDisplayInfo &displayInfo this->_fetchDisplayInfo[displayInfo.bufferIndex] = displayInfo; } +const s32 GPUClientFetchObject::GetID() const +{ + return this->_id; +} + const char* GPUClientFetchObject::GetName() const { return this->_name; diff --git a/desmume/src/GPU.h b/desmume/src/GPU.h index b78295391..c62c613d5 100644 --- a/desmume/src/GPU.h +++ b/desmume/src/GPU.h @@ -1991,6 +1991,7 @@ public: class GPUClientFetchObject { protected: + s32 _id; char _name[256]; char _description[256]; @@ -2009,6 +2010,7 @@ public: virtual void SetFetchBuffers(const NDSDisplayInfo ¤tDisplayInfo); virtual void FetchFromBufferIndex(const u8 index); + const s32 GetID() const; const char* GetName() const; const char* GetDescription() const; diff --git a/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp b/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp index 64835d0ce..fc420a76c 100644 --- a/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp +++ b/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp @@ -4570,7 +4570,7 @@ bool OGLShaderProgram::LinkOGL() #pragma mark - -OGLClientFetchObject::OGLClientFetchObject() +OGLClientSharedData::OGLClientSharedData() { _contextInfo = NULL; _useDirectToCPUFilterPipeline = true; @@ -4595,9 +4595,9 @@ OGLClientFetchObject::OGLClientFetchObject() } } -OGLClientFetchObject::~OGLClientFetchObject() +OGLClientSharedData::~OGLClientSharedData() { - if (this->_contextInfo->IsShaderSupported()) + if ( (this->_contextInfo != NULL) && this->_contextInfo->IsShaderSupported() ) { DeleteHQnxLUTs_OGL(GL_TEXTURE0 + 1, this->_texLQ2xLUT, this->_texHQ2xLUT, this->_texHQ3xLUT, this->_texHQ4xLUT); } @@ -4628,54 +4628,79 @@ OGLClientFetchObject::~OGLClientFetchObject() pthread_rwlock_destroy(&this->_texFetchRWLock[NDSDisplayID_Touch]); } -OGLContextInfo* OGLClientFetchObject::GetContextInfo() const +void OGLClientSharedData::SetContextInfo(OGLContextInfo *contextInfo) +{ + this->_contextInfo = contextInfo; +} + +OGLContextInfo* OGLClientSharedData::GetContextInfo() const { return this->_contextInfo; } -uint32_t* OGLClientFetchObject::GetSrcClone(const NDSDisplayID displayID, const u8 bufferIndex) const +void OGLClientSharedData::SetUseDirectToCPUFilterPipeline(bool willUseDirectCPU) +{ + this->_useDirectToCPUFilterPipeline = willUseDirectCPU; +} + +bool OGLClientSharedData::UseDirectToCPUFilterPipeline() const +{ + return this->_useDirectToCPUFilterPipeline; +} + +GLuint OGLClientSharedData::GetFetchTexture(const NDSDisplayID displayID) +{ + return this->_texFetch[displayID]; +} + +void OGLClientSharedData::SetFetchTexture(const NDSDisplayID displayID, GLuint texID) +{ + this->_texFetch[displayID] = texID; +} + +uint32_t* OGLClientSharedData::GetSrcClone(const NDSDisplayID displayID, const u8 bufferIndex) const { return this->_srcNativeClone[displayID][bufferIndex]; } -GLuint OGLClientFetchObject::GetTexNative(const NDSDisplayID displayID, const u8 bufferIndex) const +GLuint OGLClientSharedData::GetTexNative(const NDSDisplayID displayID, const u8 bufferIndex) const { return this->_texDisplayFetchNative[displayID][bufferIndex]; } -GLuint OGLClientFetchObject::GetTexCustom(const NDSDisplayID displayID, const u8 bufferIndex) const +GLuint OGLClientSharedData::GetTexCustom(const NDSDisplayID displayID, const u8 bufferIndex) const { return this->_texDisplayFetchCustom[displayID][bufferIndex]; } -GLuint OGLClientFetchObject::GetTexLQ2xLUT() const +GLuint OGLClientSharedData::GetTexLQ2xLUT() const { return this->_texLQ2xLUT; } -GLuint OGLClientFetchObject::GetTexHQ2xLUT() const +GLuint OGLClientSharedData::GetTexHQ2xLUT() const { return this->_texHQ2xLUT; } -GLuint OGLClientFetchObject::GetTexHQ3xLUT() const +GLuint OGLClientSharedData::GetTexHQ3xLUT() const { return this->_texHQ3xLUT; } -GLuint OGLClientFetchObject::GetTexHQ4xLUT() const +GLuint OGLClientSharedData::GetTexHQ4xLUT() const { return this->_texHQ4xLUT; } -void OGLClientFetchObject::CopyFromSrcClone(uint32_t *dstBufferPtr, const NDSDisplayID displayID, const u8 bufferIndex) +void OGLClientSharedData::CopyFromSrcClone(uint32_t *dstBufferPtr, const NDSDisplayID displayID, const u8 bufferIndex) { pthread_rwlock_rdlock(&this->_srcCloneRWLock[displayID][bufferIndex]); memcpy(dstBufferPtr, this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * sizeof(uint32_t)); pthread_rwlock_unlock(&this->_srcCloneRWLock[displayID][bufferIndex]); } -void OGLClientFetchObject::FetchNativeDisplayToSrcClone(const NDSDisplayID displayID, const u8 bufferIndex, bool needsLock) +void OGLClientSharedData::FetchNativeDisplayToSrcClone(const NDSDisplayInfo *displayInfoList, const NDSDisplayID displayID, const u8 bufferIndex, bool needsLock) { if (needsLock) { @@ -4691,7 +4716,7 @@ void OGLClientFetchObject::FetchNativeDisplayToSrcClone(const NDSDisplayID displ return; } - ColorspaceConvertBuffer555To8888Opaque(this->_fetchDisplayInfo[bufferIndex].nativeBuffer16[displayID], this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); + ColorspaceConvertBuffer555To8888Opaque(displayInfoList[bufferIndex].nativeBuffer16[displayID], this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); this->_srcCloneNeedsUpdate[displayID][bufferIndex] = false; if (needsLock) @@ -4700,7 +4725,7 @@ void OGLClientFetchObject::FetchNativeDisplayToSrcClone(const NDSDisplayID displ } } -void OGLClientFetchObject::FetchCustomDisplayToSrcClone(const NDSDisplayID displayID, const u8 bufferIndex, bool needsLock) +void OGLClientSharedData::FetchCustomDisplayToSrcClone(const NDSDisplayInfo *displayInfoList, const NDSDisplayID displayID, const u8 bufferIndex, bool needsLock) { if (needsLock) { @@ -4716,7 +4741,7 @@ void OGLClientFetchObject::FetchCustomDisplayToSrcClone(const NDSDisplayID displ return; } - ColorspaceConvertBuffer888XTo8888Opaque((u32 *)this->_fetchDisplayInfo[bufferIndex].customBuffer[displayID], this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); + ColorspaceConvertBuffer888XTo8888Opaque((u32 *)displayInfoList[bufferIndex].customBuffer[displayID], this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); this->_srcCloneNeedsUpdate[displayID][bufferIndex] = false; if (needsLock) @@ -4725,22 +4750,22 @@ void OGLClientFetchObject::FetchCustomDisplayToSrcClone(const NDSDisplayID displ } } -void OGLClientFetchObject::FetchTextureWriteLock(const NDSDisplayID displayID) +void OGLClientSharedData::FetchTextureWriteLock(const NDSDisplayID displayID) { pthread_rwlock_wrlock(&this->_texFetchRWLock[displayID]); } -void OGLClientFetchObject::FetchTextureReadLock(const NDSDisplayID displayID) +void OGLClientSharedData::FetchTextureReadLock(const NDSDisplayID displayID) { pthread_rwlock_rdlock(&this->_texFetchRWLock[displayID]); } -void OGLClientFetchObject::FetchTextureUnlock(const NDSDisplayID displayID) +void OGLClientSharedData::FetchTextureUnlock(const NDSDisplayID displayID) { pthread_rwlock_unlock(&this->_texFetchRWLock[displayID]); } -void OGLClientFetchObject::Init() +void OGLClientSharedData::InitOGL() { glGenTextures(2 * OPENGL_FETCH_BUFFER_COUNT, &this->_texDisplayFetchNative[0][0]); glGenTextures(2 * OPENGL_FETCH_BUFFER_COUNT, &this->_texDisplayFetchCustom[0][0]); @@ -4784,16 +4809,14 @@ void OGLClientFetchObject::Init() this->_texFetch[NDSDisplayID_Main] = this->_texDisplayFetchNative[NDSDisplayID_Main][0]; this->_texFetch[NDSDisplayID_Touch] = this->_texDisplayFetchNative[NDSDisplayID_Touch][0]; - if (this->_contextInfo->IsShaderSupported()) + if ( (this->_contextInfo != NULL) && this->_contextInfo->IsShaderSupported() ) { SetupHQnxLUTs_OGL(GL_TEXTURE0 + 1, this->_texLQ2xLUT, this->_texHQ2xLUT, this->_texHQ3xLUT, this->_texHQ4xLUT); } } -void OGLClientFetchObject::SetFetchBuffers(const NDSDisplayInfo ¤tDisplayInfo) +void OGLClientSharedData::SetFetchBuffersOGL(const NDSDisplayInfo *displayInfoList, const NDSDisplayInfo ¤tDisplayInfo) { - this->GPUClientFetchObject::SetFetchBuffers(currentDisplayInfo); - #ifdef MSB_FIRST this->_fetchColorFormatOGL = (currentDisplayInfo.pixelBytes == 2) ? GL_UNSIGNED_SHORT_1_5_5_5_REV : GL_UNSIGNED_INT_8_8_8_8; #else @@ -4809,19 +4832,19 @@ void OGLClientFetchObject::SetFetchBuffers(const NDSDisplayInfo ¤tDisplayI { glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchNative[NDSDisplayID_Main][i]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, this->_fetchDisplayInfo[i].nativeBuffer16[NDSDisplayID_Main]); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, displayInfoList[i].nativeBuffer16[NDSDisplayID_Main]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchNative[NDSDisplayID_Touch][i]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, this->_fetchDisplayInfo[i].nativeBuffer16[NDSDisplayID_Touch]); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, displayInfoList[i].nativeBuffer16[NDSDisplayID_Touch]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchCustom[NDSDisplayID_Main][i]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, currentDisplayInfo.customWidth, currentDisplayInfo.customHeight, 0, GL_RGBA, this->_fetchColorFormatOGL, this->_fetchDisplayInfo[i].customBuffer[NDSDisplayID_Main]); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, currentDisplayInfo.customWidth, currentDisplayInfo.customHeight, 0, GL_RGBA, this->_fetchColorFormatOGL, displayInfoList[i].customBuffer[NDSDisplayID_Main]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchCustom[NDSDisplayID_Touch][i]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, currentDisplayInfo.customWidth, currentDisplayInfo.customHeight, 0, GL_RGBA, this->_fetchColorFormatOGL, this->_fetchDisplayInfo[i].customBuffer[NDSDisplayID_Touch]); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, currentDisplayInfo.customWidth, currentDisplayInfo.customHeight, 0, GL_RGBA, this->_fetchColorFormatOGL, displayInfoList[i].customBuffer[NDSDisplayID_Touch]); pthread_rwlock_wrlock(&this->_srcCloneRWLock[NDSDisplayID_Main][i]); this->_srcCloneNeedsUpdate[NDSDisplayID_Main][i] = true; @@ -4837,14 +4860,12 @@ void OGLClientFetchObject::SetFetchBuffers(const NDSDisplayInfo ¤tDisplayI glFinish(); } -void OGLClientFetchObject::FetchFromBufferIndex(const u8 index) +void OGLClientSharedData::FetchFromBufferIndexOGL(const u8 index, const NDSDisplayInfo ¤tDisplayInfo) { - GPUClientFetchObject::FetchFromBufferIndex(index); glFlush(); GLuint texFetchMain = 0; GLuint texFetchTouch = 0; - const NDSDisplayInfo ¤tDisplayInfo = this->GetFetchDisplayInfoForBufferIndex(index); const bool isMainEnabled = currentDisplayInfo.isDisplayEnabled[NDSDisplayID_Main]; const bool isTouchEnabled = currentDisplayInfo.isDisplayEnabled[NDSDisplayID_Touch]; @@ -4876,42 +4897,32 @@ void OGLClientFetchObject::FetchFromBufferIndex(const u8 index) this->SetFetchTexture(NDSDisplayID_Touch, texFetchTouch); } -void OGLClientFetchObject::_FetchNativeDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex) +void OGLClientSharedData::FetchNativeDisplayByID_OGL(const NDSDisplayInfo *displayInfoList, const NDSDisplayID displayID, const u8 bufferIndex) { if (this->_useDirectToCPUFilterPipeline) { pthread_rwlock_wrlock(&this->_srcCloneRWLock[displayID][bufferIndex]); this->_srcCloneNeedsUpdate[displayID][bufferIndex] = true; - this->FetchNativeDisplayToSrcClone(displayID, bufferIndex, false); + this->FetchNativeDisplayToSrcClone(displayInfoList, displayID, bufferIndex, false); pthread_rwlock_unlock(&this->_srcCloneRWLock[displayID][bufferIndex]); } glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchNative[displayID][bufferIndex]); - glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, this->_fetchDisplayInfo[bufferIndex].nativeBuffer16[displayID]); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, displayInfoList[bufferIndex].nativeBuffer16[displayID]); } -void OGLClientFetchObject::_FetchCustomDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex) +void OGLClientSharedData::FetchCustomDisplayByID_OGL(const NDSDisplayInfo *displayInfoList, const NDSDisplayID displayID, const u8 bufferIndex) { - if (this->_useDirectToCPUFilterPipeline && (this->_fetchDisplayInfo[bufferIndex].renderedWidth[displayID] == GPU_FRAMEBUFFER_NATIVE_WIDTH) && (this->_fetchDisplayInfo[bufferIndex].renderedHeight[displayID] == GPU_FRAMEBUFFER_NATIVE_HEIGHT)) + if (this->_useDirectToCPUFilterPipeline && (displayInfoList[bufferIndex].renderedWidth[displayID] == GPU_FRAMEBUFFER_NATIVE_WIDTH) && (displayInfoList[bufferIndex].renderedHeight[displayID] == GPU_FRAMEBUFFER_NATIVE_HEIGHT)) { pthread_rwlock_wrlock(&this->_srcCloneRWLock[displayID][bufferIndex]); this->_srcCloneNeedsUpdate[displayID][bufferIndex] = true; - this->FetchCustomDisplayToSrcClone(displayID, bufferIndex, false); + this->FetchCustomDisplayToSrcClone(displayInfoList, displayID, bufferIndex, false); pthread_rwlock_unlock(&this->_srcCloneRWLock[displayID][bufferIndex]); } glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchCustom[displayID][bufferIndex]); - glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, this->_fetchDisplayInfo[bufferIndex].customWidth, this->_fetchDisplayInfo[bufferIndex].customHeight, GL_RGBA, this->_fetchColorFormatOGL, this->_fetchDisplayInfo[bufferIndex].customBuffer[displayID]); -} - -GLuint OGLClientFetchObject::GetFetchTexture(const NDSDisplayID displayID) -{ - return this->_texFetch[displayID]; -} - -void OGLClientFetchObject::SetFetchTexture(const NDSDisplayID displayID, GLuint texID) -{ - this->_texFetch[displayID] = texID; + glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, displayInfoList[bufferIndex].customWidth, displayInfoList[bufferIndex].customHeight, GL_RGBA, this->_fetchColorFormatOGL, displayInfoList[bufferIndex].customBuffer[displayID]); } #pragma mark - @@ -6873,10 +6884,12 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) return willUseShaderBasedPixelScaler; } + OGLClientSharedData *sharedData = (OGLClientSharedData *)this->_output->GetFetchObject().GetClientData(); + for (size_t i = 0; i < 2; i++) { OGLShaderProgram *shaderFilterProgram = _shaderFilter[i]->GetProgram(); - const bool useShader150 = _output->GetContextInfo()->IsUsingShader150(); + const bool useShader150 = this->_output->GetContextInfo()->IsUsingShader150(); const ShaderSupportTier shaderSupport = _output->GetContextInfo()->GetShaderSupport(); switch (filterID) @@ -6942,22 +6955,22 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) case VideoFilterTypeID_LQ2X: shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerLQ2xFragShader_110, false, useShader150); - currentHQnxLUT = ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexLQ2xLUT(); + currentHQnxLUT = sharedData->GetTexLQ2xLUT(); break; case VideoFilterTypeID_LQ2XS: shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerLQ2xSFragShader_110, false, useShader150); - currentHQnxLUT = ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexLQ2xLUT(); + currentHQnxLUT = sharedData->GetTexLQ2xLUT(); break; case VideoFilterTypeID_HQ2X: shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ2xFragShader_110, false, useShader150); - currentHQnxLUT = ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexHQ2xLUT(); + currentHQnxLUT = sharedData->GetTexHQ2xLUT(); break; case VideoFilterTypeID_HQ2XS: shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ2xSFragShader_110, false, useShader150); - currentHQnxLUT = ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexHQ2xLUT(); + currentHQnxLUT = sharedData->GetTexHQ2xLUT(); break; case VideoFilterTypeID_HQ3X: @@ -6965,7 +6978,7 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) if (shaderSupport >= ShaderSupport_LowTier) { shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ3xFragShader_110, false, useShader150); - currentHQnxLUT = ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexHQ3xLUT(); + currentHQnxLUT = sharedData->GetTexHQ3xLUT(); } else { @@ -6979,7 +6992,7 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) if (shaderSupport >= ShaderSupport_LowTier) { shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ3xSFragShader_110, false, useShader150); - currentHQnxLUT = ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexHQ3xLUT(); + currentHQnxLUT = sharedData->GetTexHQ3xLUT(); } else { @@ -6993,7 +7006,7 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) if (shaderSupport >= ShaderSupport_LowTier) { shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ4xFragShader_110, false, useShader150); - currentHQnxLUT = ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexHQ4xLUT(); + currentHQnxLUT = sharedData->GetTexHQ4xLUT(); } else { @@ -7007,7 +7020,7 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) if (shaderSupport >= ShaderSupport_LowTier) { shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ4xSFragShader_110, false, useShader150); - currentHQnxLUT = ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexHQ4xLUT(); + currentHQnxLUT = sharedData->GetTexHQ4xLUT(); } else { @@ -7119,13 +7132,14 @@ void OGLDisplayLayer::LoadNativeDisplayByID_OGL(const NDSDisplayID displayID) { if ((this->_output->GetPixelScaler() != VideoFilterTypeID_None) && !this->_output->WillFilterOnGPU() && !this->_output->GetSourceDeposterize()) { - OGLClientFetchObject &fetchObjMutable = (OGLClientFetchObject &)this->_output->GetFetchObject(); + const GPUClientFetchObject &fetchObj = this->_output->GetFetchObject(); + OGLClientSharedData *sharedData = (OGLClientSharedData *)fetchObj.GetClientData(); VideoFilter *vf = this->_output->GetPixelScalerObject(displayID); - const uint8_t bufferIndex = fetchObjMutable.GetLastFetchIndex(); + const uint8_t bufferIndex = fetchObj.GetLastFetchIndex(); pthread_rwlock_wrlock(&this->_cpuFilterRWLock[displayID][bufferIndex]); - fetchObjMutable.CopyFromSrcClone(vf->GetSrcBufferPtr(), displayID, bufferIndex); + sharedData->CopyFromSrcClone(vf->GetSrcBufferPtr(), displayID, bufferIndex); pthread_rwlock_unlock(&this->_cpuFilterRWLock[displayID][bufferIndex]); } } @@ -7134,20 +7148,23 @@ void OGLDisplayLayer::LoadCustomDisplayByID_OGL(const NDSDisplayID displayID) { if ((this->_output->GetPixelScaler() != VideoFilterTypeID_None) && !this->_output->WillFilterOnGPU() && !this->_output->GetSourceDeposterize() && (this->_output->GetEmuDisplayInfo().customWidth == GPU_FRAMEBUFFER_NATIVE_WIDTH) && (this->_output->GetEmuDisplayInfo().customHeight == GPU_FRAMEBUFFER_NATIVE_HEIGHT) ) { - OGLClientFetchObject &fetchObjMutable = (OGLClientFetchObject &)this->_output->GetFetchObject(); + const GPUClientFetchObject &fetchObj = this->_output->GetFetchObject(); + OGLClientSharedData *sharedData = (OGLClientSharedData *)fetchObj.GetClientData(); VideoFilter *vf = this->_output->GetPixelScalerObject(displayID); - const uint8_t bufferIndex = fetchObjMutable.GetLastFetchIndex(); + const uint8_t bufferIndex = fetchObj.GetLastFetchIndex(); pthread_rwlock_wrlock(&this->_cpuFilterRWLock[displayID][bufferIndex]); - fetchObjMutable.CopyFromSrcClone(vf->GetSrcBufferPtr(), displayID, bufferIndex); + sharedData->CopyFromSrcClone(vf->GetSrcBufferPtr(), displayID, bufferIndex); pthread_rwlock_unlock(&this->_cpuFilterRWLock[displayID][bufferIndex]); } } void OGLDisplayLayer::ProcessOGL() { - OGLClientFetchObject &fetchObj = (OGLClientFetchObject &)this->_output->GetFetchObject(); + const GPUClientFetchObject &fetchObj = this->_output->GetFetchObject(); + OGLClientSharedData *sharedData = (OGLClientSharedData *)fetchObj.GetClientData(); + const uint8_t bufferIndex = fetchObj.GetLastFetchIndex(); const NDSDisplayInfo &emuDisplayInfo = this->_output->GetEmuDisplayInfo(); const ClientDisplayMode mode = this->_output->GetPresenterProperties().mode; @@ -7156,8 +7173,8 @@ void OGLDisplayLayer::ProcessOGL() const bool didRenderNative[2] = { !emuDisplayInfo.didPerformCustomRender[selectedDisplaySource[NDSDisplayID_Main]], !emuDisplayInfo.didPerformCustomRender[selectedDisplaySource[NDSDisplayID_Touch]] }; - GLuint texMain = (selectedDisplaySource[NDSDisplayID_Main] == NDSDisplayID_Main) ? fetchObj.GetFetchTexture(NDSDisplayID_Main) : fetchObj.GetFetchTexture(NDSDisplayID_Touch); - GLuint texTouch = (selectedDisplaySource[NDSDisplayID_Touch] == NDSDisplayID_Touch) ? fetchObj.GetFetchTexture(NDSDisplayID_Touch) : fetchObj.GetFetchTexture(NDSDisplayID_Main); + GLuint texMain = (selectedDisplaySource[NDSDisplayID_Main] == NDSDisplayID_Main) ? sharedData->GetFetchTexture(NDSDisplayID_Main) : sharedData->GetFetchTexture(NDSDisplayID_Touch); + GLuint texTouch = (selectedDisplaySource[NDSDisplayID_Touch] == NDSDisplayID_Touch) ? sharedData->GetFetchTexture(NDSDisplayID_Touch) : sharedData->GetFetchTexture(NDSDisplayID_Main); GLsizei width[2] = { (GLsizei)emuDisplayInfo.renderedWidth[selectedDisplaySource[NDSDisplayID_Main]], (GLsizei)emuDisplayInfo.renderedWidth[selectedDisplaySource[NDSDisplayID_Touch]] }; GLsizei height[2] = { (GLsizei)emuDisplayInfo.renderedHeight[selectedDisplaySource[NDSDisplayID_Main]], (GLsizei)emuDisplayInfo.renderedHeight[selectedDisplaySource[NDSDisplayID_Touch]] }; @@ -7190,7 +7207,7 @@ void OGLDisplayLayer::ProcessOGL() { if (texFetchMainNeedsLock) { - fetchObj.FetchTextureReadLock(NDSDisplayID_Main); + sharedData->FetchTextureReadLock(NDSDisplayID_Main); } // For all shader-based filters, we need to temporarily disable GL_UNPACK_CLIENT_STORAGE_APPLE. @@ -7202,7 +7219,7 @@ void OGLDisplayLayer::ProcessOGL() if (texFetchMainNeedsLock) { - fetchObj.FetchTextureUnlock(NDSDisplayID_Main); + sharedData->FetchTextureUnlock(NDSDisplayID_Main); } isDisplayProcessedMain = true; @@ -7219,7 +7236,7 @@ void OGLDisplayLayer::ProcessOGL() { if (texFetchTouchNeedsLock) { - fetchObj.FetchTextureReadLock(NDSDisplayID_Touch); + sharedData->FetchTextureReadLock(NDSDisplayID_Touch); } glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE); @@ -7228,7 +7245,7 @@ void OGLDisplayLayer::ProcessOGL() if (texFetchTouchNeedsLock) { - fetchObj.FetchTextureUnlock(NDSDisplayID_Touch); + sharedData->FetchTextureUnlock(NDSDisplayID_Touch); } isDisplayProcessedTouch = true; @@ -7250,7 +7267,7 @@ void OGLDisplayLayer::ProcessOGL() { if (texFetchMainNeedsLock) { - fetchObj.FetchTextureReadLock(NDSDisplayID_Main); + sharedData->FetchTextureReadLock(NDSDisplayID_Main); } glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE); @@ -7259,7 +7276,7 @@ void OGLDisplayLayer::ProcessOGL() if (texFetchMainNeedsLock) { - fetchObj.FetchTextureUnlock(NDSDisplayID_Main); + sharedData->FetchTextureUnlock(NDSDisplayID_Main); } width[NDSDisplayID_Main] = (GLsizei)vfMain->GetDstWidth(); @@ -7278,7 +7295,7 @@ void OGLDisplayLayer::ProcessOGL() { if (texFetchTouchNeedsLock) { - fetchObj.FetchTextureReadLock(NDSDisplayID_Touch); + sharedData->FetchTextureReadLock(NDSDisplayID_Touch); } glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE); @@ -7287,7 +7304,7 @@ void OGLDisplayLayer::ProcessOGL() if (texFetchTouchNeedsLock) { - fetchObj.FetchTextureUnlock(NDSDisplayID_Touch); + sharedData->FetchTextureUnlock(NDSDisplayID_Touch); } width[NDSDisplayID_Touch] = (GLsizei)vfTouch->GetDstWidth(); @@ -7444,7 +7461,8 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped) this->_UpdateVerticesOGL(); } - OGLClientFetchObject &fetchObj = (OGLClientFetchObject &)this->_output->GetFetchObject(); + const GPUClientFetchObject &fetchObj = this->_output->GetFetchObject(); + OGLClientSharedData *sharedData = (OGLClientSharedData *)fetchObj.GetClientData(); const NDSDisplayInfo &emuDisplayInfo = this->_output->GetEmuDisplayInfo(); const float backlightIntensity[2] = { emuDisplayInfo.backlightIntensity[NDSDisplayID_Main], emuDisplayInfo.backlightIntensity[NDSDisplayID_Touch] }; @@ -7473,7 +7491,7 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped) if (texFetchMainNeedsLock) { - fetchObj.FetchTextureWriteLock(NDSDisplayID_Main); + sharedData->FetchTextureWriteLock(NDSDisplayID_Main); } glBindTexture(GL_TEXTURE_RECTANGLE_ARB, processedInfo.texID[NDSDisplayID_Main]); @@ -7483,7 +7501,7 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped) if (texFetchMainNeedsLock) { - fetchObj.FetchTextureUnlock(NDSDisplayID_Main); + sharedData->FetchTextureUnlock(NDSDisplayID_Main); texFetchMainNeedsLock = false; } } @@ -7501,7 +7519,7 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped) if (texFetchTouchNeedsLock) { - fetchObj.FetchTextureWriteLock(NDSDisplayID_Touch); + sharedData->FetchTextureWriteLock(NDSDisplayID_Touch); } glBindTexture(GL_TEXTURE_RECTANGLE_ARB, processedInfo.texID[NDSDisplayID_Touch]); @@ -7511,7 +7529,7 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped) if (texFetchTouchNeedsLock) { - fetchObj.FetchTextureUnlock(NDSDisplayID_Touch); + sharedData->FetchTextureUnlock(NDSDisplayID_Touch); texFetchTouchNeedsLock = false; } } @@ -7543,7 +7561,7 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped) if (texFetchMajorNeedsLock) { - fetchObj.FetchTextureWriteLock(majorDisplayID); + sharedData->FetchTextureWriteLock(majorDisplayID); } glBindTexture(GL_TEXTURE_RECTANGLE_ARB, processedInfo.texID[majorDisplayID]); @@ -7579,7 +7597,7 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped) if (texFetchMainNeedsLock && !texFetchMainAlreadyLocked) { - fetchObj.FetchTextureWriteLock(NDSDisplayID_Main); + sharedData->FetchTextureWriteLock(NDSDisplayID_Main); } glBindTexture(GL_TEXTURE_RECTANGLE_ARB, processedInfo.texID[NDSDisplayID_Main]); @@ -7589,7 +7607,7 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped) if (texFetchMainNeedsLock) { - fetchObj.FetchTextureUnlock(NDSDisplayID_Main); + sharedData->FetchTextureUnlock(NDSDisplayID_Main); texFetchMainNeedsLock = false; } } @@ -7603,7 +7621,7 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped) if (texFetchTouchNeedsLock && !texFetchTouchAlreadyLocked) { - fetchObj.FetchTextureWriteLock(NDSDisplayID_Touch); + sharedData->FetchTextureWriteLock(NDSDisplayID_Touch); } glBindTexture(GL_TEXTURE_RECTANGLE_ARB, processedInfo.texID[NDSDisplayID_Touch]); @@ -7613,7 +7631,7 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped) if (texFetchTouchNeedsLock) { - fetchObj.FetchTextureUnlock(NDSDisplayID_Touch); + sharedData->FetchTextureUnlock(NDSDisplayID_Touch); texFetchTouchNeedsLock = false; } } diff --git a/desmume/src/frontend/cocoa/OGLDisplayOutput.h b/desmume/src/frontend/cocoa/OGLDisplayOutput.h index 1524b7476..73ec5a2c7 100644 --- a/desmume/src/frontend/cocoa/OGLDisplayOutput.h +++ b/desmume/src/frontend/cocoa/OGLDisplayOutput.h @@ -338,7 +338,7 @@ public: virtual void RenderOGL(bool isRenderingFlipped); }; -class OGLClientFetchObject : public GPUClientFetchObject +class OGLClientSharedData { protected: OGLContextInfo *_contextInfo; @@ -360,14 +360,19 @@ protected: pthread_rwlock_t _texFetchRWLock[2]; bool _srcCloneNeedsUpdate[2][OPENGL_FETCH_BUFFER_COUNT]; - virtual void _FetchNativeDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex); - virtual void _FetchCustomDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex); - public: - OGLClientFetchObject(); - virtual ~OGLClientFetchObject(); + OGLClientSharedData(); + virtual ~OGLClientSharedData(); + void SetContextInfo(OGLContextInfo *contextInfo); OGLContextInfo* GetContextInfo() const; + + void SetUseDirectToCPUFilterPipeline(bool willUseDirectCPU); + bool UseDirectToCPUFilterPipeline() const; + + virtual GLuint GetFetchTexture(const NDSDisplayID displayID); + virtual void SetFetchTexture(const NDSDisplayID displayID, GLuint texID); + 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; @@ -380,18 +385,19 @@ public: GLuint GetTexHQ4xLUT() const; void CopyFromSrcClone(uint32_t *dstBufferPtr, const NDSDisplayID displayID, const u8 bufferIndex); - void FetchNativeDisplayToSrcClone(const NDSDisplayID displayID, const u8 bufferIndex, bool needsLock); - void FetchCustomDisplayToSrcClone(const NDSDisplayID displayID, const u8 bufferIndex, bool needsLock); + void FetchNativeDisplayToSrcClone(const NDSDisplayInfo *displayInfoList, const NDSDisplayID displayID, const u8 bufferIndex, bool needsLock); + void FetchCustomDisplayToSrcClone(const NDSDisplayInfo *displayInfoList, const NDSDisplayID displayID, const u8 bufferIndex, bool needsLock); void FetchTextureWriteLock(const NDSDisplayID displayID); void FetchTextureReadLock(const NDSDisplayID displayID); void FetchTextureUnlock(const NDSDisplayID displayID); - virtual void Init(); - virtual void SetFetchBuffers(const NDSDisplayInfo ¤tDisplayInfo); - virtual void FetchFromBufferIndex(const u8 index); - - virtual GLuint GetFetchTexture(const NDSDisplayID displayID); - virtual void SetFetchTexture(const NDSDisplayID displayID, GLuint texID); + // OpenGL-specific functions that must be called in response to their + // corresponding GPUClientFetchObject methods. + void InitOGL(); + void SetFetchBuffersOGL(const NDSDisplayInfo *displayInfoList, const NDSDisplayInfo ¤tDisplayInfo); + void FetchFromBufferIndexOGL(const u8 index, const NDSDisplayInfo ¤tDisplayInfo); + void FetchNativeDisplayByID_OGL(const NDSDisplayInfo *displayInfoList, const NDSDisplayID displayID, const u8 bufferIndex); + void FetchCustomDisplayByID_OGL(const NDSDisplayInfo *displayInfoList, const NDSDisplayID displayID, const u8 bufferIndex); }; class OGLVideoOutput : public ClientDisplay3DPresenter diff --git a/desmume/src/frontend/cocoa/cocoa_GPU.h b/desmume/src/frontend/cocoa/cocoa_GPU.h index b2e8711ab..2049dfc4d 100644 --- a/desmume/src/frontend/cocoa/cocoa_GPU.h +++ b/desmume/src/frontend/cocoa/cocoa_GPU.h @@ -15,12 +15,30 @@ along with the this software. If not, see . */ +#if defined(PORT_VERSION_OS_X_APP) + #define ENABLE_ASYNC_FETCH + #define ENABLE_DISPLAYLINK_FETCH + #define ENABLE_SHARED_FETCH_OBJECT +#endif + +#ifdef ENABLE_ASYNC_FETCH + #include + #include + #include + #include + + // This symbol only exists in the kernel headers, but not in the user headers. + // Manually define the symbol here, since we will be Mach semaphores in the user-space. + #ifndef SYNC_POLICY_PREPOST + #define SYNC_POLICY_PREPOST 0x4 + #endif +#endif + +#ifdef ENABLE_DISPLAYLINK_FETCH + #import +#endif + #import -#import -#include -#include -#include -#include #include #include #include "utilities.h" @@ -28,21 +46,11 @@ #import "cocoa_util.h" #include "../../GPU.h" -// This symbol only exists in the kernel headers, but not in the user headers. -// Manually define the symbol here, since we will be Mach semaphores in the user-space. -#ifndef SYNC_POLICY_PREPOST -#define SYNC_POLICY_PREPOST 0x4 -#endif - #ifdef BOOL #undef BOOL #endif -#if defined(PORT_VERSION_OS_X_APP) - #define ENABLE_SHARED_FETCH_OBJECT -#endif - -#if defined(ENABLE_SHARED_FETCH_OBJECT) && !defined(METAL_DISABLE_FOR_BUILD_TARGET) && defined(MAC_OS_X_VERSION_10_11) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11) +#if defined(ENABLE_ASYNC_FETCH) && defined(ENABLE_DISPLAYLINK_FETCH) && !defined(METAL_DISABLE_FOR_BUILD_TARGET) && defined(MAC_OS_X_VERSION_10_11) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11) #define ENABLE_APPLE_METAL #endif @@ -60,63 +68,132 @@ enum ClientDisplayBufferState class GPUEventHandlerOSX; class ClientDisplay3DView; -#ifdef ENABLE_SHARED_FETCH_OBJECT +#ifdef ENABLE_ASYNC_FETCH -typedef std::map DisplayLinksActiveMap; -typedef std::map DisplayLinkFlushTimeLimitMap; - -@interface MacClientSharedObject : NSObject +class MacGPUFetchObjectAsync : public GPUClientFetchObject { - GPUClientFetchObject *GPUFetchObject; +protected: task_t _taskEmulationLoop; apple_unfairlock_t _unfairlockFramebufferStates[MAX_FRAMEBUFFER_PAGES]; semaphore_t _semFramebuffer[MAX_FRAMEBUFFER_PAGES]; volatile ClientDisplayBufferState _framebufferState[MAX_FRAMEBUFFER_PAGES]; - pthread_rwlock_t *_rwlockOutputList; - pthread_mutex_t _mutexDisplayLinkLists; - NSMutableArray *_cdsOutputList; - volatile int32_t numberViewsUsingDirectToCPUFiltering; - - DisplayLinksActiveMap _displayLinksActiveList; - DisplayLinkFlushTimeLimitMap _displayLinkFlushTimeList; - uint32_t _threadMessageID; uint8_t _fetchIndex; pthread_t _threadFetch; pthread_cond_t _condSignalFetch; pthread_mutex_t _mutexFetchExecute; + +public: + MacGPUFetchObjectAsync(); + ~MacGPUFetchObjectAsync(); + + virtual void Init(); + + void SemaphoreFramebufferCreate(); + void SemaphoreFramebufferDestroy(); + uint8_t SelectBufferIndex(const uint8_t currentIndex, size_t pageCount); + semaphore_t SemaphoreFramebufferPageAtIndex(const u8 bufferIndex); + ClientDisplayBufferState FramebufferStateAtIndex(uint8_t index); + void SetFramebufferState(ClientDisplayBufferState bufferState, uint8_t index); + + void FetchSynchronousAtIndex(uint8_t index); + void SignalFetchAtIndex(uint8_t index, int32_t messageID); + void RunFetchLoop(); + virtual void DoPostFetchActions(); +}; + +#ifdef ENABLE_DISPLAYLINK_FETCH + +typedef std::map DisplayLinksActiveMap; +typedef std::map DisplayLinkFlushTimeLimitMap; + +class MacGPUFetchObjectDisplayLink : public MacGPUFetchObjectAsync +{ +protected: + pthread_rwlock_t *_rwlockOutputList; + pthread_mutex_t _mutexDisplayLinkLists; + NSMutableArray *_cdsOutputList; + volatile int32_t _numberViewsUsingDirectToCPUFiltering; + + DisplayLinksActiveMap _displayLinksActiveList; + DisplayLinkFlushTimeLimitMap _displayLinkFlushTimeList; + +public: + MacGPUFetchObjectDisplayLink(); + ~MacGPUFetchObjectDisplayLink(); + + volatile int32_t GetNumberViewsUsingDirectToCPUFiltering() const; + + void SetOutputList(NSMutableArray *theOutputList, pthread_rwlock_t *theRWLock); + void IncrementViewsUsingDirectToCPUFiltering(); + void DecrementViewsUsingDirectToCPUFiltering(); + void PushVideoDataToAllDisplayViews(); + + void DisplayLinkStartUsingID(CGDirectDisplayID displayID); + void DisplayLinkListUpdate(); + + virtual void FlushAllDisplaysOnDisplayLink(CVDisplayLinkRef displayLink, const CVTimeStamp *timeStampNow, const CVTimeStamp *timeStampOutput); + virtual void FlushMultipleViews(const std::vector &cdvFlushList, const CVTimeStamp *timeStampNow, const CVTimeStamp *timeStampOutput); + + virtual void DoPostFetchActions(); +}; + +@interface MacClientSharedObject : NSObject +{ + MacGPUFetchObjectDisplayLink *GPUFetchObject; } -@property (assign, nonatomic) GPUClientFetchObject *GPUFetchObject; -@property (readonly, nonatomic) volatile int32_t numberViewsUsingDirectToCPUFiltering; - -- (void) semaphoreFramebufferCreate; -- (void) semaphoreFramebufferDestroy; -- (u8) selectBufferIndex:(const u8)currentIndex pageCount:(size_t)pageCount; -- (semaphore_t) semaphoreFramebufferPageAtIndex:(const u8)bufferIndex; -- (ClientDisplayBufferState) framebufferStateAtIndex:(uint8_t)index; -- (void) setFramebufferState:(ClientDisplayBufferState)bufferState index:(uint8_t)index; - -- (void) setOutputList:(NSMutableArray *)theOutputList rwlock:(pthread_rwlock_t *)theRWLock; -- (void) incrementViewsUsingDirectToCPUFiltering; -- (void) decrementViewsUsingDirectToCPUFiltering; -- (void) pushVideoDataToAllDisplayViews; - -- (void) flushAllDisplaysOnDisplayLink:(CVDisplayLinkRef)displayLink timeStampNow:(const CVTimeStamp *)timeStampNow timeStampOutput:(const CVTimeStamp *)timeStampOutput; -- (void) flushMultipleViews:(const std::vector &)cdvFlushList timeStampNow:(const CVTimeStamp *)timeStampNow timeStampOutput:(const CVTimeStamp *)timeStampOutput; - -- (void) displayLinkStartUsingID:(CGDirectDisplayID)displayID; -- (void) displayLinkListUpdate; - -- (void) fetchSynchronousAtIndex:(uint8_t)index; -- (void) signalFetchAtIndex:(uint8_t)index message:(int32_t)messageID; -- (void) runFetchLoop; +@property (assign, nonatomic) MacGPUFetchObjectDisplayLink *GPUFetchObject; @end +#endif // ENABLE_DISPLAYLINK_FETCH + +#endif // ENABLE_ASYNC_FETCH + +class GPUEventHandlerOSX : public GPUEventHandlerDefault +{ +private: + GPUClientFetchObject *_fetchObject; + + pthread_mutex_t _mutexFrame; + pthread_mutex_t _mutex3DRender; + pthread_mutex_t _mutexApplyGPUSettings; + pthread_mutex_t _mutexApplyRender3DSettings; + bool _render3DNeedsFinish; + +public: + GPUEventHandlerOSX(); + ~GPUEventHandlerOSX(); + + GPUClientFetchObject* GetFetchObject() const; + void SetFetchObject(GPUClientFetchObject *fetchObject); + + void FramebufferLock(); + void FramebufferUnlock(); + void Render3DLock(); + void Render3DUnlock(); + void ApplyGPUSettingsLock(); + void ApplyGPUSettingsUnlock(); + void ApplyRender3DSettingsLock(); + void ApplyRender3DSettingsUnlock(); + + bool GetRender3DNeedsFinish(); + +#ifdef ENABLE_ASYNC_FETCH + virtual void DidFrameBegin(const size_t line, const bool isFrameSkipRequested, const size_t pageCount, u8 &selectedBufferIndexInOut); + virtual void DidFrameEnd(bool isFrameSkipped, const NDSDisplayInfo &latestDisplayInfo); #endif + + virtual void DidRender3DBegin(); + virtual void DidRender3DEnd(); + virtual void DidApplyGPUSettingsBegin(); + virtual void DidApplyGPUSettingsEnd(); + virtual void DidApplyRender3DSettingsBegin(); + virtual void DidApplyRender3DSettingsEnd(); +}; @interface CocoaDSGPU : NSObject { @@ -170,11 +247,9 @@ typedef std::map DisplayLinkFlushTimeLimitMap; @property (assign) BOOL openGLEmulateSpecialZeroAlphaBlending; @property (assign) BOOL openGLEmulateNDSDepthCalculation; @property (assign) BOOL openGLEmulateDepthLEqualPolygonFacing; - -#ifdef ENABLE_SHARED_FETCH_OBJECT @property (readonly, nonatomic) GPUClientFetchObject *fetchObject; -@property (readonly, nonatomic) MacClientSharedObject *sharedData; +#ifdef ENABLE_DISPLAYLINK_FETCH - (void) setOutputList:(NSMutableArray *)theOutputList rwlock:(pthread_rwlock_t *)theRWLock; #endif @@ -190,18 +265,6 @@ extern "C" { #endif -#ifdef ENABLE_SHARED_FETCH_OBJECT - -static void* RunFetchThread(void *arg); - -CVReturn MacDisplayLinkCallback(CVDisplayLinkRef displayLink, - const CVTimeStamp *inNow, - const CVTimeStamp *inOutputTime, - CVOptionFlags flagsIn, - CVOptionFlags *flagsOut, - void *displayLinkContext); -#endif - bool OSXOpenGLRendererInit(); bool OSXOpenGLRendererBegin(); void OSXOpenGLRendererEnd(); diff --git a/desmume/src/frontend/cocoa/cocoa_GPU.mm b/desmume/src/frontend/cocoa/cocoa_GPU.mm index f1d5a0884..b8a22163f 100644 --- a/desmume/src/frontend/cocoa/cocoa_GPU.mm +++ b/desmume/src/frontend/cocoa/cocoa_GPU.mm @@ -29,19 +29,19 @@ #include "../../OGLRender.h" #endif -#include -#import "userinterface/MacOGLDisplayView.h" +#ifdef PORT_VERSION_OS_X_APP + #import "userinterface/MacOGLDisplayView.h" -#ifdef ENABLE_APPLE_METAL - #import "userinterface/MacMetalDisplayView.h" + #ifdef ENABLE_APPLE_METAL + #import "userinterface/MacMetalDisplayView.h" + #endif #endif -#define GPU_3D_RENDERER_COUNT 3 - #ifdef BOOL #undef BOOL #endif +#define GPU_3D_RENDERER_COUNT 3 GPU3DInterface *core3DList[GPU_3D_RENDERER_COUNT+1] = { &gpu3DNull, &gpu3DRasterize, @@ -49,45 +49,6 @@ GPU3DInterface *core3DList[GPU_3D_RENDERER_COUNT+1] = { NULL }; -class GPUEventHandlerOSX : public GPUEventHandlerDefault -{ -private: - GPUClientFetchObject *_fetchObject; - - pthread_mutex_t _mutexFrame; - pthread_mutex_t _mutex3DRender; - pthread_mutex_t _mutexApplyGPUSettings; - pthread_mutex_t _mutexApplyRender3DSettings; - bool _render3DNeedsFinish; - -public: - GPUEventHandlerOSX(); - ~GPUEventHandlerOSX(); - - GPUClientFetchObject* GetFetchObject() const; - void SetFetchObject(GPUClientFetchObject *fetchObject); - - void FramebufferLock(); - void FramebufferUnlock(); - void Render3DLock(); - void Render3DUnlock(); - void ApplyGPUSettingsLock(); - void ApplyGPUSettingsUnlock(); - void ApplyRender3DSettingsLock(); - void ApplyRender3DSettingsUnlock(); - - bool GetRender3DNeedsFinish(); - - virtual void DidFrameBegin(const size_t line, const bool isFrameSkipRequested, const size_t pageCount, u8 &selectedBufferIndexInOut); - virtual void DidFrameEnd(bool isFrameSkipped, const NDSDisplayInfo &latestDisplayInfo); - virtual void DidRender3DBegin(); - virtual void DidRender3DEnd(); - virtual void DidApplyGPUSettingsBegin(); - virtual void DidApplyGPUSettingsEnd(); - virtual void DidApplyRender3DSettingsBegin(); - virtual void DidApplyRender3DSettingsEnd(); -}; - @implementation CocoaDSGPU @dynamic gpuStateFlags; @@ -127,11 +88,7 @@ public: @dynamic openGLEmulateSpecialZeroAlphaBlending; @dynamic openGLEmulateNDSDepthCalculation; @dynamic openGLEmulateDepthLEqualPolygonFacing; - -#ifdef ENABLE_SHARED_FETCH_OBJECT @synthesize fetchObject; -@dynamic sharedData; -#endif - (id)init { @@ -239,16 +196,6 @@ public: [super dealloc]; } -- (GPUClientFetchObject *) fetchObject -{ - return fetchObject; -} - -- (MacClientSharedObject *) sharedData -{ - return (MacClientSharedObject *)fetchObject->GetClientData(); -} - - (void) setGpuStateFlags:(UInt32)flags { apple_unfairlock_lock(_unfairlockGpuState); @@ -287,22 +234,22 @@ public: gpuEvent->Render3DLock(); gpuEvent->FramebufferLock(); -#ifdef ENABLE_SHARED_FETCH_OBJECT +#ifdef ENABLE_ASYNC_FETCH const size_t maxPages = GPU->GetDisplayInfo().framebufferPageCount; for (size_t i = 0; i < maxPages; i++) { - semaphore_wait([[self sharedData] semaphoreFramebufferPageAtIndex:i]); + semaphore_wait( ((MacGPUFetchObjectAsync *)fetchObject)->SemaphoreFramebufferPageAtIndex(i) ); } #endif GPU->SetCustomFramebufferSize(w, h); -#ifdef ENABLE_SHARED_FETCH_OBJECT +#ifdef ENABLE_ASYNC_FETCH fetchObject->SetFetchBuffers(GPU->GetDisplayInfo()); for (size_t i = maxPages - 1; i < maxPages; i--) { - semaphore_signal([[self sharedData] semaphoreFramebufferPageAtIndex:i]); + semaphore_signal( ((MacGPUFetchObjectAsync *)fetchObject)->SemaphoreFramebufferPageAtIndex(i) ); } #endif @@ -359,22 +306,22 @@ public: if (dispInfo.colorFormat != (NDSColorFormat)colorFormat) { -#ifdef ENABLE_SHARED_FETCH_OBJECT +#ifdef ENABLE_ASYNC_FETCH const size_t maxPages = GPU->GetDisplayInfo().framebufferPageCount; for (size_t i = 0; i < maxPages; i++) { - semaphore_wait([[self sharedData] semaphoreFramebufferPageAtIndex:i]); + semaphore_wait( ((MacGPUFetchObjectAsync *)fetchObject)->SemaphoreFramebufferPageAtIndex(i) ); } #endif GPU->SetColorFormat((NDSColorFormat)colorFormat); -#ifdef ENABLE_SHARED_FETCH_OBJECT +#ifdef ENABLE_ASYNC_FETCH fetchObject->SetFetchBuffers(GPU->GetDisplayInfo()); for (size_t i = maxPages - 1; i < maxPages; i--) { - semaphore_signal([[self sharedData] semaphoreFramebufferPageAtIndex:i]); + semaphore_signal( ((MacGPUFetchObjectAsync *)fetchObject)->SemaphoreFramebufferPageAtIndex(i) ); } #endif } @@ -399,10 +346,10 @@ public: return colorFormat; } -#ifdef ENABLE_SHARED_FETCH_OBJECT +#ifdef ENABLE_DISPLAYLINK_FETCH - (void) setOutputList:(NSMutableArray *)theOutputList rwlock:(pthread_rwlock_t *)theRWLock { - [(MacClientSharedObject *)fetchObject->GetClientData() setOutputList:theOutputList rwlock:theRWLock]; + ((MacGPUFetchObjectDisplayLink *)fetchObject)->SetOutputList(theOutputList, theRWLock); } #endif @@ -1088,28 +1035,28 @@ public: { gpuEvent->FramebufferLock(); -#ifdef ENABLE_SHARED_FETCH_OBJECT +#ifdef ENABLE_ASYNC_FETCH const size_t maxPages = GPU->GetDisplayInfo().framebufferPageCount; for (size_t i = 0; i < maxPages; i++) { - semaphore_wait([[self sharedData] semaphoreFramebufferPageAtIndex:i]); + semaphore_wait( ((MacGPUFetchObjectAsync *)fetchObject)->SemaphoreFramebufferPageAtIndex(i) ); } #endif GPU->ClearWithColor(colorBGRA5551); -#ifdef ENABLE_SHARED_FETCH_OBJECT +#ifdef ENABLE_ASYNC_FETCH for (size_t i = maxPages - 1; i < maxPages; i--) { - semaphore_signal([[self sharedData] semaphoreFramebufferPageAtIndex:i]); + semaphore_signal( ((MacGPUFetchObjectAsync *)fetchObject)->SemaphoreFramebufferPageAtIndex(i) ); } #endif gpuEvent->FramebufferUnlock(); -#ifdef ENABLE_SHARED_FETCH_OBJECT +#ifdef ENABLE_ASYNC_FETCH const u8 bufferIndex = GPU->GetDisplayInfo().bufferIndex; - [[self sharedData] signalFetchAtIndex:bufferIndex message:MESSAGE_FETCH_AND_PUSH_VIDEO]; + ((MacGPUFetchObjectAsync *)fetchObject)->SignalFetchAtIndex(bufferIndex, MESSAGE_FETCH_AND_PUSH_VIDEO); #endif } @@ -1141,7 +1088,6 @@ public: @implementation MacClientSharedObject @synthesize GPUFetchObject; -@synthesize numberViewsUsingDirectToCPUFiltering; - (id)init { @@ -1151,33 +1097,45 @@ public: return self; } - pthread_mutex_init(&_mutexDisplayLinkLists, NULL); - GPUFetchObject = nil; - _rwlockOutputList = NULL; - _cdsOutputList = nil; - numberViewsUsingDirectToCPUFiltering = 0; - _displayLinksActiveList.clear(); - _displayLinkFlushTimeList.clear(); - [self displayLinkListUpdate]; + return self; +} + +@end + +#pragma mark - + +static void* RunFetchThread(void *arg) +{ +#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) + if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber10_6) + { + pthread_setname_np("Video Fetch"); + } +#endif + MacGPUFetchObjectAsync *asyncFetchObj = (MacGPUFetchObjectAsync *)arg; + asyncFetchObj->RunFetchLoop(); + + return NULL; +} + +MacGPUFetchObjectAsync::MacGPUFetchObjectAsync() +{ + _threadFetch = NULL; _threadMessageID = MESSAGE_NONE; _fetchIndex = 0; pthread_cond_init(&_condSignalFetch, NULL); pthread_mutex_init(&_mutexFetchExecute, NULL); - pthread_attr_t threadAttr; - pthread_attr_init(&threadAttr); - pthread_attr_setschedpolicy(&threadAttr, SCHED_RR); + _id = GPUClientFetchObjectID_GenericAsync; - struct sched_param sp; - memset(&sp, 0, sizeof(struct sched_param)); - sp.sched_priority = 44; - pthread_attr_setschedparam(&threadAttr, &sp); + memset(_name, 0, sizeof(_name)); + strncpy(_name, "Generic Asynchronous Video", sizeof(_name) - 1); - pthread_create(&_threadFetch, &threadAttr, &RunFetchThread, self); - pthread_attr_destroy(&threadAttr); + memset(_description, 0, sizeof(_description)); + strncpy(_description, "No description.", sizeof(_description) - 1); _taskEmulationLoop = 0; @@ -1187,88 +1145,58 @@ public: _framebufferState[i] = ClientDisplayBufferState_Idle; _unfairlockFramebufferStates[i] = apple_unfairlock_create(); } - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(respondToScreenChange:) - name:@"NSApplicationDidChangeScreenParametersNotification" - object:NSApp]; - - return self; } -- (void)dealloc +MacGPUFetchObjectAsync::~MacGPUFetchObjectAsync() { - pthread_cancel(_threadFetch); - pthread_join(_threadFetch, NULL); - _threadFetch = NULL; + pthread_cancel(this->_threadFetch); + pthread_join(this->_threadFetch, NULL); + this->_threadFetch = NULL; - pthread_cond_destroy(&_condSignalFetch); - pthread_mutex_destroy(&_mutexFetchExecute); - - pthread_mutex_lock(&_mutexDisplayLinkLists); - - while (_displayLinksActiveList.size() > 0) - { - DisplayLinksActiveMap::iterator it = _displayLinksActiveList.begin(); - CGDirectDisplayID displayID = it->first; - CVDisplayLinkRef displayLinkRef = it->second; - - if (CVDisplayLinkIsRunning(displayLinkRef)) - { - CVDisplayLinkStop(displayLinkRef); - } - - CVDisplayLinkRelease(displayLinkRef); - - _displayLinksActiveList.erase(displayID); - _displayLinkFlushTimeList.erase(displayID); - } - - pthread_mutex_unlock(&_mutexDisplayLinkLists); - pthread_mutex_destroy(&_mutexDisplayLinkLists); - - pthread_rwlock_t *currentRWLock = _rwlockOutputList; - - if (currentRWLock != NULL) - { - pthread_rwlock_wrlock(currentRWLock); - } - - [_cdsOutputList release]; - - if (currentRWLock != NULL) - { - pthread_rwlock_unlock(currentRWLock); - } - - [super dealloc]; + pthread_cond_destroy(&this->_condSignalFetch); + pthread_mutex_destroy(&this->_mutexFetchExecute); } -- (void) semaphoreFramebufferCreate +void MacGPUFetchObjectAsync::Init() { - _taskEmulationLoop = mach_task_self(); + pthread_attr_t threadAttr; + pthread_attr_init(&threadAttr); + pthread_attr_setschedpolicy(&threadAttr, SCHED_RR); + + struct sched_param sp; + memset(&sp, 0, sizeof(struct sched_param)); + sp.sched_priority = 44; + pthread_attr_setschedparam(&threadAttr, &sp); + + pthread_create(&_threadFetch, &threadAttr, &RunFetchThread, this); + pthread_attr_destroy(&threadAttr); +} + +void MacGPUFetchObjectAsync::SemaphoreFramebufferCreate() +{ + this->_taskEmulationLoop = mach_task_self(); for (size_t i = 0; i < MAX_FRAMEBUFFER_PAGES; i++) { - semaphore_create(_taskEmulationLoop, &_semFramebuffer[i], SYNC_POLICY_FIFO, 1); + semaphore_create(this->_taskEmulationLoop, &this->_semFramebuffer[i], SYNC_POLICY_FIFO, 1); } } -- (void) semaphoreFramebufferDestroy +void MacGPUFetchObjectAsync::SemaphoreFramebufferDestroy() { for (size_t i = MAX_FRAMEBUFFER_PAGES - 1; i < MAX_FRAMEBUFFER_PAGES; i--) { - if (_semFramebuffer[i] != 0) + if (this->_semFramebuffer[i] != 0) { - semaphore_destroy(_taskEmulationLoop, _semFramebuffer[i]); - _semFramebuffer[i] = 0; + semaphore_destroy(this->_taskEmulationLoop, this->_semFramebuffer[i]); + this->_semFramebuffer[i] = 0; } } } -- (u8) selectBufferIndex:(const u8)currentIndex pageCount:(size_t)pageCount +uint8_t MacGPUFetchObjectAsync::SelectBufferIndex(const uint8_t currentIndex, size_t pageCount) { - u8 selectedIndex = currentIndex; + uint8_t selectedIndex = currentIndex; bool stillSearching = true; // First, search for an idle buffer along with its corresponding semaphore. @@ -1277,7 +1205,7 @@ public: selectedIndex = (selectedIndex + 1) % pageCount; for (; selectedIndex != currentIndex; selectedIndex = (selectedIndex + 1) % pageCount) { - if ([self framebufferStateAtIndex:selectedIndex] == ClientDisplayBufferState_Idle) + if (this->FramebufferStateAtIndex(selectedIndex) == ClientDisplayBufferState_Idle) { stillSearching = false; break; @@ -1291,8 +1219,8 @@ public: selectedIndex = (selectedIndex + 1) % pageCount; for (size_t spin = 0; spin < 100ULL * pageCount; selectedIndex = (selectedIndex + 1) % pageCount, spin++) { - if ( ([self framebufferStateAtIndex:selectedIndex] == ClientDisplayBufferState_Idle) || - (([self framebufferStateAtIndex:selectedIndex] == ClientDisplayBufferState_Ready) && (selectedIndex != currentIndex)) ) + if ( (this->FramebufferStateAtIndex(selectedIndex) == ClientDisplayBufferState_Idle) || + ((this->FramebufferStateAtIndex(selectedIndex) == ClientDisplayBufferState_Ready) && (selectedIndex != currentIndex)) ) { stillSearching = false; break; @@ -1308,7 +1236,7 @@ public: selectedIndex = (selectedIndex + 1) % pageCount; for (size_t spin = 0; spin < 10000ULL * pageCount; selectedIndex = (selectedIndex + 1) % pageCount, spin++) { - if ([self framebufferStateAtIndex:selectedIndex] == ClientDisplayBufferState_Idle) + if (this->FramebufferStateAtIndex(selectedIndex) == ClientDisplayBufferState_Idle) { stillSearching = false; break; @@ -1324,9 +1252,9 @@ public: selectedIndex = (selectedIndex + 1) % pageCount; for (; selectedIndex != currentIndex; selectedIndex = (selectedIndex + 1) % pageCount) { - if ( ([self framebufferStateAtIndex:selectedIndex] == ClientDisplayBufferState_Idle) || - ([self framebufferStateAtIndex:selectedIndex] == ClientDisplayBufferState_Ready) || - ([self framebufferStateAtIndex:selectedIndex] == ClientDisplayBufferState_Reading) ) + if ( (this->FramebufferStateAtIndex(selectedIndex) == ClientDisplayBufferState_Idle) || + (this->FramebufferStateAtIndex(selectedIndex) == ClientDisplayBufferState_Ready) || + (this->FramebufferStateAtIndex(selectedIndex) == ClientDisplayBufferState_Reading) ) { stillSearching = false; break; @@ -1337,69 +1265,211 @@ public: return selectedIndex; } -- (semaphore_t) semaphoreFramebufferPageAtIndex:(const u8)bufferIndex +semaphore_t MacGPUFetchObjectAsync::SemaphoreFramebufferPageAtIndex(const u8 bufferIndex) { assert(bufferIndex < MAX_FRAMEBUFFER_PAGES); - return _semFramebuffer[bufferIndex]; + return this->_semFramebuffer[bufferIndex]; } -- (ClientDisplayBufferState) framebufferStateAtIndex:(uint8_t)index +ClientDisplayBufferState MacGPUFetchObjectAsync::FramebufferStateAtIndex(uint8_t index) { - apple_unfairlock_lock(_unfairlockFramebufferStates[index]); - const ClientDisplayBufferState bufferState = _framebufferState[index]; - apple_unfairlock_unlock(_unfairlockFramebufferStates[index]); + apple_unfairlock_lock(this->_unfairlockFramebufferStates[index]); + const ClientDisplayBufferState bufferState = this->_framebufferState[index]; + apple_unfairlock_unlock(this->_unfairlockFramebufferStates[index]); return bufferState; } -- (void) setFramebufferState:(ClientDisplayBufferState)bufferState index:(uint8_t)index +void MacGPUFetchObjectAsync::SetFramebufferState(ClientDisplayBufferState bufferState, uint8_t index) { - apple_unfairlock_lock(_unfairlockFramebufferStates[index]); - _framebufferState[index] = bufferState; - apple_unfairlock_unlock(_unfairlockFramebufferStates[index]); + apple_unfairlock_lock(this->_unfairlockFramebufferStates[index]); + this->_framebufferState[index] = bufferState; + apple_unfairlock_unlock(this->_unfairlockFramebufferStates[index]); } -- (void) setOutputList:(NSMutableArray *)theOutputList rwlock:(pthread_rwlock_t *)theRWLock +void MacGPUFetchObjectAsync::FetchSynchronousAtIndex(uint8_t index) { - pthread_rwlock_t *currentRWLock = _rwlockOutputList; + this->FetchFromBufferIndex(index); +} + +void MacGPUFetchObjectAsync::SignalFetchAtIndex(uint8_t index, int32_t messageID) +{ + pthread_mutex_lock(&this->_mutexFetchExecute); + + this->_fetchIndex = index; + this->_threadMessageID = messageID; + pthread_cond_signal(&this->_condSignalFetch); + + pthread_mutex_unlock(&this->_mutexFetchExecute); +} + +void MacGPUFetchObjectAsync::RunFetchLoop() +{ + NSAutoreleasePool *tempPool = nil; + pthread_mutex_lock(&this->_mutexFetchExecute); + + do + { + tempPool = [[NSAutoreleasePool alloc] init]; + + while (this->_threadMessageID == MESSAGE_NONE) + { + pthread_cond_wait(&this->_condSignalFetch, &this->_mutexFetchExecute); + } + + this->FetchFromBufferIndex(this->_fetchIndex); + this->DoPostFetchActions(); + this->_threadMessageID = MESSAGE_NONE; + + [tempPool release]; + } while(true); +} + +void MacGPUFetchObjectAsync::DoPostFetchActions() +{ + // Do nothing. +} + +#pragma mark - + +static void ScreenChangeCallback(CFNotificationCenterRef center, + void *observer, + CFStringRef name, + const void *object, + CFDictionaryRef userInfo) +{ + ((MacGPUFetchObjectDisplayLink *)observer)->DisplayLinkListUpdate(); +} + +static CVReturn MacDisplayLinkCallback(CVDisplayLinkRef displayLink, + const CVTimeStamp *inNow, + const CVTimeStamp *inOutputTime, + CVOptionFlags flagsIn, + CVOptionFlags *flagsOut, + void *displayLinkContext) +{ + MacGPUFetchObjectDisplayLink *fetchObj = (MacGPUFetchObjectDisplayLink *)displayLinkContext; + + NSAutoreleasePool *tempPool = [[NSAutoreleasePool alloc] init]; + fetchObj->FlushAllDisplaysOnDisplayLink(displayLink, inNow, inOutputTime); + [tempPool release]; + + return kCVReturnSuccess; +} + +MacGPUFetchObjectDisplayLink::MacGPUFetchObjectDisplayLink() +{ + _id = GPUClientFetchObjectID_GenericDisplayLink; + + memset(_name, 0, sizeof(_name)); + strncpy(_name, "Generic Mac Display Link Video", sizeof(_name) - 1); + + memset(_description, 0, sizeof(_description)); + strncpy(_description, "No description.", sizeof(_description) - 1); + + pthread_mutex_init(&_mutexDisplayLinkLists, NULL); + + _rwlockOutputList = NULL; + _cdsOutputList = nil; + _numberViewsUsingDirectToCPUFiltering = 0; + + _displayLinksActiveList.clear(); + _displayLinkFlushTimeList.clear(); + DisplayLinkListUpdate(); + + CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(), + this, + ScreenChangeCallback, + CFSTR("NSApplicationDidChangeScreenParametersNotification"), + NULL, + CFNotificationSuspensionBehaviorDeliverImmediately); +} + +MacGPUFetchObjectDisplayLink::~MacGPUFetchObjectDisplayLink() +{ + pthread_mutex_lock(&this->_mutexDisplayLinkLists); + + while (this->_displayLinksActiveList.size() > 0) + { + DisplayLinksActiveMap::iterator it = this->_displayLinksActiveList.begin(); + CGDirectDisplayID displayID = it->first; + CVDisplayLinkRef displayLinkRef = it->second; + + if (CVDisplayLinkIsRunning(displayLinkRef)) + { + CVDisplayLinkStop(displayLinkRef); + } + + CVDisplayLinkRelease(displayLinkRef); + + this->_displayLinksActiveList.erase(displayID); + this->_displayLinkFlushTimeList.erase(displayID); + } + + pthread_mutex_unlock(&this->_mutexDisplayLinkLists); + pthread_mutex_destroy(&this->_mutexDisplayLinkLists); + + pthread_rwlock_t *currentRWLock = this->_rwlockOutputList; if (currentRWLock != NULL) { pthread_rwlock_wrlock(currentRWLock); } - [_cdsOutputList release]; - _cdsOutputList = theOutputList; - [_cdsOutputList retain]; + [this->_cdsOutputList release]; + + if (currentRWLock != NULL) + { + pthread_rwlock_unlock(currentRWLock); + } +} + +volatile int32_t MacGPUFetchObjectDisplayLink::GetNumberViewsUsingDirectToCPUFiltering() const +{ + return this->_numberViewsUsingDirectToCPUFiltering; +} + +void MacGPUFetchObjectDisplayLink::SetOutputList(NSMutableArray *theOutputList, pthread_rwlock_t *theRWLock) +{ + pthread_rwlock_t *currentRWLock = this->_rwlockOutputList; + + if (currentRWLock != NULL) + { + pthread_rwlock_wrlock(currentRWLock); + } + + [this->_cdsOutputList release]; + this->_cdsOutputList = theOutputList; + [this->_cdsOutputList retain]; if (currentRWLock != NULL) { pthread_rwlock_unlock(currentRWLock); } - _rwlockOutputList = theRWLock; + this->_rwlockOutputList = theRWLock; } -- (void) incrementViewsUsingDirectToCPUFiltering +void MacGPUFetchObjectDisplayLink::IncrementViewsUsingDirectToCPUFiltering() { - atomic_inc_32(&numberViewsUsingDirectToCPUFiltering); + atomic_inc_32(&this->_numberViewsUsingDirectToCPUFiltering); } -- (void) decrementViewsUsingDirectToCPUFiltering +void MacGPUFetchObjectDisplayLink::DecrementViewsUsingDirectToCPUFiltering() { - atomic_dec_32(&numberViewsUsingDirectToCPUFiltering); + atomic_dec_32(&this->_numberViewsUsingDirectToCPUFiltering); } -- (void) pushVideoDataToAllDisplayViews +void MacGPUFetchObjectDisplayLink::PushVideoDataToAllDisplayViews() { - pthread_rwlock_t *currentRWLock = _rwlockOutputList; + pthread_rwlock_t *currentRWLock = this->_rwlockOutputList; if (currentRWLock != NULL) { pthread_rwlock_rdlock(currentRWLock); } - for (CocoaDSOutput *cdsOutput in _cdsOutputList) + for (CocoaDSOutput *cdsOutput in this->_cdsOutputList) { if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]]) { @@ -1413,9 +1483,95 @@ public: } } -- (void) flushAllDisplaysOnDisplayLink:(CVDisplayLinkRef)displayLink timeStampNow:(const CVTimeStamp *)timeStampNow timeStampOutput:(const CVTimeStamp *)timeStampOutput +void MacGPUFetchObjectDisplayLink::DisplayLinkStartUsingID(CGDirectDisplayID displayID) { - pthread_rwlock_t *currentRWLock = _rwlockOutputList; + CVDisplayLinkRef displayLink = NULL; + + pthread_mutex_lock(&this->_mutexDisplayLinkLists); + + if (this->_displayLinksActiveList.find(displayID) != this->_displayLinksActiveList.end()) + { + displayLink = this->_displayLinksActiveList[displayID]; + } + + if ( (displayLink != NULL) && !CVDisplayLinkIsRunning(displayLink) ) + { + CVDisplayLinkStart(displayLink); + } + + pthread_mutex_unlock(&this->_mutexDisplayLinkLists); +} + +void MacGPUFetchObjectDisplayLink::DisplayLinkListUpdate() +{ + // Set up the display links + NSArray *screenList = [NSScreen screens]; + std::set screenActiveDisplayIDsList; + + pthread_mutex_lock(&this->_mutexDisplayLinkLists); + + // Add new CGDirectDisplayIDs for new screens + for (size_t i = 0; i < [screenList count]; i++) + { + NSScreen *screen = [screenList objectAtIndex:i]; + NSDictionary *deviceDescription = [screen deviceDescription]; + NSNumber *idNumber = (NSNumber *)[deviceDescription valueForKey:@"NSScreenNumber"]; + + CGDirectDisplayID displayID = [idNumber unsignedIntValue]; + bool isDisplayLinkStillActive = (this->_displayLinksActiveList.find(displayID) != this->_displayLinksActiveList.end()); + + if (!isDisplayLinkStillActive) + { + CVDisplayLinkRef newDisplayLink; + CVDisplayLinkCreateWithCGDisplay(displayID, &newDisplayLink); + CVDisplayLinkSetOutputCallback(newDisplayLink, &MacDisplayLinkCallback, this); + + this->_displayLinksActiveList[displayID] = newDisplayLink; + this->_displayLinkFlushTimeList[displayID] = 0; + } + + // While we're iterating through NSScreens, save the CGDirectDisplayID to a temporary list for later use. + screenActiveDisplayIDsList.insert(displayID); + } + + // Remove old CGDirectDisplayIDs for screens that no longer exist + for (DisplayLinksActiveMap::iterator it = this->_displayLinksActiveList.begin(); it != this->_displayLinksActiveList.end(); ) + { + CGDirectDisplayID displayID = it->first; + CVDisplayLinkRef displayLinkRef = it->second; + + if (screenActiveDisplayIDsList.find(displayID) == screenActiveDisplayIDsList.end()) + { + if (CVDisplayLinkIsRunning(displayLinkRef)) + { + CVDisplayLinkStop(displayLinkRef); + } + + CVDisplayLinkRelease(displayLinkRef); + + this->_displayLinksActiveList.erase(displayID); + this->_displayLinkFlushTimeList.erase(displayID); + + if (this->_displayLinksActiveList.empty()) + { + break; + } + else + { + it = this->_displayLinksActiveList.begin(); + continue; + } + } + + ++it; + } + + pthread_mutex_unlock(&this->_mutexDisplayLinkLists); +} + +void MacGPUFetchObjectDisplayLink::FlushAllDisplaysOnDisplayLink(CVDisplayLinkRef displayLink, const CVTimeStamp *timeStampNow, const CVTimeStamp *timeStampOutput) +{ + pthread_rwlock_t *currentRWLock = this->_rwlockOutputList; CGDirectDisplayID displayID = CVDisplayLinkGetCurrentCGDisplay(displayLink); bool didFlushOccur = false; @@ -1426,7 +1582,7 @@ public: pthread_rwlock_rdlock(currentRWLock); } - for (CocoaDSOutput *cdsOutput in _cdsOutputList) + for (CocoaDSOutput *cdsOutput in this->_cdsOutputList) { if ([cdsOutput isKindOfClass:[CocoaDSDisplayVideo class]]) { @@ -1446,7 +1602,7 @@ public: if (listSize > 0) { - [self flushMultipleViews:cdvFlushList timeStampNow:timeStampNow timeStampOutput:timeStampOutput]; + this->FlushMultipleViews(cdvFlushList, timeStampNow, timeStampOutput); didFlushOccur = true; } @@ -1458,15 +1614,15 @@ public: if (didFlushOccur) { // Set the new time limit to 8 seconds after the current time. - _displayLinkFlushTimeList[displayID] = timeStampNow->videoTime + (timeStampNow->videoTimeScale * VIDEO_FLUSH_TIME_LIMIT_OFFSET); + this->_displayLinkFlushTimeList[displayID] = timeStampNow->videoTime + (timeStampNow->videoTimeScale * VIDEO_FLUSH_TIME_LIMIT_OFFSET); } - else if (timeStampNow->videoTime > _displayLinkFlushTimeList[displayID]) + else if (timeStampNow->videoTime > this->_displayLinkFlushTimeList[displayID]) { CVDisplayLinkStop(displayLink); } } -- (void) flushMultipleViews:(const std::vector &)cdvFlushList timeStampNow:(const CVTimeStamp *)timeStampNow timeStampOutput:(const CVTimeStamp *)timeStampOutput +void MacGPUFetchObjectDisplayLink::FlushMultipleViews(const std::vector &cdvFlushList, const CVTimeStamp *timeStampNow, const CVTimeStamp *timeStampOutput) { const size_t listSize = cdvFlushList.size(); @@ -1483,139 +1639,12 @@ public: } } -- (void) displayLinkStartUsingID:(CGDirectDisplayID)displayID +void MacGPUFetchObjectDisplayLink::DoPostFetchActions() { - CVDisplayLinkRef displayLink = NULL; - - pthread_mutex_lock(&_mutexDisplayLinkLists); - - if (_displayLinksActiveList.find(displayID) != _displayLinksActiveList.end()) - { - displayLink = _displayLinksActiveList[displayID]; - } - - if ( (displayLink != NULL) && !CVDisplayLinkIsRunning(displayLink) ) - { - CVDisplayLinkStart(displayLink); - } - - pthread_mutex_unlock(&_mutexDisplayLinkLists); + this->PushVideoDataToAllDisplayViews(); } -- (void) displayLinkListUpdate -{ - // Set up the display links - NSArray *screenList = [NSScreen screens]; - std::set screenActiveDisplayIDsList; - - pthread_mutex_lock(&_mutexDisplayLinkLists); - - // Add new CGDirectDisplayIDs for new screens - for (size_t i = 0; i < [screenList count]; i++) - { - NSScreen *screen = [screenList objectAtIndex:i]; - NSDictionary *deviceDescription = [screen deviceDescription]; - NSNumber *idNumber = (NSNumber *)[deviceDescription valueForKey:@"NSScreenNumber"]; - - CGDirectDisplayID displayID = [idNumber unsignedIntValue]; - bool isDisplayLinkStillActive = (_displayLinksActiveList.find(displayID) != _displayLinksActiveList.end()); - - if (!isDisplayLinkStillActive) - { - CVDisplayLinkRef newDisplayLink; - CVDisplayLinkCreateWithCGDisplay(displayID, &newDisplayLink); - CVDisplayLinkSetOutputCallback(newDisplayLink, &MacDisplayLinkCallback, self); - - _displayLinksActiveList[displayID] = newDisplayLink; - _displayLinkFlushTimeList[displayID] = 0; - } - - // While we're iterating through NSScreens, save the CGDirectDisplayID to a temporary list for later use. - screenActiveDisplayIDsList.insert(displayID); - } - - // Remove old CGDirectDisplayIDs for screens that no longer exist - for (DisplayLinksActiveMap::iterator it = _displayLinksActiveList.begin(); it != _displayLinksActiveList.end(); ) - { - CGDirectDisplayID displayID = it->first; - CVDisplayLinkRef displayLinkRef = it->second; - - if (screenActiveDisplayIDsList.find(displayID) == screenActiveDisplayIDsList.end()) - { - if (CVDisplayLinkIsRunning(displayLinkRef)) - { - CVDisplayLinkStop(displayLinkRef); - } - - CVDisplayLinkRelease(displayLinkRef); - - _displayLinksActiveList.erase(displayID); - _displayLinkFlushTimeList.erase(displayID); - - if (_displayLinksActiveList.empty()) - { - break; - } - else - { - it = _displayLinksActiveList.begin(); - continue; - } - } - - ++it; - } - - pthread_mutex_unlock(&_mutexDisplayLinkLists); -} - -- (void) fetchSynchronousAtIndex:(uint8_t)index -{ - GPUFetchObject->FetchFromBufferIndex(index); -} - -- (void) signalFetchAtIndex:(uint8_t)index message:(int32_t)messageID -{ - pthread_mutex_lock(&_mutexFetchExecute); - - _fetchIndex = index; - _threadMessageID = messageID; - pthread_cond_signal(&_condSignalFetch); - - pthread_mutex_unlock(&_mutexFetchExecute); -} - -- (void) runFetchLoop -{ - NSAutoreleasePool *tempPool = nil; - pthread_mutex_lock(&_mutexFetchExecute); - - do - { - tempPool = [[NSAutoreleasePool alloc] init]; - - while (_threadMessageID == MESSAGE_NONE) - { - pthread_cond_wait(&_condSignalFetch, &_mutexFetchExecute); - } - - GPUFetchObject->FetchFromBufferIndex(_fetchIndex); - [self pushVideoDataToAllDisplayViews]; - _threadMessageID = MESSAGE_NONE; - - [tempPool release]; - - } while(true); -} - -- (void) respondToScreenChange:(NSNotification *)aNotification -{ - [self displayLinkListUpdate]; -} - -@end - -#endif +#endif // ENABLE_SHARED_FETCH_OBJECT #pragma mark - @@ -1652,48 +1681,47 @@ void GPUEventHandlerOSX::SetFetchObject(GPUClientFetchObject *fetchObject) this->_fetchObject = fetchObject; } +#ifdef ENABLE_ASYNC_FETCH + void GPUEventHandlerOSX::DidFrameBegin(const size_t line, const bool isFrameSkipRequested, const size_t pageCount, u8 &selectedBufferIndexInOut) { + MacGPUFetchObjectAsync *asyncFetchObj = (MacGPUFetchObjectAsync *)this->_fetchObject; + this->FramebufferLock(); -#ifdef ENABLE_SHARED_FETCH_OBJECT if (!isFrameSkipRequested) { - MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_fetchObject->GetClientData(); - if ( (pageCount > 1) && (line == 0) ) { - selectedBufferIndexInOut = [sharedViewObject selectBufferIndex:selectedBufferIndexInOut pageCount:pageCount]; + selectedBufferIndexInOut = asyncFetchObj->SelectBufferIndex(selectedBufferIndexInOut, pageCount); } - semaphore_wait([sharedViewObject semaphoreFramebufferPageAtIndex:selectedBufferIndexInOut]); - [sharedViewObject setFramebufferState:ClientDisplayBufferState_Writing index:selectedBufferIndexInOut]; + semaphore_wait( asyncFetchObj->SemaphoreFramebufferPageAtIndex(selectedBufferIndexInOut) ); + asyncFetchObj->SetFramebufferState(ClientDisplayBufferState_Writing, selectedBufferIndexInOut); } -#endif } void GPUEventHandlerOSX::DidFrameEnd(bool isFrameSkipped, const NDSDisplayInfo &latestDisplayInfo) { -#ifdef ENABLE_SHARED_FETCH_OBJECT - MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_fetchObject->GetClientData(); + MacGPUFetchObjectAsync *asyncFetchObj = (MacGPUFetchObjectAsync *)this->_fetchObject; + if (!isFrameSkipped) { - this->_fetchObject->SetFetchDisplayInfo(latestDisplayInfo); - [sharedViewObject setFramebufferState:ClientDisplayBufferState_Ready index:latestDisplayInfo.bufferIndex]; - semaphore_signal([sharedViewObject semaphoreFramebufferPageAtIndex:latestDisplayInfo.bufferIndex]); + asyncFetchObj->SetFetchDisplayInfo(latestDisplayInfo); + asyncFetchObj->SetFramebufferState(ClientDisplayBufferState_Ready, latestDisplayInfo.bufferIndex); + semaphore_signal( asyncFetchObj->SemaphoreFramebufferPageAtIndex(latestDisplayInfo.bufferIndex) ); } -#endif this->FramebufferUnlock(); -#ifdef ENABLE_SHARED_FETCH_OBJECT if (!isFrameSkipped) { - [sharedViewObject signalFetchAtIndex:latestDisplayInfo.bufferIndex message:MESSAGE_FETCH_AND_PUSH_VIDEO]; + asyncFetchObj->SignalFetchAtIndex(latestDisplayInfo.bufferIndex, MESSAGE_FETCH_AND_PUSH_VIDEO); } -#endif } +#endif // ENABLE_ASYNC_FETCH + void GPUEventHandlerOSX::DidRender3DBegin() { this->Render3DLock(); @@ -1776,41 +1804,6 @@ bool GPUEventHandlerOSX::GetRender3DNeedsFinish() CGLContextObj OSXOpenGLRendererContext = NULL; SILENCE_DEPRECATION_MACOS_10_7( CGLPBufferObj OSXOpenGLRendererPBuffer = NULL ); -#ifdef ENABLE_SHARED_FETCH_OBJECT - -static void* RunFetchThread(void *arg) -{ -#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) - if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber10_6) - { - pthread_setname_np("Video Fetch"); - } -#endif - - MacClientSharedObject *sharedData = (MacClientSharedObject *)arg; - [sharedData runFetchLoop]; - - return NULL; -} - -CVReturn MacDisplayLinkCallback(CVDisplayLinkRef displayLink, - const CVTimeStamp *inNow, - const CVTimeStamp *inOutputTime, - CVOptionFlags flagsIn, - CVOptionFlags *flagsOut, - void *displayLinkContext) -{ - MacClientSharedObject *sharedData = (MacClientSharedObject *)displayLinkContext; - - NSAutoreleasePool *tempPool = [[NSAutoreleasePool alloc] init]; - [sharedData flushAllDisplaysOnDisplayLink:displayLink timeStampNow:inNow timeStampOutput:inOutputTime]; - [tempPool release]; - - return kCVReturnSuccess; -} - -#endif - bool OSXOpenGLRendererInit() { bool isContextCreated = (OSXOpenGLRendererContext != NULL); diff --git a/desmume/src/frontend/cocoa/cocoa_core.mm b/desmume/src/frontend/cocoa/cocoa_core.mm index c61b3f054..380265431 100644 --- a/desmume/src/frontend/cocoa/cocoa_core.mm +++ b/desmume/src/frontend/cocoa/cocoa_core.mm @@ -188,7 +188,7 @@ volatile bool execute = true; [self removeAllOutputs]; - [[cdsGPU sharedData] semaphoreFramebufferDestroy]; + ((MacGPUFetchObjectAsync *)[cdsGPU fetchObject])->SemaphoreFramebufferDestroy(); [self setCdsFirmware:nil]; @@ -1179,7 +1179,7 @@ static void* RunCoreThread(void *arg) ExecutionBehavior lastBehavior = ExecutionBehavior_Pause; uint64_t frameJumpTarget = 0; - [[cdsGPU sharedData] semaphoreFramebufferCreate]; + ((MacGPUFetchObjectAsync *)[cdsGPU fetchObject])->SemaphoreFramebufferCreate(); do { diff --git a/desmume/src/frontend/cocoa/cocoa_globals.h b/desmume/src/frontend/cocoa/cocoa_globals.h index aeb7ed842..9fd81106a 100644 --- a/desmume/src/frontend/cocoa/cocoa_globals.h +++ b/desmume/src/frontend/cocoa/cocoa_globals.h @@ -395,3 +395,24 @@ enum PADDLE_CONTROL_RELATIVE = 0, PADDLE_CONTROL_DIRECT }; + +enum +{ + GPUClientFetchObjectIDMask_Async = (1 << 0), + GPUClientFetchObjectIDMask_DisplayLink = (1 << 1), + GPUClientFetchObjectIDMask_OpenGL = (1 << 2), + GPUClientFetchObjectIDMask_Metal = (1 << 3), + GPUClientFetchObjectIDMask_macOS = (1 << 4), + GPUClientFetchObjectIDMask_OpenEmu = (1 << 5) +}; + +enum +{ + GPUClientFetchObjectID_Default = 0, + GPUClientFetchObjectID_GenericAsync = GPUClientFetchObjectIDMask_Async, + GPUClientFetchObjectID_GenericDisplayLink = GPUClientFetchObjectIDMask_Async | GPUClientFetchObjectIDMask_DisplayLink, + GPUClientFetchObjectID_GenericOpenGL = GPUClientFetchObjectIDMask_Async | GPUClientFetchObjectIDMask_DisplayLink | GPUClientFetchObjectIDMask_OpenGL, + GPUClientFetchObjectID_MacOpenGL = GPUClientFetchObjectIDMask_Async | GPUClientFetchObjectIDMask_DisplayLink | GPUClientFetchObjectIDMask_OpenGL | GPUClientFetchObjectIDMask_macOS, + GPUClientFetchObjectID_MacMetal = GPUClientFetchObjectIDMask_Async | GPUClientFetchObjectIDMask_DisplayLink | GPUClientFetchObjectIDMask_Metal | GPUClientFetchObjectIDMask_macOS, + GPUClientFetchObjectID_OpenEmu = GPUClientFetchObjectIDMask_Async | GPUClientFetchObjectIDMask_DisplayLink | GPUClientFetchObjectIDMask_OpenGL | GPUClientFetchObjectIDMask_OpenEmu +}; diff --git a/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm b/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm index 7111269b0..a28e36e5a 100644 --- a/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm +++ b/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm @@ -1978,16 +1978,15 @@ static std::unordered_map _screenMap; // { DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate]; CocoaDSCore *cdsCore = (CocoaDSCore *)[[[windowController emuControl] cdsCoreController] content]; - CocoaDSGPU *cdsGPU = [cdsCore cdsGPU]; - MacClientSharedObject *macSharedData = [cdsGPU sharedData]; + MacGPUFetchObjectDisplayLink *dlFetchObj = (MacGPUFetchObjectDisplayLink *)[[cdsCore cdsGPU] fetchObject]; if (newState) { - [macSharedData incrementViewsUsingDirectToCPUFiltering]; + dlFetchObj->IncrementViewsUsingDirectToCPUFiltering(); } else { - [macSharedData decrementViewsUsingDirectToCPUFiltering]; + dlFetchObj->DecrementViewsUsingDirectToCPUFiltering(); } [[self cdsVideoOutput] signalMessage:MESSAGE_RELOAD_REPROCESS_REDRAW]; @@ -2009,16 +2008,15 @@ static std::unordered_map _screenMap; // { DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate]; CocoaDSCore *cdsCore = (CocoaDSCore *)[[[windowController emuControl] cdsCoreController] content]; - CocoaDSGPU *cdsGPU = [cdsCore cdsGPU]; - MacClientSharedObject *macSharedData = [cdsGPU sharedData]; + MacGPUFetchObjectDisplayLink *dlFetchObj = (MacGPUFetchObjectDisplayLink *)[[cdsCore cdsGPU] fetchObject]; if (newState) { - [macSharedData incrementViewsUsingDirectToCPUFiltering]; + dlFetchObj->IncrementViewsUsingDirectToCPUFiltering(); } else { - [macSharedData decrementViewsUsingDirectToCPUFiltering]; + dlFetchObj->DecrementViewsUsingDirectToCPUFiltering(); } } @@ -2051,16 +2049,15 @@ static std::unordered_map _screenMap; // { DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate]; CocoaDSCore *cdsCore = (CocoaDSCore *)[[[windowController emuControl] cdsCoreController] content]; - CocoaDSGPU *cdsGPU = [cdsCore cdsGPU]; - MacClientSharedObject *macSharedData = [cdsGPU sharedData]; + MacGPUFetchObjectDisplayLink *dlFetchObj = (MacGPUFetchObjectDisplayLink *)[[cdsCore cdsGPU] fetchObject]; if (newState) { - [macSharedData incrementViewsUsingDirectToCPUFiltering]; + dlFetchObj->IncrementViewsUsingDirectToCPUFiltering(); } else { - [macSharedData decrementViewsUsingDirectToCPUFiltering]; + dlFetchObj->DecrementViewsUsingDirectToCPUFiltering(); } } @@ -2076,17 +2073,18 @@ static std::unordered_map _screenMap; // { DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate]; CocoaDSCore *cdsCore = (CocoaDSCore *)[[[windowController emuControl] cdsCoreController] content]; - CocoaDSGPU *cdsGPU = [cdsCore cdsGPU]; - MacClientSharedObject *macSharedData = [cdsGPU sharedData]; + MacGPUFetchObjectDisplayLink *dlFetchObj = (MacGPUFetchObjectDisplayLink *)[[cdsCore cdsGPU] fetchObject]; #ifdef ENABLE_APPLE_METAL BOOL isMetalLayer = NO; - if ((macSharedData != nil) && [macSharedData isKindOfClass:[MetalDisplayViewSharedData class]]) + if ( (dlFetchObj->GetClientData() != nil) && (dlFetchObj->GetID() == GPUClientFetchObjectID_MacMetal) ) { - if ([(MetalDisplayViewSharedData *)macSharedData device] != nil) + MetalDisplayViewSharedData *metalSharedData = (MetalDisplayViewSharedData *)dlFetchObj->GetClientData(); + + if ([metalSharedData device] != nil) { - MacMetalDisplayView *macMTLCDV = new MacMetalDisplayView(macSharedData); + MacMetalDisplayView *macMTLCDV = new MacMetalDisplayView(metalSharedData); macMTLCDV->Init(); localLayer = macMTLCDV->GetCALayer(); @@ -2096,7 +2094,7 @@ static std::unordered_map _screenMap; // else #endif { - MacOGLDisplayView *macOGLCDV = new MacOGLDisplayView(macSharedData); + MacOGLDisplayView *macOGLCDV = new MacOGLDisplayView((MacOGLClientFetchObject *)dlFetchObj); macOGLCDV->Init(); localLayer = macOGLCDV->GetCALayer(); diff --git a/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm b/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm index cd8f6e062..4a96a55e3 100644 --- a/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm +++ b/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm @@ -2504,8 +2504,8 @@ CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; [cdsCore updateCurrentSessionMACAddressString:NO]; - [screenshotCaptureToolDelegate setSharedData:[[cdsCore cdsGPU] sharedData]]; - [avCaptureToolDelegate setSharedData:[[cdsCore cdsGPU] sharedData]]; + [screenshotCaptureToolDelegate setFetchObject:[[cdsCore cdsGPU] fetchObject]]; + [avCaptureToolDelegate setFetchObject:[[cdsCore cdsGPU] fetchObject]]; [self fillOpenGLMSAAMenu]; } @@ -2645,7 +2645,7 @@ [[cdsCore cdsGPU] setOpenGLEmulateNDSDepthCalculation:[[NSUserDefaults standardUserDefaults] boolForKey:@"Render3D_OpenGL_EmulateNDSDepthCalculation"]]; [[cdsCore cdsGPU] setOpenGLEmulateDepthLEqualPolygonFacing:[[NSUserDefaults standardUserDefaults] boolForKey:@"Render3D_OpenGL_EmulateDepthLEqualPolygonFacing"]]; - [[[cdsCore cdsGPU] sharedData] fetchSynchronousAtIndex:0]; + ((MacGPUFetchObjectAsync *)[[cdsCore cdsGPU] fetchObject])->FetchSynchronousAtIndex(0); // Set the stylus options per user preferences. [[cdsCore cdsController] setStylusPressure:[[NSUserDefaults standardUserDefaults] integerForKey:@"Emulation_StylusPressure"]]; diff --git a/desmume/src/frontend/cocoa/userinterface/MacAVCaptureTool.mm b/desmume/src/frontend/cocoa/userinterface/MacAVCaptureTool.mm index 1f555d6c8..4f7c04451 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacAVCaptureTool.mm +++ b/desmume/src/frontend/cocoa/userinterface/MacAVCaptureTool.mm @@ -1242,20 +1242,16 @@ ClientAVCaptureError FFmpegFileStream::WriteOneFrame(const AVStreamWriteParam &p - (void) setVideoSizeUsingEmulatorSettings { + GPUClientFetchObject *currentFetchObj = [self fetchObject]; + // Do a few sanity checks before proceeding. - if ([self sharedData] == nil) + if (currentFetchObj == NULL) { return; } - GPUClientFetchObject *fetchObject = [[self sharedData] GPUFetchObject]; - if (fetchObject == NULL) - { - return; - } - - const u8 lastBufferIndex = fetchObject->GetLastFetchIndex(); - const NDSDisplayInfo &displayInfo = fetchObject->GetFetchDisplayInfoForBufferIndex(lastBufferIndex); + const u8 lastBufferIndex = currentFetchObj->GetLastFetchIndex(); + const NDSDisplayInfo &displayInfo = currentFetchObj->GetFetchDisplayInfoForBufferIndex(lastBufferIndex); double normalWidth = 0.0; double normalHeight = 0.0; @@ -1308,6 +1304,8 @@ ClientAVCaptureError FFmpegFileStream::WriteOneFrame(const AVStreamWriteParam &p - (void) openFileStream { + GPUClientFetchObject *currentFetchObj = [self fetchObject]; + // One final check for the video size if we're using the emulator settings. if (videoSizeOption == VideoSizeOption_UseEmulatorSettings) { @@ -1315,13 +1313,7 @@ ClientAVCaptureError FFmpegFileStream::WriteOneFrame(const AVStreamWriteParam &p } // Do a few sanity checks before proceeding. - if ([self sharedData] == nil) - { - return; - } - - GPUClientFetchObject *fetchObject = [[self sharedData] GPUFetchObject]; - if (fetchObject == NULL) + if (currentFetchObj == NULL) { return; } @@ -1356,7 +1348,7 @@ ClientAVCaptureError FFmpegFileStream::WriteOneFrame(const AVStreamWriteParam &p // Set up the rendering properties. MacCaptureToolParams param; param.refObject = newCaptureObject; - param.sharedData = [self sharedData]; + param.fetchObject = currentFetchObj; param.formatID = [self formatID]; param.savePath = std::string([savePath cStringUsingEncoding:NSUTF8StringEncoding]); param.romName = std::string([romName cStringUsingEncoding:NSUTF8StringEncoding]); @@ -1372,8 +1364,8 @@ ClientAVCaptureError FFmpegFileStream::WriteOneFrame(const AVStreamWriteParam &p param.cdpProperty.clientWidth = [self videoWidth]; param.cdpProperty.clientHeight = [self videoHeight]; - const u8 lastBufferIndex = fetchObject->GetLastFetchIndex(); - const NDSDisplayInfo &displayInfo = fetchObject->GetFetchDisplayInfoForBufferIndex(lastBufferIndex); + const u8 lastBufferIndex = currentFetchObj->GetLastFetchIndex(); + const NDSDisplayInfo &displayInfo = currentFetchObj->GetFetchDisplayInfoForBufferIndex(lastBufferIndex); if ( (displayInfo.renderedWidth[NDSDisplayID_Main] == 0) || (displayInfo.renderedHeight[NDSDisplayID_Main] == 0) || (displayInfo.renderedWidth[NDSDisplayID_Touch] == 0) || (displayInfo.renderedHeight[NDSDisplayID_Touch] == 0) ) diff --git a/desmume/src/frontend/cocoa/userinterface/MacBaseCaptureTool.h b/desmume/src/frontend/cocoa/userinterface/MacBaseCaptureTool.h index ad59e511a..dfbfc926b 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacBaseCaptureTool.h +++ b/desmume/src/frontend/cocoa/userinterface/MacBaseCaptureTool.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2018-2021 DeSmuME team + Copyright (C) 2018-2022 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 @@ -28,7 +28,7 @@ #undef BOOL #endif -@class MacClientSharedObject; +class GPUClientFetchObject; #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 @interface MacBaseCaptureToolDelegate : NSObject @@ -40,7 +40,7 @@ NSWindow *window; DirectoryURLDragDestTextField *saveDirectoryPathTextField; - MacClientSharedObject *sharedData; + GPUClientFetchObject *fetchObject; NSString *saveDirectoryPath; NSString *romName; @@ -60,7 +60,7 @@ @property (readonly) IBOutlet NSWindow *window; @property (readonly) IBOutlet DirectoryURLDragDestTextField *saveDirectoryPathTextField; -@property (retain) MacClientSharedObject *sharedData; +@property (assign) GPUClientFetchObject *fetchObject; @property (copy) NSString *saveDirectoryPath; @property (copy) NSString *romName; @@ -84,7 +84,7 @@ class MacCaptureToolParams { public: void *refObject; - MacClientSharedObject *sharedData; + GPUClientFetchObject *fetchObject; NSUInteger formatID; std::string savePath; diff --git a/desmume/src/frontend/cocoa/userinterface/MacBaseCaptureTool.mm b/desmume/src/frontend/cocoa/userinterface/MacBaseCaptureTool.mm index fe7c45666..db0ab5ab2 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacBaseCaptureTool.mm +++ b/desmume/src/frontend/cocoa/userinterface/MacBaseCaptureTool.mm @@ -24,7 +24,7 @@ @synthesize dummyObject; @synthesize window; @synthesize saveDirectoryPathTextField; -@synthesize sharedData; +@synthesize fetchObject; @synthesize saveDirectoryPath; @synthesize romName; @synthesize formatID; @@ -46,7 +46,7 @@ return nil; } - sharedData = nil; + fetchObject = nil; saveDirectoryPath = nil; romName = @"No_ROM_loaded"; @@ -66,7 +66,6 @@ - (void)dealloc { - [self setSharedData:nil]; [self setSaveDirectoryPath:nil]; [self setRomName:nil]; diff --git a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.h b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.h index 6e1578031..7f29b4e85 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.h +++ b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.h @@ -294,7 +294,7 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties; #pragma mark - -class MacMetalFetchObject : public GPUClientFetchObject +class MacMetalFetchObject : public MacGPUFetchObjectDisplayLink { protected: bool _useDirectToCPUFilterPipeline; @@ -313,6 +313,8 @@ public: virtual void CopyFromSrcClone(uint32_t *dstBufferPtr, const NDSDisplayID displayID, const u8 bufferIndex); virtual void SetFetchBuffers(const NDSDisplayInfo ¤tDisplayInfo); virtual void FetchFromBufferIndex(const u8 index); + + virtual void FlushMultipleViews(const std::vector &cdvFlushList, const CVTimeStamp *timeStampNow, const CVTimeStamp *timeStampOutput); }; #pragma mark - diff --git a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm index 54f7c6452..850a9b906 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm +++ b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm @@ -707,8 +707,8 @@ { id cb = [_fetchCommandQueue commandBufferWithUnretainedReferences]; - semaphore_wait([self semaphoreFramebufferPageAtIndex:index]); - [self setFramebufferState:ClientDisplayBufferState_Reading index:index]; + semaphore_wait( GPUFetchObject->SemaphoreFramebufferPageAtIndex(index) ); + GPUFetchObject->SetFramebufferState(ClientDisplayBufferState_Reading, index); id bce = [cb blitCommandEncoder]; [self setBceFetch:bce]; @@ -726,8 +726,8 @@ [oldTexPair.main release]; [oldTexPair.touch release]; - [self setFramebufferState:ClientDisplayBufferState_Idle index:index]; - semaphore_signal([self semaphoreFramebufferPageAtIndex:index]); + GPUFetchObject->SetFramebufferState(ClientDisplayBufferState_Idle, index); + semaphore_signal( GPUFetchObject->SemaphoreFramebufferPageAtIndex(index) ); }]; [cb commit]; @@ -2473,6 +2473,7 @@ MacMetalFetchObject::MacMetalFetchObject() if (_clientData != nil) { + _id = GPUClientFetchObjectID_MacMetal; strlcpy(_name, [[(MetalDisplayViewSharedData *)_clientData name] cStringUsingEncoding:NSUTF8StringEncoding], sizeof(_name) - 1); strlcpy(_description, [[(MetalDisplayViewSharedData *)_clientData description] cStringUsingEncoding:NSUTF8StringEncoding], sizeof(_description) - 1); } @@ -2505,6 +2506,7 @@ MacMetalFetchObject::~MacMetalFetchObject() void MacMetalFetchObject::Init() { [(MacClientSharedObject *)this->_clientData setGPUFetchObject:this]; + this->MacGPUFetchObjectAsync::Init(); } void MacMetalFetchObject::CopyFromSrcClone(uint32_t *dstBufferPtr, const NDSDisplayID displayID, const u8 bufferIndex) @@ -2522,8 +2524,7 @@ void MacMetalFetchObject::SetFetchBuffers(const NDSDisplayInfo ¤tDisplayIn void MacMetalFetchObject::FetchFromBufferIndex(const u8 index) { - MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_clientData; - this->_useDirectToCPUFilterPipeline = ([sharedViewObject numberViewsUsingDirectToCPUFiltering] > 0); + this->_useDirectToCPUFilterPipeline = (this->GetNumberViewsUsingDirectToCPUFiltering() > 0); [(MetalDisplayViewSharedData *)this->_clientData fetchFromBufferIndex:index]; } @@ -2556,6 +2557,11 @@ void MacMetalFetchObject::_FetchCustomDisplayByID(const NDSDisplayID displayID, [(MetalDisplayViewSharedData *)this->_clientData fetchCustomDisplayByID:displayID bufferIndex:bufferIndex blitCommandEncoder:[(MetalDisplayViewSharedData *)this->_clientData bceFetch]]; } +void MacMetalFetchObject::FlushMultipleViews(const std::vector &cdvFlushList, const CVTimeStamp *timeStampNow, const CVTimeStamp *timeStampOutput) +{ + [(MetalDisplayViewSharedData *)this->_clientData flushMultipleViews:cdvFlushList timeStampNow:timeStampNow timeStampOutput:timeStampOutput]; +} + #pragma mark - MacMetalDisplayPresenter::MacMetalDisplayPresenter() @@ -2818,8 +2824,8 @@ void MacMetalDisplayView::SetViewNeedsFlush() void MacMetalDisplayView::SetAllowViewFlushes(bool allowFlushes) { CGDirectDisplayID displayID = (CGDirectDisplayID)this->GetDisplayViewID(); - MacClientSharedObject *sharedData = ((MacMetalDisplayPresenter *)this->_presenter)->GetSharedData(); - [sharedData displayLinkStartUsingID:displayID]; + MacGPUFetchObjectDisplayLink &fetchObj = (MacGPUFetchObjectDisplayLink &)this->_presenter->GetFetchObject(); + fetchObj.DisplayLinkStartUsingID(displayID); } void MacMetalDisplayView::FlushView(void *userData) diff --git a/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.h b/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.h index c6175e493..93c1f7e4d 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.h +++ b/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.h @@ -44,13 +44,28 @@ class MacOGLDisplayView; @end -class MacOGLClientFetchObject : public OGLClientFetchObject +class MacOGLClientSharedData : public OGLClientSharedData +{ +protected: + apple_unfairlock_t _unfairlockTexFetch[2]; + +public: + MacOGLClientSharedData(); + ~MacOGLClientSharedData(); + + virtual GLuint GetFetchTexture(const NDSDisplayID displayID); + virtual void SetFetchTexture(const NDSDisplayID displayID, GLuint texID); +}; + +class MacOGLClientFetchObject : public MacGPUFetchObjectDisplayLink { protected: NSOpenGLContext *_nsContext; CGLContextObj _context; - apple_unfairlock_t _unfairlockTexFetch[2]; + // GPUClientFetchObject methods + virtual void _FetchNativeDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex); + virtual void _FetchCustomDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex); public: void operator delete(void *ptr); @@ -60,18 +75,19 @@ public: NSOpenGLContext* GetNSContext() const; CGLContextObj GetContext() const; + void FetchNativeDisplayToSrcClone(const NDSDisplayID displayID, const u8 bufferIndex, bool needsLock); + void FetchCustomDisplayToSrcClone(const NDSDisplayID displayID, const u8 bufferIndex, bool needsLock); + + // GPUClientFetchObject methods virtual void Init(); virtual void SetFetchBuffers(const NDSDisplayInfo ¤tDisplayInfo); virtual void FetchFromBufferIndex(const u8 index); - - virtual GLuint GetFetchTexture(const NDSDisplayID displayID); - virtual void SetFetchTexture(const NDSDisplayID displayID, GLuint texID); }; -class MacOGLDisplayPresenter : public OGLVideoOutput, public MacDisplayPresenterInterface +class MacOGLDisplayPresenter : public OGLVideoOutput { private: - void __InstanceInit(MacClientSharedObject *sharedObject); + void __InstanceInit(MacOGLClientFetchObject *fetchObject); protected: NSOpenGLContext *_nsContext; @@ -83,7 +99,7 @@ protected: public: void operator delete(void *ptr); MacOGLDisplayPresenter(); - MacOGLDisplayPresenter(MacClientSharedObject *sharedObject); + MacOGLDisplayPresenter(MacOGLClientFetchObject *fetchObject); ~MacOGLDisplayPresenter(); virtual void Init(); @@ -117,14 +133,14 @@ public: class MacOGLDisplayView : public MacDisplayLayeredView { private: - void __InstanceInit(MacClientSharedObject *sharedObject); + void __InstanceInit(MacOGLClientFetchObject *fetchObject); protected: apple_unfairlock_t _unfairlockViewNeedsFlush; public: MacOGLDisplayView(); - MacOGLDisplayView(MacClientSharedObject *sharedObject); + MacOGLDisplayView(MacOGLClientFetchObject *fetchObject); virtual ~MacOGLDisplayView(); virtual bool GetViewNeedsFlush(); diff --git a/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.mm b/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.mm index 605a09305..ebd094447 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.mm +++ b/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.mm @@ -18,6 +18,7 @@ #include "MacOGLDisplayView.h" #include #include "../utilities.h" +#import "../cocoa_globals.h" @implementation DisplayViewOpenGLLayer @@ -74,21 +75,49 @@ #pragma mark - +MacOGLClientSharedData::MacOGLClientSharedData() +{ + _unfairlockTexFetch[NDSDisplayID_Main] = apple_unfairlock_create(); + _unfairlockTexFetch[NDSDisplayID_Touch] = apple_unfairlock_create(); +} + +MacOGLClientSharedData::~MacOGLClientSharedData() +{ + apple_unfairlock_destroy(this->_unfairlockTexFetch[NDSDisplayID_Main]); + this->_unfairlockTexFetch[NDSDisplayID_Main] = NULL; + apple_unfairlock_destroy(this->_unfairlockTexFetch[NDSDisplayID_Touch]); + this->_unfairlockTexFetch[NDSDisplayID_Touch] = NULL; +} + +GLuint MacOGLClientSharedData::GetFetchTexture(const NDSDisplayID displayID) +{ + apple_unfairlock_lock(this->_unfairlockTexFetch[displayID]); + const GLuint texFetchID = this->OGLClientSharedData::GetFetchTexture(displayID); + apple_unfairlock_unlock(this->_unfairlockTexFetch[displayID]); + + return texFetchID; +} + +void MacOGLClientSharedData::SetFetchTexture(const NDSDisplayID displayID, GLuint texID) +{ + apple_unfairlock_lock(this->_unfairlockTexFetch[displayID]); + this->OGLClientSharedData::SetFetchTexture(displayID, texID); + apple_unfairlock_unlock(this->_unfairlockTexFetch[displayID]); +} + +#pragma mark - + void MacOGLClientFetchObject::operator delete(void *ptr) { MacOGLClientFetchObject *fetchObjectPtr = (MacOGLClientFetchObject *)ptr; - [(MacClientSharedObject *)(fetchObjectPtr->GetClientData()) release]; - CGLContextObj context = fetchObjectPtr->GetContext(); if (context != NULL) { - OGLContextInfo *contextInfo = fetchObjectPtr->GetContextInfo(); CGLContextObj prevContext = CGLGetCurrentContext(); CGLSetCurrentContext(context); [fetchObjectPtr->GetNSContext() release]; - delete contextInfo; ::operator delete(ptr); CGLSetCurrentContext(prevContext); @@ -143,34 +172,32 @@ MacOGLClientFetchObject::MacOGLClientFetchObject() CGLContextObj prevContext = CGLGetCurrentContext(); CGLSetCurrentContext(_context); + OGLContextInfo *newContextInfo = NULL; + #ifdef _OGLDISPLAYOUTPUT_3_2_H_ if (useContext_3_2) { - _contextInfo = new OGLContextInfo_3_2; + newContextInfo = new OGLContextInfo_3_2; } else #endif { - _contextInfo = new OGLContextInfo_Legacy; + newContextInfo = new OGLContextInfo_Legacy; } CGLSetCurrentContext(prevContext); - snprintf(_name, sizeof(_name) - 1, "macOS OpenGL v%i.%i", _contextInfo->GetVersionMajor(), _contextInfo->GetVersionMinor()); - strlcpy(_description, _contextInfo->GetRendererString(), sizeof(_description) - 1); + _id = GPUClientFetchObjectID_MacOpenGL; + snprintf(_name, sizeof(_name) - 1, "macOS OpenGL v%i.%i", newContextInfo->GetVersionMajor(), newContextInfo->GetVersionMinor()); + strlcpy(_description, newContextInfo->GetRendererString(), sizeof(_description) - 1); - _clientData = [[MacClientSharedObject alloc] init]; - - _unfairlockTexFetch[NDSDisplayID_Main] = apple_unfairlock_create(); - _unfairlockTexFetch[NDSDisplayID_Touch] = apple_unfairlock_create(); + _clientData = new MacOGLClientSharedData; + ((MacOGLClientSharedData *)_clientData)->SetContextInfo(newContextInfo); } MacOGLClientFetchObject::~MacOGLClientFetchObject() { - apple_unfairlock_destroy(this->_unfairlockTexFetch[NDSDisplayID_Main]); - this->_unfairlockTexFetch[NDSDisplayID_Main] = NULL; - apple_unfairlock_destroy(this->_unfairlockTexFetch[NDSDisplayID_Touch]); - this->_unfairlockTexFetch[NDSDisplayID_Touch] = NULL; + delete (MacOGLClientSharedData *)this->_clientData; } NSOpenGLContext* MacOGLClientFetchObject::GetNSContext() const @@ -183,55 +210,80 @@ CGLContextObj MacOGLClientFetchObject::GetContext() const return this->_context; } +void MacOGLClientFetchObject::FetchNativeDisplayToSrcClone(const NDSDisplayID displayID, const u8 bufferIndex, bool needsLock) +{ + MacOGLClientSharedData *sharedData = (MacOGLClientSharedData *)this->_clientData; + sharedData->FetchNativeDisplayToSrcClone(this->_fetchDisplayInfo, displayID, bufferIndex, needsLock); +} + +void MacOGLClientFetchObject::FetchCustomDisplayToSrcClone(const NDSDisplayID displayID, const u8 bufferIndex, bool needsLock) +{ + MacOGLClientSharedData *sharedData = (MacOGLClientSharedData *)this->_clientData; + sharedData->FetchCustomDisplayToSrcClone(this->_fetchDisplayInfo, displayID, bufferIndex, needsLock); +} + void MacOGLClientFetchObject::Init() { - [(MacClientSharedObject *)this->_clientData setGPUFetchObject:this]; + MacOGLClientSharedData *sharedData = (MacOGLClientSharedData *)this->_clientData; CGLContextObj prevContext = CGLGetCurrentContext(); - CGLSetCurrentContext(_context); - this->OGLClientFetchObject::Init(); + CGLSetCurrentContext(this->_context); + sharedData->InitOGL(); CGLSetCurrentContext(prevContext); + + this->MacGPUFetchObjectDisplayLink::Init(); } void MacOGLClientFetchObject::SetFetchBuffers(const NDSDisplayInfo ¤tDisplayInfo) { + MacOGLClientSharedData *sharedData = (MacOGLClientSharedData *)this->_clientData; + CGLLockContext(this->_context); CGLSetCurrentContext(this->_context); - this->OGLClientFetchObject::SetFetchBuffers(currentDisplayInfo); + this->GPUClientFetchObject::SetFetchBuffers(currentDisplayInfo); + sharedData->SetFetchBuffersOGL(this->_fetchDisplayInfo, currentDisplayInfo); CGLUnlockContext(this->_context); } void MacOGLClientFetchObject::FetchFromBufferIndex(const u8 index) { - MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_clientData; - this->_useDirectToCPUFilterPipeline = ([sharedViewObject numberViewsUsingDirectToCPUFiltering] > 0); + MacOGLClientSharedData *sharedData = (MacOGLClientSharedData *)this->_clientData; - semaphore_wait([sharedViewObject semaphoreFramebufferPageAtIndex:index]); - [sharedViewObject setFramebufferState:ClientDisplayBufferState_Reading index:index]; + const bool willUseDirectCPU = (this->GetNumberViewsUsingDirectToCPUFiltering() > 0); + sharedData->SetUseDirectToCPUFilterPipeline(willUseDirectCPU); + + semaphore_wait( this->SemaphoreFramebufferPageAtIndex(index) ); + this->SetFramebufferState(ClientDisplayBufferState_Reading, index); CGLLockContext(this->_context); CGLSetCurrentContext(this->_context); - this->OGLClientFetchObject::FetchFromBufferIndex(index); + + this->GPUClientFetchObject::FetchFromBufferIndex(index); + glFlush(); + + const NDSDisplayInfo ¤tDisplayInfo = this->GetFetchDisplayInfoForBufferIndex(index); + sharedData->FetchFromBufferIndexOGL(index, currentDisplayInfo); + CGLUnlockContext(this->_context); - [sharedViewObject setFramebufferState:ClientDisplayBufferState_Idle index:index]; - semaphore_signal([sharedViewObject semaphoreFramebufferPageAtIndex:index]); + this->SetFramebufferState(ClientDisplayBufferState_Idle, index); + semaphore_signal( this->SemaphoreFramebufferPageAtIndex(index) ); } -GLuint MacOGLClientFetchObject::GetFetchTexture(const NDSDisplayID displayID) +void MacOGLClientFetchObject::_FetchNativeDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex) { - apple_unfairlock_lock(this->_unfairlockTexFetch[displayID]); - const GLuint texFetchID = this->OGLClientFetchObject::GetFetchTexture(displayID); - apple_unfairlock_unlock(this->_unfairlockTexFetch[displayID]); - - return texFetchID; + // This method is called from MacOGLClientFetchObject::FetchFromBufferIndex(), and so + // we should have already been assigned the current context. + MacOGLClientSharedData *sharedData = (MacOGLClientSharedData *)this->_clientData; + sharedData->FetchNativeDisplayByID_OGL(this->_fetchDisplayInfo, displayID, bufferIndex); } -void MacOGLClientFetchObject::SetFetchTexture(const NDSDisplayID displayID, GLuint texID) +void MacOGLClientFetchObject::_FetchCustomDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex) { - apple_unfairlock_lock(this->_unfairlockTexFetch[displayID]); - this->OGLClientFetchObject::SetFetchTexture(displayID, texID); - apple_unfairlock_unlock(this->_unfairlockTexFetch[displayID]); + // This method is called from MacOGLClientFetchObject::FetchFromBufferIndex(), and so + // we should have already been assigned the current context. + MacOGLClientSharedData *sharedData = (MacOGLClientSharedData *)this->_clientData; + sharedData->FetchCustomDisplayByID_OGL(this->_fetchDisplayInfo, displayID, bufferIndex); } #pragma mark - @@ -260,12 +312,12 @@ MacOGLDisplayPresenter::MacOGLDisplayPresenter() __InstanceInit(nil); } -MacOGLDisplayPresenter::MacOGLDisplayPresenter(MacClientSharedObject *sharedObject) : MacDisplayPresenterInterface(sharedObject) +MacOGLDisplayPresenter::MacOGLDisplayPresenter(MacOGLClientFetchObject *fetchObject) { - __InstanceInit(sharedObject); + __InstanceInit(fetchObject); } -void MacOGLDisplayPresenter::__InstanceInit(MacClientSharedObject *sharedObject) +void MacOGLDisplayPresenter::__InstanceInit(MacOGLClientFetchObject *fetchObject) { // Initialize the OpenGL context. // @@ -310,10 +362,7 @@ void MacOGLDisplayPresenter::__InstanceInit(MacClientSharedObject *sharedObject) _context = nil; _unfairlockProcessedInfo = apple_unfairlock_create(); - if (sharedObject != nil) - { - SetFetchObject([sharedObject GPUFetchObject]); - } + SetFetchObject(fetchObject); } MacOGLDisplayPresenter::~MacOGLDisplayPresenter() @@ -452,26 +501,20 @@ void MacOGLDisplayPresenter::SetProcessedFrameInfo(const OGLProcessedFrameInfo & void MacOGLDisplayPresenter::WriteLockEmuFramebuffer(const uint8_t bufferIndex) { - const GPUClientFetchObject &fetchObj = this->GetFetchObject(); - MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData(); - - semaphore_wait([sharedViewObject semaphoreFramebufferPageAtIndex:bufferIndex]); + MacOGLClientFetchObject &fetchObj = (MacOGLClientFetchObject &)this->GetFetchObject(); + semaphore_wait( fetchObj.SemaphoreFramebufferPageAtIndex(bufferIndex) ); } void MacOGLDisplayPresenter::ReadLockEmuFramebuffer(const uint8_t bufferIndex) { - const GPUClientFetchObject &fetchObj = this->GetFetchObject(); - MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData(); - - semaphore_wait([sharedViewObject semaphoreFramebufferPageAtIndex:bufferIndex]); + MacOGLClientFetchObject &fetchObj = (MacOGLClientFetchObject &)this->GetFetchObject(); + semaphore_wait( fetchObj.SemaphoreFramebufferPageAtIndex(bufferIndex) ); } void MacOGLDisplayPresenter::UnlockEmuFramebuffer(const uint8_t bufferIndex) { - const GPUClientFetchObject &fetchObj = this->GetFetchObject(); - MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData(); - - semaphore_signal([sharedViewObject semaphoreFramebufferPageAtIndex:bufferIndex]); + MacOGLClientFetchObject &fetchObj = (MacOGLClientFetchObject &)this->GetFetchObject(); + semaphore_signal( fetchObj.SemaphoreFramebufferPageAtIndex(bufferIndex) ); } #pragma mark - @@ -481,9 +524,9 @@ MacOGLDisplayView::MacOGLDisplayView() __InstanceInit(nil); } -MacOGLDisplayView::MacOGLDisplayView(MacClientSharedObject *sharedObject) +MacOGLDisplayView::MacOGLDisplayView(MacOGLClientFetchObject *fetchObject) { - __InstanceInit(sharedObject); + __InstanceInit(fetchObject); } MacOGLDisplayView::~MacOGLDisplayView() @@ -494,12 +537,12 @@ MacOGLDisplayView::~MacOGLDisplayView() this->_unfairlockViewNeedsFlush = NULL; } -void MacOGLDisplayView::__InstanceInit(MacClientSharedObject *sharedObject) +void MacOGLDisplayView::__InstanceInit(MacOGLClientFetchObject *fetchObject) { _allowViewUpdates = false; _unfairlockViewNeedsFlush = apple_unfairlock_create(); - MacOGLDisplayPresenter *newOpenGLPresenter = new MacOGLDisplayPresenter(sharedObject); + MacOGLDisplayPresenter *newOpenGLPresenter = new MacOGLDisplayPresenter(fetchObject); _presenter = newOpenGLPresenter; _caLayer = [[DisplayViewOpenGLLayer alloc] init]; @@ -542,8 +585,8 @@ void MacOGLDisplayView::SetViewNeedsFlush() void MacOGLDisplayView::SetAllowViewFlushes(bool allowFlushes) { CGDirectDisplayID displayID = (CGDirectDisplayID)this->GetDisplayViewID(); - MacClientSharedObject *sharedData = ((MacOGLDisplayPresenter *)this->_presenter)->GetSharedData(); - [sharedData displayLinkStartUsingID:displayID]; + MacOGLClientFetchObject &fetchObj = (MacOGLClientFetchObject &)this->_presenter->GetFetchObject(); + fetchObj.DisplayLinkStartUsingID(displayID); } void MacOGLDisplayView::SetUseVerticalSync(const bool useVerticalSync) diff --git a/desmume/src/frontend/cocoa/userinterface/MacScreenshotCaptureTool.mm b/desmume/src/frontend/cocoa/userinterface/MacScreenshotCaptureTool.mm index 81714cb5c..2b13210f1 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacScreenshotCaptureTool.mm +++ b/desmume/src/frontend/cocoa/userinterface/MacScreenshotCaptureTool.mm @@ -73,7 +73,7 @@ // Note: We're allocating the parameter's memory block here, but we will be freeing it once we copy it in the detached thread. MacCaptureToolParams *param = new MacCaptureToolParams; param->refObject = NULL; - param->sharedData = [self sharedData]; + param->fetchObject = [self fetchObject]; param->formatID = [self formatID]; param->savePath = std::string([savePath cStringUsingEncoding:NSUTF8StringEncoding]); param->romName = std::string([romName cStringUsingEncoding:NSUTF8StringEncoding]); @@ -143,7 +143,7 @@ static void* RunFileWriteThread(void *arg) MacCaptureToolParams param; param.refObject = inParams->refObject; - param.sharedData = inParams->sharedData; + param.fetchObject = inParams->fetchObject; param.formatID = inParams->formatID; param.savePath = inParams->savePath; param.romName = inParams->romName; @@ -162,19 +162,13 @@ static void* RunFileWriteThread(void *arg) inParams = NULL; // Do a few sanity checks before proceeding. - if (param.sharedData == nil) + if (param.fetchObject == NULL) { return NULL; } - GPUClientFetchObject *fetchObject = [param.sharedData GPUFetchObject]; - if (fetchObject == NULL) - { - return NULL; - } - - const u8 lastBufferIndex = fetchObject->GetLastFetchIndex(); - const NDSDisplayInfo &displayInfo = fetchObject->GetFetchDisplayInfoForBufferIndex(lastBufferIndex); + const u8 lastBufferIndex = param.fetchObject->GetLastFetchIndex(); + const NDSDisplayInfo &displayInfo = param.fetchObject->GetFetchDisplayInfoForBufferIndex(lastBufferIndex); if ( (displayInfo.renderedWidth[NDSDisplayID_Main] == 0) || (displayInfo.renderedHeight[NDSDisplayID_Main] == 0) || (displayInfo.renderedWidth[NDSDisplayID_Touch] == 0) || (displayInfo.renderedHeight[NDSDisplayID_Touch] == 0) ) @@ -227,22 +221,22 @@ static void* RunFileWriteThread(void *arg) bool isUsingMetal = false; #ifdef ENABLE_APPLE_METAL - if ([param.sharedData isKindOfClass:[MetalDisplayViewSharedData class]]) + if (param.fetchObject->GetID() == GPUClientFetchObjectID_MacMetal) { - if ([(MetalDisplayViewSharedData *)param.sharedData device] == nil) + if ([(MetalDisplayViewSharedData *)param.fetchObject->GetClientData() device] == nil) { [newImageRep release]; [autoreleasePool release]; return NULL; } - cdp = new MacMetalDisplayPresenter(param.sharedData); + cdp = new MacMetalDisplayPresenter((MetalDisplayViewSharedData *)param.fetchObject->GetClientData()); isUsingMetal = true; } else #endif { - cdp = new MacOGLDisplayPresenter(param.sharedData); + cdp = new MacOGLDisplayPresenter((MacOGLClientFetchObject *)param.fetchObject); } cdp->Init(); @@ -276,12 +270,12 @@ static void* RunFileWriteThread(void *arg) { if ( (param.cdpProperty.mode == ClientDisplayMode_Main) || (param.cdpProperty.mode == ClientDisplayMode_Dual) ) { - ((OGLClientFetchObject *)fetchObject)->FetchNativeDisplayToSrcClone(NDSDisplayID_Main, lastBufferIndex, true); + ((MacOGLClientFetchObject *)param.fetchObject)->FetchNativeDisplayToSrcClone(NDSDisplayID_Main, lastBufferIndex, true); } if ( (param.cdpProperty.mode == ClientDisplayMode_Touch) || (param.cdpProperty.mode == ClientDisplayMode_Dual) ) { - ((OGLClientFetchObject *)fetchObject)->FetchNativeDisplayToSrcClone(NDSDisplayID_Touch, lastBufferIndex, true); + ((MacOGLClientFetchObject *)param.fetchObject)->FetchNativeDisplayToSrcClone(NDSDisplayID_Touch, lastBufferIndex, true); } } }